# 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