demangle.h

00001 // C++ IA64 / g++ v3 demangler -*- C++ -*- 00002 00003 // Copyright (C) 2003, 2004 Free Software Foundation, Inc. 00004 // Written by Carlo Wood <carlo@alinoe.com> 00005 // 00006 // This file is part of the GNU ISO C++ Library. This library is free 00007 // software; you can redistribute it and/or modify it under the 00008 // terms of the GNU General Public License as published by the 00009 // Free Software Foundation; either version 2, or (at your option) 00010 // any later version. 00011 00012 // This library is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 00017 // You should have received a copy of the GNU General Public License along 00018 // with this library; see the file COPYING. If not, write to the Free 00019 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 00020 // USA. 00021 00022 // As a special exception, you may use this file as part of a free software 00023 // library without restriction. Specifically, if other files instantiate 00024 // templates or use macros or inline functions from this file, or you compile 00025 // this file and link it with other files to produce an executable, this 00026 // file does not by itself cause the resulting executable to be covered by 00027 // the GNU General Public License. This exception does not however 00028 // invalidate any other reasons why the executable file might be covered by 00029 // the GNU General Public License. 00030 00031 // This file implements demangling of "C++ ABI for Itanium"-mangled symbol 00032 // and type names as described in Revision 1.73 of the C++ ABI as can be found 00033 // at http://www.codesourcery.com/cxx-abi/abi.html#mangling 00034 00035 #ifndef _DEMANGLER_H 00036 #define _DEMANGLER_H 1 00037 00038 #include <vector> 00039 #include <string> 00040 #include <ext/new_allocator.h> 00041 00042 #ifndef _GLIBCXX_DEMANGLER_DEBUG 00043 #define _GLIBCXX_DEMANGLER_CWDEBUG 0 00044 #define _GLIBCXX_DEMANGLER_DEBUG(x) 00045 #define _GLIBCXX_DEMANGLER_DOUT(cntrl, data) 00046 #define _GLIBCXX_DEMANGLER_DOUT_ENTERING(x) 00047 #define _GLIBCXX_DEMANGLER_DOUT_ENTERING2(x) 00048 #define _GLIBCXX_DEMANGLER_DOUT_ENTERING3(x) 00049 #define _GLIBCXX_DEMANGLER_RETURN return M_result 00050 #define _GLIBCXX_DEMANGLER_RETURN2 return M_result 00051 #define _GLIBCXX_DEMANGLER_RETURN3 00052 #define _GLIBCXX_DEMANGLER_FAILURE \ 00053 do { M_result = false; return false; } while(0) 00054 #else 00055 #define _GLIBCXX_DEMANGLER_CWDEBUG 1 00056 #endif 00057 00058 namespace __gnu_cxx 00059 { 00060 namespace demangler 00061 { 00062 enum substitution_nt 00063 { 00064 type, 00065 template_template_param, 00066 nested_name_prefix, 00067 nested_name_template_prefix, 00068 unscoped_template_name 00069 }; 00070 00071 struct substitution_st 00072 { 00073 int M_start_pos; 00074 substitution_nt M_type; 00075 int M_number_of_prefixes; 00076 00077 substitution_st(int start_pos, 00078 substitution_nt type, 00079 int number_of_prefixes) 00080 : M_start_pos(start_pos), M_type(type), 00081 M_number_of_prefixes(number_of_prefixes) 00082 { } 00083 }; 00084 00085 enum simple_qualifier_nt 00086 { 00087 complex_or_imaginary = 'G', 00088 pointer = 'P', 00089 reference = 'R' 00090 }; 00091 00092 enum cv_qualifier_nt 00093 { 00094 cv_qualifier = 'K' 00095 }; 00096 00097 enum param_qualifier_nt 00098 { 00099 vendor_extension = 'U', 00100 array = 'A', 00101 pointer_to_member = 'M' 00102 }; 00103 00104 template<typename Tp, typename Allocator = __gnu_cxx::new_allocator<Tp> > 00105 class qualifier; 00106 00107 template<typename Tp, typename Allocator = __gnu_cxx::new_allocator<Tp> > 00108 class qualifier_list; 00109 00110 template<typename Tp, typename Allocator = __gnu_cxx::new_allocator<Tp> > 00111 class session; 00112 00113 template<typename Tp, typename Allocator> 00114 class qualifier 00115 { 00116 typedef typename Allocator::template rebind<char>::other 00117 char_Allocator; 00118 typedef std::basic_string<char, std::char_traits<char>, char_Allocator> 00119 string_type; 00120 00121 private: 00122 char M_qualifier1; 00123 char M_qualifier2; 00124 char M_qualifier3; 00125 mutable unsigned char M_cnt; 00126 string_type M_optional_type; 00127 int M_start_pos; 00128 bool M_part_of_substitution; 00129 00130 public: 00131 qualifier(int start_pos, 00132 simple_qualifier_nt simple_qualifier, 00133 int inside_substitution) 00134 : M_qualifier1(simple_qualifier), 00135 M_start_pos(start_pos), 00136 M_part_of_substitution(inside_substitution) 00137 { } 00138 00139 qualifier(int start_pos, 00140 cv_qualifier_nt, 00141 char const* start, 00142 int count, 00143 int inside_substitution) 00144 : M_qualifier1(start[0]), 00145 M_qualifier2((count > 1) ? start[1] : '\0'), 00146 M_qualifier3((count > 2) ? start[2] : '\0'), 00147 M_start_pos(start_pos), 00148 M_part_of_substitution(inside_substitution) 00149 { } 00150 00151 qualifier(int start_pos, 00152 param_qualifier_nt param_qualifier, 00153 string_type optional_type, 00154 int inside_substitution) 00155 : M_qualifier1(param_qualifier), 00156 M_optional_type(optional_type), 00157 M_start_pos(start_pos), 00158 M_part_of_substitution(inside_substitution) 00159 { } 00160 00161 int 00162 get_start_pos(void) const 00163 { return M_start_pos; } 00164 00165 char 00166 first_qualifier(void) const 00167 { M_cnt = 1; return M_qualifier1; } 00168 00169 char 00170 next_qualifier(void) const 00171 { 00172 return (++M_cnt == 2) ? M_qualifier2 00173 : ((M_cnt == 3) ? M_qualifier3 : 0); 00174 } 00175 00176 string_type const& 00177 get_optional_type(void) const 00178 { return M_optional_type; } 00179 00180 bool 00181 part_of_substitution(void) const 00182 { return M_part_of_substitution; } 00183 00184 #if _GLIBCXX_DEMANGLER_CWDEBUG 00185 friend std::ostream& operator<<(std::ostream& os, qualifier const& qual) 00186 { 00187 os << (char)qual.M_qualifier1; 00188 if (qual.M_qualifier1 == vendor_extension || 00189 qual.M_qualifier1 == array || 00190 qual.M_qualifier1 == pointer_to_member) 00191 os << " [" << qual.M_optional_type << ']'; 00192 else if (qual.M_qualifier1 == 'K' || 00193 qual.M_qualifier1 == 'V' || 00194 qual.M_qualifier1 == 'r') 00195 { 00196 if (qual.M_qualifier2) 00197 { 00198 os << (char)qual.M_qualifier2; 00199 if (qual.M_qualifier3) 00200 os << (char)qual.M_qualifier3; 00201 } 00202 } 00203 return os; 00204 } 00205 #endif 00206 }; 00207 00208 template<typename Tp, typename Allocator> 00209 class qualifier_list 00210 { 00211 typedef typename Allocator::template rebind<char>::other 00212 char_Allocator; 00213 typedef std::basic_string<char, std::char_traits<char>, char_Allocator> 00214 string_type; 00215 00216 private: 00217 mutable bool M_printing_suppressed; 00218 typedef qualifier<Tp, Allocator> qual; 00219 typedef typename Allocator::template rebind<qual>::other qual_Allocator; 00220 typedef std::vector<qual, qual_Allocator> qual_vector; 00221 qual_vector M_qualifier_starts; 00222 session<Tp, Allocator>& M_demangler; 00223 00224 void decode_KVrA(string_type& prefix, string_type& postfix, int cvq, 00225 typename qual_vector:: 00226 const_reverse_iterator const& iter_array) const; 00227 00228 public: 00229 qualifier_list(session<Tp, Allocator>& demangler_obj) 00230 : M_printing_suppressed(false), M_demangler(demangler_obj) 00231 { } 00232 00233 void 00234 add_qualifier_start(simple_qualifier_nt simple_qualifier, 00235 int start_pos, 00236 int inside_substitution) 00237 { M_qualifier_starts. 00238 push_back(qualifier<Tp, Allocator>(start_pos, 00239 simple_qualifier, inside_substitution)); } 00240 00241 void 00242 add_qualifier_start(cv_qualifier_nt cv_qualifier, 00243 int start_pos, 00244 int count, 00245 int inside_substitution) 00246 { M_qualifier_starts. 00247 push_back(qualifier<Tp, Allocator>(start_pos, 00248 cv_qualifier, &M_demangler.M_str[start_pos], 00249 count, inside_substitution)); } 00250 00251 void 00252 add_qualifier_start(param_qualifier_nt param_qualifier, 00253 int start_pos, 00254 string_type optional_type, 00255 int inside_substitution) 00256 { M_qualifier_starts. 00257 push_back(qualifier<Tp, Allocator>(start_pos, 00258 param_qualifier, optional_type, inside_substitution)); } 00259 00260 void 00261 decode_qualifiers(string_type& prefix, 00262 string_type& postfix, 00263 bool member_function_pointer_qualifiers) const; 00264 00265 bool 00266 suppressed(void) const 00267 { return M_printing_suppressed; } 00268 00269 void 00270 printing_suppressed(void) 00271 { M_printing_suppressed = true; } 00272 00273 size_t 00274 size(void) const 00275 { return M_qualifier_starts.size(); } 00276 00277 #if _GLIBCXX_DEMANGLER_CWDEBUG 00278 friend std::ostream& operator<<(std::ostream& os, qualifier_list const& list) 00279 { 00280 typename qual_vector::const_iterator 00281 iter = list.M_qualifier_starts.begin(); 00282 if (iter != list.M_qualifier_starts.end()) 00283 { 00284 os << "{ " << *iter; 00285 while (++iter != list.M_qualifier_starts.end()) 00286 os << ", " << *iter; 00287 os << " }"; 00288 } 00289 else 00290 os << "{ }"; 00291 return os; 00292 } 00293 #endif 00294 }; 00295 00296 struct implementation_details 00297 { 00298 private: 00299 unsigned int M_style; 00300 00301 public: 00302 // The following flags change the behaviour of the demangler. The 00303 // default behaviour is that none of these flags is set. 00304 00305 static unsigned int const style_void = 1; 00306 // Default behaviour: int f() 00307 // Use (void) instead of (): int f(void) 00308 00309 static unsigned int const style_literal = 2; 00310 // Default behaviour: (long)13, 00311 // (unsigned long long)19 00312 // Use extensions 'u', 'l' and 'll' for integral 00313 // literals (as in template arguments): 13l, 19ull 00314 00315 static unsigned int const style_literal_int = 4; 00316 // Default behaviour: 4 00317 // Use also an explicit 00318 // cast for int in literals: (int)4 00319 00320 static unsigned int const style_compact_expr_ops = 8; 00321 // Default behaviour: (i) < (3), sizeof (int) 00322 // Don't output spaces around 00323 // operators in expressions: (i)<(3), sizeof(int) 00324 00325 static unsigned int const style_sizeof_typename = 16; 00326 // Default behaviour: sizeof (X::t) 00327 // Put 'typename' infront of <nested-name> 00328 // types inside a 'sizeof': sizeof (typename X::t) 00329 00330 public: 00331 implementation_details(unsigned int style_flags = 0) : 00332 M_style(style_flags) { } 00333 virtual ~implementation_details() { } 00334 bool get_style_void(void) const 00335 { return (M_style & style_void); } 00336 bool get_style_literal(void) const 00337 { return (M_style & style_literal); } 00338 bool get_style_literal_int(void) const 00339 { return (M_style & style_literal_int); } 00340 bool get_style_compact_expr_ops(void) const 00341 { return (M_style & style_compact_expr_ops); } 00342 bool get_style_sizeof_typename(void) const 00343 { return (M_style & style_sizeof_typename); } 00344 // This can be overridden by user implementations. 00345 virtual bool decode_real(char* /* output */, unsigned long* /* input */, 00346 size_t /* size_of_real */) const 00347 { return false; } 00348 }; 00349 00350 template<typename Tp, typename Allocator> 00351 class session 00352 { 00353 public: 00354 friend class qualifier_list<Tp, Allocator>; 00355 typedef typename Allocator::template rebind<char>::other 00356 char_Allocator; 00357 typedef std::basic_string<char, std::char_traits<char>, char_Allocator> 00358 string_type; 00359 00360 private: 00361 char const* M_str; 00362 int M_pos; 00363 int M_maxpos; 00364 bool M_result; 00365 int M_inside_template_args; 00366 int M_inside_type; 00367 int M_inside_substitution; 00368 bool M_saw_destructor; 00369 bool M_name_is_cdtor; 00370 bool M_name_is_template; 00371 bool M_name_is_conversion_operator; 00372 bool M_template_args_need_space; 00373 string_type M_function_name; 00374 typedef typename Allocator::template rebind<int>::other 00375 int_Allocator; 00376 typedef typename Allocator::template rebind<substitution_st>::other 00377 subst_Allocator; 00378 std::vector<int, int_Allocator> M_template_arg_pos; 00379 int M_template_arg_pos_offset; 00380 std::vector<substitution_st, subst_Allocator> M_substitutions_pos; 00381 implementation_details const& M_implementation_details; 00382 typedef typename Allocator::template 00383 rebind<qualifier_list<Allocator> >::other qualifier_list_Allocator; 00384 qualifier_list_Allocator M_qualifier_list_alloc; 00385 #if _GLIBCXX_DEMANGLER_CWDEBUG 00386 bool M_inside_add_substitution; 00387 #endif 00388 00389 public: 00390 explicit session(char const* in, int len, 00391 implementation_details const& id = implementation_details()) 00392 : M_str(in), M_pos(0), M_maxpos(len - 1), M_result(true), 00393 M_inside_template_args(0), M_inside_type(0), 00394 M_inside_substitution(0), M_saw_destructor(false), 00395 M_name_is_cdtor(false), M_name_is_template(false), 00396 M_name_is_conversion_operator(false), 00397 M_template_args_need_space(false), M_template_arg_pos_offset(0), 00398 M_implementation_details(id) 00399 #if _GLIBCXX_DEMANGLER_CWDEBUG 00400 , M_inside_add_substitution(false) 00401 #endif 00402 { } 00403 00404 static int 00405 decode_encoding(string_type& output, char const* input, int len, 00406 implementation_details const& id = implementation_details()); 00407 00408 bool 00409 decode_type(string_type& output, 00410 qualifier_list<Tp, Allocator>* qualifiers = NULL) 00411 { 00412 string_type postfix; 00413 bool res = decode_type_with_postfix(output, postfix, qualifiers); 00414 output += postfix; 00415 return res; 00416 } 00417 00418 bool 00419 remaining_input_characters(void) const 00420 { return current() != 0; } 00421 00422 private: 00423 char 00424 current(void) const 00425 { return (M_pos > M_maxpos) ? 0 : M_str[M_pos]; } 00426 00427 char 00428 next_peek(void) const 00429 { return (M_pos >= M_maxpos) ? 0 : M_str[M_pos + 1]; } 00430 00431 char 00432 next(void) 00433 { return (M_pos >= M_maxpos) ? 0 : M_str[++M_pos]; } 00434 00435 char 00436 eat_current(void) 00437 { return (M_pos > M_maxpos) ? 0 : M_str[M_pos++]; } 00438 00439 void 00440 store(int& saved_pos) 00441 { saved_pos = M_pos; } 00442 00443 void 00444 restore(int saved_pos) 00445 { M_pos = saved_pos; M_result = true; } 00446 00447 void 00448 add_substitution(int start_pos, 00449 substitution_nt sub_type, 00450 int number_of_prefixes); 00451 00452 bool decode_type_with_postfix(string_type& prefix, 00453 string_type& postfix, qualifier_list<Tp, Allocator>* qualifiers = NULL); 00454 bool decode_bare_function_type(string_type& output); 00455 bool decode_builtin_type(string_type& output); 00456 bool decode_call_offset(string_type& output); 00457 bool decode_class_enum_type(string_type& output); 00458 bool decode_expression(string_type& output); 00459 bool decode_literal(string_type& output); 00460 bool decode_local_name(string_type& output); 00461 bool decode_name(string_type& output, 00462 string_type& nested_name_qualifiers); 00463 bool decode_nested_name(string_type& output, 00464 string_type& qualifiers); 00465 bool decode_number(string_type& output); 00466 bool decode_operator_name(string_type& output); 00467 bool decode_source_name(string_type& output); 00468 bool decode_substitution(string_type& output, 00469 qualifier_list<Tp, Allocator>* qualifiers = NULL); 00470 bool decode_template_args(string_type& output); 00471 bool decode_template_param(string_type& output, 00472 qualifier_list<Tp, Allocator>* qualifiers = NULL); 00473 bool decode_unqualified_name(string_type& output); 00474 bool decode_unscoped_name(string_type& output); 00475 bool decode_non_negative_decimal_integer(string_type& output); 00476 bool decode_special_name(string_type& output); 00477 bool decode_real(string_type& output, size_t size_of_real); 00478 }; 00479 00480 template<typename Tp, typename Allocator> 00481 #if !_GLIBCXX_DEMANGLER_CWDEBUG 00482 inline 00483 #endif 00484 void 00485 session<Tp, Allocator>::add_substitution(int start_pos, 00486 substitution_nt sub_type, 00487 int number_of_prefixes = 0) 00488 { 00489 if (!M_inside_substitution) 00490 { 00491 #if _GLIBCXX_DEMANGLER_CWDEBUG 00492 if (M_inside_add_substitution) 00493 return; 00494 #endif 00495 M_substitutions_pos. 00496 push_back(substitution_st(start_pos, 00497 sub_type, number_of_prefixes)); 00498 #if _GLIBCXX_DEMANGLER_CWDEBUG 00499 if (!DEBUGCHANNELS::dc::demangler.is_on()) 00500 return; 00501 string_type substitution_name("S"); 00502 int n = M_substitutions_pos.size() - 1; 00503 if (n > 0) 00504 substitution_name += (n <= 10) ? (char)(n + '0' - 1) 00505 : (char)(n + 'A' - 11); 00506 substitution_name += '_'; 00507 string_type subst; 00508 int saved_pos = M_pos; 00509 M_pos = start_pos; 00510 M_inside_add_substitution = true; 00511 _GLIBCXX_DEMANGLER_DEBUG( dc::demangler.off() ); 00512 switch(sub_type) 00513 { 00514 case type: 00515 decode_type(subst); 00516 break; 00517 case template_template_param: 00518 decode_template_param(subst); 00519 break; 00520 case nested_name_prefix: 00521 case nested_name_template_prefix: 00522 for (int cnt = number_of_prefixes; cnt > 0; --cnt) 00523 { 00524 if (current() == 'I') 00525 { 00526 subst += ' '; 00527 decode_template_args(subst); 00528 } 00529 else 00530 { 00531 if (cnt < number_of_prefixes) 00532 subst += "::"; 00533 if (current() == 'S') 00534 decode_substitution(subst); 00535 else if (current() == 'T') 00536 decode_template_param(subst); 00537 else 00538 decode_unqualified_name(subst); 00539 } 00540 } 00541 break; 00542 case unscoped_template_name: 00543 decode_unscoped_name(subst); 00544 break; 00545 } 00546 M_pos = saved_pos; 00547 _GLIBCXX_DEMANGLER_DEBUG( dc::demangler.on() ); 00548 _GLIBCXX_DEMANGLER_DOUT(dc::demangler, 00549 "Adding substitution " << substitution_name 00550 << " : " << subst 00551 << " (from " << location_ct((char*)__builtin_return_address(0) 00552 + builtin_return_address_offset) 00553 << " <- " << location_ct((char*)__builtin_return_address(1) 00554 + builtin_return_address_offset) 00555 << " <- " << location_ct((char*)__builtin_return_address(2) 00556 + builtin_return_address_offset) 00557 << ")."); 00558 M_inside_add_substitution = false; 00559 #endif 00560 } 00561 } 00562 00563 // We don't want to depend on locale (or include <cctype> for that matter). 00564 // We also don't want to use "safe-ctype.h" because that headerfile is not 00565 // available to the users. 00566 inline bool isdigit(char c) { return c >= '0' && c <= '9'; } 00567 inline bool islower(char c) { return c >= 'a' && c <= 'z'; } 00568 inline bool isupper(char c) { return c >= 'A' && c <= 'Z'; } 00569 inline char tolower(char c) { return isupper(c) ? c - 'A' + 'a' : c; } 00570 00571 // 00572 // <non-negative decimal integer> ::= 0 00573 // ::= 1|2|3|4|5|6|7|8|9 [<digit>+] 00574 // <digit> ::= 0|1|2|3|4|5|6|7|8|9 00575 // 00576 template<typename Tp, typename Allocator> 00577 bool 00578 session<Tp, Allocator>:: 00579 decode_non_negative_decimal_integer(string_type& output) 00580 { 00581 char c = current(); 00582 if (c == '0') 00583 { 00584 output += '0'; 00585 eat_current(); 00586 } 00587 else if (!isdigit(c)) 00588 M_result = false; 00589 else 00590 { 00591 do 00592 { 00593 output += c; 00594 } 00595 while (isdigit((c = next()))); 00596 } 00597 return M_result; 00598 } 00599 00600 // <number> ::= [n] <non-negative decimal integer> 00601 // 00602 template<typename Tp, typename Allocator> 00603 bool 00604 session<Tp, Allocator>::decode_number(string_type& output) 00605 { 00606 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_number"); 00607 if (current() != 'n') 00608 decode_non_negative_decimal_integer(output); 00609 else 00610 { 00611 output += '-'; 00612 eat_current(); 00613 decode_non_negative_decimal_integer(output); 00614 } 00615 _GLIBCXX_DEMANGLER_RETURN; 00616 } 00617 00618 // <builtin-type> ::= v # void 00619 // ::= w # wchar_t 00620 // ::= b # bool 00621 // ::= c # char 00622 // ::= a # signed char 00623 // ::= h # unsigned char 00624 // ::= s # short 00625 // ::= t # unsigned short 00626 // ::= i # int 00627 // ::= j # unsigned int 00628 // ::= l # long 00629 // ::= m # unsigned long 00630 // ::= x # long long, __int64 00631 // ::= y # unsigned long long, __int64 00632 // ::= n # __int128 00633 // ::= o # unsigned __int128 00634 // ::= f # float 00635 // ::= d # double 00636 // ::= e # long double, __float80 00637 // ::= g # __float128 00638 // ::= z # ellipsis 00639 // ::= u <source-name> # vendor extended type 00640 // 00641 char const* const builtin_type_c[26] = 00642 { 00643 "signed char", // a 00644 "bool", // b 00645 "char", // c 00646 "double", // d 00647 "long double", // e 00648 "float", // f 00649 "__float128", // g 00650 "unsigned char", // h 00651 "int", // i 00652 "unsigned int", // j 00653 NULL, // k 00654 "long", // l 00655 "unsigned long", // m 00656 "__int128", // n 00657 "unsigned __int128", // o 00658 NULL, // p 00659 NULL, // q 00660 NULL, // r 00661 "short", // s 00662 "unsigned short", // t 00663 NULL, // u 00664 "void", // v 00665 "wchar_t", // w 00666 "long long", // x 00667 "unsigned long long", // y 00668 "..." // z 00669 }; 00670 00671 // 00672 template<typename Tp, typename Allocator> 00673 bool 00674 session<Tp, Allocator>::decode_builtin_type(string_type& output) 00675 { 00676 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_builtin_type"); 00677 char const* bt; 00678 if (!islower(current()) || !(bt = builtin_type_c[current() - 'a'])) 00679 _GLIBCXX_DEMANGLER_FAILURE; 00680 output += bt; 00681 eat_current(); 00682 _GLIBCXX_DEMANGLER_RETURN; 00683 } 00684 00685 // <class-enum-type> ::= <name> 00686 // 00687 template<typename Tp, typename Allocator> 00688 bool 00689 session<Tp, Allocator>::decode_class_enum_type(string_type& output) 00690 { 00691 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_class_enum_type"); 00692 string_type nested_name_qualifiers; 00693 if (!decode_name(output, nested_name_qualifiers)) 00694 _GLIBCXX_DEMANGLER_FAILURE; 00695 output += nested_name_qualifiers; 00696 _GLIBCXX_DEMANGLER_RETURN; 00697 } 00698 00699 // <substitution> ::= 00700 // S <seq-id> _ 00701 // S_ 00702 // St # ::std:: 00703 // Sa # ::std::allocator 00704 // Sb # ::std::basic_string 00705 // Ss # ::std::basic_string<char, std::char_traits<char>, 00706 // std::allocator<char> > 00707 // Si # ::std::basic_istream<char, std::char_traits<char> > 00708 // So # ::std::basic_ostream<char, std::char_traits<char> > 00709 // Sd # ::std::basic_iostream<char, std::char_traits<char> > 00710 // 00711 // <seq-id> ::= 00712 // 0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z 00713 // [<seq-id>] # Base 36 number 00714 // 00715 template<typename Tp, typename Allocator> 00716 bool 00717 session<Tp, Allocator>::decode_substitution(string_type& output, 00718 qualifier_list<Tp, Allocator>* qualifiers) 00719 { 00720 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_substitution"); 00721 unsigned int value = 0; 00722 char c = next(); 00723 if (c != '_') 00724 { 00725 switch(c) 00726 { 00727 case 'a': 00728 { 00729 output += "std::allocator"; 00730 if (!M_inside_template_args) 00731 { 00732 M_function_name = "allocator"; 00733 M_name_is_template = true; 00734 M_name_is_cdtor = false; 00735 M_name_is_conversion_operator = false; 00736 } 00737 eat_current(); 00738 if (qualifiers) 00739 qualifiers->printing_suppressed(); 00740 _GLIBCXX_DEMANGLER_RETURN; 00741 } 00742 case 'b': 00743 { 00744 output += "std::basic_string"; 00745 if (!M_inside_template_args) 00746 { 00747 M_function_name = "basic_string"; 00748 M_name_is_template = true; 00749 M_name_is_cdtor = false; 00750 M_name_is_conversion_operator = false; 00751 } 00752 eat_current(); 00753 if (qualifiers) 00754 qualifiers->printing_suppressed(); 00755 _GLIBCXX_DEMANGLER_RETURN; 00756 } 00757 case 'd': 00758 output += "std::iostream"; 00759 if (!M_inside_template_args) 00760 { 00761 M_function_name = "iostream"; 00762 M_name_is_template = true; 00763 M_name_is_cdtor = false; 00764 M_name_is_conversion_operator = false; 00765 } 00766 eat_current(); 00767 if (qualifiers) 00768 qualifiers->printing_suppressed(); 00769 _GLIBCXX_DEMANGLER_RETURN; 00770 case 'i': 00771 output += "std::istream"; 00772 if (!M_inside_template_args) 00773 { 00774 M_function_name = "istream"; 00775 M_name_is_template = true; 00776 M_name_is_cdtor = false; 00777 M_name_is_conversion_operator = false; 00778 } 00779 eat_current(); 00780 if (qualifiers) 00781 qualifiers->printing_suppressed(); 00782 _GLIBCXX_DEMANGLER_RETURN; 00783 case 'o': 00784 output += "std::ostream"; 00785 if (!M_inside_template_args) 00786 { 00787 M_function_name = "ostream"; 00788 M_name_is_template = true; 00789 M_name_is_cdtor = false; 00790 M_name_is_conversion_operator = false; 00791 } 00792 eat_current(); 00793 if (qualifiers) 00794 qualifiers->printing_suppressed(); 00795 _GLIBCXX_DEMANGLER_RETURN; 00796 case 's': 00797 output += "std::string"; 00798 if (!M_inside_template_args) 00799 { 00800 M_function_name = "string"; 00801 M_name_is_template = true; 00802 M_name_is_cdtor = false; 00803 M_name_is_conversion_operator = false; 00804 } 00805 eat_current(); 00806 if (qualifiers) 00807 qualifiers->printing_suppressed(); 00808 _GLIBCXX_DEMANGLER_RETURN; 00809 case 't': 00810 output += "std"; 00811 eat_current(); 00812 if (qualifiers) 00813 qualifiers->printing_suppressed(); 00814 _GLIBCXX_DEMANGLER_RETURN; 00815 default: 00816 for(;; c = next()) 00817 { 00818 if (isdigit(c)) 00819 value = value * 36 + c - '0'; 00820 else if (isupper(c)) 00821 value = value * 36 + c - 'A' + 10; 00822 else if (c == '_') 00823 break; 00824 else 00825 _GLIBCXX_DEMANGLER_FAILURE; 00826 } 00827 ++value; 00828 break; 00829 } 00830 } 00831 eat_current(); 00832 if (value >= M_substitutions_pos.size() || 00833 M_inside_type > 20) // Rather than core dump. 00834 _GLIBCXX_DEMANGLER_FAILURE; 00835 ++M_inside_substitution; 00836 int saved_pos = M_pos; 00837 substitution_st& substitution(M_substitutions_pos[value]); 00838 M_pos = substitution.M_start_pos; 00839 switch(substitution.M_type) 00840 { 00841 case type: 00842 decode_type(output, qualifiers); 00843 break; 00844 case template_template_param: 00845 decode_template_param(output, qualifiers); 00846 break; 00847 case nested_name_prefix: 00848 case nested_name_template_prefix: 00849 for (int cnt = substitution.M_number_of_prefixes; cnt > 0; --cnt) 00850 { 00851 if (current() == 'I') 00852 { 00853 if (M_template_args_need_space) 00854 output += ' '; 00855 M_template_args_need_space = false; 00856 if (!decode_template_args(output)) 00857 _GLIBCXX_DEMANGLER_FAILURE; 00858 } 00859 else 00860 { 00861 if (cnt < substitution.M_number_of_prefixes) 00862 output += "::"; 00863 if (current() == 'S') 00864 { 00865 if (!decode_substitution(output)) 00866 _GLIBCXX_DEMANGLER_FAILURE; 00867 } 00868 else if (!decode_unqualified_name(output)) 00869 _GLIBCXX_DEMANGLER_FAILURE; 00870 } 00871 } 00872 if (qualifiers) 00873 qualifiers->printing_suppressed(); 00874 break; 00875 case unscoped_template_name: 00876 decode_unscoped_name(output); 00877 if (qualifiers) 00878 qualifiers->printing_suppressed(); 00879 break; 00880 } 00881 M_pos = saved_pos; 00882 --M_inside_substitution; 00883 _GLIBCXX_DEMANGLER_RETURN; 00884 } 00885 00886 // <template-param> ::= T_ # first template parameter 00887 // ::= T <parameter-2 non-negative number> _ 00888 // 00889 template<typename Tp, typename Allocator> 00890 bool 00891 session<Tp, Allocator>::decode_template_param(string_type& output, 00892 qualifier_list<Tp, Allocator>* qualifiers) 00893 { 00894 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_template_parameter"); 00895 if (current() != 'T') 00896 _GLIBCXX_DEMANGLER_FAILURE; 00897 unsigned int value = 0; 00898 char c; 00899 if ((c = next()) != '_') 00900 { 00901 while(isdigit(c)) 00902 { 00903 value = value * 10 + c - '0'; 00904 c = next(); 00905 } 00906 ++value; 00907 } 00908 if (eat_current() != '_') 00909 _GLIBCXX_DEMANGLER_FAILURE; 00910 value += M_template_arg_pos_offset; 00911 if (value >= M_template_arg_pos.size()) 00912 _GLIBCXX_DEMANGLER_FAILURE; 00913 int saved_pos = M_pos; 00914 M_pos = M_template_arg_pos[value]; 00915 if (M_inside_type > 20) // Rather than core dump. 00916 _GLIBCXX_DEMANGLER_FAILURE; 00917 ++M_inside_substitution; 00918 if (current() == 'X') 00919 { 00920 eat_current(); 00921 decode_expression(output); 00922 } 00923 else if (current() == 'L') 00924 decode_literal(output); 00925 else 00926 decode_type(output, qualifiers); 00927 --M_inside_substitution; 00928 M_pos = saved_pos; 00929 _GLIBCXX_DEMANGLER_RETURN; 00930 } 00931 00932 template<typename Tp, typename Allocator> 00933 bool 00934 session<Tp, Allocator>::decode_real(string_type& output, size_t size_of_real) 00935 { 00936 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_real"); 00937 00938 unsigned long words[4]; // 32 bit per long, maximum of 128 bits. 00939 unsigned long* word = &words[0]; 00940 00941 int saved_pos; 00942 store(saved_pos); 00943 00944 // The following assumes that leading zeroes are also included in the 00945 // mangled name, I am not sure that is conforming to the C++-ABI, but 00946 // it is what g++ does. 00947 unsigned char nibble, c = current(); 00948 for(size_t word_cnt = size_of_real / 4; word_cnt > 0; --word_cnt) 00949 { 00950 for (int nibble_cnt = 0; nibble_cnt < 8; ++nibble_cnt) 00951 { 00952 // Translate character into nibble. 00953 if (c < '0' || c > 'f') 00954 _GLIBCXX_DEMANGLER_FAILURE; 00955 if (c <= '9') 00956 nibble = c - '0'; 00957 else if (c >= 'a') 00958 nibble = c - 'a' + 10; 00959 else 00960 _GLIBCXX_DEMANGLER_FAILURE; 00961 // Write nibble into word array. 00962 if (nibble_cnt == 0) 00963 *word = nibble << 28; 00964 else 00965 *word |= (nibble << (28 - 4 * nibble_cnt)); 00966 c = next(); 00967 } 00968 ++word; 00969 } 00970 char buf[24]; 00971 if (M_implementation_details.decode_real(buf, words, size_of_real)) 00972 { 00973 output += buf; 00974 _GLIBCXX_DEMANGLER_RETURN; 00975 } 00976 restore(saved_pos); 00977 00978 output += '['; 00979 c = current(); 00980 for(size_t nibble_cnt = 0; nibble_cnt < 2 * size_of_real; ++nibble_cnt) 00981 { 00982 if (c < '0' || c > 'f' || (c > '9' && c < 'a')) 00983 _GLIBCXX_DEMANGLER_FAILURE; 00984 output += c; 00985 c = next(); 00986 } 00987 output += ']'; 00988 00989 _GLIBCXX_DEMANGLER_RETURN; 00990 } 00991 00992 template<typename Tp, typename Allocator> 00993 bool 00994 session<Tp, Allocator>::decode_literal(string_type& output) 00995 { 00996 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_literal"); 00997 eat_current(); // Eat the 'L'. 00998 if (current() == '_') 00999 { 01000 if (next() != 'Z') 01001 _GLIBCXX_DEMANGLER_FAILURE; 01002 eat_current(); 01003 if ((M_pos += decode_encoding(output, M_str + M_pos, 01004 M_maxpos - M_pos + 1, M_implementation_details)) < 0) 01005 _GLIBCXX_DEMANGLER_FAILURE; 01006 } 01007 else 01008 { 01009 // Special cases 01010 if (current() == 'b') 01011 { 01012 if (next() == '0') 01013 output += "false"; 01014 else 01015 output += "true"; 01016 eat_current(); 01017 _GLIBCXX_DEMANGLER_RETURN; 01018 } 01019 char c = current(); 01020 if ((c == 'i' || c == 'j' || c == 'l' || 01021 c == 'm' || c == 'x' || c == 'y') && 01022 M_implementation_details.get_style_literal()) 01023 eat_current(); 01024 else if (c == 'i' && 01025 !M_implementation_details.get_style_literal_int()) 01026 eat_current(); 01027 else 01028 { 01029 output += '('; 01030 if (!decode_type(output)) 01031 _GLIBCXX_DEMANGLER_FAILURE; 01032 output += ')'; 01033 } 01034 if (c >= 'd' && c <= 'g') 01035 { 01036 size_t size_of_real = (c == 'd') ? sizeof(double) : 01037 ((c == 'f') ? sizeof(float) : 01038 (c == 'e') ? sizeof(long double) : 16); 01039 if (!decode_real(output, size_of_real)) 01040 _GLIBCXX_DEMANGLER_FAILURE; 01041 } 01042 else if (!decode_number(output)) 01043 _GLIBCXX_DEMANGLER_FAILURE; 01044 if (M_implementation_details.get_style_literal()) 01045 { 01046 if (c == 'j' || c == 'm' || c == 'y') 01047 output += 'u'; 01048 if (c == 'l' || c == 'm') 01049 output += 'l'; 01050 if (c == 'x' || c == 'y') 01051 output += "ll"; 01052 } 01053 } 01054 _GLIBCXX_DEMANGLER_RETURN; 01055 } 01056 01057 // <operator-name> ::= 01058 // nw # new 01059 // na # new[] 01060 // dl # delete 01061 // da # delete[] 01062 // ps # + (unary) 01063 // ng # - (unary) 01064 // ad # & (unary) 01065 // de # * (unary) 01066 // co # ~ 01067 // pl # + 01068 // mi # - 01069 // ml # * 01070 // dv # / 01071 // rm # % 01072 // an # & 01073 // or # | 01074 // eo # ^ 01075 // aS # = 01076 // pL # += 01077 // mI # -= 01078 // mL # *= 01079 // dV # /= 01080 // rM # %= 01081 // aN # &= 01082 // oR # |= 01083 // eO # ^= 01084 // ls # << 01085 // rs # >> 01086 // lS # <<= 01087 // rS # >>= 01088 // eq # == 01089 // ne # != 01090 // lt # < 01091 // gt # > 01092 // le # <= 01093 // ge # >= 01094 // nt # ! 01095 // aa # && 01096 // oo # || 01097 // pp # ++ 01098 // mm # -- 01099 // cm # , 01100 // pm # ->* 01101 // pt # -> 01102 // cl # () 01103 // ix # [] 01104 // qu # ? 01105 // st # sizeof (a type) 01106 // sz # sizeof (an expression) 01107 // cv <type> # (cast) 01108 // v <digit> <source-name> # vendor extended operator 01109 // 01110 // Symbol operator codes exist of two characters, we need to find a 01111 // quick hash so that their names can be looked up in a table. 01112 // 01113 // The puzzle :) 01114 // Shift the rows so that there is at most one character per column. 01115 // 01116 // A perfect solution (Oh no, it's THE MATRIX!): 01117 // horizontal 01118 // ....................................... offset + 'a' 01119 // a, a||d|||||||||n||||s|||||||||||||||||||| 0 01120 // c, || |||||||lm o||| |||||||||||||||||||| 0 01121 // d, || a|||e|| l|| ||||||v||||||||||||| 4 01122 // e, || ||| || || |||o|q ||||||||||||| 8 01123 // g, || ||| || || e|| | ||||||||t|||| 15 01124 // i, || ||| || || || | |||||||| |||x 15 01125 // l, |e ||| || st || | |||||||| ||| -2 01126 // m, | |i| lm || | |||||||| ||| -2 01127 // n, a e g t| w |||||||| ||| 1 01128 // o, | ||||o||r ||| 16 01129 // p, | ||lm |p st| 17 01130 // q, | u| | | 6 01131 // r, m s | | 9 01132 // s, t z 12 01133 // ....................................... 01134 // ^ ^__ second character 01135 // |___ first character 01136 // 01137 01138 // Putting that solution in tables: 01139 01140 char const offset_table_c [1 + CHAR_MAX - CHAR_MIN ] = 01141 { 01142 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 01143 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 01144 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 01145 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 01146 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 01147 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 01148 #if (CHAR_MIN < 0) 01149 // Add -CHAR_MIN extra zeroes (128): 01150 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 01151 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 01152 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 01153 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 01154 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 01155 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 01156 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 01157 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 01158 // a b c d e f g h i j k 01159 0, -97, 0, -97, -93, -89, 0, -82, 0, -82, 0, 0, 01160 // l m n o p q r s t u v 01161 -99, -99, -96, -81, -80, -91, -88, -85, 0, 0, 0, 01162 #else 01163 // a b c d e f g h i j k 01164 0, 159, 0, 159, 163, 167, 0, 174, 0, 174, 0, 0, 01165 // l m n o p q r s t u v 01166 157, 157, 160, 175, 176, 165, 168, 171, 0, 0, 0, 01167 #endif 01168 // ... more zeros 01169 }; 01170 01171 enum xary_nt { 01172 unary, 01173 binary, 01174 trinary 01175 }; 01176 01177 struct entry_st 01178 { 01179 char const* opcode; 01180 char const* symbol_name; 01181 xary_nt type; 01182 }; 01183 01184 entry_st const symbol_name_table_c[39] = { 01185 { "aa", "operator&&", binary }, 01186 { "na", "operator new[]", unary }, 01187 { "le", "operator<=", binary }, 01188 { "ad", "operator&", unary }, 01189 { "da", "operator delete[]", unary }, 01190 { "ne", "operator!=", binary }, 01191 { "mi=", "operator-", binary }, 01192 { "ng", "operator-", unary }, 01193 { "de", "operator*", unary }, 01194 { "ml=", "operator*", binary }, 01195 { "mm", "operator--", unary }, 01196 { "cl", "operator()", unary }, 01197 { "cm", "operator,", binary }, 01198 { "an=", "operator&", binary }, 01199 { "co", "operator~", binary }, 01200 { "dl", "operator delete", unary }, 01201 { "ls=", "operator<<", binary }, 01202 { "lt", "operator<", binary }, 01203 { "as=", "operator", binary }, 01204 { "ge", "operator>=", binary }, 01205 { "nt", "operator!", unary }, 01206 { "rm=", "operator%", binary }, 01207 { "eo=", "operator^", binary }, 01208 { "nw", "operator new", unary }, 01209 { "eq", "operator==", binary }, 01210 { "dv=", "operator/", binary }, 01211 { "qu", "operator?", trinary }, 01212 { "rs=", "operator>>", binary }, 01213 { "pl=", "operator+", binary }, 01214 { "pm", "operator->*", binary }, 01215 { "oo", "operator||", binary }, 01216 { "st", "sizeof", unary }, 01217 { "pp", "operator++", unary }, 01218 { "or=", "operator|", binary }, 01219 { "gt", "operator>", binary }, 01220 { "ps", "operator+", unary }, 01221 { "pt", "operator->", binary }, 01222 { "sz", "sizeof", unary }, 01223 { "ix", "operator[]", unary } 01224 }; 01225 01226 template<typename Tp, typename Allocator> 01227 bool 01228 session<Tp, Allocator>::decode_operator_name(string_type& output) 01229 { 01230 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_operator_name"); 01231 01232 char opcode0 = current(); 01233 char opcode1 = tolower(next()); 01234 01235 register char hash; 01236 if ((hash = offset_table_c[opcode0 - CHAR_MIN])) 01237 { 01238 hash += opcode1; 01239 if ( 01240 #if (CHAR_MIN < 0) 01241 hash >= 0 && 01242 #endif 01243 hash < 39) 01244 { 01245 int index = static_cast<int>(static_cast<unsigned char>(hash)); 01246 entry_st entry = symbol_name_table_c[index]; 01247 if (entry.opcode[0] == opcode0 && entry.opcode[1] == opcode1 01248 && (opcode1 == current() || entry.opcode[2] == '=')) 01249 { 01250 output += entry.symbol_name; 01251 if (opcode1 != current()) 01252 output += '='; 01253 eat_current(); 01254 if (hash == 16 || hash == 17) 01255 M_template_args_need_space = true; 01256 _GLIBCXX_DEMANGLER_RETURN; 01257 } 01258 else if (opcode0 == 'c' && opcode1 == 'v') // casting operator 01259 { 01260 eat_current(); 01261 output += "operator "; 01262 if (current() == 'T') 01263 { 01264 // This is a templated cast operator. 01265 // It must be of the form "cvT_I...E". 01266 // Let M_template_arg_pos already point 01267 // to the template argument. 01268 M_template_arg_pos_offset = M_template_arg_pos.size(); 01269 M_template_arg_pos.push_back(M_pos + 3); 01270 } 01271 if (!decode_type(output)) 01272 _GLIBCXX_DEMANGLER_FAILURE; 01273 if (!M_inside_template_args) 01274 M_name_is_conversion_operator = true; 01275 _GLIBCXX_DEMANGLER_RETURN; 01276 } 01277 } 01278 } 01279 _GLIBCXX_DEMANGLER_FAILURE; 01280 } 01281 01282 // 01283 // <expression> ::= <unary operator-name> <expression> 01284 // ::= <binary operator-name> <expression> <expression> 01285 // ::= <trinary operator-name> <expression> <expression> <expression> 01286 // ::= st <type> 01287 // ::= <template-param> 01288 // ::= sr <type> <unqualified-name> # dependent name 01289 // ::= sr <type> <unqualified-name> <template-args> # dependent template-id 01290 // ::= <expr-primary> 01291 // 01292 // <expr-primary> ::= L <type> <value number> E # integer literal 01293 // ::= L <type> <value float> E # floating literal 01294 // ::= L <mangled-name> E # external name 01295 // 01296 template<typename Tp, typename Allocator> 01297 bool 01298 session<Tp, Allocator>::decode_expression(string_type& output) 01299 { 01300 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_expression"); 01301 if (current() == 'T') 01302 { 01303 if (!decode_template_param(output)) 01304 _GLIBCXX_DEMANGLER_FAILURE; 01305 _GLIBCXX_DEMANGLER_RETURN; 01306 } 01307 else if (current() == 'L') 01308 { 01309 if (!decode_literal(output)) 01310 _GLIBCXX_DEMANGLER_FAILURE; 01311 if (current() != 'E') 01312 _GLIBCXX_DEMANGLER_FAILURE; 01313 eat_current(); 01314 _GLIBCXX_DEMANGLER_RETURN; 01315 } 01316 else if (current() == 's') 01317 { 01318 char opcode1 = next(); 01319 if (opcode1 == 't' || opcode1 == 'z') 01320 { 01321 eat_current(); 01322 if (M_implementation_details.get_style_compact_expr_ops()) 01323 output += "sizeof("; 01324 else 01325 output += "sizeof ("; 01326 if (opcode1 == 't') 01327 { 01328 // I cannot think of a mangled name that is valid for both cases 01329 // when just replacing the 't' by a 'z' or vica versa, which 01330 // indicates that there is no ambiguity that dictates the need 01331 // for a seperate "st" case, except to be able catch invalid 01332 // mangled names. However there CAN be ambiguity in the demangled 01333 // name when there are both a type and a symbol of the same name, 01334 // which then leads to different encoding (of course) with 01335 // sizeof (type) or sizeof (expression) respectively, but that 01336 // ambiguity is not per se related to "sizeof" except that that 01337 // is the only place where both a type AND an expression are valid 01338 // in as part of a (template function) type. 01339 // 01340 // Example: 01341 // 01342 // struct B { typedef int t; }; 01343 // struct A : public B { static int t[2]; }; 01344 // template<int i, int j> struct C { typedef int q; }; 01345 // template<int i, typename T> 01346 // void f(typename C<sizeof (typename T::t), 01347 // sizeof (T::t)>::q) { } 01348 // void instantiate() { f<5, A>(0); } 01349 // 01350 // Leads to _Z1fILi5E1AEvN1CIXstN1T1tEEXszsrS2_1tEE1qE which 01351 // demangles as 01352 // void f<5, A>(C<sizeof (T::t), sizeof (T::t)>::q) 01353 // 01354 // This is ambiguity is very unlikely to happen and it is kind 01355 // of fuzzy to detect when adding a 'typename' makes sense. 01356 // 01357 if (M_implementation_details.get_style_sizeof_typename()) 01358 { 01359 // We can only get here inside a template parameter, 01360 // so this is syntactically correct if the given type is 01361 // a typedef. The only disadvantage is that it is inconsistent 01362 // with all other places where the 'typename' keyword should be 01363 // used and we don't. 01364 // With this, the above example will demangle as 01365 // void f<5, A>(C<sizeof (typename T::t), sizeof (T::t)>::q) 01366 if (current() == 'N' || // <nested-name> 01367 // This should be a safe bet. 01368 (current() == 'S' && 01369 next_peek() == 't')) // std::something, guess that 01370 // this involves a typedef. 01371 output += "typename "; 01372 } 01373 if (!decode_type(output)) 01374 _GLIBCXX_DEMANGLER_FAILURE; 01375 } 01376 else 01377 { 01378 if (!decode_expression(output)) 01379 _GLIBCXX_DEMANGLER_FAILURE; 01380 } 01381 output += ')'; 01382 _GLIBCXX_DEMANGLER_RETURN; 01383 } 01384 else if (current() == 'r') 01385 { 01386 eat_current(); 01387 if (!decode_type(output)) 01388 _GLIBCXX_DEMANGLER_FAILURE; 01389 output += "::"; 01390 if (!decode_unqualified_name(output)) 01391 _GLIBCXX_DEMANGLER_FAILURE; 01392 if (current() != 'I' || decode_template_args(output)) 01393 _GLIBCXX_DEMANGLER_RETURN; 01394 } 01395 } 01396 else 01397 { 01398 char opcode0 = current(); 01399 char opcode1 = tolower(next()); 01400 01401 register char hash; 01402 if ((hash = offset_table_c[opcode0 - CHAR_MIN])) 01403 { 01404 hash += opcode1; 01405 if ( 01406 #if (CHAR_MIN < 0) 01407 hash >= 0 && 01408 #endif 01409 hash < 39) 01410 { 01411 int index = static_cast<int>(static_cast<unsigned char>(hash)); 01412 entry_st entry = symbol_name_table_c[index]; 01413 if (entry.opcode[0] == opcode0 && entry.opcode[1] == opcode1 01414 && (opcode1 == current() || entry.opcode[2] == '=')) 01415 { 01416 char const* op = entry.symbol_name + 8; // Skip "operator". 01417 if (*op == ' ') // operator new and delete. 01418 ++op; 01419 if (entry.type == unary) 01420 output += op; 01421 bool is_eq = (opcode1 != current()); 01422 eat_current(); 01423 if (index == 34 && M_inside_template_args) // operator> 01424 output += '('; 01425 output += '('; 01426 if (!decode_expression(output)) 01427 _GLIBCXX_DEMANGLER_FAILURE; 01428 output += ')'; 01429 if (entry.type != unary) 01430 { 01431 if (!M_implementation_details.get_style_compact_expr_ops()) 01432 output += ' '; 01433 output += op; 01434 if (is_eq) 01435 output += '='; 01436 if (!M_implementation_details.get_style_compact_expr_ops()) 01437 output += ' '; 01438 output += '('; 01439 if (!decode_expression(output)) 01440 _GLIBCXX_DEMANGLER_FAILURE; 01441 output += ')'; 01442 if (index == 34 && M_inside_template_args) 01443 output += ')'; 01444 if (entry.type == trinary) 01445 { 01446 if (M_implementation_details.get_style_compact_expr_ops()) 01447 output += ":("; 01448 else 01449 output += " : ("; 01450 if (!decode_expression(output)) 01451 _GLIBCXX_DEMANGLER_FAILURE; 01452 output += ')'; 01453 } 01454 } 01455 _GLIBCXX_DEMANGLER_RETURN; 01456 } 01457 else if (opcode0 == 'c' && 01458 opcode1 == 'v') // casting operator. 01459 { 01460 eat_current(); 01461 output += '('; 01462 if (!decode_type(output)) 01463 _GLIBCXX_DEMANGLER_FAILURE; 01464 output += ")("; 01465 if (!decode_expression(output)) 01466 _GLIBCXX_DEMANGLER_FAILURE; 01467 output += ')'; 01468 _GLIBCXX_DEMANGLER_RETURN; 01469 } 01470 } 01471 } 01472 } 01473 _GLIBCXX_DEMANGLER_FAILURE; 01474 } 01475 01476 // 01477 // <template-args> ::= I <template-arg>+ E 01478 // <template-arg> ::= <type> # type or template 01479 // ::= L <type> <value number> E # integer literal 01480 // ::= L <type> <value float> E # floating literal 01481 // ::= L <mangled-name> E # external name 01482 // ::= X <expression> E # expression 01483 template<typename Tp, typename Allocator> 01484 bool 01485 session<Tp, Allocator>::decode_template_args(string_type& output) 01486 { 01487 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_template_args"); 01488 if (eat_current() != 'I') 01489 _GLIBCXX_DEMANGLER_FAILURE; 01490 int prev_size = M_template_arg_pos.size(); 01491 ++M_inside_template_args; 01492 if (M_template_args_need_space) 01493 { 01494 output += ' '; 01495 M_template_args_need_space = false; 01496 } 01497 output += '<'; 01498 for(;;) 01499 { 01500 if (M_inside_template_args == 1 && !M_inside_type) 01501 M_template_arg_pos.push_back(M_pos); 01502 if (current() == 'X') 01503 { 01504 eat_current(); 01505 if (!decode_expression(output)) 01506 _GLIBCXX_DEMANGLER_FAILURE; 01507 if (current() != 'E') 01508 _GLIBCXX_DEMANGLER_FAILURE; 01509 eat_current(); 01510 } 01511 else if (current() == 'L') 01512 { 01513 if (!decode_literal(output)) 01514 _GLIBCXX_DEMANGLER_FAILURE; 01515 if (current() != 'E') 01516 _GLIBCXX_DEMANGLER_FAILURE; 01517 eat_current(); 01518 } 01519 else if (!decode_type(output)) 01520 _GLIBCXX_DEMANGLER_FAILURE; 01521 if (current() == 'E') 01522 break; 01523 output += ", "; 01524 } 01525 eat_current(); 01526 if (*(output.rbegin()) == '>') 01527 output += ' '; 01528 output += '>'; 01529 --M_inside_template_args; 01530 if (!M_inside_template_args && !M_inside_type) 01531 { 01532 M_name_is_template = true; 01533 M_template_arg_pos_offset = prev_size; 01534 } 01535 _GLIBCXX_DEMANGLER_RETURN; 01536 } 01537 01538 // <bare-function-type> ::= 01539 // <signature type>+ # Types are parameter types. 01540 // 01541 // Note that the possible return type of the <bare-function-type> 01542 // has already been eaten before we call this function. This makes 01543 // our <bare-function-type> slightly different from the one in 01544 // the C++-ABI description. 01545 // 01546 template<typename Tp, typename Allocator> 01547 bool 01548 session<Tp, Allocator>::decode_bare_function_type(string_type& output) 01549 { 01550 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_bare_function_type"); 01551 if (M_saw_destructor) 01552 { 01553 if (eat_current() != 'v' || (current() != 'E' && current() != 0)) 01554 _GLIBCXX_DEMANGLER_FAILURE; 01555 output += "()"; 01556 M_saw_destructor = false; 01557 _GLIBCXX_DEMANGLER_RETURN; 01558 } 01559 if (current() == 'v' && !M_implementation_details.get_style_void()) 01560 { 01561 eat_current(); 01562 if (current() != 'E' && current() != 0) 01563 _GLIBCXX_DEMANGLER_FAILURE; 01564 output += "()"; 01565 M_saw_destructor = false; 01566 _GLIBCXX_DEMANGLER_RETURN; 01567 } 01568 output += '('; 01569 M_template_args_need_space = false; 01570 if (!decode_type(output)) // Must have at least one parameter. 01571 _GLIBCXX_DEMANGLER_FAILURE; 01572 while (current() != 'E' && current() != 0) 01573 { 01574 output += ", "; 01575 if (!decode_type(output)) 01576 _GLIBCXX_DEMANGLER_FAILURE; 01577 } 01578 output += ')'; 01579 _GLIBCXX_DEMANGLER_RETURN; 01580 } 01581 01582 // <type> ::= 01583 // <builtin-type> # Starts with a lower case character != r. 01584 // <function-type> # Starts with F 01585 // <class-enum-type> # Starts with N, S, C, D, Z, a digit or a lower 01586 // # case character. Since a lower case character 01587 // # would be an operator name, that would be an 01588 // # error. The S is a substitution or St 01589 // # (::std::). A 'C' would be a constructor and 01590 // # thus also an error. 01591 // <template-param> # Starts with T 01592 // <substitution> # Starts with S 01593 // <template-template-param> <template-args> # Starts with T or S, 01594 // # equivalent with the above. 01595 // 01596 // <array-type> # Starts with A 01597 // <pointer-to-member-type> # Starts with M 01598 // <CV-qualifiers> <type> # Starts with r, V or K 01599 // P <type> # pointer-to # Starts with P 01600 // R <type> # reference-to # Starts with R 01601 // C <type> # complex (C 2000) # Starts with C 01602 // G <type> # imaginary (C 2000)# Starts with G 01603 // U <source-name> <type> # vendor extended type qualifier, 01604 // # starts with U 01605 // 01606 // <template-template-param> ::= <template-param> 01607 // ::= <substitution> 01608 01609 // My own analysis of how to decode qualifiers: 01610 // 01611 // F is a <function-type>, <T> is a <builtin-type>, <class-enum-type>, 01612 // <template-param> or <template-template-param> <template-args>. 01613 // <Q> represents a series of qualifiers (not G or C). 01614 // <C> is an unqualified type. 01615 // <R> is a qualified type. 01616 // <B> is the bare-function-type without return type. 01617 // <I> is the array index. 01618 // Substitutions: 01619 // <Q>M<C><Q2>F<R><B>E ==> R (C::*Q)B Q2 "<C>", "F<R><B>E" 01620 // (<R> and <B> recursive), 01621 // "M<C><Q2>F<R><B>E". 01622 // <Q>F<R><B>E ==> R (Q)B "<R>", "<B>" (<B> recursive) 01623 // and "F<R><B>E". 01624 // 01625 // Note that if <R> has postfix qualifiers (an array or function), then 01626 // those are added AFTER the (member) function type. For example: 01627 // <Q>FPA<R><B>E ==> R (*(Q)B) [], where the PA added the prefix 01628 // "(*" and the postfix ") []". 01629 // 01630 // <Q>G<T> ==> imaginary T Q "<T>", "G<T>" (<T> recursive). 01631 // <Q>C<T> ==> complex T Q "<T>", "C<T>" (<T> recursive). 01632 // <Q><T> ==> T Q "<T>" (<T> recursive). 01633 // 01634 // where <Q> is any of: 01635 // 01636 // <Q>P ==> *Q "P..." 01637 // <Q>R ==> &Q "R..." 01638 // <Q>[K|V|r]+ ==> [ const| volatile| restrict]+Q "KVr..." 01639 // <Q>U<S> ==> SQ "U<S>..." 01640 // <Q>M<C> ==> C::*Q "M<C>..." (<C> recurs.) 01641 // A<I> ==> [I] "A<I>..." (<I> recurs.) 01642 // <Q>A<I> ==> (Q) [I] "A<I>..." (<I> recurs.) 01643 // Note that when <Q> ends on an A<I2> then the brackets are omitted 01644 // and no space is written between the two: 01645 // A<I2>A<I> ==> [I2][I] 01646 // If <Q> ends on [KVr]+, which can happen in combination with 01647 // substitutions only, then special handling is required, see below. 01648 // 01649 // A <substitution> is handled with an input position switch during which 01650 // new substitutions are turned off. Because recursive handling of types 01651 // (and therefore the order in which substitutions must be generated) must 01652 // be done left to right, but the generation of Q needs processing right to 01653 // left, substitutions per <type> are generated by reading the input left 01654 // to right and marking the starts of all substitutions only - implicitly 01655 // finishing them at the end of the type. Then the output and real 01656 // substitutions are generated. 01657 // 01658 // The following comment was for the demangling of g++ version 3.0.x. The 01659 // mangling (and I believe even the ABI description) have been fixed now 01660 // (as of g++ version 3.1). 01661 // 01662 // g++ 3.0.x only: 01663 // The ABI specifies for pointer-to-member function types the format 01664 // <Q>M<T>F<R><B>E. In other words, the qualifier <Q2> (see above) is 01665 // implicitely contained in <T> instead of explicitly part of the M format. 01666 // I am convinced that this is a bug in the ABI. Unfortunately, this is 01667 // how we have to demangle things as it has a direct impact on the order 01668 // in which substitutions are stored. This ill-formed design results in 01669 // rather ill-formed demangler code too however :/ 01670 // 01671 // <Q2> is now explicitely part of the M format. 01672 // For some weird reason, g++ (3.2.1) does not add substitutions for 01673 // qualified member function pointers. I think that is another bug. 01674 // 01675 01676 // In the case of 01677 // <Q>A<I> 01678 // where <Q> ends on [K|V|r]+ then that part should be processed as 01679 // if it was behind the A<I> instead of in front of it. This is 01680 // because a constant array of ints is normally always mangled as 01681 // an array of constant ints. KVr qualifiers can end up in front 01682 // of an array when the array is part of a substitution or template 01683 // parameter, but the demangling should still result in the same 01684 // syntax; thus KA2_i (const array of ints) must result in the same 01685 // demangling as A2_Ki (array of const ints). As a result we must 01686 // demangle ...[...[[KVr]+A<I0>][KVr]+A<I1>]...[KVr]+A<In>[KVr]+ 01687 // as A<I0>A<I1>...A<In>[KVr]+ where each K, V and r in the series 01688 // collapses to a single character at the right of the string. 01689 // For example: 01690 // VA9_KrA6_KVi --> A9_A6_KVri --> int volatile const restrict [9][6] 01691 // Note that substitutions are still added as usual (the translation 01692 // to A9_A6_KVri does not really happen). 01693 // 01694 // This decoding is achieved by delaying the decoding of any sequence 01695 // of [KVrA]'s and processing them together in the order: first the 01696 // short-circuited KVr part and then the arrays. 01697 static int const cvq_K = 1; // Saw at least one K 01698 static int const cvq_V = 2; // Saw at least one V 01699 static int const cvq_r = 4; // Saw at least one r 01700 static int const cvq_A = 8; // Saw at least one A 01701 static int const cvq_last = 16; // No remaining qualifiers. 01702 static int const cvq_A_cnt = 32; // Bit 5 and higher represent the 01703 // number of A's in the series. 01704 // In the function below, iter_array points to the first (right most) 01705 // A in the series, if any. 01706 template<typename Tp, typename Allocator> 01707 void 01708 qualifier_list<Tp, Allocator>::decode_KVrA( 01709 string_type& prefix, string_type& postfix, int cvq, 01710 typename qual_vector::const_reverse_iterator const& iter_array) const 01711 { 01712 _GLIBCXX_DEMANGLER_DOUT_ENTERING3("decode_KVrA"); 01713 if ((cvq & cvq_K)) 01714 prefix += " const"; 01715 if ((cvq & cvq_V)) 01716 prefix += " volatile"; 01717 if ((cvq & cvq_r)) 01718 prefix += " restrict"; 01719 if ((cvq & cvq_A)) 01720 { 01721 int n = cvq >> 5; 01722 for (typename qual_vector:: 01723 const_reverse_iterator iter = iter_array; 01724 iter != M_qualifier_starts.rend(); ++iter) 01725 { 01726 switch((*iter).first_qualifier()) 01727 { 01728 case 'K': 01729 case 'V': 01730 case 'r': 01731 break; 01732 case 'A': 01733 { 01734 string_type index = (*iter).get_optional_type(); 01735 if (--n == 0 && (cvq & cvq_last)) 01736 postfix = " [" + index + "]" + postfix; 01737 else if (n > 0) 01738 postfix = "[" + index + "]" + postfix; 01739 else 01740 { 01741 prefix += " ("; 01742 postfix = ") [" + index + "]" + postfix; 01743 } 01744 break; 01745 } 01746 default: 01747 _GLIBCXX_DEMANGLER_RETURN3; 01748 } 01749 } 01750 } 01751 _GLIBCXX_DEMANGLER_RETURN3; 01752 } 01753 01754 template<typename Tp, typename Allocator> 01755 void 01756 qualifier_list<Tp, Allocator>::decode_qualifiers( 01757 string_type& prefix, 01758 string_type& postfix, 01759 bool member_function_pointer_qualifiers = false) const 01760 { 01761 _GLIBCXX_DEMANGLER_DOUT_ENTERING3("decode_qualifiers"); 01762 int cvq = 0; 01763 typename qual_vector::const_reverse_iterator iter_array; 01764 for(typename qual_vector:: 01765 const_reverse_iterator iter = M_qualifier_starts.rbegin(); 01766 iter != M_qualifier_starts.rend(); ++iter) 01767 { 01768 if (!member_function_pointer_qualifiers 01769 && !(*iter).part_of_substitution()) 01770 { 01771 int saved_inside_substitution = M_demangler.M_inside_substitution; 01772 M_demangler.M_inside_substitution = 0; 01773 M_demangler.add_substitution((*iter).get_start_pos(), type); 01774 M_demangler.M_inside_substitution = saved_inside_substitution; 01775 } 01776 char qualifier_char = (*iter).first_qualifier(); 01777 for(; qualifier_char; qualifier_char = (*iter).next_qualifier()) 01778 { 01779 switch(qualifier_char) 01780 { 01781 case 'P': 01782 if (cvq) 01783 { 01784 decode_KVrA(prefix, postfix, cvq, iter_array); 01785 cvq = 0; 01786 } 01787 prefix += "*"; 01788 break; 01789 case 'R': 01790 if (cvq) 01791 { 01792 decode_KVrA(prefix, postfix, cvq, iter_array); 01793 cvq = 0; 01794 } 01795 prefix += "&"; 01796 break; 01797 case 'K': 01798 cvq |= cvq_K; 01799 continue; 01800 case 'V': 01801 cvq |= cvq_V; 01802 continue; 01803 case 'r': 01804 cvq |= cvq_r; 01805 continue; 01806 case 'A': 01807 if (!(cvq & cvq_A)) 01808 { 01809 cvq |= cvq_A; 01810 iter_array = iter; 01811 } 01812 cvq += cvq_A_cnt; 01813 break; 01814 case 'M': 01815 if (cvq) 01816 { 01817 decode_KVrA(prefix, postfix, cvq, iter_array); 01818 cvq = 0; 01819 } 01820 prefix += " "; 01821 prefix += (*iter).get_optional_type(); 01822 prefix += "::*"; 01823 break; 01824 case 'U': 01825 if (cvq) 01826 { 01827 decode_KVrA(prefix, postfix, cvq, iter_array); 01828 cvq = 0; 01829 } 01830 prefix += " "; 01831 prefix += (*iter).get_optional_type(); 01832 break; 01833 case 'G': // Only here so we added a substitution. 01834 break; 01835 } 01836 break; 01837 } 01838 } 01839 if (cvq) 01840 decode_KVrA(prefix, postfix, cvq|cvq_last, iter_array); 01841 M_printing_suppressed = false; 01842 _GLIBCXX_DEMANGLER_RETURN3; 01843 } 01844 01845 // 01846 template<typename Tp, typename Allocator> 01847 bool 01848 session<Tp, Allocator>::decode_type_with_postfix( 01849 string_type& prefix, string_type& postfix, 01850 qualifier_list<Tp, Allocator>* qualifiers) 01851 { 01852 _GLIBCXX_DEMANGLER_DOUT_ENTERING2("decode_type"); 01853 ++M_inside_type; 01854 bool recursive_template_param_or_substitution_call; 01855 if (!(recursive_template_param_or_substitution_call = qualifiers)) 01856 { 01857 qualifier_list<Allocator>* raw_qualifiers = M_qualifier_list_alloc.allocate(1); 01858 qualifiers = new (raw_qualifiers) qualifier_list<Allocator>(*this); 01859 } 01860 // First eat all qualifiers. 01861 bool failure = false; 01862 for(;;) // So we can use 'continue' to eat the next qualifier. 01863 { 01864 int start_pos = M_pos; 01865 switch(current()) 01866 { 01867 case 'P': 01868 qualifiers->add_qualifier_start(pointer, start_pos, 01869 M_inside_substitution); 01870 eat_current(); 01871 continue; 01872 case 'R': 01873 qualifiers->add_qualifier_start(reference, start_pos, 01874 M_inside_substitution); 01875 eat_current(); 01876 continue; 01877 case 'K': 01878 case 'V': 01879 case 'r': 01880 { 01881 char c; 01882 int count = 0; 01883 do 01884 { 01885 ++count; 01886 c = next(); 01887 } 01888 while(c == 'K' || c == 'V' || c == 'r'); 01889 qualifiers->add_qualifier_start(cv_qualifier, start_pos, count, 01890 M_inside_substitution); 01891 continue; 01892 } 01893 case 'U': 01894 { 01895 eat_current(); 01896 string_type source_name; 01897 if (!decode_source_name(source_name)) 01898 { 01899 failure = true; 01900 break; 01901 } 01902 qualifiers->add_qualifier_start(vendor_extension, start_pos, 01903 source_name, M_inside_substitution); 01904 continue; 01905 } 01906 case 'A': 01907 { 01908 // <array-type> ::= A <positive dimension number> _ <element type> 01909 // ::= A [<dimension expression>] _ <element type> 01910 // 01911 string_type index; 01912 int saved_pos; 01913 store(saved_pos); 01914 if (next() == 'n' || !decode_number(index)) 01915 { 01916 restore(saved_pos); 01917 if (next() != '_' && !decode_expression(index)) 01918 { 01919 failure = true; 01920 break; 01921 } 01922 } 01923 if (eat_current() != '_') 01924 { 01925 failure = true; 01926 break; 01927 } 01928 qualifiers->add_qualifier_start(array, start_pos, index, 01929 M_inside_substitution); 01930 continue; 01931 } 01932 case 'M': 01933 { 01934 // <pointer-to-member-type> ::= M <class type> <member type> 01935 // <Q>M<C> or <Q>M<C><Q2>F<R><B>E 01936 eat_current(); 01937 string_type class_type; 01938 if (!decode_type(class_type)) // Substitution: "<C>". 01939 { 01940 failure = true; 01941 break; 01942 } 01943 char c = current(); 01944 if (c == 'F' || c == 'K' || c == 'V' || c == 'r') 01945 // Must be CV-qualifiers and a member function pointer. 01946 { 01947 // <Q>M<C><Q2>F<R><B>E ==> R (C::*Q)B Q2 01948 // substitutions: "<C>", "F<R><B>E" (<R> and <B> 01949 // recursive), "M<C><Q2>F<R><B>E". 01950 int count = 0; 01951 int Q2_start_pos = M_pos; 01952 while(c == 'K' || c == 'V' || c == 'r') // Decode <Q2>. 01953 { 01954 ++count; 01955 c = next(); 01956 } 01957 qualifier_list<Tp, Allocator> class_type_qualifiers(*this); 01958 if (count) 01959 class_type_qualifiers. 01960 add_qualifier_start(cv_qualifier, Q2_start_pos, 01961 count, M_inside_substitution); 01962 string_type member_function_qualifiers; 01963 // It is unclear why g++ doesn't add a substitution for 01964 // "<Q2>F<R><B>E" as it should I think. 01965 string_type member_function_qualifiers_postfix; 01966 class_type_qualifiers. 01967 decode_qualifiers(member_function_qualifiers, 01968 member_function_qualifiers_postfix, true); 01969 member_function_qualifiers += 01970 member_function_qualifiers_postfix; 01971 // I don't think this substitution is actually ever used. 01972 int function_pos = M_pos; 01973 if (eat_current() != 'F') 01974 { 01975 failure = true; 01976 break; 01977 } 01978 // Return type. 01979 // Constructors, destructors and conversion operators don't 01980 // have a return type, but seem to never get here. 01981 string_type return_type_postfix; 01982 if (!decode_type_with_postfix(prefix, return_type_postfix)) 01983 // substitution: <R> recursive 01984 { 01985 failure = true; 01986 break; 01987 } 01988 prefix += " ("; 01989 prefix += class_type; 01990 prefix += "::*"; 01991 string_type bare_function_type; 01992 if (!decode_bare_function_type(bare_function_type) 01993 || eat_current() != 'E') // Substitution: <B> recursive. 01994 { 01995 failure = true; 01996 break; 01997 } 01998 // substitution: "F<R><B>E". 01999 add_substitution(function_pos, type); 02000 // substitution: "M<C><Q2>F<R><B>E". 02001 add_substitution(start_pos, type); 02002 // substitution: all qualified types if any. 02003 qualifiers->decode_qualifiers(prefix, postfix); 02004 postfix += ")"; 02005 postfix += bare_function_type; 02006 postfix += member_function_qualifiers; 02007 postfix += return_type_postfix; 02008 goto decode_type_exit; 02009 } 02010 qualifiers->add_qualifier_start(pointer_to_member, start_pos, 02011 class_type, M_inside_substitution); 02012 continue; 02013 } 02014 default: 02015 break; 02016 } 02017 break; 02018 } 02019 if (!failure) 02020 { 02021 // <Q>G<T> ==> imaginary T Q 02022 // substitutions: "<T>", "G<T>" (<T> recursive). 02023 // <Q>C<T> ==> complex T Q 02024 // substitutions: "<T>", "C<T>" (<T> recursive). 02025 if (current() == 'C' || current() == 'G') 02026 { 02027 prefix += current() == 'C' ? "complex " : "imaginary "; 02028 qualifiers->add_qualifier_start(complex_or_imaginary, M_pos, 02029 M_inside_substitution); 02030 eat_current(); 02031 } 02032 int start_pos = M_pos; 02033 switch(current()) 02034 { 02035 case 'F': 02036 { 02037 // <function-type> ::= F [Y] <bare-function-type> E 02038 // 02039 // Note that g++ never generates the 'Y', but we try to 02040 // demangle it anyway. 02041 bool extern_C = (next() == 'Y'); 02042 if (extern_C) 02043 eat_current(); 02044 02045 // <Q>F<R><B>E ==> R (Q)B 02046 // substitution: "<R>", "<B>" (<B> recursive) and "F<R><B>E". 02047 02048 // Return type. 02049 string_type return_type_postfix; 02050 if (!decode_type_with_postfix(prefix, return_type_postfix)) 02051 // Substitution: "<R>". 02052 { 02053 failure = true; 02054 break; 02055 } 02056 // Only array and function (pointer) types have a postfix. 02057 // In that case we don't want the space but expect something 02058 // like prefix is "int (*" and postfix is ") [1]". 02059 // We do want the space if this pointer is qualified. 02060 if (return_type_postfix.size() == 0 || 02061 (prefix.size() > 0 && *prefix.rbegin() != '*')) 02062 prefix += ' '; 02063 prefix += '('; 02064 string_type bare_function_type; 02065 if (!decode_bare_function_type(bare_function_type) 02066 // substitution: "<B>" (<B> recursive). 02067 || eat_current() != 'E') 02068 { 02069 failure = true; 02070 break; 02071 } 02072 add_substitution(start_pos, type); // Substitution: "F<R><B>E". 02073 qualifiers->decode_qualifiers(prefix, postfix); 02074 // substitution: all qualified types, if any. 02075 postfix += ")"; 02076 if (extern_C) 02077 postfix += " [extern \"C\"] "; 02078 postfix += bare_function_type; 02079 postfix += return_type_postfix; 02080 break; 02081 } 02082 case 'T': 02083 if (!decode_template_param(prefix, qualifiers)) 02084 { 02085 failure = true; 02086 break; 02087 } 02088 if (current() == 'I') 02089 { 02090 add_substitution(start_pos, template_template_param); 02091 // substitution: "<template-template-param>". 02092 if (!decode_template_args(prefix)) 02093 { 02094 failure = true; 02095 break; 02096 } 02097 } 02098 if (!recursive_template_param_or_substitution_call 02099 && qualifiers->suppressed()) 02100 { 02101 add_substitution(start_pos, type); 02102 // substitution: "<template-param>" or 02103 // "<template-template-param> <template-args>". 02104 qualifiers->decode_qualifiers(prefix, postfix); 02105 // substitution: all qualified types, if any. 02106 } 02107 break; 02108 case 'S': 02109 if (M_pos >= M_maxpos) 02110 { 02111 failure = true; 02112 break; 02113 } 02114 if (M_str[M_pos + 1] != 't') 02115 { 02116 if (!decode_substitution(prefix, qualifiers)) 02117 { 02118 failure = true; 02119 break; 02120 } 02121 if (current() == 'I') 02122 { 02123 if (!decode_template_args(prefix)) 02124 { 02125 failure = true; 02126 break; 02127 } 02128 if (!recursive_template_param_or_substitution_call 02129 && qualifiers->suppressed()) 02130 add_substitution(start_pos, type); 02131 // Substitution: 02132 // "<template-template-param> <template-args>". 02133 } 02134 if (!recursive_template_param_or_substitution_call 02135 && qualifiers->suppressed()) 02136 qualifiers->decode_qualifiers(prefix, postfix); 02137 // Substitution: all qualified types, if any. 02138 break; 02139 } 02140 /* Fall-through for St */ 02141 case 'N': 02142 case 'Z': 02143 case '0': 02144 case '1': 02145 case '2': 02146 case '3': 02147 case '4': 02148 case '5': 02149 case '6': 02150 case '7': 02151 case '8': 02152 case '9': 02153 // <Q><T> ==> T Q 02154 // substitutions: "<T>" (<T> recursive). 02155 if (!decode_class_enum_type(prefix)) 02156 { 02157 failure = true; 02158 break; 02159 } 02160 if (!recursive_template_param_or_substitution_call) 02161 { 02162 add_substitution(start_pos, type); 02163 // substitution: "<class-enum-type>". 02164 qualifiers->decode_qualifiers(prefix, postfix); 02165 // substitution: all qualified types, if any. 02166 } 02167 else 02168 qualifiers->printing_suppressed(); 02169 break; 02170 default: 02171 // <Q><T> ==> T Q 02172 // substitutions: "<T>" (<T> recursive). 02173 if (!decode_builtin_type(prefix)) 02174 { 02175 failure = true; 02176 break; 02177 } 02178 // If decode_type was called from decode_template_param then we 02179 // need to suppress calling qualifiers here in order to get a 02180 // substitution added anyway (for the <template-param>). 02181 if (!recursive_template_param_or_substitution_call) 02182 qualifiers->decode_qualifiers(prefix, postfix); 02183 else 02184 qualifiers->printing_suppressed(); 02185 break; 02186 } 02187 } 02188 decode_type_exit: 02189 --M_inside_type; 02190 if (!recursive_template_param_or_substitution_call) 02191 { 02192 qualifiers->~qualifier_list<Allocator>(); 02193 M_qualifier_list_alloc.deallocate(qualifiers, 1); 02194 } 02195 if (failure) 02196 _GLIBCXX_DEMANGLER_FAILURE; 02197 _GLIBCXX_DEMANGLER_RETURN2; 02198 } 02199 02200 // <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E 02201 // ::= N [<CV-qualifiers>] <template-prefix> <template-args> E 02202 // 02203 // <prefix> ::= <prefix> <unqualified-name> 02204 // ::= <template-prefix> <template-args> 02205 // ::= <template-param> 02206 // ::= # empty 02207 // ::= <substitution> 02208 // 02209 // <template-prefix> ::= <prefix> <template unqualified-name> 02210 // ::= <template-param> 02211 // ::= <substitution> 02212 // 02213 template<typename Tp, typename Allocator> 02214 bool 02215 session<Tp, Allocator>::decode_nested_name(string_type& output, 02216 string_type& qualifiers) 02217 { 02218 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_nested_name"); 02219 02220 if (current() != 'N' || M_pos >= M_maxpos) 02221 _GLIBCXX_DEMANGLER_FAILURE; 02222 02223 // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const 02224 char const* qualifiers_start = &M_str[M_pos + 1]; 02225 for (char c = next(); c == 'K' || c == 'V' || c == 'r'; c = next()); 02226 for (char const* qualifier_ptr = &M_str[M_pos - 1]; 02227 qualifier_ptr >= qualifiers_start; --qualifier_ptr) 02228 switch(*qualifier_ptr) 02229 { 02230 case 'K': 02231 qualifiers += " const"; 02232 break; 02233 case 'V': 02234 qualifiers += " volatile"; 02235 break; 02236 case 'r': 02237 qualifiers += " restrict"; 02238 break; 02239 } 02240 02241 int number_of_prefixes = 0; 02242 int substitution_start = M_pos; 02243 for(;;) 02244 { 02245 ++number_of_prefixes; 02246 if (current() == 'S') 02247 { 02248 if (!decode_substitution(output)) 02249 _GLIBCXX_DEMANGLER_FAILURE; 02250 } 02251 else if (current() == 'I') 02252 { 02253 if (!decode_template_args(output)) 02254 _GLIBCXX_DEMANGLER_FAILURE; 02255 if (current() != 'E') 02256 { 02257 // substitution: "<template-prefix> <template-args>". 02258 add_substitution(substitution_start, nested_name_prefix, 02259 number_of_prefixes); 02260 } 02261 } 02262 else 02263 { 02264 if (current() == 'T') 02265 { 02266 if (!decode_template_param(output)) 02267 _GLIBCXX_DEMANGLER_FAILURE; 02268 } 02269 else if (!decode_unqualified_name(output)) 02270 _GLIBCXX_DEMANGLER_FAILURE; 02271 if (current() != 'E') 02272 { 02273 // substitution: "<prefix> <unqualified-name>" or 02274 // "<prefix> <template unqualified-name>". 02275 add_substitution(substitution_start, 02276 (current() == 'I') ? nested_name_template_prefix 02277 : nested_name_prefix, 02278 number_of_prefixes); 02279 } 02280 } 02281 if (current() == 'E') 02282 { 02283 eat_current(); 02284 _GLIBCXX_DEMANGLER_RETURN; 02285 } 02286 if (current() != 'I') 02287 output += "::"; 02288 else if (M_template_args_need_space) 02289 output += ' '; 02290 M_template_args_need_space = false; 02291 } 02292 _GLIBCXX_DEMANGLER_FAILURE; 02293 } 02294 02295 // <local-name> := Z <function encoding> E <entity name> [<discriminator>] 02296 // := Z <function encoding> E s [<discriminator>] 02297 // <discriminator> := _ <non-negative number> 02298 // 02299 template<typename Tp, typename Allocator> 02300 bool 02301 session<Tp, Allocator>::decode_local_name(string_type& output) 02302 { 02303 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_local_name"); 02304 if (current() != 'Z' || M_pos >= M_maxpos) 02305 _GLIBCXX_DEMANGLER_FAILURE; 02306 if ((M_pos += decode_encoding(output, M_str + M_pos + 1, 02307 M_maxpos - M_pos, M_implementation_details) + 1) < 0 || 02308 eat_current() != 'E') 02309 _GLIBCXX_DEMANGLER_FAILURE; 02310 output += "::"; 02311 if (current() == 's') 02312 { 02313 eat_current(); 02314 output += "string literal"; 02315 } 02316 else 02317 { 02318 string_type nested_name_qualifiers; 02319 if (!decode_name(output, nested_name_qualifiers)) 02320 _GLIBCXX_DEMANGLER_FAILURE; 02321 output += nested_name_qualifiers; 02322 } 02323 string_type discriminator; 02324 if (current() == '_' && next() != 'n' && !decode_number(discriminator)) 02325 _GLIBCXX_DEMANGLER_FAILURE; 02326 _GLIBCXX_DEMANGLER_RETURN; 02327 } 02328 02329 // <source-name> ::= <positive length number> <identifier> 02330 // 02331 template<typename Tp, typename Allocator> 02332 bool 02333 session<Tp, Allocator>::decode_source_name(string_type& output) 02334 { 02335 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_source_name"); 02336 int length = current() - '0'; 02337 if (length < 1 || length > 9) 02338 _GLIBCXX_DEMANGLER_FAILURE; 02339 while(isdigit(next())) 02340 length = 10 * length + current() - '0'; 02341 char const* ptr = &M_str[M_pos]; 02342 if (length > 11 && !strncmp(ptr, "_GLOBAL_", 8) && ptr[9] == 'N' 02343 && ptr[8] == ptr[10]) 02344 { 02345 output += "(anonymous namespace)"; 02346 if ((M_pos += length) > M_maxpos + 1) 02347 _GLIBCXX_DEMANGLER_FAILURE; 02348 } 02349 else 02350 while(length--) 02351 { 02352 if (current() == 0) 02353 _GLIBCXX_DEMANGLER_FAILURE; 02354 output += eat_current(); 02355 } 02356 _GLIBCXX_DEMANGLER_RETURN; 02357 } 02358 02359 // <unqualified-name> ::= <operator-name> # Starts with lower case. 02360 // ::= <ctor-dtor-name> # Starts with 'C' or 'D'. 02361 // ::= <source-name> # Starts with a digit. 02362 // 02363 template<typename Tp, typename Allocator> 02364 bool 02365 session<Tp, Allocator>::decode_unqualified_name(string_type& output) 02366 { 02367 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_unqualified_name"); 02368 if (M_inside_template_args) 02369 { 02370 if (!decode_source_name(output)) 02371 _GLIBCXX_DEMANGLER_FAILURE; 02372 } 02373 else if (isdigit(current())) 02374 { 02375 bool recursive_unqualified_name = (&M_function_name == &output); 02376 // This can be a recursive call when we are decoding 02377 // an <operator-name> that is a cast operator for a some 02378 // <unqualified-name>; for example "operator Foo()". 02379 // In that case this is thus not a ctor or dtor and we 02380 // are not interested in updating M_function_name. 02381 if (!recursive_unqualified_name) 02382 M_function_name.clear(); 02383 M_name_is_template = false; 02384 M_name_is_cdtor = false; 02385 M_name_is_conversion_operator = false; 02386 if (!decode_source_name(M_function_name)) 02387 _GLIBCXX_DEMANGLER_FAILURE; 02388 if (!recursive_unqualified_name) 02389 output += M_function_name; 02390 } 02391 else if (islower(current())) 02392 { 02393 M_function_name.clear(); 02394 M_name_is_template = false; 02395 M_name_is_cdtor = false; 02396 M_name_is_conversion_operator = false; 02397 if (!decode_operator_name(M_function_name)) 02398 _GLIBCXX_DEMANGLER_FAILURE; 02399 output += M_function_name; 02400 } 02401 else if (current() == 'C' || current() == 'D') 02402 { 02403 // <ctor-dtor-name> ::= 02404 // C1 # complete object (in-charge) constructor 02405 // C2 # base object (not-in-charge) constructor 02406 // C3 # complete object (in-charge) allocating constructor 02407 // D0 # deleting (in-charge) destructor 02408 // D1 # complete object (in-charge) destructor 02409 // D2 # base object (not-in-charge) destructor 02410 // 02411 if (current() == 'C') 02412 { 02413 char c = next(); 02414 if (c < '1' || c > '3') 02415 _GLIBCXX_DEMANGLER_FAILURE; 02416 } 02417 else 02418 { 02419 char c = next(); 02420 if (c < '0' || c > '2') 02421 _GLIBCXX_DEMANGLER_FAILURE; 02422 output += '~'; 02423 M_saw_destructor = true; 02424 } 02425 M_name_is_cdtor = true; 02426 eat_current(); 02427 output += M_function_name; 02428 } 02429 else 02430 _GLIBCXX_DEMANGLER_FAILURE; 02431 _GLIBCXX_DEMANGLER_RETURN; 02432 } 02433 02434 // <unscoped-name> ::= 02435 // <unqualified-name> # Starts not with an 'S' 02436 // St <unqualified-name> # ::std:: 02437 // 02438 template<typename Tp, typename Allocator> 02439 bool 02440 session<Tp, Allocator>::decode_unscoped_name(string_type& output) 02441 { 02442 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_unscoped_name"); 02443 if (current() == 'S') 02444 { 02445 if (next() != 't') 02446 _GLIBCXX_DEMANGLER_FAILURE; 02447 eat_current(); 02448 output += "std::"; 02449 } 02450 decode_unqualified_name(output); 02451 _GLIBCXX_DEMANGLER_RETURN; 02452 } 02453 02454 // <name> ::= 02455 // <nested-name> # Starts with 'N' 02456 // <unscoped-template-name> <template-args> # idem 02457 // <local-name> # Starts with 'Z' 02458 // <unscoped-name> # Starts with 'S', 'C', 'D', 02459 // # a digit or a lower case 02460 // # character. 02461 // 02462 // <unscoped-template-name> ::= <unscoped-name> 02463 // ::= <substitution> 02464 template<typename Tp, typename Allocator> 02465 bool 02466 session<Tp, Allocator>::decode_name(string_type& output, 02467 string_type& nested_name_qualifiers) 02468 { 02469 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_name"); 02470 int substitution_start = M_pos; 02471 if (current() == 'S' && (M_pos >= M_maxpos || M_str[M_pos + 1] != 't')) 02472 { 02473 if (!decode_substitution(output)) 02474 _GLIBCXX_DEMANGLER_FAILURE; 02475 } 02476 else if (current() == 'N') 02477 { 02478 decode_nested_name(output, nested_name_qualifiers); 02479 _GLIBCXX_DEMANGLER_RETURN; 02480 } 02481 else if (current() == 'Z') 02482 { 02483 decode_local_name(output); 02484 _GLIBCXX_DEMANGLER_RETURN; 02485 } 02486 else if (!decode_unscoped_name(output)) 02487 _GLIBCXX_DEMANGLER_FAILURE; 02488 if (current() == 'I') 02489 { 02490 // Must have been an <unscoped-template-name>. 02491 add_substitution(substitution_start, unscoped_template_name); 02492 if (!decode_template_args(output)) 02493 _GLIBCXX_DEMANGLER_FAILURE; 02494 } 02495 M_template_args_need_space = false; 02496 _GLIBCXX_DEMANGLER_RETURN; 02497 } 02498 02499 // <call-offset> ::= h <nv-offset> _ 02500 // ::= v <v-offset> _ 02501 // <nv-offset> ::= <offset number> 02502 // non-virtual base override 02503 // 02504 // <v-offset> ::= <offset number> _ <virtual offset number> 02505 // virtual base override, with vcall offset 02506 template<typename Tp, typename Allocator> 02507 bool 02508 session<Tp, Allocator>::decode_call_offset(string_type& 02509 #if _GLIBCXX_DEMANGLER_CWDEBUG 02510 output 02511 #endif 02512 ) 02513 { 02514 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_call_offset"); 02515 if (current() == 'h') 02516 { 02517 string_type dummy; 02518 eat_current(); 02519 if (decode_number(dummy) && current() == '_') 02520 { 02521 eat_current(); 02522 _GLIBCXX_DEMANGLER_RETURN; 02523 } 02524 } 02525 else if (current() == 'v') 02526 { 02527 string_type dummy; 02528 eat_current(); 02529 if (decode_number(dummy) && current() == '_') 02530 { 02531 eat_current(); 02532 if (decode_number(dummy) && current() == '_') 02533 { 02534 eat_current(); 02535 _GLIBCXX_DEMANGLER_RETURN; 02536 } 02537 } 02538 } 02539 _GLIBCXX_DEMANGLER_FAILURE; 02540 } 02541 02542 // 02543 // <special-name> ::= 02544 // TV <type> # virtual table 02545 // TT <type> # VTT structure (construction 02546 // vtable index). 02547 // TI <type> # typeinfo structure 02548 // TS <type> # typeinfo name (null-terminated 02549 // byte string). 02550 // GV <object name> # Guard variable for one-time 02551 // initialization of static objects in 02552 // a local scope. 02553 // T <call-offset> <base encoding># base is the nominal target function 02554 // of thunk. 02555 // Tc <call-offset> <call-offset> <base encoding> # base is the nominal 02556 // target function of thunk; first 02557 // call-offset is 'this' adjustment; 02558 // second call-offset is result 02559 // adjustment 02560 // 02561 template<typename Tp, typename Allocator> 02562 bool 02563 session<Tp, Allocator>::decode_special_name(string_type& output) 02564 { 02565 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_special_name"); 02566 if (current() == 'G') 02567 { 02568 if (next() != 'V') 02569 _GLIBCXX_DEMANGLER_FAILURE; 02570 output += "guard variable for "; 02571 string_type nested_name_qualifiers; 02572 eat_current(); 02573 if (!decode_name(output, nested_name_qualifiers)) 02574 _GLIBCXX_DEMANGLER_FAILURE; 02575 output += nested_name_qualifiers; 02576 _GLIBCXX_DEMANGLER_RETURN; 02577 } 02578 else if (current() != 'T') 02579 _GLIBCXX_DEMANGLER_FAILURE; 02580 switch(next()) 02581 { 02582 case 'V': 02583 output += "vtable for "; 02584 eat_current(); 02585 decode_type(output); 02586 _GLIBCXX_DEMANGLER_RETURN; 02587 case 'T': 02588 output += "VTT for "; 02589 eat_current(); 02590 decode_type(output); 02591 _GLIBCXX_DEMANGLER_RETURN; 02592 case 'I': 02593 output += "typeinfo for "; 02594 eat_current(); 02595 decode_type(output); 02596 _GLIBCXX_DEMANGLER_RETURN; 02597 case 'S': 02598 output += "typeinfo name for "; 02599 eat_current(); 02600 decode_type(output); 02601 _GLIBCXX_DEMANGLER_RETURN; 02602 case 'c': 02603 output += "covariant return thunk to "; 02604 if (!decode_call_offset(output) 02605 || !decode_call_offset(output) 02606 || (M_pos += decode_encoding(output, M_str + M_pos, 02607 M_maxpos - M_pos + 1, M_implementation_details)) < 0) 02608 _GLIBCXX_DEMANGLER_FAILURE; 02609 _GLIBCXX_DEMANGLER_RETURN; 02610 case 'C': // GNU extension? 02611 { 02612 string_type first; 02613 output += "construction vtable for "; 02614 eat_current(); 02615 if (!decode_type(first)) 02616 _GLIBCXX_DEMANGLER_FAILURE; 02617 while(isdigit(current())) 02618 eat_current(); 02619 if (eat_current() != '_') 02620 _GLIBCXX_DEMANGLER_FAILURE; 02621 if (!decode_type(output)) 02622 _GLIBCXX_DEMANGLER_FAILURE; 02623 output += "-in-"; 02624 output += first; 02625 _GLIBCXX_DEMANGLER_RETURN; 02626 } 02627 default: 02628 if (current() == 'v') 02629 output += "virtual thunk to "; 02630 else 02631 output += "non-virtual thunk to "; 02632 if (!decode_call_offset(output) 02633 || (M_pos += decode_encoding(output, M_str + M_pos, 02634 M_maxpos - M_pos + 1, M_implementation_details)) < 0) 02635 _GLIBCXX_DEMANGLER_FAILURE; 02636 _GLIBCXX_DEMANGLER_RETURN; 02637 } 02638 } 02639 02640 // <encoding> ::= 02641 // <function name> <bare-function-type> # Starts with 'C', 'D', 'N', 02642 // 'S', a digit or a lower case 02643 // character. 02644 // <data name> # Idem. 02645 // <special-name> # Starts with 'T' or 'G'. 02646 template<typename Tp, typename Allocator> 02647 int 02648 session<Tp, Allocator>::decode_encoding(string_type& output, 02649 char const* in, int len, implementation_details const& id) 02650 { 02651 #if _GLIBCXX_DEMANGLER_CWDEBUG 02652 _GLIBCXX_DEMANGLER_DOUT(dc::demangler, 02653 "Output thus far: \"" << output << '"'); 02654 string_type input(in, len > 0x40000000 ? strlen(in) : len); 02655 _GLIBCXX_DEMANGLER_DOUT( 02656 dc::demangler, "Entering decode_encoding(\"" << input << "\")"); 02657 #endif 02658 if (len <= 0) 02659 return INT_MIN; 02660 session<Tp, Allocator> demangler_session(in, len, id); 02661 string_type nested_name_qualifiers; 02662 int saved_pos; 02663 demangler_session.store(saved_pos); 02664 if (demangler_session.decode_special_name(output)) 02665 return demangler_session.M_pos; 02666 demangler_session.restore(saved_pos); 02667 string_type name; 02668 if (!demangler_session.decode_name(name, nested_name_qualifiers)) 02669 return INT_MIN; 02670 if (demangler_session.current() == 0 02671 || demangler_session.current() == 'E') 02672 { 02673 output += name; 02674 output += nested_name_qualifiers; 02675 return demangler_session.M_pos; 02676 } 02677 // Must have been a <function name>. 02678 string_type return_type_postfix; 02679 if (demangler_session.M_name_is_template 02680 && !(demangler_session.M_name_is_cdtor 02681 || demangler_session.M_name_is_conversion_operator)) 02682 { 02683 // Return type of function 02684 if (!demangler_session.decode_type_with_postfix(output, 02685 return_type_postfix)) 02686 return INT_MIN; 02687 output += ' '; 02688 } 02689 output += name; 02690 if (!demangler_session.decode_bare_function_type(output)) 02691 return INT_MIN; 02692 output += nested_name_qualifiers; 02693 output += return_type_postfix; 02694 return demangler_session.M_pos; 02695 } 02696 02697 } // namespace demangler 02698 02699 // Public interface 02700 template<typename Tp, typename Allocator> 02701 struct demangle 02702 { 02703 typedef typename Allocator::template rebind<char>::other char_Allocator; 02704 typedef std::basic_string<char, std::char_traits<char>, char_Allocator> 02705 string_type; 02706 static string_type symbol(char const* in, 02707 demangler::implementation_details const& id); 02708 static string_type type(char const* in, 02709 demangler::implementation_details const& id); 02710 }; 02711 02712 // demangle::symbol() 02713 // 02714 // Demangle `input' which should be a mangled function name as for 02715 // instance returned by nm(1). 02716 template<typename Tp, typename Allocator> 02717 typename demangle<Tp, Allocator>::string_type 02718 demangle<Tp, Allocator>::symbol(char const* input, 02719 demangler::implementation_details const& id) 02720 { 02721 // <mangled-name> ::= _Z <encoding> 02722 // <mangled-name> ::= _GLOBAL_ _<type>_ <disambiguation part> 02723 // <type> can be I or D (GNU extension) 02724 typedef demangler::session<Tp, Allocator> demangler_type; 02725 string_type result; 02726 bool failure = (input[0] != '_'); 02727 02728 if (!failure) 02729 { 02730 if (input[1] == 'G') 02731 { 02732 if (!strncmp(input, "_GLOBAL__", 9) 02733 && (input[9] == 'D' || input[9] == 'I') 02734 && input[10] == '_') 02735 { 02736 if (input[9] == 'D') 02737 result.assign("global destructors keyed to ", 28); 02738 else 02739 result.assign("global constructors keyed to ", 29); 02740 // Output the disambiguation part as-is. 02741 result += input + 11; 02742 } 02743 else 02744 failure = true; 02745 } 02746 else if (input[1] == 'Z') 02747 { 02748 int cnt = 02749 demangler_type::decode_encoding(result, input + 2, INT_MAX, id); 02750 if (cnt < 0 || input[cnt + 2] != 0) 02751 failure = true; 02752 } 02753 else 02754 failure = true; 02755 } 02756 02757 // Failure to demangle, return the mangled name. 02758 if (failure) 02759 result.assign(input, strlen(input)); 02760 02761 return result; 02762 } 02763 02764 // demangle::type() 02765 // Demangle `input' which must be a zero terminated mangled type 02766 // name as for instance returned by std::type_info::name(). 02767 template<typename Tp, typename Allocator> 02768 typename demangle<Tp, Allocator>::string_type 02769 demangle<Tp, Allocator>::type(char const* input, 02770 demangler::implementation_details const& id) 02771 { 02772 std::basic_string<char, std::char_traits<char>, Allocator> result; 02773 if (input == NULL) 02774 result = "(null)"; 02775 else 02776 { 02777 demangler::session<Tp, Allocator> demangler_session(input, INT_MAX, id); 02778 if (!demangler_session.decode_type(result) 02779 || demangler_session.remaining_input_characters()) 02780 { 02781 // Failure to demangle, return the mangled name. 02782 result = input; 02783 } 02784 } 02785 return result; 02786 } 02787 } // namespace __gnu_cxx 02788 02789 #endif // __DEMANGLE_H

Generated on Tue Sep 7 10:05:02 2004 for libstdc++-v3 Source by doxygen 1.3.8