[PATCH] PR libstdc++/13045 / C++ demangler, floating values and function pointer type return type postfix fix.

Carlo Wood carlo@alinoe.com
Mon Nov 24 01:20:00 GMT 2003


2003-11-24  Carlo Wood  <carlo@alinoe.com>

	PR libstdc++/13045
	* bits/demangle.h
	namespace __gnu_cxx::demangler
	(enum substitution_nt): Removed trailing comma.
	(print_IEEE_fp): Added extern declaration.
	(session<Allocator>::decode_real): Added.
	(session<Allocator>::decode_literal): Call decode_real for
	float and double literals.
	(session<Allocator>::decode_type_with_postfix): Put the postfix
	of the return type of (member) functions after the function
	instead of after the return type.  Also, put a space after the
	prefix of qualified function pointers: "int (* const<space>".
	* src/demangle.cc: include most dependent header file first.
	namespace <anonymous>
	(struct decimal_float_data): Added.
	(class decimal_float): Added.
	(int const m1023, int const m1, int const m0, int const p1): Added.
	(decimal_float_data const constants[]): Added.
        namespace __gnu_cxx::demangler
	(print_IEEE_fp): Added.
	* testsuite/demangle/regression/cw-16.cc: Updated one
	and added three tests.

OK?

-- 
Carlo Wood <carlo@alinoe.com>
-------------- next part --------------
Index: libstdc++-v3/include/bits/demangle.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/demangle.h,v
retrieving revision 1.11
diff -u -d -p -r1.11 demangle.h
--- libstdc++-v3/include/bits/demangle.h	12 Nov 2003 02:18:36 -0000	1.11
+++ libstdc++-v3/include/bits/demangle.h	23 Nov 2003 14:31:18 -0000
@@ -91,7 +91,7 @@ namespace __gnu_cxx
       template_template_param,
       nested_name_prefix,
       nested_name_template_prefix,
-      unscoped_template_name,
+      unscoped_template_name
     };
 
     struct substitution_st
@@ -408,6 +408,7 @@ namespace __gnu_cxx
 	bool decode_class_enum_type(string_type& output);
 	bool decode_expression(string_type& output);
 	bool decode_literal(string_type& output);
+	template<typename FloatType> bool decode_real(string_type& output);
 	bool decode_local_name(string_type& output);
 	bool decode_name(string_type& output,
 	    string_type& nested_name_qualifiers);
@@ -879,6 +880,71 @@ namespace __gnu_cxx
 	_GLIBCXX_DEMANGLER_RETURN;
       }
 
+    extern void print_IEEE_fp(char* buf, unsigned long* words,
+	int nbits_exponent, int nbits_fraction, int precision);
+
+    template<typename Allocator>
+      template<typename FloatType>
+	bool
+	session<Allocator>::decode_real(string_type& output)
+	{
+	  _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_real<" <<
+	      type_info_of<FloatType>().demangled_name() << '>');
+
+	  if (sizeof(FloatType) != 4 && sizeof(FloatType) != 8)
+	  {
+	    // Don't fail - just print out the literal string in hex.
+	    output += '[';
+	    char c = current();
+	    for(size_t nibble_cnt = 0; nibble_cnt < 2 * sizeof(FloatType); ++nibble_cnt)
+	    {
+	      if (c < '0' || c > 'f' || (c > '9' && c < 'a'))
+		_GLIBCXX_DEMANGLER_FAILURE;
+	      output += c;
+	      c = next();
+	    }
+	    output += ']';
+	    _GLIBCXX_DEMANGLER_RETURN;
+	  }
+
+	  unsigned long words[sizeof(FloatType) / 4];	// 32 bit per long.
+          unsigned long* word = &words[0];
+
+	  // The following assumes that leading zeroes are also included
+	  // in the mangled name (which is what g++ does), I am not sure
+	  // that is conforming to the standard though.
+	  unsigned char nibble, c = current();
+	  for(size_t word_cnt = sizeof(FloatType) / 4; word_cnt > 0; --word_cnt)
+	  {
+	    for (int nibble_cnt = 0; nibble_cnt < 8; ++nibble_cnt)
+	    {
+	      // Translate character into nibble.
+	      if (c < '0' || c > 'f')
+		_GLIBCXX_DEMANGLER_FAILURE;
+	      if (c <= '9')
+		nibble = c - '0';
+	      else if (c >= 'a')
+		nibble = c - 'a' + 10;
+	      else
+		_GLIBCXX_DEMANGLER_FAILURE;
+	      // Write nibble into word array.
+	      if (nibble_cnt == 0)
+		*word = nibble << 28;
+              else
+		*word |= (nibble << (28 - 4 * nibble_cnt));
+	      c = next();
+	    }
+	    ++word;
+	  }
+	  char buf[24];
+	  if (sizeof(FloatType) == 8)
+	    print_IEEE_fp(buf, words, 11, 52, 17);
+	  else
+	    print_IEEE_fp(buf, words, 8, 23, 8);
+	  output += buf;
+	  _GLIBCXX_DEMANGLER_RETURN;
+	}
+
     template<typename Allocator>
       bool
       session<Allocator>::decode_literal(string_type& output)
@@ -925,7 +991,17 @@ namespace __gnu_cxx
 	      _GLIBCXX_DEMANGLER_FAILURE;
 	    output += ')';
 	  }
-	  if (!decode_number(output))
+	  if (c == 'd')
+	  {
+	    if (!decode_real<double>(output))
+	      _GLIBCXX_DEMANGLER_FAILURE;
+	  }
+	  else if (c == 'f')
+	  {
+	    if (!decode_real<float>(output))
+	      _GLIBCXX_DEMANGLER_FAILURE;
+	  }
+	  else if (!decode_number(output))
 	    _GLIBCXX_DEMANGLER_FAILURE;
 #ifdef _GLIBCXX_DEMANGLER_STYLE_LITERAL
 	  if (c == 'j' || c == 'm' || c == 'y')
@@ -1508,8 +1584,8 @@ namespace __gnu_cxx
     // <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), then those
-    // are added AFTER the (member) function type.  For example:
+    // 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 ") []".
     //
@@ -1863,7 +1939,8 @@ namespace __gnu_cxx
 		// Return type.
 		// Constructors, destructors and conversion operators don't
 		// have a return type, but seem to never get here.
-		if (!decode_type_with_postfix(prefix, postfix))
+		string_type return_type_postfix;
+		if (!decode_type_with_postfix(prefix, return_type_postfix))
 		    // substitution: <R> recursive
 		{
 		  failure = true;
@@ -1885,9 +1962,10 @@ namespace __gnu_cxx
 		add_substitution(start_pos, type);
 		// substitution: all qualified types if any.
 		qualifiers->decode_qualifiers(prefix, postfix);
-		prefix += ")";
-		prefix += bare_function_type;
-		prefix += member_function_qualifiers;
+		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,
@@ -1929,17 +2007,19 @@ namespace __gnu_cxx
 	      //     substitution: "<R>", "<B>" (<B> recursive) and "F<R><B>E".
 
 	      // Return type.
-	      if (!decode_type_with_postfix(prefix, postfix))
+	      string_type return_type_postfix;
+	      if (!decode_type_with_postfix(prefix, return_type_postfix))
 		  // Substitution: "<R>".
 	      {
 		failure = true;
 		break;
 	      }
-	      // Only array (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]".
-	      if (postfix.size() == 0)
+	      // 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;
@@ -1953,10 +2033,11 @@ namespace __gnu_cxx
 	      add_substitution(start_pos, type);  // Substitution: "F<R><B>E".
 	      qualifiers->decode_qualifiers(prefix, postfix);
 		  // substitution: all qualified types, if any.
-	      prefix += ")";
+	      postfix += ")";
 	      if (extern_C)
-	        prefix += " [extern \"C\"] ";
-	      prefix += bare_function_type;
+	        postfix += " [extern \"C\"] ";
+	      postfix += bare_function_type;
+	      postfix += return_type_postfix;
 	      break;
 	    }
 	    case 'T':
Index: libstdc++-v3/src/demangle.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/src/demangle.cc,v
retrieving revision 1.3
diff -u -d -p -r1.3 demangle.cc
--- libstdc++-v3/src/demangle.cc	2 Oct 2003 14:29:26 -0000	1.3
+++ libstdc++-v3/src/demangle.cc	23 Nov 2003 14:31:26 -0000
@@ -28,8 +28,8 @@
 // invalidate any other reasons why the executable file might be covered by
 // the GNU General Public License.
 
-#include <cxxabi.h>
 #include <bits/demangle.h>
+#include <cxxabi.h>
 
 // __cxa_demangle
 //
@@ -164,4 +164,558 @@ namespace __cxxabiv1 
     }
     return finish(result.data(), result.size(), buf, n, status);
   }
+
 } // namespace __cxxabiv1
+
+namespace
+{
+
+// class decimal_float
+//
+// This internal class represents a floating point value
+// with a precision of `mantissa_size_c' * 4 digits.
+// With `mantissa_size_c' set to 5 that gives 20 digits,
+// being more than 66 bits.  However, due to round off
+// errors, the last `size of binary exponent' bits are
+// unreliable.
+//
+// For IEEE double precision, the size of the exponent
+// is 11 bits and thus is this class only accurate in
+// 55 bits.  Therefore, only 17 digits may be printed
+// in that case.  This size is precisely significant for
+// the 52 bits of precision in the IEEE format as well.
+//
+// For IEEE single precision, the size of the exponent
+// is 8 bits and we will have 58 bits of precision.  It
+// makes no sense to print more than 7 digits in that
+// case because IEEE single precision has only 23 bits
+// of precision by itself.
+//
+// The internal value of a `decimal_float' object is
+//
+// (            mantissa[0] +
+//   10000    * mantissa[1] +
+//   10000**2 * mantissa[2] +
+//   10000**3 * mantissa[3] +
+//   10000**4 * mantissa[4]   ) * 10**exponent
+//
+// The member `max_precision_reached' is set to true
+// when the value of the object cannot be multiplied
+// with 10 anymore without changing the exponent,
+// in other words, when mantissa[4] >= 1000.
+// Its value is fuzzy however and only influences
+// the maximum achievable accuracy.
+
+static int const mantissa_size_c = 5;
+
+struct decimal_float_data {
+  unsigned long mantissa[mantissa_size_c];
+  int exponent;
+  bool max_precision_reached;
+};
+
+class decimal_float {
+private:
+  decimal_float_data M_data;
+
+private:
+  void M_do_overflow(unsigned long prev_borrow);
+  void M_do_carry(void);
+
+public:
+  void set_2pow2pow(int power);
+  void set_2pow(int power);
+  void set_expstart(int expsize);
+  void set_zero(void);
+  void divide_by_two(bool decrement_exponent);
+  bool decrement_exponent(void);
+  decimal_float& operator+=(decimal_float const& term);
+  decimal_float& operator*=(decimal_float const& factor);
+  void print_to_with_precision(char* buf, int precision) const;
+};
+
+// These names must match the corresponding index of the table below
+// and the p* constants must be contigious and in the given order.
+// Same for the constants m1023 ... m15.
+//        Name    Table-index
+int const m1023 = 0;		// Corresponds with an exponent of 11 bits.
+#if 0
+int const m511  = 1;
+int const m255  = 2;
+int const m127  = 3;		// Corresponds with an exponent of 8 bits.
+int const m63   = 4;
+int const m31   = 5;
+int const m15   = 6;
+#endif
+int const m1    = 7;
+int const m0    = 8;		// Must have the same exponent as m1.
+int const p1    = 9;
+#if 0
+int const p2    = 10;
+int const p4    = 11;
+int const p8    = 12;
+int const p16   = 13;
+int const p32   = 14;
+int const p64   = 15;
+int const p128  = 16;
+int const p256  = 17;
+int const p512  = 18;
+int const p1024 = 19;
+#endif
+
+decimal_float_data const constants[] = {
+  { 6915, 3600, 2925, 5369, 1112, -327, true  },	// m1023; 2 ** -1023
+  { 3487,   41, 4624, 6681, 1491, -173, true  },	// m511; 2 ** -511
+  { 9251, 8888, 1101, 2337, 1727,  -96, true  },	// m255; 2 ** -255
+  { 5398, 1437, 5411, 4717, 5877,  -58, true  },	// m127; 2 ** -127
+  { 4340, 5504, 7248, 2021, 1084,  -38, true  },	// m63; 2 ** -63
+  { 5781, 7392, 7307, 6128, 4656,  -29, true  },	// m31; 2 ** -31
+  {    0,    0, 1250, 7578, 3051,  -24, true  },	// m15; 2 ** -15
+  {    5,    0,    0,    0,    0,   -1, false },	// m1; 2 ** -1
+  {   10,    0,    0,    0,    0,   -1, false },	// m0; 2 ** 0
+  {    2,    0,    0,    0,    0,    0, false },	// p1; 2 ** 1
+  {    4,    0,    0,    0,    0,    0, false },	// p2; 2 ** 2
+  {   16,    0,    0,    0,    0,    0, false },	// p4; 2 ** 4
+  {  256,    0,    0,    0,    0,    0, false },	// p8; 2 ** 8
+  { 5536,    6,    0,    0,    0,    0, false },	// p16; 2 ** 16
+  { 7296, 9496,   42,    0,    0,    0, false },	// p32; 2 ** 32
+  { 1616,  955,  737, 6744, 1844,    0, true  },	// p64; 2 ** 64
+  { 6346, 9384, 6920, 8236, 3402,   19, true  },	// p128; 2 ** 128
+  { 9542, 3161, 9237, 9208, 1157,   58, true  },	// p256; 2 ** 256
+  { 7100, 4259, 9299, 7807, 1340,  135, true  },	// p512; 2 ** 512
+  { 9077, 2315, 3486, 6931, 1797,  289, true  },	// p1024; 2 ** 1024
+};
+
+// Handle access digits in the most significant
+// element of the mantissa array.
+void decimal_float::M_do_overflow(unsigned long prev_borrow)
+{
+  // assert(M_data.mantissa[mantissa_size_c - 1] > 9999);
+
+  // Even after shifting the access digits right,
+  // M_data.mantissa[mantissa_size_c - 1] will still be
+  // larger than 999.
+  M_data.max_precision_reached = true;
+
+  // Count the access digits and update the exponent
+  // already in order to keep the value constant.
+  unsigned long divider = 10;
+  ++M_data.exponent;
+  while (prev_borrow >= divider)
+  {
+    divider *= 10;
+    ++M_data.exponent;
+  }
+
+  // Finally, shift the value in the mantissa a few
+  // digits to the right.  Round off what falls off.
+  unsigned long multiplier = 10000 / divider;
+  for (int i = mantissa_size_c - 1; i >= 0; --i)
+  {
+    unsigned long borrow = M_data.mantissa[i] % divider;
+    if (i == 0)
+      M_data.mantissa[i] += divider / 2;	// Round off.
+    M_data.mantissa[i] /= divider;
+    M_data.mantissa[i] += prev_borrow * multiplier;
+    prev_borrow = borrow;
+  }
+}
+
+// Handle access digits in the elements of the mantissa array.
+void decimal_float::M_do_carry(void)
+{
+  for (int i = 0; i < mantissa_size_c - 1; ++i)
+  {
+    if (M_data.mantissa[i] >= 10000)
+    {
+      M_data.mantissa[i + 1] += M_data.mantissa[i] / 10000;
+      M_data.mantissa[i] %= 10000;
+    }
+  }
+  if (M_data.mantissa[mantissa_size_c - 1] >= 10000)
+    M_do_overflow(0);
+}
+
+// Initialize the object to a value of 2 ** (2 ** power).
+inline void decimal_float::set_2pow2pow(int power)
+{
+  // assert(0 <= power && power <= 10);
+  std::memcpy(&M_data, &constants[p1 + power], sizeof(decimal_float_data));
+}
+
+// Initialize the object to a value of 2 ** power.
+inline void decimal_float::set_2pow(int power)
+{
+  // assert(power == 0 || power == 1);
+  std::memcpy(&M_data, &constants[power], sizeof(decimal_float_data));
+}
+
+// Initialize the object to a value of 2 ** (1 - (2 ** (expsize - 1))).
+inline void decimal_float::set_expstart(int expsize)
+{
+  // assert(expsize <= 11 && expsize >= 5);
+  std::memcpy(&M_data, &constants[m1023 + 11 - expsize],
+      sizeof(decimal_float_data));
+}
+
+// Initialize the object to zero.  Must have the same exponent as m0.
+inline void decimal_float::set_zero(void)
+{
+  std::memcpy(&M_data, &constants[m0], sizeof(decimal_float_data));
+  M_data.mantissa[0] = 0;
+}
+
+// Divide the value of this object by two in one of two possible ways:
+// If `decrement_exponent' is true - then decrement the exponent by
+// one and multiply the mantissa with five.  Otherwise just divide
+// the mantissa by two.
+void decimal_float::divide_by_two(bool decrement_exponent)
+{
+  if (decrement_exponent)
+  {
+    for (int i = 0; i < mantissa_size_c; ++i)
+      M_data.mantissa[i] *= 5;
+    M_do_carry();
+    --M_data.exponent;
+  }
+  else
+  {
+    unsigned long prev_borrow = M_data.mantissa[mantissa_size_c - 1] % 2;
+    if ((M_data.mantissa[mantissa_size_c - 1] /= 2) < 1000)
+      M_data.max_precision_reached = false;
+    for (int i = mantissa_size_c - 2; i >= 0; --i)
+    {
+      unsigned long borrow = M_data.mantissa[i] % 2;
+      M_data.mantissa[i] /= 2;
+      M_data.mantissa[i] += prev_borrow * 5000;
+      prev_borrow = borrow;
+    }
+    if (prev_borrow)
+    {
+      // Round off.
+      if (++M_data.mantissa[0] == 10000)
+        M_do_carry();
+    }
+  }
+}
+
+// If possible, multiply the mantissa with 10 and
+// decrement the exponent with one.  This is used
+// to keep the exponent of this object equal to
+// another object that is being divided by two.
+bool decimal_float::decrement_exponent(void)
+{
+  if (M_data.max_precision_reached)
+    return false;
+  for (int i = 0; i < mantissa_size_c; ++i)
+    M_data.mantissa[i] *= 10;
+  M_do_carry();
+  if (M_data.mantissa[mantissa_size_c - 1] >= 1000)
+    M_data.max_precision_reached = true;
+  --M_data.exponent;
+  return true;
+}
+
+// Add two decimal_floats that have the same exponent.
+decimal_float& decimal_float::operator+=(decimal_float const& term)
+{
+  // assert(M_data.exponent == term.M_data.exponent);
+  for (int i = 0; i < mantissa_size_c; ++i)
+    M_data.mantissa[i] += term.M_data.mantissa[i];
+  M_do_carry();
+  return *this;
+}
+
+// The real work.  Multiply this object with `factor'.
+decimal_float& decimal_float::operator*=(decimal_float const& factor)
+{
+  // Count the number of most-significant mantissa elements (digits)
+  // that contain zero (of either factor), but stop counting if we reach
+  // mantissa_size_c - 1.
+  int zero_digits = 0;
+  while (M_data.mantissa[mantissa_size_c - 1 - zero_digits] == 0)
+    if (++zero_digits == mantissa_size_c - 1)
+      break;
+  if (zero_digits < mantissa_size_c - 1)
+  {
+    int offset = mantissa_size_c - 1 + zero_digits;
+    while (factor.M_data.mantissa[offset - zero_digits] == 0)
+      if (++zero_digits == mantissa_size_c - 1)
+	break;
+  }
+
+  // Set `this_mantissa' to point to the mantissa of this object;
+  // make a copy only when we would overwrite its values when
+  // still needed below.
+  unsigned long tmp_mantissa[mantissa_size_c];
+  unsigned long* this_mantissa;
+  if (zero_digits == 0)
+    this_mantissa = M_data.mantissa;
+  else
+  {
+    std::memcpy(tmp_mantissa, M_data.mantissa, sizeof(tmp_mantissa));
+    this_mantissa = tmp_mantissa;
+  }
+
+  // Set lss (least significant (loop) size, but don't ask me why it is
+  // called that way - it gets a bit complicated here) to, heh, what works.
+  int lss = mantissa_size_c - 1 - zero_digits;
+  // Now hold your breath...
+  M_data.exponent += factor.M_data.exponent + 4 * lss;
+  unsigned long sum = 0;
+  for (int i = 0; i < lss; ++i)
+    sum += this_mantissa[i] * factor.M_data.mantissa[lss - 1 - i];
+  sum += 5000;	// Round off.
+  sum /= 10000;
+  for (int j = 0; j < mantissa_size_c; ++j)
+  {
+    int loop_bgn = std::max(0, lss + j - (mantissa_size_c - 1));
+    int loop_end = std::min(mantissa_size_c - 1, lss + j);
+    for (int i = loop_bgn; i <= loop_end; ++i)
+      sum += this_mantissa[i] * factor.M_data.mantissa[lss + j - i];
+    M_data.mantissa[j] = sum;
+    sum /= 10000;
+    M_data.mantissa[j] -= 10000 * sum;
+  }
+  // ... ahhh. Ok. And do overflow management when needed.
+  if (sum > 0)
+    M_do_overflow(sum);
+}
+
+// Print to `buf', writes: "<digit>.<digits>e<sign><exponent>\0".
+// sizeof(buf) must be at least 7 larger than `precision':
+// strlen(<digit><digits>) <= precision.
+// strlen(.e<sign><exponent>) == 6, plus one for the trailing '\0'.
+void decimal_float::print_to_with_precision(char* buf, int precision) const
+{
+  // First do the round off.
+  decimal_float tmp(*this);
+  if (!M_data.max_precision_reached)
+  {
+    // In this case we are probably exact, so we
+    // don't really need to round off.  Because leading
+    // zeroes are not printed, add number of leading 0's
+    // to `precision'.
+    for (int i = mantissa_size_c - 1; i >= 0; --i)
+      for(int shift = 1000; shift; shift /= 10)
+      {
+        if (M_data.mantissa[i] >= shift)
+	{
+	  i = 0;
+	  break;
+        }
+	++precision;
+      }
+  }
+  int e = 4 * mantissa_size_c - 1;
+  if (precision < mantissa_size_c * 4)
+  {
+    int cut = e - precision;
+    int cuti = cut / 4;
+    int cutr = cut % 4;
+    unsigned long shift = 10;
+    while(cutr--)
+      shift *= 10;
+    tmp.M_data.mantissa[cuti] += shift / 2;	// Round off.
+    if (tmp.M_data.mantissa[cuti] >= 10000)
+      tmp.M_do_carry();
+  }
+
+  bool leading = true;
+  char* p = buf;
+  int tz = 0;
+  for (int i = mantissa_size_c - 1; i >= 0 && precision; --i)
+  {
+    unsigned long digit = tmp.M_data.mantissa[i];
+    for(int shift = 1000; shift; shift /= 10)
+    {
+      int d = digit / shift;
+      digit -= d * shift;
+      if (leading && d != 0)
+        leading = false;
+      if (leading)	// Suppress leading zeroes.
+        --e;
+      else
+      {
+	if (d == 0)	// Suppress and count trailing zeroes.
+	  ++tz;
+	else
+	{
+	  if (p == buf + 1)
+	    *p++ = '.';
+	  while(tz--)
+	    *p++ = '0';
+	  *p++ = d + '0';
+	  tz = 0;
+	}
+	if (--precision == 0)
+	  break;
+      }
+    }
+  }
+  e += tmp.M_data.exponent;
+  if (e != 0)
+  {
+    *p++ = 'e';
+    if (e > 0)
+      *p++ = '+';
+    else
+    {
+      *p++ = '-';
+      e = -e;
+    }
+    int shift = 100;
+    leading = true;
+    while(shift)
+    {
+      int d = e / shift;
+      e -= d * shift;
+      if (leading && d != 0)
+        leading = false;
+      if (!leading)
+        *p++ = '0' + d;
+      shift /= 10;
+    }
+  } 
+  *p = 0;
+}
+
+} // namespace
+
+namespace __gnu_cxx
+{
+  namespace demangler
+  {
+
+// Important note:
+// Please realize that this function, and thus the class decimal_float above,
+// do NOT allocate ANY memory.  Therefore it does not need Allocator and
+// therefore we can put it here instead of in bits/demangle.h but that
+// doesn't mean we can start to allocate memory through malloc(), or call
+// system library calls that might do so, like sprintf(.."%e"..) would do!.
+//
+// It is an important feature of the bits/demangler.h API that it never
+// allocates any memory except through the Allocator class.
+
+
+// External interface (used by bits/demangle.h):
+
+// print_IEEE_fp(buf, words, nbits_exponent, nbits_fraction, precision)
+//
+// buf                  : Output buffer, the result is written to this buffer
+//                        and terminated with a trailing '\0'.  The size of
+//                        this buffer must be at least `precision + 7'.
+// words                : A pointer to an array with unsigned integers.  Only
+//                        the 32 least significant bits of each element are
+//                        used.  The first element contains the word with the
+//                        most significant bits.  Bit 31 in each element
+//                        represents the most significant bit of that 32-bit
+//                        word.  See the description of IEEE 754-1985 for
+//                        the exact meaning.  Basically they mean:
+//                        SEEEEEEEEMMMMMMMMMMMMMMMMMMMM, where S is the sign
+//                        bit, EEEEEEEE the exponent and MMMMMMMMMMMMMMMMMMMM
+//                        the mantissa.
+// nbits_exponent       : The number of bits in `sign_and_exponent' that
+//                        represent the exponent.
+// nbits_fraction       : The total number of bits in `fraction', a value
+//                        larger than 52 will result in inaccurate output.
+// precision            : The maximum number of digits in the mantissa
+//                        (including the first digit before the dot) that
+//                        will be written to `buf'.  This precision should
+//                        correspond to the accuracy given by `nbits_fraction'
+//                        of course.
+
+void print_IEEE_fp(char* buf, unsigned long* words,
+    int nbits_exponent, int nbits_fraction, int precision)
+{
+  // This function was written using
+  // http://www.psc.edu/general/software/packages/ieee/ieee.html
+  // as reference for the IEEE 754-1985 standard.
+
+  // assert( nbits_fraction <= 52 && nbits_exponent <= 11 &&
+  //         nbits_exponent >= 5 && precision <= 17 );
+  unsigned long sign_mask = 1 << nbits_exponent;
+  unsigned long exponent_mask = sign_mask - 1;
+  unsigned long sign_and_exponent = words[0] >> (31 - nbits_exponent);
+  unsigned long exponent = sign_and_exponent & exponent_mask;
+  int nelem_fraction = (nbits_fraction + nbits_exponent) / 32 + 1;
+  unsigned long mask_first_elem = 0xffffffffUL >> (nbits_exponent + 1);
+  unsigned long mask_last_elem = ~((1UL << (nelem_fraction * 32 -
+      nbits_fraction - nbits_exponent - 1)) - 1);
+  unsigned long fraction_nonzero = (words[0] & mask_first_elem);
+  if (nelem_fraction == 1)
+    fraction_nonzero &= mask_last_elem;
+  else
+  {
+    fraction_nonzero |= (words[nelem_fraction - 1] & mask_last_elem);
+    for (int i = 1; i < nelem_fraction - 1; ++i)
+      fraction_nonzero |= words[i];
+  }
+  if (exponent == exponent_mask && fraction_nonzero)
+  {
+    strcpy(buf, "nan");
+    return;
+  }
+  if ((sign_and_exponent & sign_mask))
+    *buf++ = '-';
+  if (exponent == exponent_mask && !fraction_nonzero)
+  {
+    strcpy(buf, "inf");
+    return;
+  }
+  bool normalized = true;
+  if (exponent == 0)
+  {
+    if (!fraction_nonzero)
+    {
+      strcpy(buf, "0");
+      return;
+    }
+    else
+    {
+      normalized = false;
+      exponent = 1;
+    }
+  }
+
+  decimal_float result;
+  if (normalized)
+    result.set_2pow(m0);		// 1.0 ; The 1 in (1.F)
+  else
+    result.set_zero();			// 0.0 ; The 0 in (0.F)
+  decimal_float bit;
+  bit.set_2pow(m1);			// 0.5 ; 2 ** (-bit_cnt - 1)
+  unsigned long mask = 0x40000000 >> nbits_exponent;
+  for (int bit_cnt = 0; bit_cnt < nbits_fraction; ++bit_cnt)
+  {
+    if ((*words & mask))
+      result += bit;
+    bool success = result.decrement_exponent();
+    bit.divide_by_two(success);		// Keep exponents equal for easy addition.
+    if (!(mask >>= 1))
+    {
+      mask = 0x80000000;
+      ++words;
+    }
+  }
+  decimal_float two_pow_exponent;
+  two_pow_exponent.set_expstart(nbits_exponent);
+      // 2 ** (1 - 2 ** (nbits_exponent - 1)),
+      // where 1 - 2 ** (nbits_exponent - 1) is
+      // the two's-complement exponent 'offset'.
+  mask = 1 << (nbits_exponent - 1);
+  for (int bit_cnt = nbits_exponent - 1; bit_cnt >= 0; --bit_cnt)
+  {
+    if ((exponent & mask))
+    {
+      bit.set_2pow2pow(bit_cnt);	// 2 ** (2 ** bit_cnt)
+      two_pow_exponent *= bit;
+    }
+    mask >>= 1;
+  }
+  result *= two_pow_exponent;
+  result.print_to_with_precision(buf, precision);
+}
+
+  } // namespace demangler
+} // namespace __gnu_cxx
Index: libstdc++-v3/testsuite/demangle/regression/cw-16.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/demangle/regression/cw-16.cc,v
retrieving revision 1.3
diff -u -d -p -r1.3 cw-16.cc
--- libstdc++-v3/testsuite/demangle/regression/cw-16.cc	12 Nov 2003 02:18:37 -0000	1.3
+++ libstdc++-v3/testsuite/demangle/regression/cw-16.cc	23 Nov 2003 14:31:31 -0000
@@ -36,11 +36,18 @@ verify_demangle("_Z1fILi5E1AEvN1CIXqugtT
 verify_demangle("_Z1fILi5EEvN1AIXcvimlT_Li22EEE1qE",
                 "void f<5>(A<(int)((5) * (22))>::q)");
 verify_demangle("_Z1fPFYPFiiEiE",
-                "f(int (*)(int) (*) [extern \"C\"] (int))");
+                "f(int (*(*) [extern \"C\"] (int))(int))");
 verify_demangle("_Z1fI1XENT_1tES2_",
                 "X::t f<X>(X::t)");
 verify_demangle("_Z1fILi5E1AEvN1CIXstN1T1tEEXszsrS2_1tEE1qE",
                 "void f<5, A>(C<sizeof (T::t), sizeof (T::t)>::q)");
+// 2003/11/22, libstdc++/13045
+verify_demangle("_Z1fILi1ELc120EEv1AIXplT_cviLd4028ae147ae147aeEEE",
+                "void f<1, (char)120>(A<(1) + ((int)((double)1.234e+1))>)");
+verify_demangle("_Z1fILi1ELc120EEv1AIXplT_cviLf3f800000EEE",
+                "void f<1, (char)120>(A<(1) + ((int)((float)1))>)");
+verify_demangle("_Z9hairyfuncM1YKFPVPFrPA2_PM1XKFKPA3_ilEPcEiE",
+                "hairyfunc(int (* const (X::** (* restrict (* volatile* (Y::*)(int) const)(char*)) [2])(long) const) [3])");
 
   return 0;
 }


More information about the Libstdc++ mailing list