/* Print values for GNU debugger GDB.
- Copyright (C) 1986-2019 Free Software Foundation, Inc.
+ Copyright (C) 1986-2021 Free Software Foundation, Inc.
This file is part of GDB.
#include "source.h"
#include "gdbsupport/byte-vector.h"
#include "gdbsupport/gdb_optional.h"
+#include "safe-ctype.h"
/* Last specified output format. */
static int current_display_number;
+/* Last allocated display number. */
+
+static int display_number;
+
struct display
{
- /* Chain link to next auto-display item. */
- struct display *next;
+ display (const char *exp_string_, expression_up &&exp_,
+ const struct format_data &format_, struct program_space *pspace_,
+ const struct block *block_)
+ : exp_string (exp_string_),
+ exp (std::move (exp_)),
+ number (++display_number),
+ format (format_),
+ pspace (pspace_),
+ block (block_),
+ enabled_p (true)
+ {
+ }
/* The expression as the user typed it. */
- char *exp_string;
+ std::string exp_string;
/* Expression to be evaluated and displayed. */
expression_up exp;
const struct block *block;
/* Status of this display (enabled or disabled). */
- int enabled_p;
+ bool enabled_p;
};
-/* Chain of expressions whose values should be displayed
- automatically each time the program stops. */
-
-static struct display *display_chain;
-
-static int display_number;
-
-/* Walk the following statement or block through all displays.
- ALL_DISPLAYS_SAFE does so even if the statement deletes the current
- display. */
-
-#define ALL_DISPLAYS(B) \
- for (B = display_chain; B; B = B->next)
+/* Expressions whose values should be displayed automatically each
+ time the program stops. */
-#define ALL_DISPLAYS_SAFE(B,TMP) \
- for (B = display_chain; \
- B ? (TMP = B->next, 1): 0; \
- B = TMP)
+static std::vector<std::unique_ptr<struct display>> all_displays;
/* Prototypes for local functions. */
/* We often wrap here if there are long symbolic names. */
wrap_here (" ");
next_address = (value_address (val)
- + gdb_print_insn (get_type_arch (type),
+ + gdb_print_insn (type->arch (),
value_address (val), stream,
&branch_delay_insns));
return;
}
if (options->format == 0 || options->format == 's'
- || TYPE_CODE (type) == TYPE_CODE_REF
- || TYPE_CODE (type) == TYPE_CODE_ARRAY
- || TYPE_CODE (type) == TYPE_CODE_STRING
- || TYPE_CODE (type) == TYPE_CODE_STRUCT
- || TYPE_CODE (type) == TYPE_CODE_UNION
- || TYPE_CODE (type) == TYPE_CODE_NAMESPACE)
+ || type->code () == TYPE_CODE_VOID
+ || type->code () == TYPE_CODE_REF
+ || type->code () == TYPE_CODE_ARRAY
+ || type->code () == TYPE_CODE_STRING
+ || type->code () == TYPE_CODE_STRUCT
+ || type->code () == TYPE_CODE_UNION
+ || type->code () == TYPE_CODE_NAMESPACE)
value_print (val, stream, options);
else
/* User specified format, so don't look to the type to tell us
what to do. */
- val_print_scalar_formatted (type,
- value_embedded_offset (val),
- val,
- options, size, stream);
+ value_print_scalar_formatted (val, options, size, stream);
}
/* Return builtin floating point type of same length as TYPE.
static struct type *
float_type_from_length (struct type *type)
{
- struct gdbarch *gdbarch = get_type_arch (type);
+ struct gdbarch *gdbarch = type->arch ();
const struct builtin_type *builtin = builtin_type (gdbarch);
if (TYPE_LENGTH (type) == TYPE_LENGTH (builtin->builtin_float))
const struct value_print_options *options,
int size, struct ui_file *stream)
{
- struct gdbarch *gdbarch = get_type_arch (type);
+ struct gdbarch *gdbarch = type->arch ();
unsigned int len = TYPE_LENGTH (type);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ enum bfd_endian byte_order = type_byte_order (type);
/* String printing should go through val_print_scalar_formatted. */
gdb_assert (options->format != 's');
/* If the value is a pointer, and pointers and addresses are not the
same, then at this point, the value's length (in target bytes) is
gdbarch_addr_bit/TARGET_CHAR_BIT, not TYPE_LENGTH (type). */
- if (TYPE_CODE (type) == TYPE_CODE_PTR)
+ if (type->code () == TYPE_CODE_PTR)
len = gdbarch_addr_bit (gdbarch) / TARGET_CHAR_BIT;
/* If we are printing it as unsigned, truncate it in case it is actually
a negative signed value (e.g. "print/u (short)-1" should print 65535
(if shorts are 16 bits) instead of 4294967295). */
if (options->format != 'c'
- && (options->format != 'd' || TYPE_UNSIGNED (type)))
+ && (options->format != 'd' || type->is_unsigned ()))
{
if (len < TYPE_LENGTH (type) && byte_order == BFD_ENDIAN_BIG)
valaddr += TYPE_LENGTH (type) - len;
}
+ /* Allow LEN == 0, and in this case, don't assume that VALADDR is
+ valid. */
+ const gdb_byte zero = 0;
+ if (len == 0)
+ {
+ len = 1;
+ valaddr = &zero;
+ }
+
if (size != 0 && (options->format == 'x' || options->format == 't'))
{
/* Truncate to fit. */
long, and then printing the long. PR cli/16242 suggests changing
this to using C-style hex float format.
- Biased range types must also be unbiased here; the unbiasing is
- done by unpack_long. */
+ Biased range types and sub-word scalar types must also be handled
+ here; the value is correctly computed by unpack_long. */
gdb::byte_vector converted_bytes;
/* Some cases below will unpack the value again. In the biased
range case, we want to avoid this, so we store the unpacked value
here for possible use later. */
gdb::optional<LONGEST> val_long;
- if ((TYPE_CODE (type) == TYPE_CODE_FLT
+ if (((type->code () == TYPE_CODE_FLT
+ || is_fixed_point_type (type))
&& (options->format == 'o'
|| options->format == 'x'
|| options->format == 't'
|| options->format == 'z'
|| options->format == 'd'
|| options->format == 'u'))
- || (TYPE_CODE (type) == TYPE_CODE_RANGE
- && TYPE_RANGE_DATA (type)->bias != 0))
+ || (type->code () == TYPE_CODE_RANGE && type->bounds ()->bias != 0)
+ || type->bit_size_differs_p ())
{
val_long.emplace (unpack_long (type, valaddr));
converted_bytes.resize (TYPE_LENGTH (type));
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)
+ if (format == 'f' && type->code () != TYPE_CODE_FLT)
{
type = float_type_from_length (type);
- if (TYPE_CODE (type) != TYPE_CODE_FLT)
- format = 0;
+ if (type->code () != TYPE_CODE_FLT)
+ format = 0;
}
switch (format)
print_decimal_chars (stream, valaddr, len, false, byte_order);
break;
case 0:
- if (TYPE_CODE (type) != TYPE_CODE_FLT)
+ if (type->code () != TYPE_CODE_FLT)
{
- print_decimal_chars (stream, valaddr, len, !TYPE_UNSIGNED (type),
+ print_decimal_chars (stream, valaddr, len, !type->is_unsigned (),
byte_order);
break;
}
val_long.emplace (unpack_long (type, valaddr));
opts.format = 0;
- if (TYPE_UNSIGNED (type))
+ if (type->is_unsigned ())
type = builtin_type (gdbarch)->builtin_true_unsigned_char;
else
type = builtin_type (gdbarch)->builtin_true_char;
int line = 0;
if (build_address_symbolic (gdbarch, addr, do_demangle, false, &name,
- &offset, &filename, &line, &unmapped))
+ &offset, &filename, &line, &unmapped))
return 0;
fputs_filtered (leadin, stream);
name_location = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (symbol));
if (do_demangle || asm_demangle)
- name_temp = SYMBOL_PRINT_NAME (symbol);
+ name_temp = symbol->print_name ();
else
- name_temp = SYMBOL_LINKAGE_NAME (symbol);
+ name_temp = symbol->linkage_name ();
}
if (msymbol.minsym != NULL
3) The symbol address is not identical to that of the address
under consideration. */
if (symbol == NULL ||
- (!prefer_sym_over_minsym
+ (!prefer_sym_over_minsym
&& BMSYMBOL_VALUE_ADDRESS (msymbol) == addr
&& name_location != addr))
{
symbol = 0;
name_location = BMSYMBOL_VALUE_ADDRESS (msymbol);
if (do_demangle || asm_demangle)
- name_temp = MSYMBOL_PRINT_NAME (msymbol.minsym);
+ name_temp = msymbol.minsym->print_name ();
else
- name_temp = MSYMBOL_LINKAGE_NAME (msymbol.minsym);
+ name_temp = msymbol.minsym->linkage_name ();
}
}
if (symbol == NULL && msymbol.minsym == NULL)
static CORE_ADDR
find_instruction_backward (struct gdbarch *gdbarch, CORE_ADDR addr,
- int inst_count, int *inst_read)
+ int inst_count, int *inst_read)
{
/* The vector PCS is used to store instruction addresses within
a pc range. */
pcs.clear ();
sal = find_pc_sect_line (loop_start, NULL, 1);
if (sal.line <= 0)
- {
- /* We reach here when line info is not available. In this case,
- we print a message and just exit the loop. The return value
- is calculated after the loop. */
- printf_filtered (_("No line number information available "
- "for address "));
- wrap_here (" ");
- print_address (gdbarch, loop_start - 1, gdb_stdout);
- printf_filtered ("\n");
- break;
- }
+ {
+ /* We reach here when line info is not available. In this case,
+ we print a message and just exit the loop. The return value
+ is calculated after the loop. */
+ printf_filtered (_("No line number information available "
+ "for address "));
+ wrap_here (" ");
+ print_address (gdbarch, loop_start - 1, gdb_stdout);
+ printf_filtered ("\n");
+ break;
+ }
loop_end = loop_start;
loop_start = sal.pc;
/* This loop pushes instruction addresses in the range from
- LOOP_START to LOOP_END. */
+ LOOP_START to LOOP_END. */
for (p = loop_start; p < loop_end;)
- {
+ {
pcs.push_back (p);
- p += gdb_insn_length (gdbarch, p);
- }
+ p += gdb_insn_length (gdbarch, p);
+ }
inst_count -= pcs.size ();
*inst_read += pcs.size ();
the reason below.
Let's assume the following instruction addresses and run 'x/-4i 0x400e'.
Line X of File
- 0x4000
- 0x4001
- 0x4005
+ 0x4000
+ 0x4001
+ 0x4005
Line Y of File
- 0x4009
- 0x400c
+ 0x4009
+ 0x400c
=> 0x400e
- 0x4011
+ 0x4011
find_instruction_backward is called with INST_COUNT = 4 and expected to
return 0x4001. When we reach here, INST_COUNT is set to -1 because
it was subtracted by 2 (from Line Y) and 3 (from Line X). The value
static int
read_memory_backward (struct gdbarch *gdbarch,
- CORE_ADDR memaddr, gdb_byte *myaddr, int len)
+ CORE_ADDR memaddr, gdb_byte *myaddr, int len)
{
int errcode;
int nread; /* Number of bytes actually read. */
memaddr += len;
myaddr += len;
for (nread = 0; nread < len; ++nread)
- {
- errcode = target_read_memory (--memaddr, --myaddr, 1);
- if (errcode != 0)
- {
- /* The read was unsuccessful, so exit the loop. */
- printf_filtered (_("Cannot access memory at address %s\n"),
- paddress (gdbarch, memaddr));
- break;
- }
- }
+ {
+ errcode = target_read_memory (--memaddr, --myaddr, 1);
+ if (errcode != 0)
+ {
+ /* The read was unsuccessful, so exit the loop. */
+ printf_filtered (_("Cannot access memory at address %s\n"),
+ paddress (gdbarch, memaddr));
+ break;
+ }
+ }
}
return nread;
}
static CORE_ADDR
find_string_backward (struct gdbarch *gdbarch,
- CORE_ADDR addr, int count, int char_size,
- const struct value_print_options *options,
- int *strings_counted)
+ CORE_ADDR addr, int count, int char_size,
+ const struct value_print_options *options,
+ int *strings_counted)
{
const int chunk_size = 0x20;
int read_error = 0;
addr -= chars_to_read * char_size;
chars_read = read_memory_backward (gdbarch, addr, buffer.data (),
- chars_to_read * char_size);
+ chars_to_read * char_size);
chars_read /= char_size;
read_error = (chars_read == chars_to_read) ? 0 : 1;
/* Searching for '\0' from the end of buffer in backward direction. */
for (i = 0; i < chars_read && count > 0 ; ++i, ++chars_counted)
- {
- int offset = (chars_to_read - i - 1) * char_size;
-
- if (integer_is_zero (&buffer[offset], char_size)
- || chars_counted == options->print_max)
- {
- /* Found '\0' or reached print_max. As OFFSET is the offset to
- '\0', we add CHAR_SIZE to return the start address of
- a string. */
- --count;
- string_start_addr = addr + offset + char_size;
- chars_counted = 0;
- }
- }
+ {
+ int offset = (chars_to_read - i - 1) * char_size;
+
+ if (integer_is_zero (&buffer[offset], char_size)
+ || chars_counted == options->print_max)
+ {
+ /* Found '\0' or reached print_max. As OFFSET is the offset to
+ '\0', we add CHAR_SIZE to return the start address of
+ a string. */
+ --count;
+ string_start_addr = addr + offset + char_size;
+ chars_counted = 0;
+ }
+ }
}
/* Update STRINGS_COUNTED with the actual number of loaded strings. */
if (read_error != 0)
{
/* In error case, STRING_START_ADDR is pointing to the string that
- was last successfully loaded. Rewind the partially loaded string. */
+ was last successfully loaded. Rewind the partially loaded string. */
string_start_addr -= chars_counted * char_size;
}
else if (size == 'w')
char_type = builtin_type (next_gdbarch)->builtin_char32;
if (char_type)
- val_type = char_type;
+ val_type = char_type;
else
- {
+ {
if (size != '\0' && size != 'b')
warning (_("Unable to display strings with "
"size '%c', using 'b' instead."), size);
size = 'b';
val_type = builtin_type (next_gdbarch)->builtin_int8;
- }
+ }
}
maxelts = 8;
if (count < 0)
{
/* This is the negative repeat count case.
- We rewind the address based on the given repeat count and format,
- then examine memory from there in forward direction. */
+ We rewind the address based on the given repeat count and format,
+ then examine memory from there in forward direction. */
count = -count;
if (format == 'i')
- {
- next_address = find_instruction_backward (gdbarch, addr, count,
- &count);
- }
+ {
+ next_address = find_instruction_backward (gdbarch, addr, count,
+ &count);
+ }
else if (format == 's')
- {
- next_address = find_string_backward (gdbarch, addr, count,
- TYPE_LENGTH (val_type),
- &opts, &count);
- }
+ {
+ next_address = find_string_backward (gdbarch, addr, count,
+ TYPE_LENGTH (val_type),
+ &opts, &count);
+ }
else
- {
- next_address = addr - count * TYPE_LENGTH (val_type);
- }
+ {
+ next_address = addr - count * TYPE_LENGTH (val_type);
+ }
/* The following call to print_formatted updates next_address in every
- iteration. In backward case, we store the start address here
- and update next_address with it before exiting the function. */
+ iteration. In backward case, we store the start address here
+ and update next_address with it before exiting the function. */
addr_rewound = (format == 's'
- ? next_address - TYPE_LENGTH (val_type)
- : next_address);
+ ? next_address - TYPE_LENGTH (val_type)
+ : next_address);
need_to_update_next_address = 1;
}
{
const char *exp = *expp;
+ /* opts->raw value might already have been set by 'set print raw-values'
+ or by using 'print -raw-values'.
+ So, do not set opts->raw to 0, only set it to 1 if /r is given. */
if (exp && *exp == '/')
{
format_data fmt;
last_format = fmt.format;
opts->format = fmt.format;
- opts->raw = fmt.raw;
+ opts->raw = opts->raw || fmt.raw;
}
else
{
opts->format = 0;
- opts->raw = 0;
}
*expp = exp;
/* Implementation of the "print" and "call" commands. */
static void
-print_command_1 (const char *args, int voidprint)
+print_command_1 (const char *args, bool voidprint)
{
struct value *val;
value_print_options print_opts;
if (exp != nullptr && *exp)
{
- expression_up expr = parse_expression (exp);
+ /* VOIDPRINT is true to indicate that we do want to print a void
+ value, so invert it for parse_expression. */
+ expression_up expr = parse_expression (exp, nullptr, !voidprint);
val = evaluate_expression (expr.get ());
}
else
val = access_value_history (0);
if (voidprint || (val && value_type (val) &&
- TYPE_CODE (value_type (val)) != TYPE_CODE_VOID))
+ value_type (val)->code () != TYPE_CODE_VOID))
print_value (val, print_opts);
}
+/* Called from command completion function to skip over /FMT
+ specifications, allowing the rest of the line to be completed. Returns
+ true if the /FMT is at the end of the current line and there is nothing
+ left to complete, otherwise false is returned.
+
+ In either case *ARGS can be updated to point after any part of /FMT that
+ is present.
+
+ This function is designed so that trying to complete '/' will offer no
+ completions, the user needs to insert the format specification
+ themselves. Trying to complete '/FMT' (where FMT is any non-empty set
+ of alpha-numeric characters) will cause readline to insert a single
+ space, setting the user up to enter the expression. */
+
+static bool
+skip_over_slash_fmt (completion_tracker &tracker, const char **args)
+{
+ const char *text = *args;
+
+ if (text[0] == '/')
+ {
+ bool in_fmt;
+ tracker.set_use_custom_word_point (true);
+
+ if (text[1] == '\0')
+ {
+ /* The user tried to complete after typing just the '/' character
+ of the /FMT string. Step the completer past the '/', but we
+ don't offer any completions. */
+ in_fmt = true;
+ ++text;
+ }
+ else
+ {
+ /* The user has typed some characters after the '/', we assume
+ this is a complete /FMT string, first skip over it. */
+ text = skip_to_space (text);
+
+ if (*text == '\0')
+ {
+ /* We're at the end of the input string. The user has typed
+ '/FMT' and asked for a completion. Push an empty
+ completion string, this will cause readline to insert a
+ space so the user now has '/FMT '. */
+ in_fmt = true;
+ tracker.add_completion (make_unique_xstrdup (text));
+ }
+ else
+ {
+ /* The user has already typed things after the /FMT, skip the
+ whitespace and return false. Whoever called this function
+ should then try to complete what comes next. */
+ in_fmt = false;
+ text = skip_spaces (text);
+ }
+ }
+
+ tracker.advance_custom_word_point_by (text - *args);
+ *args = text;
+ return in_fmt;
+ }
+
+ return false;
+}
+
/* See valprint.h. */
void
(tracker, &text, gdb::option::PROCESS_OPTIONS_REQUIRE_DELIMITER, group))
return;
+ if (skip_over_slash_fmt (tracker, &text))
+ return;
+
const char *word = advance_to_expression_complete_word_point (tracker, text);
expression_completer (ignore, tracker, text, word);
}
static void
print_command (const char *exp, int from_tty)
{
- print_command_1 (exp, 1);
+ print_command_1 (exp, true);
}
/* Same as print, except it doesn't print void results. */
static void
call_command (const char *exp, int from_tty)
{
- print_command_1 (exp, 0);
+ print_command_1 (exp, false);
}
/* Implementation of the "output" command. */
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);
+ msym_name = msymbol->print_name ();
/* Don't print the offset if it is zero.
We assume there's no need to handle i18n of "sym + offset". */
gdb_assert (osect->objfile && objfile_name (osect->objfile));
obj_name = objfile_name (osect->objfile);
- if (MULTI_OBJFILE_P ())
+ if (current_program_space->multi_objfile_p ())
if (pc_in_unmapped_range (addr, osect))
if (section_is_overlay (osect))
printf_filtered (_("%s in load address range of "
{
struct objfile *objfile = msymbol.objfile;
- gdbarch = get_objfile_arch (objfile);
+ gdbarch = objfile->arch ();
load_addr = BMSYMBOL_VALUE_ADDRESS (msymbol);
printf_filtered ("Symbol \"");
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);
+ section = msymbol.minsym->obj_section (objfile);
if (section_is_overlay (section))
{
load_addr = overlay_unmapped_address (load_addr, section);
}
printf_filtered ("Symbol \"");
- fprintf_symbol_filtered (gdb_stdout, SYMBOL_PRINT_NAME (sym),
+ fprintf_symbol_filtered (gdb_stdout, sym->print_name (),
current_language->la_language, DMGL_ANSI);
printf_filtered ("\" is ");
val = SYMBOL_VALUE (sym);
if (SYMBOL_OBJFILE_OWNED (sym))
- section = SYMBOL_OBJ_SECTION (symbol_objfile (sym), sym);
+ section = sym->obj_section (symbol_objfile (sym));
else
section = NULL;
gdbarch = symbol_arch (sym);
{
struct bound_minimal_symbol msym;
- msym = lookup_bound_minimal_symbol (SYMBOL_LINKAGE_NAME (sym));
+ msym = lookup_bound_minimal_symbol (sym->linkage_name ());
if (msym.minsym == NULL)
printf_filtered ("unresolved");
else
{
- section = MSYMBOL_OBJ_SECTION (msym.objfile, msym.minsym);
+ section = msym.obj_section ();
if (section
&& (section->the_bfd_section->flags & SEC_THREAD_LOCAL) != 0)
{
expression_up expr = parse_expression (exp);
/* Cause expression not to be there any more if this command is
- repeated with Newline. But don't clobber a user-defined
- command's definition. */
+ repeated with Newline. But don't clobber a user-defined
+ command's definition. */
if (from_tty)
set_repeat_arguments ("");
val = evaluate_expression (expr.get ());
if (TYPE_IS_REFERENCE (value_type (val)))
val = coerce_ref (val);
/* In rvalue contexts, such as this, functions are coerced into
- pointers to functions. This makes "x/i main" work. */
- if (/* last_format == 'i' && */
- TYPE_CODE (value_type (val)) == TYPE_CODE_FUNC
+ pointers to functions. This makes "x/i main" work. */
+ if (value_type (val)->code () == TYPE_CODE_FUNC
&& VALUE_LVAL (val) == lval_memory)
next_address = value_address (val);
else
if (last_examine_value != nullptr)
{
/* Make last address examined available to the user as $_. Use
- the correct pointer type. */
+ the correct pointer type. */
struct type *pointer_type
= lookup_pointer_type (value_type (last_examine_value.get ()));
set_internalvar (lookup_internalvar ("_"),
set_internalvar (lookup_internalvar ("__"), last_examine_value.get ());
}
}
+
+/* Command completion for the 'display' and 'x' commands. */
+
+static void
+display_and_x_command_completer (struct cmd_list_element *ignore,
+ completion_tracker &tracker,
+ const char *text, const char * /*word*/)
+{
+ if (skip_over_slash_fmt (tracker, &text))
+ return;
+
+ const char *word = advance_to_expression_complete_word_point (tracker, text);
+ expression_completer (ignore, tracker, text, word);
+}
+
\f
/* Add an expression to the auto-display chain.
innermost_block_tracker tracker;
expression_up expr = parse_expression (exp, &tracker);
- newobj = new display ();
-
- newobj->exp_string = xstrdup (exp);
- newobj->exp = std::move (expr);
- newobj->block = tracker.block ();
- newobj->pspace = current_program_space;
- newobj->number = ++display_number;
- newobj->format = fmt;
- newobj->enabled_p = 1;
- newobj->next = NULL;
-
- if (display_chain == NULL)
- display_chain = newobj;
- else
- {
- struct display *last;
-
- for (last = display_chain; last->next != NULL; last = last->next)
- ;
- last->next = newobj;
- }
+ newobj = new display (exp, std::move (expr), fmt,
+ current_program_space, tracker.block ());
+ all_displays.emplace_back (newobj);
if (from_tty)
do_one_display (newobj);
dont_repeat ();
}
-static void
-free_display (struct display *d)
-{
- xfree (d->exp_string);
- delete d;
-}
-
/* Clear out the display_chain. Done when new symtabs are loaded,
since this invalidates the types stored in many expressions. */
void
-clear_displays (void)
+clear_displays ()
{
- struct display *d;
-
- while ((d = display_chain) != NULL)
- {
- display_chain = d->next;
- free_display (d);
- }
+ all_displays.clear ();
}
/* Delete the auto-display DISPLAY. */
static void
delete_display (struct display *display)
{
- struct display *d;
-
gdb_assert (display != NULL);
- if (display_chain == display)
- display_chain = display->next;
-
- ALL_DISPLAYS (d)
- if (d->next == display)
- {
- d->next = display->next;
- break;
- }
-
- free_display (display);
+ auto iter = std::find_if (all_displays.begin (),
+ all_displays.end (),
+ [=] (const std::unique_ptr<struct display> &item)
+ {
+ return item.get () == display;
+ });
+ gdb_assert (iter != all_displays.end ());
+ all_displays.erase (iter);
}
/* Call FUNCTION on each of the displays whose numbers are given in
static void
map_display_numbers (const char *args,
- void (*function) (struct display *,
- void *),
- void *data)
+ gdb::function_view<void (struct display *)> function)
{
int num;
warning (_("bad display number at or near '%s'"), p);
else
{
- struct display *d, *tmp;
-
- ALL_DISPLAYS_SAFE (d, tmp)
- if (d->number == num)
- break;
- if (d == NULL)
+ auto iter = std::find_if (all_displays.begin (),
+ all_displays.end (),
+ [=] (const std::unique_ptr<display> &item)
+ {
+ return item->number == num;
+ });
+ if (iter == all_displays.end ())
printf_unfiltered (_("No display number %d.\n"), num);
else
- function (d, data);
+ function (iter->get ());
}
}
}
-/* Callback for map_display_numbers, that deletes a display. */
-
-static void
-do_delete_display (struct display *d, void *data)
-{
- delete_display (d);
-}
-
/* "undisplay" command. */
static void
return;
}
- map_display_numbers (args, do_delete_display, NULL);
+ map_display_numbers (args, delete_display);
dont_repeat ();
}
{
int within_current_scope;
- if (d->enabled_p == 0)
+ if (!d->enabled_p)
return;
/* The expression carries the architecture that was used at parse time.
try
{
innermost_block_tracker tracker;
- d->exp = parse_expression (d->exp_string, &tracker);
+ d->exp = parse_expression (d->exp_string.c_str (), &tracker);
d->block = tracker.block ();
}
catch (const gdb_exception &ex)
{
/* Can't re-parse the expression. Disable this display item. */
- d->enabled_p = 0;
+ d->enabled_p = false;
warning (_("Unable to display \"%s\": %s"),
- d->exp_string, ex.what ());
+ d->exp_string.c_str (), ex.what ());
return;
}
}
annotate_display_expression ();
- puts_filtered (d->exp_string);
+ puts_filtered (d->exp_string.c_str ());
annotate_display_expression_end ();
if (d->format.count != 1 || d->format.format == 'i')
annotate_display_value ();
try
- {
+ {
struct value *val;
CORE_ADDR addr;
}
catch (const gdb_exception_error &ex)
{
- fprintf_filtered (gdb_stdout, _("<error: %s>\n"),
- ex.what ());
+ fprintf_filtered (gdb_stdout, _("%p[<error: %s>%p]\n"),
+ metadata_style.style ().ptr (), ex.what (),
+ nullptr);
}
}
else
annotate_display_expression ();
- puts_filtered (d->exp_string);
+ puts_filtered (d->exp_string.c_str ());
annotate_display_expression_end ();
printf_filtered (" = ");
opts.raw = d->format.raw;
try
- {
+ {
struct value *val;
val = evaluate_expression (d->exp.get ());
}
catch (const gdb_exception_error &ex)
{
- fprintf_filtered (gdb_stdout, _("<error: %s>"), ex.what ());
+ fprintf_styled (gdb_stdout, metadata_style.style (),
+ _("<error: %s>"), ex.what ());
}
printf_filtered ("\n");
void
do_displays (void)
{
- struct display *d;
-
- for (d = display_chain; d; d = d->next)
- do_one_display (d);
+ for (auto &d : all_displays)
+ do_one_display (d.get ());
}
/* Delete the auto-display which we were in the process of displaying.
void
disable_display (int num)
{
- struct display *d;
-
- for (d = display_chain; d; d = d->next)
+ for (auto &d : all_displays)
if (d->number == num)
{
- d->enabled_p = 0;
+ d->enabled_p = false;
return;
}
printf_unfiltered (_("No display number %d.\n"), num);
static void
info_display_command (const char *ignore, int from_tty)
{
- struct display *d;
-
- if (!display_chain)
+ if (all_displays.empty ())
printf_unfiltered (_("There are no auto-display expressions now.\n"));
else
printf_filtered (_("Auto-display expressions now in effect:\n\
Num Enb Expression\n"));
- for (d = display_chain; d; d = d->next)
+ for (auto &d : all_displays)
{
printf_filtered ("%d: %c ", d->number, "ny"[(int) d->enabled_p]);
if (d->format.size)
d->format.format);
else if (d->format.format)
printf_filtered ("/%c ", d->format.format);
- puts_filtered (d->exp_string);
+ puts_filtered (d->exp_string.c_str ());
if (d->block && !contained_in (get_selected_block (0), d->block, true))
printf_filtered (_(" (cannot be evaluated in the current context)"));
printf_filtered ("\n");
}
}
-/* Callback fo map_display_numbers, that enables or disables the
- passed in display D. */
-
-static void
-do_enable_disable_display (struct display *d, void *data)
-{
- d->enabled_p = *(int *) data;
-}
-
-/* Implamentation of both the "disable display" and "enable display"
+/* Implementation of both the "disable display" and "enable display"
commands. ENABLE decides what to do. */
static void
-enable_disable_display_command (const char *args, int from_tty, int enable)
+enable_disable_display_command (const char *args, int from_tty, bool enable)
{
if (args == NULL)
{
- struct display *d;
-
- ALL_DISPLAYS (d)
+ for (auto &d : all_displays)
d->enabled_p = enable;
return;
}
- map_display_numbers (args, do_enable_disable_display, &enable);
+ map_display_numbers (args,
+ [=] (struct display *d)
+ {
+ d->enabled_p = enable;
+ });
}
/* The "enable display" command. */
static void
enable_display_command (const char *args, int from_tty)
{
- enable_disable_display_command (args, from_tty, 1);
+ enable_disable_display_command (args, from_tty, true);
}
/* The "disable display" command. */
static void
disable_display_command (const char *args, int from_tty)
{
- enable_disable_display_command (args, from_tty, 0);
+ enable_disable_display_command (args, from_tty, false);
}
/* display_chain items point to blocks and expressions. Some expressions in
static void
clear_dangling_display_expressions (struct objfile *objfile)
{
- struct display *d;
struct program_space *pspace;
/* With no symbol file we cannot have a block or expression from it. */
gdb_assert (objfile->pspace == pspace);
}
- for (d = display_chain; d != NULL; d = d->next)
+ for (auto &d : all_displays)
{
if (d->pspace != pspace)
continue;
- if (lookup_objfile_from_block (d->block) == objfile
+ struct objfile *bl_objf = nullptr;
+ if (d->block != nullptr)
+ {
+ bl_objf = block_objfile (d->block);
+ if (bl_objf->separate_debug_objfile_backlink != nullptr)
+ bl_objf = bl_objf->separate_debug_objfile_backlink;
+ }
+
+ if (bl_objf == objfile
|| (d->exp != NULL && exp_uses_objfile (d->exp.get (), objfile)))
- {
- d->exp.reset ();
- d->block = NULL;
- }
+ {
+ d->exp.reset ();
+ d->block = NULL;
+ }
}
}
\f
{
if (!name)
- name = SYMBOL_PRINT_NAME (var);
+ name = var->print_name ();
- fprintf_filtered (stream, "%s%ps = ", n_spaces (2 * indent),
+ fprintf_filtered (stream, "%*s%ps = ", 2 * indent, "",
styled_string (variable_name_style.style (), name));
try
}
catch (const gdb_exception_error &except)
{
- fprintf_filtered (stream, "<error reading variable %s (%s)>", name,
- except.what ());
+ fprintf_styled (stream, metadata_style.style (),
+ "<error reading variable %s (%s)>", name,
+ except.what ());
}
fprintf_filtered (stream, "\n");
{
const gdb_byte *str;
- if (VALUE_LVAL (value) == lval_internalvar
+ if (value_type (value)->code () != TYPE_CODE_PTR
+ && VALUE_LVAL (value) == lval_internalvar
&& c_is_string_type_p (value_type (value)))
{
size_t len = TYPE_LENGTH (value_type (value));
{
const gdb_byte *str;
size_t len;
- struct gdbarch *gdbarch = get_type_arch (value_type (value));
- struct type *wctype = lookup_typename (current_language, gdbarch,
+ struct gdbarch *gdbarch = value_type (value)->arch ();
+ struct type *wctype = lookup_typename (current_language,
"wchar_t", NULL, 0);
int wcwidth = TYPE_LENGTH (wctype);
{
/* Parameter data. */
struct type *param_type = value_type (value);
- struct gdbarch *gdbarch = get_type_arch (param_type);
+ struct gdbarch *gdbarch = param_type->arch ();
/* Determine target type corresponding to the format string. */
struct type *fmt_type;
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)
+ if (fmt_type->code () == TYPE_CODE_FLT)
{
param_type = float_type_from_length (param_type);
if (param_type != value_type (value))
break;
case wide_char_arg:
{
- struct gdbarch *gdbarch
- = get_type_arch (value_type (val_args[i]));
- struct type *wctype = lookup_typename (current_language, gdbarch,
+ struct gdbarch *gdbarch = value_type (val_args[i])->arch ();
+ struct type *wctype = lookup_typename (current_language,
"wchar_t", NULL, 0);
struct type *valtype;
const gdb_byte *bytes;
valtype = value_type (val_args[i]);
if (TYPE_LENGTH (valtype) != TYPE_LENGTH (wctype)
- || TYPE_CODE (valtype) != TYPE_CODE_INT)
+ || valtype->code () != TYPE_CODE_INT)
error (_("expected wchar_t argument for %%lc"));
bytes = value_contents (val_args[i]);
DIAGNOSTIC_PUSH
DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
fprintf_filtered (stream, current_substring,
- obstack_base (&output));
+ obstack_base (&output));
DIAGNOSTIC_POP
}
break;
DIAGNOSTIC_PUSH
DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
- fprintf_filtered (stream, current_substring, val);
+ fprintf_filtered (stream, current_substring, val);
DIAGNOSTIC_POP
break;
}
DIAGNOSTIC_PUSH
DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
- fprintf_filtered (stream, current_substring, val);
+ fprintf_filtered (stream, current_substring, val);
DIAGNOSTIC_POP
break;
}
DIAGNOSTIC_PUSH
DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
- fprintf_filtered (stream, current_substring, val);
+ fprintf_filtered (stream, current_substring, val);
+ DIAGNOSTIC_POP
+ break;
+ }
+ case size_t_arg:
+ {
+ size_t val = value_as_long (val_args[i]);
+
+ DIAGNOSTIC_PUSH
+ DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
+ fprintf_filtered (stream, current_substring, val);
DIAGNOSTIC_POP
break;
}
ui_printf (arg, gdb_stdout);
reset_terminal_style (gdb_stdout);
wrap_here ("");
- gdb_flush (gdb_stdout);
+ gdb_stdout->flush ();
}
/* Implement the "eval" command. */
execute_command (expanded.c_str (), from_tty);
}
+void _initialize_printcmd ();
void
-_initialize_printcmd (void)
+_initialize_printcmd ()
{
struct cmd_list_element *c;
Usage: info symbol ADDR\n\
Only for symbols with fixed locations (global or static scope)."));
- add_com ("x", class_vars, x_command, _("\
+ c = add_com ("x", class_vars, x_command, _("\
Examine memory: x/FMT ADDRESS.\n\
ADDRESS is an expression for the memory address to examine.\n\
FMT is a repeat count followed by a format letter and a size letter.\n\
Defaults for format and size letters are those previously used.\n\
Default count is 1. Default address is following last thing printed\n\
with this command or \"print\"."));
+ set_cmd_completer_handle_brkchars (c, display_and_x_command_completer);
add_info ("display", info_display_command, _("\
Expressions to display when program stops, with code numbers.\n\
Do \"info display\" to see current list of code numbers."),
&cmdlist);
- add_com ("display", class_vars, display_command, _("\
+ c = add_com ("display", class_vars, display_command, _("\
Print value of expression EXP each time the program stops.\n\
Usage: display[/FMT] EXP\n\
/FMT may be used before EXP as in the \"print\" command.\n\
and examining is done as in the \"x\" command.\n\n\
With no argument, display all currently requested auto-display expressions.\n\
Use \"undisplay\" to cancel display requests previously made."));
+ set_cmd_completer_handle_brkchars (c, display_and_x_command_completer);
add_cmd ("display", class_vars, enable_display_command, _("\
Enable some expressions to be displayed when program stops.\n\