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

📄 demangle.h

📁 mingw32.rar
💻 H
📖 第 1 页 / 共 5 页
字号:
	    {
	      output += entry.symbol_name;
	      if (opcode1 != current())
		output += '=';
	      eat_current();
	      if (hash == 16 || hash == 17)
		M_template_args_need_space = true;
	      _GLIBCXX_DEMANGLER_RETURN;
	    }
	    else if (opcode0 == 'c' && opcode1 == 'v')	// casting operator
	    {
	      eat_current();
	      output += "operator ";
	      if (current() == 'T')
	      {
		// This is a templated cast operator.
		// It must be of the form "cvT_I...E".
		// Let M_template_arg_pos already point
		// to the template argument.
		M_template_arg_pos_offset = M_template_arg_pos.size();
		M_template_arg_pos.push_back(M_pos + 3);
	      }
	      if (!decode_type(output))
		_GLIBCXX_DEMANGLER_FAILURE;
	      if (!M_inside_template_args)
		M_name_is_conversion_operator = true;
	      _GLIBCXX_DEMANGLER_RETURN;
	    }
	  }
	}
	_GLIBCXX_DEMANGLER_FAILURE;
      }

    //
    // <expression> ::= <unary operator-name> <expression>
    //              ::= <binary operator-name> <expression> <expression>
    //              ::= <trinary operator-name> <expression> <expression> <expression>
    //              ::= st <type>
    //              ::= <template-param>
    //              ::= sr <type> <unqualified-name>                   # dependent name
    //              ::= sr <type> <unqualified-name> <template-args>   # dependent template-id
    //              ::= <expr-primary>
    //
    // <expr-primary> ::= L <type> <value number> E     # integer literal
    //                ::= L <type> <value float> E	# floating literal
    //                ::= L <mangled-name> E		# external name
    //
    template<typename Tp, typename Allocator>
      bool
      session<Tp, Allocator>::decode_expression(string_type& output)
      {
	_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

⌨️ 快捷键说明

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