/* Print values for GNU debugger GDB.
- Copyright (C) 1986-2017 Free Software Foundation, Inc.
+ Copyright (C) 1986-2019 Free Software Foundation, Inc.
This file is part of GDB.
#include "ui-out.h"
#include "block.h"
#include "disasm.h"
-#include "dfp.h"
-#include "observer.h"
+#include "target-float.h"
+#include "observable.h"
#include "solist.h"
#include "parser-defs.h"
#include "charset.h"
#include "arch-utils.h"
#include "cli/cli-utils.h"
#include "cli/cli-script.h"
-#include "format.h"
+#include "cli/cli-style.h"
+#include "common/format.h"
#include "source.h"
#include "common/byte-vector.h"
-#ifdef TUI
-#include "tui/tui.h" /* For tui_active et al. */
-#endif
-
/* Last specified output format. */
static char last_format = 0;
static char last_size = 'w';
+/* Last specified count for the 'x' command. */
+
+static int last_count;
+
/* Default address to examine next, and associated architecture. */
static struct gdbarch *next_gdbarch;
/* Contents of last address examined.
This is not valid past the end of the `x' command! */
-static struct value *last_examine_value;
+static value_ref_ptr last_examine_value;
/* Largest offset between a symbolic value and an address, that will be
printed as `0x1234 <symbol+offset>'. */
break;
}
- while (*p == ' ' || *p == '\t')
- p++;
- *string_ptr = p;
+ *string_ptr = skip_spaces (p);
/* Set defaults for format and size if not specified. */
if (val.format == '?')
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);
}
}
struct ui_file *stream,
int do_demangle, const char *leadin)
{
- char *name = NULL;
- char *filename = NULL;
+ std::string name, filename;
int unmapped = 0;
int offset = 0;
int line = 0;
- /* Throw away both name and filename. */
- struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &name);
- make_cleanup (free_current_contents, &filename);
-
if (build_address_symbolic (gdbarch, addr, do_demangle, &name, &offset,
&filename, &line, &unmapped))
- {
- do_cleanups (cleanup_chain);
- return 0;
- }
+ return 0;
fputs_filtered (leadin, stream);
if (unmapped)
fputs_filtered ("<*", stream);
else
fputs_filtered ("<", stream);
- fputs_filtered (name, stream);
+ fputs_styled (name.c_str (), function_name_style.style (), stream);
if (offset != 0)
fprintf_filtered (stream, "+%u", (unsigned int) offset);
/* Append source filename and line number if desired. Give specific
line # of this addr, if we have it; else line # of the nearest symbol. */
- if (print_symbol_filename && filename != NULL)
+ if (print_symbol_filename && !filename.empty ())
{
+ fputs_filtered (line == -1 ? " in " : " at ", stream);
+ fputs_styled (filename.c_str (), file_name_style.style (), stream);
if (line != -1)
- fprintf_filtered (stream, " at %s:%d", filename, line);
- else
- fprintf_filtered (stream, " in %s", filename);
+ fprintf_filtered (stream, ":%d", line);
}
if (unmapped)
fputs_filtered ("*>", stream);
else
fputs_filtered (">", stream);
- do_cleanups (cleanup_chain);
return 1;
}
-/* Given an address ADDR return all the elements needed to print the
- address in a symbolic form. NAME can be mangled or not depending
- on DO_DEMANGLE (and also on the asm_demangle global variable,
- manipulated via ''set print asm-demangle''). Return 0 in case of
- success, when all the info in the OUT paramters is valid. Return 1
- otherwise. */
+/* See valprint.h. */
+
int
build_address_symbolic (struct gdbarch *gdbarch,
CORE_ADDR addr, /* IN */
int do_demangle, /* IN */
- char **name, /* OUT */
+ std::string *name, /* OUT */
int *offset, /* OUT */
- char **filename, /* OUT */
+ std::string *filename, /* OUT */
int *line, /* OUT */
int *unmapped) /* OUT */
{
pointer is <function+3>. This matches the ISA behavior. */
addr = gdbarch_addr_bits_remove (gdbarch, addr);
- name_location = BLOCK_START (SYMBOL_BLOCK_VALUE (symbol));
+ name_location = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (symbol));
if (do_demangle || asm_demangle)
name_temp = SYMBOL_PRINT_NAME (symbol);
else
*offset = addr - name_location;
- *name = xstrdup (name_temp);
+ *name = name_temp;
if (print_symbol_filename)
{
if (sal.symtab)
{
- *filename = xstrdup (symtab_to_filename_for_display (sal.symtab));
+ *filename = symtab_to_filename_for_display (sal.symtab);
*line = sal.line;
}
}
print_address (struct gdbarch *gdbarch,
CORE_ADDR addr, struct ui_file *stream)
{
- fputs_filtered (paddress (gdbarch, addr), stream);
+ fputs_styled (paddress (gdbarch, addr), address_style.style (), stream);
print_address_symbolic (gdbarch, addr, stream, asm_demangle, " ");
}
{
if (opts->addressprint)
{
- fputs_filtered (paddress (gdbarch, addr), stream);
+ fputs_styled (paddress (gdbarch, addr), address_style.style (), stream);
print_address_symbolic (gdbarch, addr, stream, do_demangle, " ");
}
else
object. */
last_examine_address = next_address;
- if (last_examine_value)
- value_free (last_examine_value);
-
/* The value to be displayed is not fetched greedily.
Instead, to avoid the possibility of a fetched value not
being used, its retrieval is delayed until the print code
the disassembler be modified so that LAST_EXAMINE_VALUE
is left with the byte sequence from the last complete
instruction fetched from memory? */
- last_examine_value = value_at_lazy (val_type, next_address);
-
- if (last_examine_value)
- release_value (last_examine_value);
+ last_examine_value
+ = release_value (value_at_lazy (val_type, next_address));
- print_formatted (last_examine_value, size, &opts, gdb_stdout);
+ print_formatted (last_examine_value.get (), size, &opts, gdb_stdout);
/* Display any branch delay slots following the final insn. */
if (format == 'i' && count == 1)
}
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 (exp, from_tty);
-}
-
-/* Like output_command, but takes a const string as argument. */
-
void
-output_command_const (const char *exp, int from_tty)
+output_command (const char *exp, int from_tty)
{
char format = 0;
struct value *val;
evaluate_expression (expr.get ());
}
-/* Temporary non-const version of set_command. */
-
-static void
-non_const_set_command (char *exp, int from_tty)
-{
- set_command (exp, from_tty);
-}
-
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;
struct obj_section *osect;
CORE_ADDR addr, sect_addr;
int matches = 0;
error_no_arg (_("address"));
addr = parse_and_eval_address (arg);
- ALL_OBJSECTIONS (objfile, osect)
- {
- /* Only process each object file once, even if there's a separate
- debug file. */
- if (objfile->separate_debug_objfile_backlink)
- continue;
-
- sect_addr = overlay_mapped_address (addr, osect);
-
- if (obj_section_addr (osect) <= sect_addr
- && sect_addr < obj_section_endaddr (osect)
- && (msymbol
- = lookup_minimal_symbol_by_pc_section (sect_addr, osect).minsym))
+ for (objfile *objfile : current_program_space->objfiles ())
+ ALL_OBJFILE_OSECTIONS (objfile, osect)
{
- const char *obj_name, *mapped, *sec_name, *msym_name;
- const char *loc_string;
- struct cleanup *old_chain;
-
- matches = 1;
- offset = sect_addr - MSYMBOL_VALUE_ADDRESS (objfile, msymbol);
- mapped = section_is_mapped (osect) ? _("mapped") : _("unmapped");
- sec_name = osect->the_bfd_section->name;
- msym_name = MSYMBOL_PRINT_NAME (msymbol);
-
- /* 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)
+ /* Only process each object file once, even if there's a separate
+ debug file. */
+ if (objfile->separate_debug_objfile_backlink)
+ continue;
+
+ sect_addr = overlay_mapped_address (addr, osect);
+
+ if (obj_section_addr (osect) <= sect_addr
+ && sect_addr < obj_section_endaddr (osect)
+ && (msymbol
+ = lookup_minimal_symbol_by_pc_section (sect_addr,
+ osect).minsym))
{
- string_holder = string_printf ("%s + %u", msym_name, offset);
- loc_string = string_holder.c_str ();
- }
- else
- loc_string = msym_name;
-
- gdb_assert (osect->objfile && objfile_name (osect->objfile));
- obj_name = objfile_name (osect->objfile);
-
- if (MULTI_OBJFILE_P ())
- if (pc_in_unmapped_range (addr, osect))
- if (section_is_overlay (osect))
- printf_filtered (_("%s in load address range of "
- "%s overlay section %s of %s\n"),
- loc_string, mapped, sec_name, obj_name);
- else
- printf_filtered (_("%s in load address range of "
- "section %s of %s\n"),
- loc_string, sec_name, obj_name);
- else
- if (section_is_overlay (osect))
- printf_filtered (_("%s in %s overlay section %s of %s\n"),
- loc_string, mapped, sec_name, obj_name);
- else
- printf_filtered (_("%s in section %s of %s\n"),
- loc_string, sec_name, obj_name);
- else
- if (pc_in_unmapped_range (addr, osect))
- if (section_is_overlay (osect))
- printf_filtered (_("%s in load address range of %s overlay "
- "section %s\n"),
- loc_string, mapped, sec_name);
+ const char *obj_name, *mapped, *sec_name, *msym_name;
+ const char *loc_string;
+
+ matches = 1;
+ offset = sect_addr - MSYMBOL_VALUE_ADDRESS (objfile, msymbol);
+ mapped = section_is_mapped (osect) ? _("mapped") : _("unmapped");
+ sec_name = osect->the_bfd_section->name;
+ msym_name = MSYMBOL_PRINT_NAME (msymbol);
+
+ /* 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)
+ {
+ string_holder = string_printf ("%s + %u", msym_name, offset);
+ loc_string = string_holder.c_str ();
+ }
else
- printf_filtered (_("%s in load address range of section %s\n"),
- loc_string, sec_name);
- else
- if (section_is_overlay (osect))
- printf_filtered (_("%s in %s overlay section %s\n"),
- loc_string, mapped, sec_name);
+ loc_string = msym_name;
+
+ gdb_assert (osect->objfile && objfile_name (osect->objfile));
+ obj_name = objfile_name (osect->objfile);
+
+ if (MULTI_OBJFILE_P ())
+ if (pc_in_unmapped_range (addr, osect))
+ if (section_is_overlay (osect))
+ printf_filtered (_("%s in load address range of "
+ "%s overlay section %s of %s\n"),
+ loc_string, mapped, sec_name, obj_name);
+ else
+ printf_filtered (_("%s in load address range of "
+ "section %s of %s\n"),
+ loc_string, sec_name, obj_name);
+ else
+ if (section_is_overlay (osect))
+ printf_filtered (_("%s in %s overlay section %s of %s\n"),
+ loc_string, mapped, sec_name, obj_name);
+ else
+ printf_filtered (_("%s in section %s of %s\n"),
+ loc_string, sec_name, obj_name);
else
- printf_filtered (_("%s in section %s\n"),
- loc_string, sec_name);
+ if (pc_in_unmapped_range (addr, osect))
+ if (section_is_overlay (osect))
+ printf_filtered (_("%s in load address range of %s overlay "
+ "section %s\n"),
+ loc_string, mapped, sec_name);
+ else
+ printf_filtered
+ (_("%s in load address range of section %s\n"),
+ loc_string, sec_name);
+ else
+ if (section_is_overlay (osect))
+ printf_filtered (_("%s in %s overlay section %s\n"),
+ loc_string, mapped, sec_name);
+ else
+ printf_filtered (_("%s in section %s\n"),
+ loc_string, sec_name);
+ }
}
- }
if (matches == 0)
printf_filtered (_("No symbol matches %s.\n"), arg);
}
static void
-info_address_command (char *exp, int from_tty)
+info_address_command (const char *exp, int from_tty)
{
struct gdbarch *gdbarch;
int regno;
fprintf_symbol_filtered (gdb_stdout, exp,
current_language->la_language, DMGL_ANSI);
printf_filtered ("\" is at ");
- fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
+ fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
+ gdb_stdout);
printf_filtered (" in a file compiled without debugging");
section = MSYMBOL_OBJ_SECTION (objfile, msymbol.minsym);
if (section_is_overlay (section))
{
load_addr = overlay_unmapped_address (load_addr, section);
printf_filtered (",\n -- loaded at ");
- fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
+ fputs_styled (paddress (gdbarch, load_addr),
+ address_style.style (),
+ gdb_stdout);
printf_filtered (" in overlay section %s",
section->the_bfd_section->name);
}
case LOC_LABEL:
printf_filtered ("a label at address ");
load_addr = SYMBOL_VALUE_ADDRESS (sym);
- fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
+ fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
+ gdb_stdout);
if (section_is_overlay (section))
{
load_addr = overlay_unmapped_address (load_addr, section);
printf_filtered (",\n -- loaded at ");
- fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
+ fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
+ gdb_stdout);
printf_filtered (" in overlay section %s",
section->the_bfd_section->name);
}
case LOC_STATIC:
printf_filtered (_("static storage at address "));
load_addr = SYMBOL_VALUE_ADDRESS (sym);
- fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
+ fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
+ gdb_stdout);
if (section_is_overlay (section))
{
load_addr = overlay_unmapped_address (load_addr, section);
printf_filtered (_(",\n -- loaded at "));
- fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
+ fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
+ gdb_stdout);
printf_filtered (_(" in overlay section %s"),
section->the_bfd_section->name);
}
case LOC_BLOCK:
printf_filtered (_("a function at address "));
- load_addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
- fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
+ load_addr = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym));
+ fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
+ gdb_stdout);
if (section_is_overlay (section))
{
load_addr = overlay_unmapped_address (load_addr, section);
printf_filtered (_(",\n -- loaded at "));
- fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
+ fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
+ gdb_stdout);
printf_filtered (_(" in overlay section %s"),
section->the_bfd_section->name);
}
{
struct bound_minimal_symbol msym;
- msym = lookup_minimal_symbol_and_objfile (SYMBOL_LINKAGE_NAME (sym));
+ msym = lookup_bound_minimal_symbol (SYMBOL_LINKAGE_NAME (sym));
if (msym.minsym == NULL)
printf_filtered ("unresolved");
else
{
load_addr = BMSYMBOL_VALUE_ADDRESS (msym);
printf_filtered (_("static storage at address "));
- fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
+ fputs_styled (paddress (gdbarch, load_addr),
+ address_style.style (), gdb_stdout);
if (section_is_overlay (section))
{
load_addr = overlay_unmapped_address (load_addr, section);
printf_filtered (_(",\n -- loaded at "));
- fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
+ fputs_styled (paddress (gdbarch, load_addr),
+ address_style.style (),
+ gdb_stdout);
printf_filtered (_(" in overlay section %s"),
section->the_bfd_section->name);
}
\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;
fmt.count = 1;
fmt.raw = 0;
+ /* If there is no expression and no format, use the most recent
+ count. */
+ if (exp == nullptr && last_count > 0)
+ fmt.count = last_count;
+
if (exp && *exp == '/')
{
const char *tmp = exp + 1;
exp = (char *) tmp;
}
+ last_count = fmt.count;
+
/* If we have an expression, evaluate it and use it as the address. */
if (exp != 0 && *exp != 0)
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);
last_format = fmt.format;
/* Set a couple of internal variables if appropriate. */
- if (last_examine_value)
+ if (last_examine_value != nullptr)
{
/* Make last address examined available to the user as $_. Use
the correct pointer type. */
struct type *pointer_type
- = lookup_pointer_type (value_type (last_examine_value));
+ = lookup_pointer_type (value_type (last_examine_value.get ()));
set_internalvar (lookup_internalvar ("_"),
value_from_pointer (pointer_type,
last_examine_address));
as $__. If the last value has not been fetched from memory
then don't fetch it now; instead mark it by voiding the $__
variable. */
- if (value_lazy (last_examine_value))
+ if (value_lazy (last_examine_value.get ()))
clear_internalvar (lookup_internalvar ("__"));
else
- set_internalvar (lookup_internalvar ("__"), last_examine_value);
+ set_internalvar (lookup_internalvar ("__"), last_examine_value.get ());
}
}
\f
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;
fmt.raw = 0;
}
- innermost_block = NULL;
+ innermost_block.reset ();
expression_up expr = parse_expression (exp);
newobj = new display ();
newobj->exp_string = xstrdup (exp);
newobj->exp = std::move (expr);
- newobj->block = innermost_block;
+ newobj->block = innermost_block.block ();
newobj->pspace = current_program_space;
newobj->number = ++display_number;
newobj->format = fmt;
TRY
{
- innermost_block = NULL;
+ innermost_block.reset ();
d->exp = parse_expression (d->exp_string);
- d->block = innermost_block;
+ d->block = innermost_block.block ();
}
CATCH (ex, RETURN_MASK_ALL)
{
}
static void
-info_display_command (char *ignore, int from_tty)
+info_display_command (const char *ignore, int from_tty)
{
struct display *d;
if (!name)
name = SYMBOL_PRINT_NAME (var);
- fprintf_filtered (stream, "%s%s = ", n_spaces (2 * indent), name);
+ fputs_filtered (n_spaces (2 * indent), stream);
+ fputs_styled (name, variable_name_style.style (), stream);
+ fputs_filtered (" = ", stream);
+
TRY
{
struct value *val;
int j;
tem = value_as_address (value);
+ if (tem == 0)
+ {
+ DIAGNOSTIC_PUSH
+ DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
+ fprintf_filtered (stream, format, "(null)");
+ DIAGNOSTIC_POP
+ return;
+ }
/* This is a %s argument. Find the length of the string. */
for (j = 0;; j++)
read_memory (tem, str, j);
str[j] = 0;
+ DIAGNOSTIC_PUSH
+ DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
fprintf_filtered (stream, format, (char *) str);
+ DIAGNOSTIC_POP
}
/* Subroutine of ui_printf to simplify it.
gdb_byte *buf = (gdb_byte *) alloca (wcwidth);
tem = value_as_address (value);
+ if (tem == 0)
+ {
+ DIAGNOSTIC_PUSH
+ DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
+ fprintf_filtered (stream, format, "(null)");
+ DIAGNOSTIC_POP
+ return;
+ }
/* This is a %s argument. Find the length of the string. */
for (j = 0;; j += wcwidth)
&output, translit_char);
obstack_grow_str0 (&output, "");
+ DIAGNOSTIC_PUSH
+ DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
fprintf_filtered (stream, format, obstack_base (&output));
+ DIAGNOSTIC_POP
}
/* 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;
+ /* Determine target type corresponding to the format string. */
+ struct type *fmt_type;
+ switch (argclass)
+ {
+ 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");
+ }
- /* Points to the end of the string so that we can go back
- and check for DFP length modifiers. */
- p = format + strlen (format);
+ /* To match the traditional GDB behavior, the conversion is
+ done differently depending on the type of the parameter:
- /* Look for the float/double format specifier. */
- while (*p != 'f' && *p != 'e' && *p != 'E'
- && *p != 'g' && *p != 'G')
- p--;
+ - if the parameter has floating-point type, it's value
+ is converted to the target type;
- /* Search for the '%' char and extract the size and type of
- the output decimal value based on its modifiers
- (%Hf, %Df, %DDf). */
- while (*--p != '%')
- {
- 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;
- }
- }
+ - 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);
- /* 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");
+ - otherwise, if the source value has an integer value,
+ it's value is converted to the target type;
- dfp_value = value_from_decfloat (dfp_type, dec);
+ - otherwise, an error is raised.
- dfp_ptr = (gdb_byte *) value_contents (dfp_value);
+ 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 = decimal_to_string (dfp_ptr, dfp_len, byte_order);
+ std::string str
+ = target_float_to_string (value_contents (value), fmt_type, format);
fputs_filtered (str.c_str (), stream);
-#endif
}
/* Subroutine of ui_printf to simplify it.
if (val != 0)
*fmt_p++ = '#';
- /* Copy any width. */
- while (*p >= '0' && *p < '9')
+ /* Copy any width or flags. Only the "-" flag is valid for pointers
+ -- see the format_pieces constructor. */
+ while (*p == '-' || (*p >= '0' && *p < '9'))
*fmt_p++ = *p++;
gdb_assert (*p == 'p' && *(p + 1) == '\0');
*fmt_p++ = 'l';
*fmt_p++ = 'x';
*fmt_p++ = '\0';
+ DIAGNOSTIC_PUSH
+ DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
fprintf_filtered (stream, fmt, val);
+ DIAGNOSTIC_POP
}
else
{
*fmt_p++ = 's';
*fmt_p++ = '\0';
+ DIAGNOSTIC_PUSH
+ DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
fprintf_filtered (stream, fmt, "(nil)");
+ DIAGNOSTIC_POP
}
}
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]);
&output, translit_char);
obstack_grow_str0 (&output, "");
+ DIAGNOSTIC_PUSH
+ DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
fprintf_filtered (stream, current_substring,
obstack_base (&output));
+ DIAGNOSTIC_POP
}
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
{
long long val = value_as_long (val_args[i]);
+ DIAGNOSTIC_PUSH
+ DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
fprintf_filtered (stream, current_substring, val);
+ DIAGNOSTIC_POP
break;
}
#else
{
int val = value_as_long (val_args[i]);
+ DIAGNOSTIC_PUSH
+ DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
fprintf_filtered (stream, current_substring, val);
+ DIAGNOSTIC_POP
break;
}
case long_arg:
{
long val = value_as_long (val_args[i]);
+ DIAGNOSTIC_PUSH
+ DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
fprintf_filtered (stream, current_substring, val);
+ DIAGNOSTIC_POP
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]);
have modified GCC to include -Wformat-security by
default, which will warn here if there is no
argument. */
+ DIAGNOSTIC_PUSH
+ DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
fprintf_filtered (stream, current_substring, 0);
+ DIAGNOSTIC_POP
break;
default:
internal_error (__FILE__, __LINE__,
_("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);
+ reset_terminal_style (gdb_stdout);
+ wrap_here ("");
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
current_display_number = -1;
- observer_attach_free_objfile (clear_dangling_display_expressions);
+ gdb::observers::free_objfile.attach (clear_dangling_display_expressions);
add_info ("address", info_address_command,
_("Describe where symbol SYM is stored."));
Do \"info display\" to see current list of code numbers."), &deletelist);
add_com ("printf", class_vars, printf_command, _("\
-printf \"printf format string\", arg1, arg2, arg3, ..., argn\n\
-This is useful for formatted output in user-defined commands."));
+Formatted printing, like the C \"printf\" function.\n\
+Usage: printf \"format string\", arg1, arg2, arg3, ..., argn\n\
+This supports most C printf format specifications, like %s, %d, etc."));
add_com ("output", class_vars, output_command, _("\
Like \"print\" but don't put in value history and don't print newline.\n\
You can see these environment settings with the \"show\" command."),
&setlist, "set ", 1, &cmdlist);
if (dbx_commands)
- add_com ("assign", class_vars, non_const_set_command, _("\
+ add_com ("assign", class_vars, 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\
variable in the program being debugged. EXP is any valid expression.\n\
This may usually be abbreviated to simply \"set\"."),
&setlist);
+ add_alias_cmd ("var", "variable", class_vars, 0, &setlist);
c = add_com ("print", class_vars, print_command, _("\
Print value of expression EXP.\n\