Target FP printing: Simplify and fix ui_printf
[deliverable/binutils-gdb.git] / gdb / doublest.c
index cafa7d3441bae637dc30c7b0efae697890faa2c7..27d1c12f7f4ba83af8d06447a6527916e2895ca4 100644 (file)
@@ -789,45 +789,78 @@ floatformat_from_doublest (const struct floatformat *fmt,
 }
 
 /* Convert the byte-stream ADDR, interpreted as floating-point format FMT,
-   to a string.  */
+   to a string, optionally using the print format FORMAT.  */
 std::string
 floatformat_to_string (const struct floatformat *fmt,
-                      const gdb_byte *in)
+                      const gdb_byte *in, const char *format)
 {
-  /* Detect invalid representations.  */
-  if (!floatformat_is_valid (fmt, in))
-    return "<invalid float value>";
-
-  /* Handle NaN and Inf.  */
-  enum float_kind kind = floatformat_classify (fmt, in);
-  if (kind == float_nan)
-    {
-      const char *sign = floatformat_is_negative (fmt, in)? "-" : "";
-      const char *mantissa = floatformat_mantissa (fmt, in);
-      return string_printf ("%snan(0x%s)", sign, mantissa);
-    }
-  else if (kind == float_infinite)
+  /* Unless we need to adhere to a specific format, provide special
+     output for certain cases.  */
+  if (format == nullptr)
     {
-      const char *sign = floatformat_is_negative (fmt, in)? "-" : "";
-      return string_printf ("%sinf", sign);
+      /* Detect invalid representations.  */
+      if (!floatformat_is_valid (fmt, in))
+       return "<invalid float value>";
+
+      /* Handle NaN and Inf.  */
+      enum float_kind kind = floatformat_classify (fmt, in);
+      if (kind == float_nan)
+       {
+         const char *sign = floatformat_is_negative (fmt, in)? "-" : "";
+         const char *mantissa = floatformat_mantissa (fmt, in);
+         return string_printf ("%snan(0x%s)", sign, mantissa);
+       }
+      else if (kind == float_infinite)
+       {
+         const char *sign = floatformat_is_negative (fmt, in)? "-" : "";
+         return string_printf ("%sinf", sign);
+       }
     }
 
-  /* Print the number using a format string where the precision is set
-     to the DECIMAL_DIG value for the given floating-point format.
-     This value is computed as
+  /* Determine the format string to use on the host side.  */
+  std::string host_format;
+  char conversion;
+
+  if (format == nullptr)
+    {
+      /* If no format was specified, print the number using a format string
+        where the precision is set to the DECIMAL_DIG value for the given
+        floating-point format.  This value is computed as
 
                ceil(1 + p * log10(b)),
 
-     where p is the precision of the floating-point format in bits, and
-     b is the base (which is always 2 for the formats we support).  */
-  const double log10_2 = .30102999566398119521;
-  double d_decimal_dig = 1 + floatformat_precision (fmt) * log10_2;
-  int decimal_dig = d_decimal_dig;
-  if (decimal_dig < d_decimal_dig)
-    decimal_dig++;
+        where p is the precision of the floating-point format in bits, and
+        b is the base (which is always 2 for the formats we support).  */
+      const double log10_2 = .30102999566398119521;
+      double d_decimal_dig = 1 + floatformat_precision (fmt) * log10_2;
+      int decimal_dig = d_decimal_dig;
+      if (decimal_dig < d_decimal_dig)
+       decimal_dig++;
+
+      host_format = string_printf ("%%.%d", decimal_dig);
+      conversion = 'g';
+    }
+  else
+    {
+      /* Use the specified format, stripping out the conversion character
+         and length modifier, if present.  */
+      size_t len = strlen (format);
+      gdb_assert (len > 1);
+      conversion = format[--len];
+      gdb_assert (conversion == 'e' || conversion == 'f' || conversion == 'g'
+                 || conversion == 'E' || conversion == 'G');
+      if (format[len - 1] == 'L')
+       len--;
 
-  std::string host_format
-    = string_printf ("%%.%d" DOUBLEST_PRINT_FORMAT, decimal_dig);
+      host_format = std::string (format, len);
+    }
+
+  /* Add the length modifier and conversion character appropriate for
+     handling the host DOUBLEST type.  */
+#ifdef HAVE_LONG_DOUBLE
+  host_format += 'L';
+#endif
+  host_format += conversion;
 
   DOUBLEST doub;
   floatformat_to_doublest (fmt, in, &doub);
This page took 0.033273 seconds and 4 git commands to generate.