⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 demangle.h

📁 symbian上STL模板库的实现
💻 H
📖 第 1 页 / 共 5 页
字号:
	_GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_expression");	if (current() == 'T')	{	  if (!decode_template_param(output))	    _GLIBCXX_DEMANGLER_FAILURE;	  _GLIBCXX_DEMANGLER_RETURN;	}	else if (current() == 'L')	{	  if (!decode_literal(output))	    _GLIBCXX_DEMANGLER_FAILURE;	  if (current() != 'E')	    _GLIBCXX_DEMANGLER_FAILURE;	  eat_current();	  _GLIBCXX_DEMANGLER_RETURN;	}	else if (current() == 's')	{	  char opcode1 = next();	  if (opcode1 == 't' || opcode1 == 'z')	  {	    eat_current();	    if (M_implementation_details.get_style_compact_expr_ops())	      output += "sizeof(";	    else	      output += "sizeof (";	    if (opcode1 == 't')	    {	      // I cannot think of a mangled name that is valid for both cases	      // when just replacing the 't' by a 'z' or vica versa, which	      // indicates that there is no ambiguity that dictates the need	      // for a seperate "st" case, except to be able catch invalid	      // mangled names.  However there CAN be ambiguity in the demangled	      // name when there are both a type and a symbol of the same name,	      // which then leads to different encoding (of course) with	      // sizeof (type) or sizeof (expression) respectively, but that	      // ambiguity is not per se related to "sizeof" except that that	      // is the only place where both a type AND an expression are valid	      // in as part of a (template function) type.	      //	      // Example:	      //	      // struct B { typedef int t; };	      // struct A : public B { static int t[2]; };	      // template<int i, int j> struct C { typedef int q; };	      // template<int i, typename T>	      //   void f(typename C<sizeof (typename T::t),	      //                     sizeof (T::t)>::q) { }	      // void instantiate() { f<5, A>(0); }	      //	      // Leads to _Z1fILi5E1AEvN1CIXstN1T1tEEXszsrS2_1tEE1qE which	      // demangles as	      // void f<5, A>(C<sizeof (T::t), sizeof (T::t)>::q)	      //	      // This is ambiguity is very unlikely to happen and it is kind	      // of fuzzy to detect when adding a 'typename' makes sense.	      //	      if (M_implementation_details.get_style_sizeof_typename())	      {		// We can only get here inside a template parameter,		// so this is syntactically correct if the given type is		// a typedef.  The only disadvantage is that it is inconsistent		// with all other places where the 'typename' keyword should be		// used and we don't.		// With this, the above example will demangle as		// void f<5, A>(C<sizeof (typename T::t), sizeof (T::t)>::q)		if (current() == 'N' ||	// <nested-name>					  // This should be a safe bet.		    (current() == 'S' &&		     next_peek() == 't'))	// std::something, guess that					  // this involves a typedef.		  output += "typename ";	      }	      if (!decode_type(output))		_GLIBCXX_DEMANGLER_FAILURE;	    }	    else	    {	      if (!decode_expression(output))		_GLIBCXX_DEMANGLER_FAILURE;	    }	    output += ')';	    _GLIBCXX_DEMANGLER_RETURN;	  }	  else if (current() == 'r')	  {	    eat_current();	    if (!decode_type(output))	      _GLIBCXX_DEMANGLER_FAILURE;	    output += "::";	    if (!decode_unqualified_name(output))	      _GLIBCXX_DEMANGLER_FAILURE;	    if (current() != 'I' || decode_template_args(output))	      _GLIBCXX_DEMANGLER_RETURN;	  }	}	else	{	  char opcode0 = current();	  char opcode1 = tolower(next());	  register char hash;	  if ((hash = offset_table_c[opcode0 - CHAR_MIN]))	  {	    hash += opcode1;	    if (#if (CHAR_MIN < 0)		hash >= 0 &&#endif		hash < 39)	    {	      int index = static_cast<int>(static_cast<unsigned char>(hash));	      entry_st entry = symbol_name_table_c[index];	      if (entry.opcode[0] == opcode0 && entry.opcode[1] == opcode1		  && (opcode1 == current() || entry.opcode[2] == '='))	      {		char const* op = entry.symbol_name + 8;	// Skip "operator".		if (*op == ' ')				// operator new and delete.		  ++op;		if (entry.type == unary)		  output += op;		bool is_eq = (opcode1 != current());		eat_current();		if (index == 34 && M_inside_template_args)	// operator>		  output += '(';		output += '(';		if (!decode_expression(output))		  _GLIBCXX_DEMANGLER_FAILURE;		output += ')';		if (entry.type != unary)		{	          if (!M_implementation_details.get_style_compact_expr_ops())		    output += ' ';		  output += op;		  if (is_eq)		    output += '=';	          if (!M_implementation_details.get_style_compact_expr_ops())		    output += ' ';		  output += '(';		  if (!decode_expression(output))		    _GLIBCXX_DEMANGLER_FAILURE;		  output += ')';		  if (index == 34 && M_inside_template_args)		    output += ')';		  if (entry.type == trinary)		  {		    if (M_implementation_details.get_style_compact_expr_ops())		      output += ":(";		    else		      output += " : (";		    if (!decode_expression(output))		      _GLIBCXX_DEMANGLER_FAILURE;		    output += ')';		  }		}		_GLIBCXX_DEMANGLER_RETURN;	      }	      else if (opcode0 == 'c' &&	               opcode1 == 'v')		// casting operator.	      {		eat_current();		output += '(';		if (!decode_type(output))		  _GLIBCXX_DEMANGLER_FAILURE;		output += ")(";		if (!decode_expression(output))		  _GLIBCXX_DEMANGLER_FAILURE;		output += ')';		_GLIBCXX_DEMANGLER_RETURN;	      }	    }	  }	}	_GLIBCXX_DEMANGLER_FAILURE;      }    //    // <template-args> ::= I <template-arg>+ E    // <template-arg> ::= <type>			# type or template    //                ::= L <type> <value number> E	# integer literal    //                ::= L <type> <value float> E	# floating literal    //                ::= L <mangled-name> E		# external name    //                ::= X <expression> E		# expression    template<typename Tp, typename Allocator>      bool      session<Tp, Allocator>::decode_template_args(string_type& output)      {	_GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_template_args");	if (eat_current() != 'I')	  _GLIBCXX_DEMANGLER_FAILURE;	int prev_size = M_template_arg_pos.size();	++M_inside_template_args;	if (M_template_args_need_space)	{	  output += ' ';	  M_template_args_need_space = false;	}	output += '<';	for(;;)	{	  if (M_inside_template_args == 1 && !M_inside_type)	    M_template_arg_pos.push_back(M_pos);	  if (current() == 'X')	  {	    eat_current();	    if (!decode_expression(output))	      _GLIBCXX_DEMANGLER_FAILURE;	    if (current() != 'E')	      _GLIBCXX_DEMANGLER_FAILURE;	    eat_current();	  }	  else if (current() == 'L')	  {	    if (!decode_literal(output))	      _GLIBCXX_DEMANGLER_FAILURE;	    if (current() != 'E')	      _GLIBCXX_DEMANGLER_FAILURE;	    eat_current();	  }	  else if (!decode_type(output))	    _GLIBCXX_DEMANGLER_FAILURE;	  if (current() == 'E')	    break;	  output += ", ";	}	eat_current();	if (*(output.rbegin()) == '>')	  output += ' ';	output += '>';	--M_inside_template_args;	if (!M_inside_template_args && !M_inside_type)	{	  M_name_is_template = true;	  M_template_arg_pos_offset = prev_size;	}	_GLIBCXX_DEMANGLER_RETURN;      }    // <bare-function-type> ::=    //   <signature type>+		# Types are parameter types.    //    // Note that the possible return type of the <bare-function-type>    // has already been eaten before we call this function.  This makes    // our <bare-function-type> slightly different from the one in    // the C++-ABI description.    //    template<typename Tp, typename Allocator>      bool      session<Tp, Allocator>::decode_bare_function_type(string_type& output)      {	_GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_bare_function_type");	if (M_saw_destructor)	{	  if (eat_current() != 'v' || (current() != 'E' && current() != 0))	    _GLIBCXX_DEMANGLER_FAILURE;	  output += "()";	  M_saw_destructor = false;	  _GLIBCXX_DEMANGLER_RETURN;	}	if (current() == 'v' && !M_implementation_details.get_style_void())	{	  eat_current();	  if (current() != 'E' && current() != 0)	    _GLIBCXX_DEMANGLER_FAILURE;	  output += "()";	  M_saw_destructor = false;	  _GLIBCXX_DEMANGLER_RETURN;	}	output += '(';	M_template_args_need_space = false;	if (!decode_type(output))	// Must have at least one parameter.	  _GLIBCXX_DEMANGLER_FAILURE;	while (current() != 'E' && current() != 0)	{	  output += ", ";	  if (!decode_type(output))	    _GLIBCXX_DEMANGLER_FAILURE;	}	output += ')';	_GLIBCXX_DEMANGLER_RETURN;      }    // <type> ::=    //   <builtin-type>		# Starts with a lower case character != r.    //   <function-type>	# Starts with F    //   <class-enum-type>	# Starts with N, S, C, D, Z, a digit or a lower    //				# case character.  Since a lower case character    //				# would be an operator name, that would be an    //				# error.  The S is a substitution or St    //				# (::std::).  A 'C' would be a constructor and    //				# thus also an error.    //   <template-param>	# Starts with T    //   <substitution>         # Starts with S    //   <template-template-param> <template-args>  # Starts with T or S,    //						    # equivalent with the above.    //    //   <array-type>			# Starts with A    //   <pointer-to-member-type>	# Starts with M    //   <CV-qualifiers> <type>		# Starts with r, V or K    //   P <type>   # pointer-to	# Starts with P    //   R <type>   # reference-to	# Starts with R    //   C <type>   # complex (C 2000)	# Starts with C    //   G <type>   # imaginary (C 2000)# Starts with G    //   U <source-name> <type>		# vendor extended type qualifier,    //					# starts with U    //    // <template-template-param> ::= <template-param>    //                           ::= <substitution>    // My own analysis of how to decode qualifiers:    //    // F is a <function-type>, <T> is a <builtin-type>, <class-enum-type>,    //   <template-param> or <template-template-param> <template-args>.    // <Q> represents a series of qualifiers (not G or C).    // <C> is an unqualified type.    // <R> is a qualified type.    // <B> is the bare-function-type without return type.    // <I> is the array index.    //						Substitutions:    // <Q>M<C><Q2>F<R><B>E  ==> R (C::*Q)B Q2	"<C>", "F<R><B>E"    //						    (<R> and <B> recursive),    //						    "M<C><Q2>F<R><B>E".    // <Q>F<R><B>E	    ==> R (Q)B		"<R>", "<B>" (<B> recursive)    //                                              and "F<R><B>E".    //    // Note that if <R> has postfix qualifiers (an array or function), then    // those are added AFTER the (member) function type.  For example:    // <Q>FPA<R><B>E ==> R (*(Q)B) [], where the PA added the prefix    // "(*" and the postfix ") []".    //    // <Q>G<T>		    ==> imaginary T Q	"<T>", "G<T>" (<T> recursive).    // <Q>C<T>		    ==> complex T Q	"<T>", "C<T>" (<T> recursive).    // <Q><T>		    ==> T Q		"<T>" (<T> recursive).    //    // where <Q> is any of:    //    // <Q>P		==> *Q				"P..."    // <Q>R		==> &Q				"R..."    // <Q>[K|V|r]+	==> [ const| volatile| restrict]+Q	"KVr..."    // <Q>U<S>		==>  SQ				"U<S>..."    // <Q>M<C>		==> C::*Q			"M<C>..." (<C> recurs.)    // A<I>		==>  [I]			"A<I>..." (<I> recurs.)    // <Q>A<I>		==>  (Q) [I]			"A<I>..." (<I> recurs.)    //   Note that when <Q> ends on an A<I2> then the brackets are omitted    //   and no space is written between the two:    //   A<I2>A<I>	==>  [I2][I]    //   If <Q> ends on [KVr]+, which can happen in combination with    //   substitutions only, then special handling is required, see below.    //    // A <substitution> is handled with an input position switch during which    // new substitutions are turned off.  Because recursive handling of types    // (and therefore the order in which substitutions must be generated) must    // be done left to right, but the generation of Q needs processing right to    // left, substitutions per <type> are generated by reading the input left    // to right and marking the starts of all substitutions only - implicitly    // finishing them at the end of the type.  Then the output and real    // substitutions are generated.    //    // The following comment was for the demangling of g++ version 3.0.x.  The    // mangling (and I believe even the ABI description) have been fixed now    // (as of g++ version 3.1).    //    // g++ 3.0.x only:    // The ABI specifies for pointer-to-member function types the format    // <Q>M<T>F<R><B>E.  In other words, the qualifier <Q2> (see above) is    // implicitely contained in <T> instead of explicitly part of the M format.    // I am convinced that this is a bug in the ABI.  Unfortunately, this is    // how we have to demangle things as it has a direct impact on the order    // in which substitutions are stored.  This ill-formed design results in    // rather ill-formed demangler code too however :/    //    // <Q2> is now explicitely part of the M format.    // For some weird reason, g++ (3.2.1) does not add substitutions for    // qualified member function pointers.  I think that is another bug.    //    // In the case of    // <Q>A<I>    // where <Q> ends on [K|V|r]+ then that part should be processed as    // if it was behind the A<I> instead of in front of it.  This is    // because a constant array of ints is normally always mangled as    // an array of constant ints.  KVr qualifiers can end up in front    // of an array when the array is part of a substitution or template    // parameter, but the demangling should still result in the same    // syntax; thus KA2_i (const array of ints) must result in the same    // demangling as A2_Ki (array of const ints).  As a result we must    // demangle ...[...[[KVr]+A<I0>][KVr]+A<I1>]...[KVr]+A<In>[KVr]+    // as A<I0>A<I1>...A<In>[KVr]+ where each K, V and r in the series    // collapses to a single character at the right of the string.    // For example:    // VA9_KrA6_KVi --> A9_A6_KVri --> int volatile const restrict [9][6]    // Note that substitutions are still added as usual (the translation    // to A9_A6_KVri does not really happen).    //    // This decoding is achieved by delaying the decoding of any sequence    // of [KVrA]'s and processing them together in the order: first the    // short-circuited KVr part and then the arrays.    static int const cvq_K = 1;		// Saw at least one K    static int const cvq_V = 2;		// Saw at least one V    static int const cvq_r = 4;		// Saw at least one r    static int const cvq_A = 8;		// Saw at least one A    static int const cvq_last = 16;	// No remaining qualifiers.    static int const cvq_A_cnt = 32;	// Bit 5 and higher represent the					//   number of A's in the series.    // In the function below, iter_array points to the first (right most)    // A in the series, if any.    template<typename Tp, typename Allocator>      void      qualifier_list<Tp, Allocator>::decode_KVrA(          string_type& prefix, string_type& postfix, int cvq,          typename qual_vector::const_reverse_iterator const& iter_array) const	{	  _GLIBCXX_DEMANGLER_DOUT_ENTERING3("decode_KVrA");	  if ((cvq & cvq_K))	    prefix += " const";	  if ((cvq & cvq_V))	    prefix += " volatile";	  if ((cvq & cvq_r))	    prefix += " restrict";	  if ((cvq & cvq_A))	  {	    int n = cvq >> 5;	    for (typename qual_vector::	        const_reverse_iterator iter = iter_array;		iter != M_qualifier_starts.rend(); ++iter)	    {	      switch((*iter).first_qualifier())	      {		case 'K':		case 'V':		case 'r':		  break;		case 'A':

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -