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
00033
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
00303
00304
00305
static unsigned int const style_void = 1;
00306
00307
00308
00309
static unsigned int const style_literal = 2;
00310
00311
00312
00313
00314
00315
static unsigned int const style_literal_int = 4;
00316
00317
00318
00319
00320
static unsigned int const style_compact_expr_ops = 8;
00321
00322
00323
00324
00325
static unsigned int const style_sizeof_typename = 16;
00326
00327
00328
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
00345
virtual bool decode_real(
char* ,
unsigned long* ,
00346 size_t )
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
00564
00565
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
00573
00574
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
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
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
char const*
const builtin_type_c[26] =
00642 {
00643
"signed char",
00644
"bool",
00645
"char",
00646
"double",
00647
"long double",
00648
"float",
00649
"__float128",
00650
"unsigned char",
00651
"int",
00652
"unsigned int",
00653 NULL,
00654
"long",
00655
"unsigned long",
00656
"__int128",
00657
"unsigned __int128",
00658 NULL,
00659 NULL,
00660 NULL,
00661
"short",
00662
"unsigned short",
00663 NULL,
00664
"void",
00665
"wchar_t",
00666
"long long",
00667
"unsigned long long",
00668
"..."
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
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
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
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)
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
00887
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)
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];
00939
unsigned long* word = &words[0];
00940
00941
int saved_pos;
00942 store(saved_pos);
00943
00944
00945
00946
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
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
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();
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
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
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
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
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
01159 0, -97, 0, -97, -93, -89, 0, -82, 0, -82, 0, 0,
01160
01161 -99, -99, -96, -81, -80, -91, -88, -85, 0, 0, 0,
01162
#else
01163
01164 0, 159, 0, 159, 163, 167, 0, 174, 0, 174, 0, 0,
01165
01166 157, 157, 160, 175, 176, 165, 168, 171, 0, 0, 0,
01167
#endif
01168
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')
01259 {
01260 eat_current();
01261 output +=
"operator ";
01262
if (current() ==
'T')
01263 {
01264
01265
01266
01267
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
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
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
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
if (M_implementation_details.get_style_sizeof_typename())
01358 {
01359
01360
01361
01362
01363
01364
01365
01366
if (current() ==
'N' ||
01367
01368 (current() ==
'S' &&
01369 next_peek() ==
't'))
01370
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;
01417
if (*op ==
' ')
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)
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')
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
01478
01479
01480
01481
01482
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
01539
01540
01541
01542
01543
01544
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))
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
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
static int const cvq_K = 1;
01698
static int const cvq_V = 2;
01699
static int const cvq_r = 4;
01700
static int const cvq_A = 8;
01701
static int const cvq_last = 16;
01702
static int const cvq_A_cnt = 32;
01703
01704
01705
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':
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
01861
bool failure =
false;
01862
for(;;)
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
01909
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
01935
01936 eat_current();
01937 string_type class_type;
01938
if (!decode_type(class_type))
01939 {
01940 failure =
true;
01941
break;
01942 }
01943
char c = current();
01944
if (c ==
'F' || c ==
'K' || c ==
'V' || c ==
'r')
01945
01946 {
01947
01948
01949
01950
int count = 0;
01951
int Q2_start_pos = M_pos;
01952
while(c ==
'K' || c ==
'V' || c ==
'r')
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
01964
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
01972
int function_pos = M_pos;
01973
if (eat_current() !=
'F')
01974 {
01975 failure =
true;
01976
break;
01977 }
01978
01979
01980
01981 string_type return_type_postfix;
01982
if (!decode_type_with_postfix(prefix, return_type_postfix))
01983
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')
01994 {
01995 failure =
true;
01996
break;
01997 }
01998
01999 add_substitution(function_pos, type);
02000
02001 add_substitution(start_pos, type);
02002
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
02022
02023
02024
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
02038
02039
02040
02041
bool extern_C = (next() ==
'Y');
02042
if (extern_C)
02043 eat_current();
02044
02045
02046
02047
02048
02049 string_type return_type_postfix;
02050
if (!decode_type_with_postfix(prefix, return_type_postfix))
02051
02052 {
02053 failure =
true;
02054
break;
02055 }
02056
02057
02058
02059
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
02067 || eat_current() !=
'E')
02068 {
02069 failure =
true;
02070
break;
02071 }
02072 add_substitution(start_pos, type);
02073 qualifiers->decode_qualifiers(prefix, postfix);
02074
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
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
02103
02104 qualifiers->decode_qualifiers(prefix, postfix);
02105
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
02132
02133 }
02134
if (!recursive_template_param_or_substitution_call
02135 && qualifiers->suppressed())
02136 qualifiers->decode_qualifiers(prefix, postfix);
02137
02138
break;
02139 }
02140
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
02154
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
02164 qualifiers->decode_qualifiers(prefix, postfix);
02165
02166 }
02167
else
02168 qualifiers->printing_suppressed();
02169
break;
02170
default:
02171
02172
02173
if (!decode_builtin_type(prefix))
02174 {
02175 failure =
true;
02176
break;
02177 }
02178
02179
02180
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
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
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
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
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
02274
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
02296
02297
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
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
02360
02361
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
02377
02378
02379
02380
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
02404
02405
02406
02407
02408
02409
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
02435
02436
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
02455
02456
02457
02458
02459
02460
02461
02462
02463
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
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
02500
02501
02502
02503
02504
02505
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
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558
02559
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':
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
02641
02642
02643
02644
02645
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
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
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 }
02698
02699
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
02713
02714
02715
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
02722
02723
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
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
02758
if (failure)
02759 result.assign(input, strlen(input));
02760
02761
return result;
02762 }
02763
02764
02765
02766
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
02782 result = input;
02783 }
02784 }
02785
return result;
02786 }
02787 }
02788
02789
#endif // __DEMANGLE_H