#include "ui-out.h"
#include "block.h"
#include "disasm.h"
-#include "dfp.h"
+#include "target-float.h"
#include "observer.h"
#include "solist.h"
#include "parser-defs.h"
valaddr = converted_float_bytes.data ();
}
- switch (options->format)
+ /* Printing a non-float type as 'f' will interpret the data as if it were
+ of a floating-point type of the same length, if that exists. Otherwise,
+ the data is printed as integer. */
+ char format = options->format;
+ if (format == 'f' && TYPE_CODE (type) != TYPE_CODE_FLT)
+ {
+ type = float_type_from_length (type);
+ if (TYPE_CODE (type) != TYPE_CODE_FLT)
+ format = 0;
+ }
+
+ switch (format)
{
case 'o':
print_octal_chars (stream, valaddr, len, byte_order);
}
/* FALLTHROUGH */
case 'f':
- type = float_type_from_length (type);
print_floating (valaddr, type, stream);
break;
break;
default:
- error (_("Undefined output format \"%c\"."), options->format);
+ error (_("Undefined output format \"%c\"."), format);
}
}
}
static void
-print_command (char *exp, int from_tty)
+print_command (const char *exp, int from_tty)
{
print_command_1 (exp, 1);
}
/* Same as print, except it doesn't print void results. */
static void
-call_command (char *exp, int from_tty)
+call_command (const char *exp, int from_tty)
{
print_command_1 (exp, 0);
}
/* Implementation of the "output" command. */
static void
-output_command (char *exp, int from_tty)
+output_command (const char *exp, int from_tty)
{
output_command_const (exp, from_tty);
}
}
static void
-set_command (char *exp, int from_tty)
+set_command (const char *exp, int from_tty)
{
expression_up expr = parse_expression (exp);
}
static void
-info_symbol_command (char *arg, int from_tty)
+info_symbol_command (const char *arg, int from_tty)
{
struct minimal_symbol *msymbol;
struct objfile *objfile;
}
static void
-info_address_command (char *exp, int from_tty)
+info_address_command (const char *exp, int from_tty)
{
struct gdbarch *gdbarch;
int regno;
\f
static void
-x_command (char *exp, int from_tty)
+x_command (const char *exp, int from_tty)
{
struct format_data fmt;
struct value *val;
repeated with Newline. But don't clobber a user-defined
command's definition. */
if (from_tty)
- *exp = 0;
+ set_repeat_arguments ("");
val = evaluate_expression (expr.get ());
if (TYPE_IS_REFERENCE (value_type (val)))
val = coerce_ref (val);
Specify the expression. */
static void
-display_command (char *arg, int from_tty)
+display_command (const char *arg, int from_tty)
{
struct format_data fmt;
struct display *newobj;
}
static void
-info_display_command (char *ignore, int from_tty)
+info_display_command (const char *ignore, int from_tty)
{
struct display *d;
}
/* Subroutine of ui_printf to simplify it.
- Print VALUE, a decimal floating point value, to STREAM using FORMAT. */
+ Print VALUE, a floating point value, to STREAM using FORMAT. */
static void
-printf_decfloat (struct ui_file *stream, const char *format,
- struct value *value)
+printf_floating (struct ui_file *stream, const char *format,
+ struct value *value, enum argclass argclass)
{
- const gdb_byte *param_ptr = value_contents (value);
-
-#if defined (PRINTF_HAS_DECFLOAT)
- /* If we have native support for Decimal floating
- printing, handle it here. */
- fprintf_filtered (stream, format, param_ptr);
-#else
- /* As a workaround until vasprintf has native support for DFP
- we convert the DFP values to string and print them using
- the %s format specifier. */
- const char *p;
-
/* Parameter data. */
struct type *param_type = value_type (value);
struct gdbarch *gdbarch = get_type_arch (param_type);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- /* DFP output data. */
- struct value *dfp_value = NULL;
- gdb_byte *dfp_ptr;
- int dfp_len = 16;
- gdb_byte dec[16];
- struct type *dfp_type = NULL;
- char decstr[MAX_DECIMAL_STRING];
-
- /* Points to the end of the string so that we can go back
- and check for DFP length modifiers. */
- p = format + strlen (format);
-
- /* Look for the float/double format specifier. */
- while (*p != 'f' && *p != 'e' && *p != 'E'
- && *p != 'g' && *p != 'G')
- p--;
-
- /* Search for the '%' char and extract the size and type of
- the output decimal value based on its modifiers
- (%Hf, %Df, %DDf). */
- while (*--p != '%')
+ /* Determine target type corresponding to the format string. */
+ struct type *fmt_type;
+ switch (argclass)
{
- if (*p == 'H')
- {
- dfp_len = 4;
- dfp_type = builtin_type (gdbarch)->builtin_decfloat;
- }
- else if (*p == 'D' && *(p - 1) == 'D')
- {
- dfp_len = 16;
- dfp_type = builtin_type (gdbarch)->builtin_declong;
- p--;
- }
- else
- {
- dfp_len = 8;
- dfp_type = builtin_type (gdbarch)->builtin_decdouble;
- }
+ case double_arg:
+ fmt_type = builtin_type (gdbarch)->builtin_double;
+ break;
+ case long_double_arg:
+ fmt_type = builtin_type (gdbarch)->builtin_long_double;
+ break;
+ case dec32float_arg:
+ fmt_type = builtin_type (gdbarch)->builtin_decfloat;
+ break;
+ case dec64float_arg:
+ fmt_type = builtin_type (gdbarch)->builtin_decdouble;
+ break;
+ case dec128float_arg:
+ fmt_type = builtin_type (gdbarch)->builtin_declong;
+ break;
+ default:
+ gdb_assert_not_reached ("unexpected argument class");
}
- /* Conversion between different DFP types. */
- if (TYPE_CODE (param_type) == TYPE_CODE_DECFLOAT)
- decimal_convert (param_ptr, TYPE_LENGTH (param_type),
- byte_order, dec, dfp_len, byte_order);
- else
- /* If this is a non-trivial conversion, just output 0.
- A correct converted value can be displayed by explicitly
- casting to a DFP type. */
- decimal_from_string (dec, dfp_len, byte_order, "0");
+ /* To match the traditional GDB behavior, the conversion is
+ done differently depending on the type of the parameter:
- dfp_value = value_from_decfloat (dfp_type, dec);
+ - if the parameter has floating-point type, it's value
+ is converted to the target type;
- dfp_ptr = (gdb_byte *) value_contents (dfp_value);
+ - otherwise, if the parameter has a type that is of the
+ same size as a built-in floating-point type, the value
+ bytes are interpreted as if they were of that type, and
+ then converted to the target type (this is not done for
+ decimal floating-point argument classes);
- decimal_to_string (dfp_ptr, dfp_len, byte_order, decstr);
+ - otherwise, if the source value has an integer value,
+ it's value is converted to the target type;
- /* Print the DFP value. */
- fprintf_filtered (stream, "%s", decstr);
-#endif
+ - otherwise, an error is raised.
+
+ In either case, the result of the conversion is a byte buffer
+ formatted in the target format for the target type. */
+
+ if (TYPE_CODE (fmt_type) == TYPE_CODE_FLT)
+ {
+ param_type = float_type_from_length (param_type);
+ if (param_type != value_type (value))
+ value = value_from_contents (param_type, value_contents (value));
+ }
+
+ value = value_cast (fmt_type, value);
+
+ /* Convert the value to a string and print it. */
+ std::string str
+ = target_float_to_string (value_contents (value), fmt_type, format);
+ fputs_filtered (str.c_str (), stream);
}
/* Subroutine of ui_printf to simplify it.
static void
ui_printf (const char *arg, struct ui_file *stream)
{
- struct format_piece *fpieces;
const char *s = arg;
- struct value **val_args;
- int allocated_args = 20;
- struct cleanup *old_cleanups;
-
- val_args = XNEWVEC (struct value *, allocated_args);
- old_cleanups = make_cleanup (free_current_contents, &val_args);
+ std::vector<struct value *> val_args;
if (s == 0)
error_no_arg (_("format-control string and values to print"));
if (*s++ != '"')
error (_("Bad format string, missing '\"'."));
- fpieces = parse_format_string (&s);
-
- make_cleanup (free_format_pieces_cleanup, &fpieces);
+ format_pieces fpieces (&s);
if (*s++ != '"')
error (_("Bad format string, non-terminated '\"'."));
s = skip_spaces (s);
{
- int nargs = 0;
int nargs_wanted;
- int i, fr;
- char *current_substring;
+ int i;
+ const char *current_substring;
nargs_wanted = 0;
- for (fr = 0; fpieces[fr].string != NULL; fr++)
- if (fpieces[fr].argclass != literal_piece)
+ for (auto &&piece : fpieces)
+ if (piece.argclass != literal_piece)
++nargs_wanted;
/* Now, parse all arguments and evaluate them.
{
const char *s1;
- if (nargs == allocated_args)
- val_args = (struct value **) xrealloc ((char *) val_args,
- (allocated_args *= 2)
- * sizeof (struct value *));
s1 = s;
- val_args[nargs] = parse_to_comma_and_eval (&s1);
+ val_args.push_back (parse_to_comma_and_eval (&s1));
- nargs++;
s = s1;
if (*s == ',')
s++;
}
- if (nargs != nargs_wanted)
+ if (val_args.size () != nargs_wanted)
error (_("Wrong number of arguments for specified format-string"));
/* Now actually print them. */
i = 0;
- for (fr = 0; fpieces[fr].string != NULL; fr++)
+ for (auto &&piece : fpieces)
{
- current_substring = fpieces[fr].string;
- switch (fpieces[fr].argclass)
+ current_substring = piece.string;
+ switch (piece.argclass)
{
case string_arg:
printf_c_string (stream, current_substring, val_args[i]);
obstack_base (&output));
}
break;
- case double_arg:
- {
- struct type *type = value_type (val_args[i]);
- DOUBLEST val;
- int inv;
-
- /* If format string wants a float, unchecked-convert the value
- to floating point of the same size. */
- type = float_type_from_length (type);
- val = unpack_double (type, value_contents (val_args[i]), &inv);
- if (inv)
- error (_("Invalid floating value found in program."));
-
- fprintf_filtered (stream, current_substring, (double) val);
- break;
- }
- case long_double_arg:
-#ifdef HAVE_LONG_DOUBLE
- {
- struct type *type = value_type (val_args[i]);
- DOUBLEST val;
- int inv;
-
- /* If format string wants a float, unchecked-convert the value
- to floating point of the same size. */
- type = float_type_from_length (type);
- val = unpack_double (type, value_contents (val_args[i]), &inv);
- if (inv)
- error (_("Invalid floating value found in program."));
-
- fprintf_filtered (stream, current_substring,
- (long double) val);
- break;
- }
-#else
- error (_("long double not supported in printf"));
-#endif
case long_long_arg:
#ifdef PRINTF_HAS_LONG_LONG
{
fprintf_filtered (stream, current_substring, val);
break;
}
- /* Handles decimal floating values. */
- case decfloat_arg:
- printf_decfloat (stream, current_substring, val_args[i]);
+ /* Handles floating-point values. */
+ case double_arg:
+ case long_double_arg:
+ case dec32float_arg:
+ case dec64float_arg:
+ case dec128float_arg:
+ printf_floating (stream, current_substring, val_args[i],
+ piece.argclass);
break;
case ptr_arg:
printf_pointer (stream, current_substring, val_args[i]);
_("failed internal consistency check"));
}
/* Maybe advance to the next argument. */
- if (fpieces[fr].argclass != literal_piece)
+ if (piece.argclass != literal_piece)
++i;
}
}
- do_cleanups (old_cleanups);
}
/* Implement the "printf" command. */
static void
-printf_command (char *arg, int from_tty)
+printf_command (const char *arg, int from_tty)
{
ui_printf (arg, gdb_stdout);
gdb_flush (gdb_stdout);
/* Implement the "eval" command. */
static void
-eval_command (char *arg, int from_tty)
+eval_command (const char *arg, int from_tty)
{
string_file stb;
std::string expanded = insert_user_defined_cmd_args (stb.c_str ());
- execute_command (&expanded[0], from_tty);
+ execute_command (expanded.c_str (), from_tty);
}
void