}
/* 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);