#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"
B ? (TMP = B->next, 1): 0; \
B = TMP)
-/* Prototypes for exported functions. */
-
-void _initialize_printcmd (void);
-
/* Prototypes for local functions. */
static void do_one_display (struct display *);
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
-set_command (char *exp, int from_tty)
+set_command (const char *exp, int from_tty)
{
expression_up expr = parse_expression (exp);
evaluate_expression (expr.get ());
}
+/* Temporary non-const version of set_command. */
+
static void
-sym_info (char *arg, int from_tty)
+non_const_set_command (char *exp, int from_tty)
+{
+ set_command (exp, from_tty);
+}
+
+static void
+info_symbol_command (char *arg, int from_tty)
{
struct minimal_symbol *msymbol;
struct objfile *objfile;
= lookup_minimal_symbol_by_pc_section (sect_addr, osect).minsym))
{
const char *obj_name, *mapped, *sec_name, *msym_name;
- char *loc_string;
+ const char *loc_string;
struct cleanup *old_chain;
matches = 1;
/* Don't print the offset if it is zero.
We assume there's no need to handle i18n of "sym + offset". */
+ std::string string_holder;
if (offset)
- loc_string = xstrprintf ("%s + %u", msym_name, offset);
+ {
+ string_holder = string_printf ("%s + %u", msym_name, offset);
+ loc_string = string_holder.c_str ();
+ }
else
- loc_string = xstrprintf ("%s", msym_name);
-
- /* Use a cleanup to free loc_string in case the user quits
- a pagination request inside printf_filtered. */
- old_chain = make_cleanup (xfree, loc_string);
+ loc_string = msym_name;
gdb_assert (osect->objfile && objfile_name (osect->objfile));
obj_name = objfile_name (osect->objfile);
else
printf_filtered (_("%s in section %s\n"),
loc_string, sec_name);
-
- do_cleanups (old_chain);
}
}
if (matches == 0)
}
static void
-address_info (char *exp, int from_tty)
+info_address_command (char *exp, int from_tty)
{
struct gdbarch *gdbarch;
int regno;
x_command (char *exp, int from_tty)
{
struct format_data fmt;
- struct cleanup *old_chain;
struct value *val;
fmt.format = last_format ? last_format : 'x';
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);
ARGS. DATA is passed unmodified to FUNCTION. */
static void
-map_display_numbers (char *args,
+map_display_numbers (const char *args,
void (*function) (struct display *,
void *),
void *data)
/* "undisplay" command. */
static void
-undisplay_command (char *args, int from_tty)
+undisplay_command (const char *args, int from_tty)
{
if (args == NULL)
{
}
static void
-display_info (char *ignore, int from_tty)
+info_display_command (char *ignore, int from_tty)
{
struct display *d;
commands. ENABLE decides what to do. */
static void
-enable_disable_display_command (char *args, int from_tty, int enable)
+enable_disable_display_command (const char *args, int from_tty, int enable)
{
if (args == NULL)
{
/* The "enable display" command. */
static void
-enable_display_command (char *args, int from_tty)
+enable_display_command (const char *args, int from_tty)
{
enable_disable_display_command (args, from_tty, 1);
}
/* The "disable display" command. */
static void
-disable_display_command (char *args, int from_tty)
+disable_display_command (const char *args, int from_tty)
{
enable_disable_display_command (args, from_tty, 0);
}
}
/* 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.
if (s == 0)
error_no_arg (_("format-control string and values to print"));
- s = skip_spaces_const (s);
+ s = skip_spaces (s);
/* A format string should follow, enveloped in double quotes. */
if (*s++ != '"')
if (*s++ != '"')
error (_("Bad format string, non-terminated '\"'."));
- s = skip_spaces_const (s);
+ s = skip_spaces (s);
if (*s != ',' && *s != 0)
error (_("Invalid argument syntax"));
if (*s == ',')
s++;
- s = skip_spaces_const (s);
+ s = skip_spaces (s);
{
int nargs = 0;
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],
+ fpieces[fr].argclass);
break;
case ptr_arg:
printf_pointer (stream, current_substring, val_args[i]);
observer_attach_free_objfile (clear_dangling_display_expressions);
- add_info ("address", address_info,
+ add_info ("address", info_address_command,
_("Describe where symbol SYM is stored."));
- add_info ("symbol", sym_info, _("\
+ add_info ("symbol", info_symbol_command, _("\
Describe what symbol is at location ADDR.\n\
Only for symbols with fixed locations (global or static scope)."));
_("Print line number and file of definition of variable."));
#endif
- add_info ("display", display_info, _("\
+ add_info ("display", info_display_command, _("\
Expressions to display when program stops, with code numbers."));
add_cmd ("undisplay", class_vars, undisplay_command, _("\
You can see these environment settings with the \"show\" command."),
&setlist, "set ", 1, &cmdlist);
if (dbx_commands)
- add_com ("assign", class_vars, set_command, _("\
+ add_com ("assign", class_vars, non_const_set_command, _("\
Evaluate expression EXP and assign result to variable VAR, using assignment\n\
syntax appropriate for the current language (VAR = EXP or VAR := EXP for\n\
example). VAR may be a debugger \"convenience\" variable (names starting\n\