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

📄 demangle.h

📁 mingw32.rar
💻 H
📖 第 1 页 / 共 5 页
字号:
    // 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':
		{
		  string_type index = (*iter).get_optional_type();
		  if (--n == 0 && (cvq & cvq_last))
		    postfix = " [" + index + "]" + postfix;
		  else if (n > 0)
		    postfix = "[" + index + "]" + postfix;
		  else
		  {
		    prefix += " (";
		    postfix = ") [" + index + "]" + postfix;
		  }
		  break;
		}
		default:
		  _GLIBCXX_DEMANGLER_RETURN3;
	      }
	    }
	  }
	  _GLIBCXX_DEMANGLER_RETURN3;
	}

    template<typename Tp, typename Allocator>
      void
      qualifier_list<Tp, Allocator>::decode_qualifiers(
	  string_type& prefix,
	  string_type& postfix,
	  bool member_function_pointer_qualifiers = false) const
      {
	_GLIBCXX_DEMANGLER_DOUT_ENTERING3("decode_qualifiers");
	int cvq = 0;
	typename qual_vector::const_reverse_iterator iter_array;
	for(typename qual_vector::
	    const_reverse_iterator iter = M_qualifier_starts.rbegin();
	    iter != M_qualifier_starts.rend(); ++iter)
	{
	  if (!member_function_pointer_qualifiers
	      && !(*iter).part_of_substitution())
	  {
	    int saved_inside_substitution = M_demangler.M_inside_substitution;
	    M_demangler.M_inside_substitution = 0;
	    M_demangler.add_substitution((*iter).get_start_pos(), type);
	    M_demangler.M_inside_substitution = saved_inside_substitution;
	  }
	  char qualifier_char = (*iter).first_qualifier();
	  for(; qualifier_char; qualifier_char = (*iter).next_qualifier())
	  {
	    switch(qualifier_char)
	    {
	      case 'P':
		if (cvq)
		{
		  decode_KVrA(prefix, postfix, cvq, iter_array);
		  cvq = 0;
		}
		prefix += "*";
		break;
	      case 'R':
		if (cvq)
		{
		  decode_KVrA(prefix, postfix, cvq, iter_array);
		  cvq = 0;
		}
		prefix += "&";
		break;
	      case 'K':
		cvq |= cvq_K;
		continue;
	      case 'V':
		cvq |= cvq_V;
		continue;
	      case 'r':
		cvq |= cvq_r;
		continue;
	      case 'A':
	        if (!(cvq & cvq_A))
		{
		  cvq |= cvq_A;
		  iter_array = iter;
		}
		cvq += cvq_A_cnt;
		break;
	      case 'M':
	        if (cvq)
		{
		  decode_KVrA(prefix, postfix, cvq, iter_array);
		  cvq = 0;
		}
		prefix += " ";
		prefix += (*iter).get_optional_type();
		prefix += "::*";
		break;
	      case 'U':
	        if (cvq)
		{
		  decode_KVrA(prefix, postfix, cvq, iter_array);
		  cvq = 0;
		}
		prefix += " ";
		prefix += (*iter).get_optional_type();
		break;
	      case 'G':	// Only here so we added a substitution.
		break;
	    }
	    break;
	  }
	}
	if (cvq)
	  decode_KVrA(prefix, postfix, cvq|cvq_last, iter_array);
	M_printing_suppressed = false;
	_GLIBCXX_DEMANGLER_RETURN3;
      }

    //
    template<typename Tp, typename Allocator>
      bool
      session<Tp, Allocator>::decode_type_with_postfix(
	  string_type& prefix, string_type& postfix,
	  qualifier_list<Tp, Allocator>* qualifiers)
      {
	_GLIBCXX_DEMANGLER_DOUT_ENTERING2("decode_type");
	++M_inside_type;
	bool recursive_template_param_or_substitution_call;
	if (!(recursive_template_param_or_substitution_call = qualifiers))
	{
          qualifier_list<Allocator>* raw_qualifiers = M_qualifier_list_alloc.allocate(1);
	  qualifiers = new (raw_qualifiers) qualifier_list<Allocator>(*this);
	}
	// First eat all qualifiers.
	bool failure = false;
	for(;;)		// So we can use 'continue' to eat the next qualifier.
	{
	  int start_pos = M_pos;
	  switch(current())
	  {
	    case 'P':
	      qualifiers->add_qualifier_start(pointer, start_pos,
		  M_inside_substitution);
	      eat_current();
	      continue;
	    case 'R':
	      qualifiers->add_qualifier_start(reference, start_pos,
		  M_inside_substitution);
	      eat_current();
	      continue;
	    case 'K':
	    case 'V':
	    case 'r':
	    {
	      char c;
	      int count = 0;
	      do
	      {
		++count;
		c = next();
	      }
	      while(c == 'K' || c == 'V' || c == 'r');
	      qualifiers->add_qualifier_start(cv_qualifier, start_pos, count,
		  M_inside_substitution);
	      continue;
	    }
	    case 'U':
	    {
	      eat_current();
	      string_type source_name;
	      if (!decode_source_name(source_name))
	      {
		failure = true;
		break;
	      }
	      qualifiers->add_qualifier_start(vendor_extension, start_pos,
		  source_name, M_inside_substitution);
	      continue;
	    }
	    case 'A':
	    {
	      // <array-type> ::= A <positive dimension number> _ <element type>
	      //              ::= A [<dimension expression>] _ <element type>
	      //
	      string_type index;
	      int saved_pos;
	      store(saved_pos);
	      if (next() == 'n' || !decode_number(index))
	      {
		restore(saved_pos);
		if (next() != '_' && !decode_expression(index))
		{
		  failure = true;
		  break;
		}
	      }
	      if (eat_current() != '_')
	      {
		failure = true;
		break;
	      }
	      qualifiers->add_qualifier_start(array, start_pos, index,
		  M_inside_substitution);
	      continue;
	    }
	    case 'M':
	    {
	      // <pointer-to-member-type> ::= M <class type> <member type>
	      // <Q>M<C> or <Q>M<C><Q2>F<R><B>E
	      eat_current();
	      string_type class_type;
	      if (!decode_type(class_type))		// Substitution: "<C>".
	      {
		failure = true;
		break;
	      }
	      char c = current();
	      if (c == 'F' || c == 'K' || c == 'V' || c == 'r')
		  // Must be CV-qualifiers and a member function pointer.
	      {
		// <Q>M<C><Q2>F<R><B>E	==> R (C::*Q)B Q2
		//     substitutions: "<C>", "F<R><B>E" (<R> and <B>
		//                    recursive), "M<C><Q2>F<R><B>E".
		int count = 0;
		int Q2_start_pos = M_pos;
		while(c == 'K' || c == 'V' || c == 'r')		// Decode <Q2>.
		{
		  ++count;
		  c = next();
		}
		qualifier_list<Tp, Allocator> class_type_qualifiers(*this);
		if (count)
		  class_type_qualifiers.
		      add_qualifier_start(cv_qualifier, Q2_start_pos,
			  count, M_inside_substitution);
		string_type member_function_qualifiers;
		// It is unclear why g++ doesn't add a substitution for
		// "<Q2>F<R><B>E" as it should I think.
		string_type member_function_qualifiers_postfix;
		class_type_qualifiers.
		    decode_qualifiers(member_function_qualifiers,
			member_function_qualifiers_postfix, true);
		member_function_qualifiers +=
		    member_function_qualifiers_postfix;
		// I don't think this substitution is actually ever used.
		int function_pos = M_pos;
		if (eat_current() != 'F')
		{
		  failure = true;
		  break;
		}
		// Return type.
		// Constructors, destructors and conversion operators don't
		// have a return type, but seem to never get here.
		string_type return_type_postfix;
		if (!decode_type_with_postfix(prefix, return_type_postfix))
		    // substitution: <R> recursive
		{
		  failure = true;
		  break;
		}
		prefix += " (";
		prefix += class_type;
		prefix += "::*";
		string_type bare_function_type;
		if (!decode_bare_function_type(bare_function_type)
		    || eat_current() != 'E')	// Substitution: <B> recursive.
		{
		  failure = true;
		  break;
		}
		// substitution: "F<R><B>E".
		add_substitution(function_pos, type);
		// substitution: "M<C><Q2>F<R><B>E".
		add_substitution(start_pos, type);
		// substitution: all qualified types if any.
		qualifiers->decode_qualifiers(prefix, postfix);
		postfix += ")";
		postfix += bare_function_type;
		postfix += member_function_qualifiers;
		postfix += return_type_postfix;
		goto decode_type_exit;
	      }
	      qualifiers->add_qualifier_start(pointer_to_member, start_pos,
		  class_type, M_inside_substitution);
	      continue;
	    }
	    default:
	      break;
	  }
	  break;
	}
	if (!failure)
	{
	  // <Q>G<T>			==> imaginary T Q
	  //     substitutions: "<T>", "G<T>" (<T> recursive).
	  // <Q>C<T>			==> complex T Q
	  //     substitutions: "<T>", "C<T>" (<T> recursive).
	  if (current() == 'C' || current() == 'G')
	  {
	    prefix += current() == 'C' ? "complex " : "imaginary ";
	    qualifiers->add_qualifier_start(complex_or_imaginary, M_pos,
		M_inside_substitution);
	    eat_current();
	  }
	  int start_pos = M_pos;
	  switch(current())
	  {
	    case 'F':
	    {
	      // <function-type> ::= F [Y] <bare-function-type> E
	      //
	      // Note that g++ never generates the 'Y', but we try to
	      // demangle it anyway.
	      bool extern_C = (next() == 'Y');
	      if (extern_C)
		eat_current();

	      // <Q>F<R><B>E		==> R (Q)B
	      //     substitution: "<R>", "<B>" (<B> recursive) and "F<R><B>E".

	      // Return type.
	      string_type return_type_postfix;
	      if (!decode_type_with_postfix(prefix, return_type_postfix))
		  // Substitution: "<R>".
	      {
		failure = true;
		break;
	      }
	      // Only array and function (pointer) types have a postfix.
	      // In that case we don't want the space but expect something
	      // like prefix is "int (*" and postfix is ") [1]".
	      // We do want the space if this pointer is qualified.
	      if (return_type_postfix.size() == 0 ||
	          (prefix.size() > 0 && *prefix.rbegin() != '*'))
		prefix += ' ';
	      prefix += '(';
	      string_type bare_function_type;
	      if (!decode_bare_function_type(bare_function_type)
		  // substitution: "<B>" (<B> recursive).
		  || eat_current() != 'E')
	      {
		failure = true;
		break;
	      }
	      add_substitution(start_pos, type);  // Substitution: "F<R><B>E".
	      qualifiers->decode_qualifiers(prefix, postfix);
		  // substitution: all qualified types, if any.
	      postfix += ")";
	      if (extern_C)
	        postfix += " [extern \"C\"] ";
	      postfix += bare_function_type;

⌨️ 快捷键说明

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