mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 12:34:43 +00:00
Compare commits
7 Commits
binutils-2
...
users/palv
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc0a76bef5 | ||
|
|
2d3081ce81 | ||
|
|
4b4de9f875 | ||
|
|
47f969f4d9 | ||
|
|
03c6774d01 | ||
|
|
67f57a9be2 | ||
|
|
9507d5238b |
20
gdb/NEWS
20
gdb/NEWS
@@ -46,6 +46,21 @@ pipe -d DELIM COMMAND DELIM SHELL_COMMAND
|
||||
With no COMMAND, repeat the last executed command
|
||||
and send its output to SHELL_COMMAND.
|
||||
|
||||
with SETTING [VALUE] [-- COMMAND]
|
||||
w SETTING [VALUE] [-- COMMAND]
|
||||
Temporarily set SETTING, run COMMAND, and restore SETTING.
|
||||
Usage: with SETTING -- COMMAND
|
||||
With no COMMAND, repeats the last executed command.
|
||||
SETTING is any GDB setting you can change with the "set"
|
||||
subcommands. For example, 'with language c -- print someobj'
|
||||
temporarily switches to the C language in order to print someobj.
|
||||
Settings can be combined: 'w lang c -- w print elements unlimited --
|
||||
usercmd' switches to the C language and runs usercmd with no limit
|
||||
of array elements to print.
|
||||
|
||||
maint with SETTING [VALUE] [-- COMMAND]
|
||||
Like "with", but works with "maintenance set" settings.
|
||||
|
||||
set may-call-functions [on|off]
|
||||
show may-call-functions
|
||||
This controls whether GDB will attempt to call functions in
|
||||
@@ -84,7 +99,8 @@ set style highlight background COLOR
|
||||
set style highlight intensity VALUE
|
||||
Control the styling of highlightings.
|
||||
|
||||
maint test-settings KIND
|
||||
maint set test-settings KIND
|
||||
maint show test-settings KIND
|
||||
A set of commands used by the testsuite for exercising the settings
|
||||
infrastructure.
|
||||
|
||||
@@ -194,6 +210,8 @@ maint show test-options-completion-result
|
||||
"taas" commands, and their "-ascending" option can now be
|
||||
abbreviated.
|
||||
|
||||
** GDB can now complete the options of the "info threads" command.
|
||||
|
||||
** GDB can now complete the options of the "compile file" and
|
||||
"compile code" commands. The "compile file" command now
|
||||
completes on filenames.
|
||||
|
||||
@@ -211,6 +211,116 @@ show_command (const char *arg, int from_tty)
|
||||
cmd_show_list (showlist, from_tty, "");
|
||||
}
|
||||
|
||||
/* See cli/cli-cmds.h. */
|
||||
|
||||
void
|
||||
with_command_1 (const char *set_cmd_prefix,
|
||||
cmd_list_element *setlist, const char *args, int from_tty)
|
||||
{
|
||||
const char *delim = strstr (args, "--");
|
||||
const char *nested_cmd = nullptr;
|
||||
|
||||
if (delim == args)
|
||||
error (_("Missing setting before '--' delimiter"));
|
||||
|
||||
if (delim == nullptr || *skip_spaces (&delim[2]) == '\0')
|
||||
nested_cmd = repeat_previous ();
|
||||
|
||||
cmd_list_element *set_cmd = lookup_cmd (&args, setlist, set_cmd_prefix,
|
||||
/*allow_unknown=*/ 0,
|
||||
/*ignore_help_classes=*/ 1);
|
||||
gdb_assert (set_cmd != nullptr);
|
||||
|
||||
if (set_cmd->var == nullptr)
|
||||
error (_("Cannot use this setting with the \"with\" command"));
|
||||
|
||||
std::string temp_value
|
||||
= (delim == nullptr ? args : std::string (args, delim - args));
|
||||
|
||||
if (nested_cmd == nullptr)
|
||||
nested_cmd = skip_spaces (delim + 2);
|
||||
|
||||
std::string org_value = get_setshow_command_value_string (set_cmd);
|
||||
|
||||
/* Tweak the setting to the new temporary value. */
|
||||
do_set_command (temp_value.c_str (), from_tty, set_cmd);
|
||||
|
||||
try
|
||||
{
|
||||
scoped_restore save_async = make_scoped_restore (¤t_ui->async, 0);
|
||||
|
||||
/* Execute the nested command. */
|
||||
execute_command (nested_cmd, from_tty);
|
||||
}
|
||||
catch (const gdb_exception &ex)
|
||||
{
|
||||
/* Restore the setting and rethrow. If restoring the setting
|
||||
throws, swallow the new exception and warn. There's nothing
|
||||
else we can reasonably do. */
|
||||
try
|
||||
{
|
||||
do_set_command (org_value.c_str (), from_tty, set_cmd);
|
||||
}
|
||||
catch (const gdb_exception &ex2)
|
||||
{
|
||||
warning (_("Couldn't restore setting: %s"), ex2.what ());
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
/* Restore the setting. */
|
||||
do_set_command (org_value.c_str (), from_tty, set_cmd);
|
||||
}
|
||||
|
||||
/* See cli/cli-cmds.h. */
|
||||
|
||||
void
|
||||
with_command_completer_1 (const char *set_cmd_prefix,
|
||||
completion_tracker &tracker,
|
||||
const char *text)
|
||||
{
|
||||
tracker.set_use_custom_word_point (true);
|
||||
|
||||
const char *delim = strstr (text, "--");
|
||||
|
||||
/* If we're still not past the "--" delimiter, complete the "with"
|
||||
command as if it was a "set" command. */
|
||||
if (delim == text
|
||||
|| delim == nullptr
|
||||
|| !isspace (delim[-1])
|
||||
|| !(isspace (delim[2]) || delim[2] == '\0'))
|
||||
{
|
||||
std::string new_text = std::string (set_cmd_prefix) + text;
|
||||
tracker.advance_custom_word_point_by (-(int) strlen (set_cmd_prefix));
|
||||
complete_nested_command_line (tracker, new_text.c_str ());
|
||||
return;
|
||||
}
|
||||
|
||||
/* We're past the "--" delimiter. Complete on the sub command. */
|
||||
const char *nested_cmd = skip_spaces (delim + 2);
|
||||
tracker.advance_custom_word_point_by (nested_cmd - text);
|
||||
complete_nested_command_line (tracker, nested_cmd);
|
||||
}
|
||||
|
||||
/* The "with" command. */
|
||||
|
||||
static void
|
||||
with_command (const char *args, int from_tty)
|
||||
{
|
||||
with_command_1 ("set ", setlist, args, from_tty);
|
||||
}
|
||||
|
||||
/* "with" command completer. */
|
||||
|
||||
static void
|
||||
with_command_completer (struct cmd_list_element *ignore,
|
||||
completion_tracker &tracker,
|
||||
const char *text, const char * /*word*/)
|
||||
{
|
||||
with_command_completer_1 ("set ", tracker, text);
|
||||
}
|
||||
|
||||
|
||||
/* Provide documentation on command or list given by COMMAND. FROM_TTY
|
||||
is ignored. */
|
||||
@@ -850,40 +960,71 @@ edit_command (const char *arg, int from_tty)
|
||||
xfree (p);
|
||||
}
|
||||
|
||||
/* The options for the "pipe" command. */
|
||||
|
||||
struct pipe_cmd_opts
|
||||
{
|
||||
/* For "-d". */
|
||||
char *delimiter = nullptr;
|
||||
|
||||
~pipe_cmd_opts ()
|
||||
{
|
||||
xfree (delimiter);
|
||||
}
|
||||
};
|
||||
|
||||
static const gdb::option::option_def pipe_cmd_option_defs[] = {
|
||||
|
||||
gdb::option::string_option_def<pipe_cmd_opts> {
|
||||
"d",
|
||||
[] (pipe_cmd_opts *opts) { return &opts->delimiter; },
|
||||
nullptr,
|
||||
N_("Indicates to use the specified delimiter string to separate\n\
|
||||
COMMAND from SHELL_COMMAND, in alternative to |. This is useful in\n\
|
||||
case COMMAND contains a | character."),
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
/* Create an option_def_group for the "pipe" command's options, with
|
||||
OPTS as context. */
|
||||
|
||||
static inline gdb::option::option_def_group
|
||||
make_pipe_cmd_options_def_group (pipe_cmd_opts *opts)
|
||||
{
|
||||
return {{pipe_cmd_option_defs}, opts};
|
||||
}
|
||||
|
||||
/* Implementation of the "pipe" command. */
|
||||
|
||||
static void
|
||||
pipe_command (const char *arg, int from_tty)
|
||||
{
|
||||
std::string delim ("|");
|
||||
pipe_cmd_opts opts;
|
||||
|
||||
if (arg != nullptr && check_for_argument (&arg, "-d", 2))
|
||||
{
|
||||
delim = extract_arg (&arg);
|
||||
if (delim.empty ())
|
||||
error (_("Missing delimiter DELIM after -d"));
|
||||
}
|
||||
auto grp = make_pipe_cmd_options_def_group (&opts);
|
||||
gdb::option::process_options
|
||||
(&arg, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
|
||||
|
||||
const char *delim = "|";
|
||||
if (opts.delimiter != nullptr)
|
||||
delim = opts.delimiter;
|
||||
|
||||
const char *command = arg;
|
||||
if (command == nullptr)
|
||||
error (_("Missing COMMAND"));
|
||||
|
||||
arg = strstr (arg, delim.c_str ());
|
||||
arg = strstr (arg, delim);
|
||||
|
||||
if (arg == nullptr)
|
||||
error (_("Missing delimiter before SHELL_COMMAND"));
|
||||
|
||||
std::string gdb_cmd (command, arg - command);
|
||||
|
||||
arg += delim.length (); /* Skip the delimiter. */
|
||||
arg += strlen (delim); /* Skip the delimiter. */
|
||||
|
||||
if (gdb_cmd.empty ())
|
||||
{
|
||||
repeat_previous ();
|
||||
gdb_cmd = skip_spaces (get_saved_command_line ());
|
||||
if (gdb_cmd.empty ())
|
||||
error (_("No previous command to relaunch"));
|
||||
}
|
||||
gdb_cmd = repeat_previous ();
|
||||
|
||||
const char *shell_command = skip_spaces (arg);
|
||||
if (*shell_command == '\0')
|
||||
@@ -914,6 +1055,43 @@ pipe_command (const char *arg, int from_tty)
|
||||
exit_status_set_internal_vars (exit_status);
|
||||
}
|
||||
|
||||
/* Completer for the pipe command. */
|
||||
|
||||
static void
|
||||
pipe_command_completer (struct cmd_list_element *ignore,
|
||||
completion_tracker &tracker,
|
||||
const char *text, const char *word_ignored)
|
||||
{
|
||||
pipe_cmd_opts opts;
|
||||
|
||||
const char *org_text = text;
|
||||
auto grp = make_pipe_cmd_options_def_group (&opts);
|
||||
if (gdb::option::complete_options
|
||||
(tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp))
|
||||
return;
|
||||
|
||||
const char *delimiter = "|";
|
||||
if (opts.delimiter != nullptr)
|
||||
delimiter = opts.delimiter;
|
||||
|
||||
/* Check if we're past option values already. */
|
||||
if (text > org_text && !isspace (text[-1]))
|
||||
return;
|
||||
|
||||
const char *delim = strstr (text, delimiter);
|
||||
|
||||
/* If we're still not past the delimiter, complete the gdb
|
||||
command. */
|
||||
if (delim == nullptr || delim == text)
|
||||
{
|
||||
complete_nested_command_line (tracker, text);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We're past the delimiter. What follows is a shell command, which
|
||||
we don't know how to complete. */
|
||||
}
|
||||
|
||||
static void
|
||||
list_command (const char *arg, int from_tty)
|
||||
{
|
||||
@@ -1849,6 +2027,23 @@ Generic command for showing things about the debugger."),
|
||||
/* Another way to get at the same thing. */
|
||||
add_info ("set", show_command, _("Show all GDB settings."));
|
||||
|
||||
c = add_com ("with", class_vars, with_command, _("\
|
||||
Temporarily set SETTING to VALUE, run COMMAND, and restore SETTING.\n\
|
||||
Usage: with SETTING [VALUE] [-- COMMAND]\n\
|
||||
Usage: w SETTING [VALUE] [-- COMMAND]\n\
|
||||
With no COMMAND, repeats the last executed command.\n\
|
||||
\n\
|
||||
SETTING is any setting you can change with the \"set\" subcommands.\n\
|
||||
E.g.:\n\
|
||||
with language pascal -- print obj\n\
|
||||
with print elements unlimited -- print obj\n\
|
||||
\n\
|
||||
You can change multiple settings using nested with, and use\n\
|
||||
abbreviations for commands and/or values. E.g.:\n\
|
||||
w la p -- w p el u -- p obj"));
|
||||
set_cmd_completer_handle_brkchars (c, with_command_completer);
|
||||
add_com_alias ("w", "with", class_vars, 1);
|
||||
|
||||
add_cmd ("commands", no_set_class, show_commands, _("\
|
||||
Show the history of commands you typed.\n\
|
||||
You can supply a command number to start with, or a `+' to start after\n\
|
||||
@@ -1907,7 +2102,10 @@ Uses EDITOR environment variable contents as editor (or ex as default)."));
|
||||
|
||||
c->completer = location_completer;
|
||||
|
||||
c = add_com ("pipe", class_support, pipe_command, _("\
|
||||
const auto pipe_cmd_opts = make_pipe_cmd_options_def_group (nullptr);
|
||||
|
||||
static std::string pipe_cmd_help
|
||||
= gdb::option::build_help (_("\
|
||||
Send the output of a gdb command to a shell command.\n\
|
||||
Usage: | [COMMAND] | SHELL_COMMAND\n\
|
||||
Usage: | -d DELIM COMMAND DELIM SHELL_COMMAND\n\
|
||||
@@ -1916,12 +2114,15 @@ Usage: pipe -d DELIM COMMAND DELIM SHELL_COMMAND\n\
|
||||
\n\
|
||||
Executes COMMAND and sends its output to SHELL_COMMAND.\n\
|
||||
\n\
|
||||
The -d option indicates to use the string DELIM to separate COMMAND\n\
|
||||
from SHELL_COMMAND, in alternative to |. This is useful in\n\
|
||||
case COMMAND contains a | character.\n\
|
||||
\n\
|
||||
Options:\n\
|
||||
%OPTIONS%\
|
||||
With no COMMAND, repeat the last executed command\n\
|
||||
and send its output to SHELL_COMMAND."));
|
||||
and send its output to SHELL_COMMAND."),
|
||||
pipe_cmd_opts);
|
||||
|
||||
c = add_com ("pipe", class_support, pipe_command,
|
||||
pipe_cmd_help.c_str ());
|
||||
set_cmd_completer_handle_brkchars (c, pipe_command_completer);
|
||||
add_com_alias ("|", "pipe", class_support, 0);
|
||||
|
||||
add_com ("list", class_files, list_command, _("\
|
||||
|
||||
@@ -142,4 +142,19 @@ extern gdb::optional<open_script>
|
||||
extern int source_verbose;
|
||||
extern int trace_commands;
|
||||
|
||||
/* Common code for the "with" and "maintenance with" commands.
|
||||
SET_CMD_PREFIX is the spelling of the corresponding "set" command
|
||||
prefix: i.e., "set " or "maintenance set ". SETLIST is the command
|
||||
element for the same "set" command prefix. */
|
||||
extern void with_command_1 (const char *set_cmd_prefix,
|
||||
cmd_list_element *setlist,
|
||||
const char *args, int from_tty);
|
||||
|
||||
/* Common code for the completers of the "with" and "maintenance with"
|
||||
commands. SET_CMD_PREFIX is the spelling of the corresponding
|
||||
"set" command prefix: i.e., "set " or "maintenance set ". */
|
||||
extern void with_command_completer_1 (const char *set_cmd_prefix,
|
||||
completion_tracker &tracker,
|
||||
const char *text);
|
||||
|
||||
#endif /* CLI_CLI_CMDS_H */
|
||||
|
||||
@@ -43,6 +43,9 @@ union option_value
|
||||
|
||||
/* For var_enum options. */
|
||||
const char *enumeration;
|
||||
|
||||
/* For var_string options. This is malloc-allocated. */
|
||||
char *string;
|
||||
};
|
||||
|
||||
/* Holds an options definition and its value. */
|
||||
@@ -56,8 +59,57 @@ struct option_def_and_value
|
||||
|
||||
/* The option's value, if any. */
|
||||
gdb::optional<option_value> value;
|
||||
|
||||
option_def_and_value (const option_def &option_, void *ctx_,
|
||||
gdb::optional<option_value> &&value_)
|
||||
: option (option_),
|
||||
ctx (ctx_),
|
||||
value (std::move (value_))
|
||||
{
|
||||
clear_value (option_, value_);
|
||||
}
|
||||
|
||||
option_def_and_value (const option_def &option_, void *ctx_)
|
||||
: option (option_),
|
||||
ctx (ctx_)
|
||||
{
|
||||
}
|
||||
|
||||
option_def_and_value (option_def_and_value &&rval)
|
||||
: option (rval.option),
|
||||
ctx (rval.ctx),
|
||||
value (std::move (rval.value))
|
||||
{
|
||||
clear_value (rval.option, rval.value);
|
||||
}
|
||||
|
||||
~option_def_and_value ()
|
||||
{
|
||||
if (value.has_value ())
|
||||
{
|
||||
if (option.type == var_string)
|
||||
xfree (value->string);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/* Clear the option_value, without releasing it. This is used after
|
||||
the value has been moved to some other option_def_and_value
|
||||
instance. */
|
||||
static void clear_value (const option_def &option,
|
||||
gdb::optional<option_value> &value)
|
||||
{
|
||||
if (value.has_value ())
|
||||
{
|
||||
if (option.type == var_string)
|
||||
value->string = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void save_option_value_in_ctx (gdb::optional<option_def_and_value> &ov);
|
||||
|
||||
/* Info passed around when handling completion. */
|
||||
struct parse_option_completion_info
|
||||
{
|
||||
@@ -370,6 +422,25 @@ parse_option (gdb::array_view<const option_def_group> options_group,
|
||||
val.enumeration = parse_cli_var_enum (args, match->enums);
|
||||
return option_def_and_value {*match, match_ctx, val};
|
||||
}
|
||||
case var_string:
|
||||
{
|
||||
if (check_for_argument (args, "--"))
|
||||
{
|
||||
/* Treat e.g., "pipe -d --" as if there was no argument
|
||||
after "-d". */
|
||||
error (_("-%s requires an argument"), match->name);
|
||||
}
|
||||
|
||||
const char *arg_start = *args;
|
||||
*args = skip_to_space (*args);
|
||||
|
||||
if (*args == arg_start)
|
||||
error (_("-%s requires an argument"), match->name);
|
||||
|
||||
option_value val;
|
||||
val.string = savestring (arg_start, *args - arg_start);
|
||||
return option_def_and_value {*match, match_ctx, val};
|
||||
}
|
||||
|
||||
default:
|
||||
/* Not yet. */
|
||||
@@ -456,6 +527,11 @@ complete_options (completion_tracker &tracker,
|
||||
(*args - text);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If the caller passed in a context, then it is
|
||||
interested in the option argument values. */
|
||||
if (ov && ov->ctx != nullptr)
|
||||
save_option_value_in_ctx (ov);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -499,6 +575,41 @@ complete_options (completion_tracker &tracker,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Save the parsed value in the option's context. */
|
||||
|
||||
static void
|
||||
save_option_value_in_ctx (gdb::optional<option_def_and_value> &ov)
|
||||
{
|
||||
switch (ov->option.type)
|
||||
{
|
||||
case var_boolean:
|
||||
{
|
||||
bool value = ov->value.has_value () ? ov->value->boolean : true;
|
||||
*ov->option.var_address.boolean (ov->option, ov->ctx) = value;
|
||||
}
|
||||
break;
|
||||
case var_uinteger:
|
||||
*ov->option.var_address.uinteger (ov->option, ov->ctx)
|
||||
= ov->value->uinteger;
|
||||
break;
|
||||
case var_zuinteger_unlimited:
|
||||
*ov->option.var_address.integer (ov->option, ov->ctx)
|
||||
= ov->value->integer;
|
||||
break;
|
||||
case var_enum:
|
||||
*ov->option.var_address.enumeration (ov->option, ov->ctx)
|
||||
= ov->value->enumeration;
|
||||
break;
|
||||
case var_string:
|
||||
*ov->option.var_address.string (ov->option, ov->ctx)
|
||||
= ov->value->string;
|
||||
ov->value->string = nullptr;
|
||||
break;
|
||||
default:
|
||||
gdb_assert_not_reached ("unhandled option type");
|
||||
}
|
||||
}
|
||||
|
||||
/* See cli-option.h. */
|
||||
|
||||
bool
|
||||
@@ -534,29 +645,7 @@ process_options (const char **args,
|
||||
|
||||
processed_any = true;
|
||||
|
||||
switch (ov->option.type)
|
||||
{
|
||||
case var_boolean:
|
||||
{
|
||||
bool value = ov->value.has_value () ? ov->value->boolean : true;
|
||||
*ov->option.var_address.boolean (ov->option, ov->ctx) = value;
|
||||
}
|
||||
break;
|
||||
case var_uinteger:
|
||||
*ov->option.var_address.uinteger (ov->option, ov->ctx)
|
||||
= ov->value->uinteger;
|
||||
break;
|
||||
case var_zuinteger_unlimited:
|
||||
*ov->option.var_address.integer (ov->option, ov->ctx)
|
||||
= ov->value->integer;
|
||||
break;
|
||||
case var_enum:
|
||||
*ov->option.var_address.enumeration (ov->option, ov->ctx)
|
||||
= ov->value->enumeration;
|
||||
break;
|
||||
default:
|
||||
gdb_assert_not_reached ("unhandled option type");
|
||||
}
|
||||
save_option_value_in_ctx (ov);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -588,6 +677,8 @@ get_val_type_str (const option_def &opt, std::string &buffer)
|
||||
}
|
||||
return buffer.c_str ();
|
||||
}
|
||||
case var_string:
|
||||
return "STRING";
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
@@ -715,6 +806,15 @@ add_setshow_cmds_for_options (command_class cmd_class,
|
||||
nullptr, option.show_cmd_cb,
|
||||
set_list, show_list);
|
||||
}
|
||||
else if (option.type == var_string)
|
||||
{
|
||||
add_setshow_string_cmd (option.name, cmd_class,
|
||||
option.var_address.string (option, data),
|
||||
option.set_doc, option.show_doc,
|
||||
option.help_doc,
|
||||
nullptr, option.show_cmd_cb,
|
||||
set_list, show_list);
|
||||
}
|
||||
else
|
||||
gdb_assert_not_reached (_("option type not handled"));
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ public:
|
||||
unsigned int *(*uinteger) (const option_def &, void *ctx);
|
||||
int *(*integer) (const option_def &, void *ctx);
|
||||
const char **(*enumeration) (const option_def &, void *ctx);
|
||||
char **(*string) (const option_def &, void *ctx);
|
||||
}
|
||||
var_address;
|
||||
|
||||
@@ -261,6 +262,26 @@ struct enum_option_def : option_def
|
||||
}
|
||||
};
|
||||
|
||||
/* An var_string command line option. */
|
||||
|
||||
template<typename Context>
|
||||
struct string_option_def : option_def
|
||||
{
|
||||
string_option_def (const char *long_option_,
|
||||
char **(*get_var_address_cb_) (Context *),
|
||||
show_value_ftype *show_cmd_cb_,
|
||||
const char *set_doc_,
|
||||
const char *show_doc_ = nullptr,
|
||||
const char *help_doc_ = nullptr)
|
||||
: option_def (long_option_, var_string,
|
||||
(erased_get_var_address_ftype *) get_var_address_cb_,
|
||||
show_cmd_cb_,
|
||||
set_doc_, show_doc_, help_doc_)
|
||||
{
|
||||
var_address.enumeration = detail::get_var_address<const char *, Context>;
|
||||
}
|
||||
};
|
||||
|
||||
/* A group of options that all share the same context pointer to pass
|
||||
to the options' get-current-value callbacks. */
|
||||
struct option_def_group
|
||||
|
||||
@@ -190,7 +190,7 @@ parse_cli_var_uinteger (var_types var_type, const char **arg,
|
||||
{
|
||||
LONGEST val;
|
||||
|
||||
if (*arg == nullptr)
|
||||
if (*arg == nullptr || **arg == '\0')
|
||||
{
|
||||
if (var_type == var_uinteger)
|
||||
error_no_arg (_("integer to set it to, or \"unlimited\"."));
|
||||
@@ -225,7 +225,7 @@ parse_cli_var_zuinteger_unlimited (const char **arg, bool expression)
|
||||
{
|
||||
LONGEST val;
|
||||
|
||||
if (*arg == nullptr)
|
||||
if (*arg == nullptr || **arg == '\0')
|
||||
error_no_arg (_("integer to set it to, or \"unlimited\"."));
|
||||
|
||||
if (is_unlimited_literal (arg, expression))
|
||||
@@ -308,6 +308,9 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
|
||||
|
||||
gdb_assert (c->type == set_cmd);
|
||||
|
||||
if (arg == NULL)
|
||||
arg = "";
|
||||
|
||||
switch (c->var_type)
|
||||
{
|
||||
case var_string:
|
||||
@@ -317,8 +320,6 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
|
||||
char *q;
|
||||
int ch;
|
||||
|
||||
if (arg == NULL)
|
||||
arg = "";
|
||||
newobj = (char *) xmalloc (strlen (arg) + 2);
|
||||
p = arg;
|
||||
q = newobj;
|
||||
@@ -364,9 +365,6 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
|
||||
}
|
||||
break;
|
||||
case var_string_noescape:
|
||||
if (arg == NULL)
|
||||
arg = "";
|
||||
|
||||
if (*(char **) c->var == NULL || strcmp (*(char **) c->var, arg) != 0)
|
||||
{
|
||||
xfree (*(char **) c->var);
|
||||
@@ -376,14 +374,14 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
|
||||
}
|
||||
break;
|
||||
case var_filename:
|
||||
if (arg == NULL)
|
||||
if (*arg == '\0')
|
||||
error_no_arg (_("filename to set it to."));
|
||||
/* FALLTHROUGH */
|
||||
case var_optional_filename:
|
||||
{
|
||||
char *val = NULL;
|
||||
|
||||
if (arg != NULL)
|
||||
if (*arg != '\0')
|
||||
{
|
||||
/* Clear trailing whitespace of filename. */
|
||||
const char *ptr = arg + strlen (arg) - 1;
|
||||
@@ -455,7 +453,7 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
|
||||
{
|
||||
LONGEST val;
|
||||
|
||||
if (arg == NULL)
|
||||
if (*arg == '\0')
|
||||
{
|
||||
if (c->var_type == var_integer)
|
||||
error_no_arg (_("integer to set it to, or \"unlimited\"."));
|
||||
@@ -625,24 +623,13 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
|
||||
}
|
||||
}
|
||||
|
||||
/* Do a "show" command. ARG is NULL if no argument, or the
|
||||
text of the argument, and FROM_TTY is nonzero if this command is
|
||||
being entered directly by the user (i.e. these are just like any
|
||||
other command). C is the command list element for the command. */
|
||||
/* See cli/cli-setshow.h. */
|
||||
|
||||
void
|
||||
do_show_command (const char *arg, int from_tty, struct cmd_list_element *c)
|
||||
std::string
|
||||
get_setshow_command_value_string (cmd_list_element *c)
|
||||
{
|
||||
struct ui_out *uiout = current_uiout;
|
||||
|
||||
gdb_assert (c->type == show_cmd);
|
||||
|
||||
string_file stb;
|
||||
|
||||
/* Possibly call the pre hook. */
|
||||
if (c->pre_show_hook)
|
||||
(c->pre_show_hook) (c);
|
||||
|
||||
switch (c->var_type)
|
||||
{
|
||||
case var_string:
|
||||
@@ -672,9 +659,7 @@ do_show_command (const char *arg, int from_tty, struct cmd_list_element *c)
|
||||
stb.puts ("auto");
|
||||
break;
|
||||
default:
|
||||
internal_error (__FILE__, __LINE__,
|
||||
_("do_show_command: "
|
||||
"invalid var_auto_boolean"));
|
||||
gdb_assert_not_reached ("invalid var_auto_boolean");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -703,23 +688,42 @@ do_show_command (const char *arg, int from_tty, struct cmd_list_element *c)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error (_("gdb internal error: bad var_type in do_show_command"));
|
||||
gdb_assert_not_reached ("bad var_type");
|
||||
}
|
||||
|
||||
return std::move (stb.string ());
|
||||
}
|
||||
|
||||
/* FIXME: cagney/2005-02-10: Need to split this in half: code to
|
||||
convert the value into a string (esentially the above); and
|
||||
code to print the value out. For the latter there should be
|
||||
MI and CLI specific versions. */
|
||||
|
||||
/* Do a "show" command. ARG is NULL if no argument, or the
|
||||
text of the argument, and FROM_TTY is nonzero if this command is
|
||||
being entered directly by the user (i.e. these are just like any
|
||||
other command). C is the command list element for the command. */
|
||||
|
||||
void
|
||||
do_show_command (const char *arg, int from_tty, struct cmd_list_element *c)
|
||||
{
|
||||
struct ui_out *uiout = current_uiout;
|
||||
|
||||
gdb_assert (c->type == show_cmd);
|
||||
|
||||
/* Possibly call the pre hook. */
|
||||
if (c->pre_show_hook)
|
||||
(c->pre_show_hook) (c);
|
||||
|
||||
std::string val = get_setshow_command_value_string (c);
|
||||
|
||||
/* FIXME: cagney/2005-02-10: There should be MI and CLI specific
|
||||
versions of code to print the value out. */
|
||||
|
||||
if (uiout->is_mi_like_p ())
|
||||
uiout->field_stream ("value", stb);
|
||||
uiout->field_string ("value", val.c_str ());
|
||||
else
|
||||
{
|
||||
if (c->show_value_func != NULL)
|
||||
c->show_value_func (gdb_stdout, from_tty, c, stb.c_str ());
|
||||
c->show_value_func (gdb_stdout, from_tty, c, val.c_str ());
|
||||
else
|
||||
deprecated_show_value_hack (gdb_stdout, from_tty, c, stb.c_str ());
|
||||
deprecated_show_value_hack (gdb_stdout, from_tty, c, val.c_str ());
|
||||
}
|
||||
|
||||
c->func (c, NULL, from_tty);
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#ifndef CLI_CLI_SETSHOW_H
|
||||
#define CLI_CLI_SETSHOW_H
|
||||
|
||||
#include <string>
|
||||
|
||||
struct cmd_list_element;
|
||||
|
||||
/* Parse ARG, an option to a boolean variable.
|
||||
@@ -55,6 +57,9 @@ extern void do_set_command (const char *arg, int from_tty,
|
||||
extern void do_show_command (const char *arg, int from_tty,
|
||||
struct cmd_list_element *c);
|
||||
|
||||
/* Get a string version of C's current value. */
|
||||
extern std::string get_setshow_command_value_string (cmd_list_element *c);
|
||||
|
||||
extern void cmd_show_list (struct cmd_list_element *list, int from_tty,
|
||||
const char *prefix);
|
||||
|
||||
|
||||
@@ -461,14 +461,17 @@ extern void error_no_arg (const char *) ATTRIBUTE_NORETURN;
|
||||
|
||||
extern void dont_repeat ();
|
||||
|
||||
/* Commands call repeat_previous if they want to repeat the previous command.
|
||||
Such commands that repeat the previous command must indicate
|
||||
to not repeat themselves, to avoid recursive repeat.
|
||||
repeat_previous will mark the current command as not repeating,
|
||||
and will ensure get_saved_command_line returns the previous command,
|
||||
so that the currently executing command can repeat it. */
|
||||
/* Commands call repeat_previous if they want to repeat the previous
|
||||
command. Such commands that repeat the previous command must
|
||||
indicate to not repeat themselves, to avoid recursive repeat.
|
||||
repeat_previous marks the current command as not repeating, and
|
||||
ensures get_saved_command_line returns the previous command, so
|
||||
that the currently executing command can repeat it. If there's no
|
||||
previous command, throws an error. Otherwise, returns the result
|
||||
of get_saved_command_line, which now points at the command to
|
||||
repeat. */
|
||||
|
||||
extern void repeat_previous ();
|
||||
extern const char *repeat_previous ();
|
||||
|
||||
/* Prevent dont_repeat from working, and return a cleanup that
|
||||
restores the previous state. */
|
||||
|
||||
@@ -1560,6 +1560,7 @@ show you the alternatives available, if there is more than one possibility).
|
||||
|
||||
@menu
|
||||
* Command Syntax:: How to give commands to @value{GDBN}
|
||||
* Command Settings:: How to change default behavior of commands
|
||||
* Completion:: Command completion
|
||||
* Command Options:: Command options
|
||||
* Help:: How to ask @value{GDBN} for help
|
||||
@@ -1616,6 +1617,98 @@ commands. This command accepts the current line, like @key{RET}, and
|
||||
then fetches the next line relative to the current line from the history
|
||||
for editing.
|
||||
|
||||
|
||||
@node Command Settings
|
||||
@section Command Settings
|
||||
@cindex default behavior of commands, changing
|
||||
@cindex default settings, changing
|
||||
|
||||
Many commands change their behavior according to command-specific
|
||||
variables or settings. These settings can be changed with the
|
||||
@code{set} subcommands. For example, the @code{print} command
|
||||
(@pxref{Data, ,Examining Data}) prints arrays differently depending on
|
||||
settings changeable with the commands @code{set print elements
|
||||
NUMBER-OF-ELEMENTS} and @code{set print array-indexes}, among others.
|
||||
|
||||
You can change these settings to your preference in the gdbinit files
|
||||
loaded at @value{GDBN} startup. @xref{Startup}.
|
||||
|
||||
The settings can also be changed interactively during the debugging
|
||||
session. For example, to change the limit of array elements to print,
|
||||
you can do the following:
|
||||
@smallexample
|
||||
(@value{GDBN}) set print elements 10
|
||||
(@value{GDBN}) print some_array
|
||||
$1 = @{0, 10, 20, 30, 40, 50, 60, 70, 80, 90...@}
|
||||
@end smallexample
|
||||
|
||||
The above @code{set print elements 10} command changes the number of
|
||||
elements to print from the default of 200 to 10. If you only intend
|
||||
this limit of 10 to be used for printing @code{some_array}, then you
|
||||
must restore the limit back to 200, with @code{set print elements
|
||||
200}.
|
||||
|
||||
Some commands allow overriding settings with command options. For
|
||||
example, the @code{print} command supports a number of options that
|
||||
allow overriding relevant global print settings as set by @code{set
|
||||
print} subcommands. @xref{print options}. The example above could be
|
||||
rewritten as:
|
||||
@smallexample
|
||||
(@value{GDBN}) print -elements 10 -- some_array
|
||||
$1 = @{0, 10, 20, 30, 40, 50, 60, 70, 80, 90...@}
|
||||
@end smallexample
|
||||
|
||||
Alternatively, you can use the @code{with} command to change a setting
|
||||
temporarily, for the duration of a command invocation.
|
||||
|
||||
@table @code
|
||||
@kindex with command
|
||||
@kindex w @r{(@code{with})}
|
||||
@cindex settings
|
||||
@cindex temporarily change settings
|
||||
@item with @var{setting} [@var{value}] [-- @var{command}]
|
||||
@itemx w @var{setting} [@var{value}] [-- @var{command}]
|
||||
Temporarily set @var{setting} to @var{value} for the duration of
|
||||
@var{command}.
|
||||
|
||||
@var{setting} is any setting you can change with the @code{set}
|
||||
subcommands. @var{value} is the value to assign to @code{setting}
|
||||
while running @code{command}.
|
||||
|
||||
If no @var{command} is provided, the last command executed is
|
||||
repeated.
|
||||
|
||||
If a @var{command} is provided, it must be preceded by a double dash
|
||||
(@code{--}) separator. This is required because some settings accept
|
||||
free-form arguments, such as expressions or filenames.
|
||||
|
||||
For example, the command
|
||||
@smallexample
|
||||
(@value{GDBN}) with print array on -- print some_array
|
||||
@end smallexample
|
||||
@noindent
|
||||
is equivalent to the following 3 commands:
|
||||
@smallexample
|
||||
(@value{GDBN}) set print array on
|
||||
(@value{GDBN}) print some_array
|
||||
(@value{GDBN}) set print array off
|
||||
@end smallexample
|
||||
|
||||
The @code{with} command is particularly useful when you want to
|
||||
override a setting while running user-defined commands, or commands
|
||||
defined in Python or Guile. @xref{Extending GDB,, Extending GDB}.
|
||||
|
||||
@smallexample
|
||||
(@value{GDBN}) with print pretty on -- my_complex_command
|
||||
@end smallexample
|
||||
|
||||
To change several settings for the same command, you can nest
|
||||
@code{with} commands. For example, @code{with language ada -- with
|
||||
print elements 10} temporarily changes the language to Ada and sets a
|
||||
limit of 10 elements to print for arrays and strings.
|
||||
|
||||
@end table
|
||||
|
||||
@node Completion
|
||||
@section Command Completion
|
||||
|
||||
@@ -37626,12 +37719,20 @@ Shows the result of completing the @code{maint test-options}
|
||||
subcommands. This is used by the testsuite to validate completion
|
||||
support in the command options framework.
|
||||
|
||||
@kindex maint test-settings
|
||||
@item maint test-settings set @var{kind}
|
||||
@itemx maint test-settings show @var{kind}
|
||||
@kindex maint set test-settings
|
||||
@kindex maint show test-settings
|
||||
@item maint set test-settings @var{kind}
|
||||
@itemx maint show test-settings @var{kind}
|
||||
These are representative commands for each @var{kind} of setting type
|
||||
@value{GDBN} supports. They are used by the testsuite for exercising
|
||||
the settings infrastructure.
|
||||
|
||||
@kindex maint with
|
||||
@item maint with @var{setting} [@var{value}] [-- @var{command}]
|
||||
Like the @code{with} command, but works with @code{maintenance set}
|
||||
variables. This is used by the testsuite to exercise the @code{with}
|
||||
command's infrastructure.
|
||||
|
||||
@end table
|
||||
|
||||
The following command is useful for non-interactive invocations of
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Support for GDB maintenance commands.
|
||||
/* Maintenance commands for testing the settings framework.
|
||||
|
||||
Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
|
||||
@@ -21,46 +21,33 @@
|
||||
#include "defs.h"
|
||||
#include "gdbcmd.h"
|
||||
|
||||
/* Command list for "maint test-settings". */
|
||||
static cmd_list_element *maintenance_test_settings_list;
|
||||
/* Command list for "maint set test-settings". */
|
||||
static cmd_list_element *maintenance_set_test_settings_list;
|
||||
|
||||
/* Command list for "maint test-settings set/show". */
|
||||
static cmd_list_element *maintenance_test_settings_set_list;
|
||||
static cmd_list_element *maintenance_test_settings_show_list;
|
||||
/* Command list for "maint show test-settings". */
|
||||
static cmd_list_element *maintenance_show_test_settings_list;
|
||||
|
||||
/* The "maintenance test-options" prefix command. */
|
||||
/* The "maintenance set test-settings" prefix command. */
|
||||
|
||||
static void
|
||||
maintenance_test_settings_cmd (const char *arg, int from_tty)
|
||||
maintenance_set_test_settings_cmd (const char *args, int from_tty)
|
||||
{
|
||||
printf_unfiltered
|
||||
(_("\"maintenance test-settings\" must be followed "
|
||||
"by the name of a subcommand.\n"));
|
||||
help_list (maintenance_test_settings_list, "maintenance test-settings ",
|
||||
all_commands, gdb_stdout);
|
||||
}
|
||||
|
||||
/* The "maintenance test-options set" prefix command. */
|
||||
|
||||
static void
|
||||
maintenance_test_settings_set_cmd (const char *args, int from_tty)
|
||||
{
|
||||
printf_unfiltered (_("\"maintenance test-settings set\" must be followed "
|
||||
printf_unfiltered (_("\"maintenance set test-settings\" must be followed "
|
||||
"by the name of a set command.\n"));
|
||||
help_list (maintenance_test_settings_set_list,
|
||||
"maintenance test-settings set ",
|
||||
help_list (maintenance_set_test_settings_list,
|
||||
"maintenance set test-settings ",
|
||||
all_commands, gdb_stdout);
|
||||
}
|
||||
|
||||
/* The "maintenance test-options show" prefix command. */
|
||||
/* The "maintenance show test-settings" prefix command. */
|
||||
|
||||
static void
|
||||
maintenance_test_settings_show_cmd (const char *args, int from_tty)
|
||||
maintenance_show_test_settings_cmd (const char *args, int from_tty)
|
||||
{
|
||||
cmd_show_list (maintenance_test_settings_show_list, from_tty, "");
|
||||
cmd_show_list (maintenance_show_test_settings_list, from_tty, "");
|
||||
}
|
||||
|
||||
/* Control variables for all the "maintenance test-options set/show
|
||||
/* Control variables for all the "maintenance set/show test-settings
|
||||
xxx" commands. */
|
||||
|
||||
static int maintenance_test_settings_boolean;
|
||||
@@ -85,18 +72,26 @@ static char *maintenance_test_settings_optional_filename;
|
||||
|
||||
static char *maintenance_test_settings_filename;
|
||||
|
||||
static const char *maintenance_test_settings_enum;
|
||||
|
||||
/* Enum values for the "maintenance test-settings set/show boolean"
|
||||
/* Enum values for the "maintenance set/show test-settings boolean"
|
||||
commands. */
|
||||
static const char maintenance_test_settings_xxx[] = "xxx";
|
||||
static const char maintenance_test_settings_yyy[] = "yyy";
|
||||
static const char maintenance_test_settings_zzz[] = "zzz";
|
||||
|
||||
static const char *const maintenance_test_settings_enums[] = {
|
||||
"xxx", "yyy", "zzz", nullptr
|
||||
maintenance_test_settings_xxx,
|
||||
maintenance_test_settings_yyy,
|
||||
maintenance_test_settings_zzz,
|
||||
nullptr
|
||||
};
|
||||
|
||||
/* The "maintenance test-options show xxx" commands. */
|
||||
static const char *maintenance_test_settings_enum
|
||||
= maintenance_test_settings_xxx;
|
||||
|
||||
/* The "maintenance show test-settings xxx" commands. */
|
||||
|
||||
static void
|
||||
maintenance_test_settings_show_value_cmd
|
||||
maintenance_show_test_settings_value_cmd
|
||||
(struct ui_file *file, int from_tty,
|
||||
struct cmd_list_element *c, const char *value)
|
||||
{
|
||||
@@ -107,29 +102,23 @@ maintenance_test_settings_show_value_cmd
|
||||
void
|
||||
_initialize_maint_test_settings (void)
|
||||
{
|
||||
add_prefix_cmd ("test-settings", no_class,
|
||||
maintenance_test_settings_cmd,
|
||||
_("\
|
||||
Generic command for testing the settings infrastructure."),
|
||||
&maintenance_test_settings_list,
|
||||
"maintenance test-settings ", 0,
|
||||
&maintenancelist);
|
||||
maintenance_test_settings_filename = xstrdup ("/foo/bar");
|
||||
|
||||
add_prefix_cmd ("set", class_maintenance,
|
||||
maintenance_test_settings_set_cmd, _("\
|
||||
add_prefix_cmd ("test-settings", class_maintenance,
|
||||
maintenance_set_test_settings_cmd, _("\
|
||||
Set GDB internal variables used for set/show command infrastructure testing."),
|
||||
&maintenance_test_settings_set_list,
|
||||
"maintenance test-settings set ",
|
||||
&maintenance_set_test_settings_list,
|
||||
"maintenance set test-settings ",
|
||||
0/*allow-unknown*/,
|
||||
&maintenance_test_settings_list);
|
||||
&maintenance_set_cmdlist);
|
||||
|
||||
add_prefix_cmd ("show", class_maintenance,
|
||||
maintenance_test_settings_show_cmd, _("\
|
||||
add_prefix_cmd ("test-settings", class_maintenance,
|
||||
maintenance_show_test_settings_cmd, _("\
|
||||
Show GDB internal variables used for set/show command infrastructure testing."),
|
||||
&maintenance_test_settings_show_list,
|
||||
"maintenance test-settings show ",
|
||||
&maintenance_show_test_settings_list,
|
||||
"maintenance show test-settings ",
|
||||
0/*allow-unknown*/,
|
||||
&maintenance_test_settings_list);
|
||||
&maintenance_show_cmdlist);
|
||||
|
||||
add_setshow_boolean_cmd ("boolean", class_maintenance,
|
||||
&maintenance_test_settings_boolean, _("\
|
||||
@@ -137,9 +126,9 @@ command used for internal testing"), _("\
|
||||
command used for internal testing"),
|
||||
nullptr, /* help_doc */
|
||||
nullptr, /* set_cmd */
|
||||
maintenance_test_settings_show_value_cmd,
|
||||
&maintenance_test_settings_set_list,
|
||||
&maintenance_test_settings_show_list);
|
||||
maintenance_show_test_settings_value_cmd,
|
||||
&maintenance_set_test_settings_list,
|
||||
&maintenance_show_test_settings_list);
|
||||
|
||||
add_setshow_auto_boolean_cmd ("auto-boolean", class_maintenance,
|
||||
&maintenance_test_settings_auto_boolean, _("\
|
||||
@@ -147,19 +136,19 @@ command used for internal testing"), _("\
|
||||
command used for internal testing"),
|
||||
nullptr, /* help_doc */
|
||||
nullptr, /* set_cmd */
|
||||
maintenance_test_settings_show_value_cmd,
|
||||
&maintenance_test_settings_set_list,
|
||||
&maintenance_test_settings_show_list);
|
||||
maintenance_show_test_settings_value_cmd,
|
||||
&maintenance_set_test_settings_list,
|
||||
&maintenance_show_test_settings_list);
|
||||
|
||||
add_setshow_uinteger_cmd ("uinteger", class_maintenance,
|
||||
&maintenance_test_settings_uinteger, _("\
|
||||
command used for internal testing"), _("\
|
||||
command used for internal testing"),
|
||||
nullptr, /* help_doc */
|
||||
nullptr, /* set_cmd */
|
||||
maintenance_test_settings_show_value_cmd,
|
||||
&maintenance_test_settings_set_list,
|
||||
&maintenance_test_settings_show_list);
|
||||
nullptr, /* help_doc */
|
||||
nullptr, /* set_cmd */
|
||||
maintenance_show_test_settings_value_cmd,
|
||||
&maintenance_set_test_settings_list,
|
||||
&maintenance_show_test_settings_list);
|
||||
|
||||
add_setshow_integer_cmd ("integer", class_maintenance,
|
||||
&maintenance_test_settings_integer, _("\
|
||||
@@ -167,9 +156,9 @@ command used for internal testing"), _("\
|
||||
command used for internal testing"),
|
||||
nullptr, /* help_doc */
|
||||
nullptr, /* set_cmd */
|
||||
maintenance_test_settings_show_value_cmd,
|
||||
&maintenance_test_settings_set_list,
|
||||
&maintenance_test_settings_show_list);
|
||||
maintenance_show_test_settings_value_cmd,
|
||||
&maintenance_set_test_settings_list,
|
||||
&maintenance_show_test_settings_list);
|
||||
|
||||
add_setshow_string_cmd ("string", class_maintenance,
|
||||
&maintenance_test_settings_string, _("\
|
||||
@@ -177,9 +166,9 @@ command used for internal testing"), _("\
|
||||
command used for internal testing"),
|
||||
nullptr, /* help_doc */
|
||||
nullptr, /* set_cmd */
|
||||
maintenance_test_settings_show_value_cmd,
|
||||
&maintenance_test_settings_set_list,
|
||||
&maintenance_test_settings_show_list);
|
||||
maintenance_show_test_settings_value_cmd,
|
||||
&maintenance_set_test_settings_list,
|
||||
&maintenance_show_test_settings_list);
|
||||
|
||||
add_setshow_string_noescape_cmd
|
||||
("string-noescape", class_maintenance,
|
||||
@@ -188,9 +177,9 @@ command used for internal testing"), _("\
|
||||
command used for internal testing"),
|
||||
nullptr, /* help_doc */
|
||||
nullptr, /* set_cmd */
|
||||
maintenance_test_settings_show_value_cmd,
|
||||
&maintenance_test_settings_set_list,
|
||||
&maintenance_test_settings_show_list);
|
||||
maintenance_show_test_settings_value_cmd,
|
||||
&maintenance_set_test_settings_list,
|
||||
&maintenance_show_test_settings_list);
|
||||
|
||||
add_setshow_optional_filename_cmd
|
||||
("optional-filename", class_maintenance,
|
||||
@@ -199,9 +188,9 @@ command used for internal testing"), _("\
|
||||
command used for internal testing"),
|
||||
nullptr, /* help_doc */
|
||||
nullptr, /* set_cmd */
|
||||
maintenance_test_settings_show_value_cmd,
|
||||
&maintenance_test_settings_set_list,
|
||||
&maintenance_test_settings_show_list);
|
||||
maintenance_show_test_settings_value_cmd,
|
||||
&maintenance_set_test_settings_list,
|
||||
&maintenance_show_test_settings_list);
|
||||
|
||||
add_setshow_filename_cmd ("filename", class_maintenance,
|
||||
&maintenance_test_settings_filename, _("\
|
||||
@@ -209,9 +198,9 @@ command used for internal testing"), _("\
|
||||
command used for internal testing"),
|
||||
nullptr, /* help_doc */
|
||||
nullptr, /* set_cmd */
|
||||
maintenance_test_settings_show_value_cmd,
|
||||
&maintenance_test_settings_set_list,
|
||||
&maintenance_test_settings_show_list);
|
||||
maintenance_show_test_settings_value_cmd,
|
||||
&maintenance_set_test_settings_list,
|
||||
&maintenance_show_test_settings_list);
|
||||
|
||||
add_setshow_zinteger_cmd ("zinteger", class_maintenance,
|
||||
&maintenance_test_settings_zinteger, _("\
|
||||
@@ -219,9 +208,9 @@ command used for internal testing"), _("\
|
||||
command used for internal testing"),
|
||||
nullptr, /* help_doc */
|
||||
nullptr, /* set_cmd */
|
||||
maintenance_test_settings_show_value_cmd,
|
||||
&maintenance_test_settings_set_list,
|
||||
&maintenance_test_settings_show_list);
|
||||
maintenance_show_test_settings_value_cmd,
|
||||
&maintenance_set_test_settings_list,
|
||||
&maintenance_show_test_settings_list);
|
||||
|
||||
add_setshow_zuinteger_cmd ("zuinteger", class_maintenance,
|
||||
&maintenance_test_settings_zuinteger, _("\
|
||||
@@ -229,9 +218,9 @@ command used for internal testing"), _("\
|
||||
command used for internal testing"),
|
||||
nullptr, /* help_doc */
|
||||
nullptr, /* set_cmd */
|
||||
maintenance_test_settings_show_value_cmd,
|
||||
&maintenance_test_settings_set_list,
|
||||
&maintenance_test_settings_show_list);
|
||||
maintenance_show_test_settings_value_cmd,
|
||||
&maintenance_set_test_settings_list,
|
||||
&maintenance_show_test_settings_list);
|
||||
|
||||
add_setshow_zuinteger_unlimited_cmd
|
||||
("zuinteger-unlimited", class_maintenance,
|
||||
@@ -240,9 +229,9 @@ command used for internal testing"), _("\
|
||||
command used for internal testing"),
|
||||
nullptr, /* help_doc */
|
||||
nullptr, /* set_cmd */
|
||||
maintenance_test_settings_show_value_cmd,
|
||||
&maintenance_test_settings_set_list,
|
||||
&maintenance_test_settings_show_list);
|
||||
maintenance_show_test_settings_value_cmd,
|
||||
&maintenance_set_test_settings_list,
|
||||
&maintenance_show_test_settings_list);
|
||||
|
||||
add_setshow_enum_cmd ("enum", class_maintenance,
|
||||
maintenance_test_settings_enums,
|
||||
@@ -251,7 +240,7 @@ command used for internal testing"), _("\
|
||||
command used for internal testing"),
|
||||
nullptr, /* help_doc */
|
||||
nullptr, /* set_cmd */
|
||||
maintenance_test_settings_show_value_cmd,
|
||||
&maintenance_test_settings_set_list,
|
||||
&maintenance_test_settings_show_list);
|
||||
maintenance_show_test_settings_value_cmd,
|
||||
&maintenance_set_test_settings_list,
|
||||
&maintenance_show_test_settings_list);
|
||||
}
|
||||
|
||||
28
gdb/maint.c
28
gdb/maint.c
@@ -43,6 +43,7 @@
|
||||
#include "cli/cli-decode.h"
|
||||
#include "cli/cli-utils.h"
|
||||
#include "cli/cli-setshow.h"
|
||||
#include "cli/cli-cmds.h"
|
||||
|
||||
static void maintenance_do_deprecate (const char *, int);
|
||||
|
||||
@@ -634,6 +635,24 @@ maintenance_show_cmd (const char *args, int from_tty)
|
||||
cmd_show_list (maintenance_show_cmdlist, from_tty, "");
|
||||
}
|
||||
|
||||
/* "maintenance with" command. */
|
||||
|
||||
static void
|
||||
maintenance_with_cmd (const char *args, int from_tty)
|
||||
{
|
||||
with_command_1 ("maintenance set ", maintenance_set_cmdlist, args, from_tty);
|
||||
}
|
||||
|
||||
/* "maintenance with" command completer. */
|
||||
|
||||
static void
|
||||
maintenance_with_cmd_completer (struct cmd_list_element *ignore,
|
||||
completion_tracker &tracker,
|
||||
const char *text, const char * /*word*/)
|
||||
{
|
||||
with_command_completer_1 ("maintenance set ", tracker, text);
|
||||
}
|
||||
|
||||
/* Profiling support. */
|
||||
|
||||
static int maintenance_profile_p;
|
||||
@@ -1023,6 +1042,15 @@ Configure variables internal to GDB that aid in GDB's maintenance"),
|
||||
0/*allow-unknown*/,
|
||||
&maintenancelist);
|
||||
|
||||
cmd = add_cmd ("with", class_maintenance, maintenance_with_cmd, _("\
|
||||
Like \"with\", but works with \"maintenance set\" variables.\n\
|
||||
Usage: maintenance with SETTING [VALUE] [-- COMMAND]\n\
|
||||
With no COMMAND, repeats the last executed command.\n\
|
||||
SETTING is any setting you can change with the \"maintenance set\"\n\
|
||||
subcommands."),
|
||||
&maintenancelist);
|
||||
set_cmd_completer_handle_brkchars (cmd, maintenance_with_cmd_completer);
|
||||
|
||||
#ifndef _WIN32
|
||||
add_cmd ("dump-me", class_maintenance, maintenance_dump_me, _("\
|
||||
Get fatal error; make debugger dump its core.\n\
|
||||
|
||||
@@ -454,6 +454,21 @@ proc_with_prefix test-thread-apply {} {
|
||||
}
|
||||
}
|
||||
|
||||
# Basic option-machinery + "info threads" command integration tests.
|
||||
proc_with_prefix test-info-threads {} {
|
||||
test_gdb_complete_multiple "info threads " "" "" {
|
||||
"-gid"
|
||||
"ID"
|
||||
}
|
||||
|
||||
test_gdb_complete_unique \
|
||||
"info threads -" \
|
||||
"info threads -gid"
|
||||
|
||||
# "ID" isn't really something the user can type.
|
||||
test_gdb_complete_none "info threads I"
|
||||
}
|
||||
|
||||
# Miscellaneous tests.
|
||||
proc_with_prefix test-misc {variant} {
|
||||
global all_options
|
||||
@@ -921,3 +936,6 @@ test-frame-apply
|
||||
|
||||
# Basic "thread apply" integration tests.
|
||||
test-thread-apply
|
||||
|
||||
# Basic "info threads" integration tests.
|
||||
test-info-threads
|
||||
|
||||
@@ -45,8 +45,8 @@ proc show_setting {show_cmd expected_re} {
|
||||
# var_Xinteger tests. VARIANT determines which command/variant to
|
||||
# exercise.
|
||||
proc test-integer {variant} {
|
||||
set set_cmd "maint test-settings set $variant"
|
||||
set show_cmd "maint test-settings show $variant"
|
||||
set set_cmd "maint set test-settings $variant"
|
||||
set show_cmd "maint show test-settings $variant"
|
||||
|
||||
# A bogus value.
|
||||
gdb_test "$set_cmd bogus" \
|
||||
@@ -122,7 +122,7 @@ proc test-integer {variant} {
|
||||
}
|
||||
|
||||
if {$variant == "zuinteger"} {
|
||||
test_gdb_complete_multiple "maint test-settings set " "zuinteger" "" {
|
||||
test_gdb_complete_multiple "maint set test-settings " "zuinteger" "" {
|
||||
"zuinteger"
|
||||
"zuinteger-unlimited"
|
||||
}
|
||||
@@ -166,7 +166,7 @@ proc test-integer {variant} {
|
||||
|
||||
# Check show command completion.
|
||||
if {$variant == "zuinteger"} {
|
||||
test_gdb_complete_multiple "maintenance test-settings show " "zuinteger" "" {
|
||||
test_gdb_complete_multiple "maintenance show test-settings " "zuinteger" "" {
|
||||
"zuinteger"
|
||||
"zuinteger-unlimited"
|
||||
}
|
||||
@@ -182,8 +182,8 @@ proc test-integer {variant} {
|
||||
proc_with_prefix test-boolean {} {
|
||||
# Use these variables to make sure we don't call the wrong command
|
||||
# by mistake.
|
||||
set set_cmd "maint test-settings set boolean"
|
||||
set show_cmd "maint test-settings show boolean"
|
||||
set set_cmd "maint set test-settings boolean"
|
||||
set show_cmd "maint show test-settings boolean"
|
||||
|
||||
# A bogus value.
|
||||
gdb_test "$set_cmd bogus" \
|
||||
@@ -277,8 +277,8 @@ proc_with_prefix test-boolean {} {
|
||||
proc_with_prefix test-auto-boolean {} {
|
||||
# Use these variables to make sure we don't call the wrong command
|
||||
# by mistake.
|
||||
set set_cmd "maint test-settings set auto-boolean"
|
||||
set show_cmd "maint test-settings show auto-boolean"
|
||||
set set_cmd "maint set test-settings auto-boolean"
|
||||
set show_cmd "maint show test-settings auto-boolean"
|
||||
|
||||
# A bogus value.
|
||||
gdb_test "$set_cmd bogus" \
|
||||
@@ -381,8 +381,8 @@ proc_with_prefix test-auto-boolean {} {
|
||||
proc_with_prefix test-enum {} {
|
||||
# Use these variables to make sure we don't call the wrong command
|
||||
# by mistake.
|
||||
set set_cmd "maint test-settings set enum"
|
||||
set show_cmd "maint test-settings show enum"
|
||||
set set_cmd "maint set test-settings enum"
|
||||
set show_cmd "maint show test-settings enum"
|
||||
|
||||
# Missing value.
|
||||
gdb_test "$set_cmd" \
|
||||
@@ -444,12 +444,15 @@ proc test-string {variant} {
|
||||
|
||||
# Use these variables to make sure we don't call the wrong command
|
||||
# by mistake.
|
||||
set set_cmd "maint test-settings set $variant"
|
||||
set show_cmd "maint test-settings show $variant"
|
||||
set set_cmd "maint set test-settings $variant"
|
||||
set show_cmd "maint show test-settings $variant"
|
||||
|
||||
# Empty string. Also checks that gdb doesn't crash if we haven't
|
||||
# set the string yet.
|
||||
gdb_test "$show_cmd" "^$show_cmd\r\n" "$show_cmd: empty first time"
|
||||
# Checks that gdb doesn't crash if we haven't set the string yet.
|
||||
if {$variant != "filename"} {
|
||||
gdb_test "$show_cmd" "^$show_cmd\r\n" "$show_cmd: show default"
|
||||
} else {
|
||||
gdb_test "$show_cmd" "/foo/bar" "$show_cmd: show default"
|
||||
}
|
||||
|
||||
# A string value.
|
||||
gdb_test_no_output "$set_cmd hello world"
|
||||
@@ -516,7 +519,7 @@ proc test-string {variant} {
|
||||
|
||||
# Check show command completion.
|
||||
if {$variant == "string"} {
|
||||
test_gdb_complete_multiple "maint test-settings show " "string" "" {
|
||||
test_gdb_complete_multiple "maint show test-settings " "string" "" {
|
||||
"string"
|
||||
"string-noescape"
|
||||
}
|
||||
|
||||
41
gdb/testsuite/gdb.base/with.c
Normal file
41
gdb/testsuite/gdb.base/with.c
Normal file
@@ -0,0 +1,41 @@
|
||||
/* This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
Copyright 2019 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
int xxx1 = 123;
|
||||
|
||||
struct S
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
};
|
||||
|
||||
struct S g_s = {1, 2, 3};
|
||||
|
||||
static void
|
||||
inc ()
|
||||
{
|
||||
g_s.a++;;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
inc ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
289
gdb/testsuite/gdb.base/with.exp
Normal file
289
gdb/testsuite/gdb.base/with.exp
Normal file
@@ -0,0 +1,289 @@
|
||||
# This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
# Copyright 2019 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Test the "with" command.
|
||||
|
||||
load_lib completion-support.exp
|
||||
|
||||
standard_testfile .c
|
||||
|
||||
if {[build_executable "failed to prepare" $testfile $srcfile debug]} {
|
||||
return -1
|
||||
}
|
||||
|
||||
clean_restart $binfile
|
||||
|
||||
# Test "maint with". VALUES is a list of values. A nested "with" is
|
||||
# performed with each combination of pair of values from this list.
|
||||
# This exercises setting a value, and restoring it too. This is
|
||||
# particularly important for the "special" values like "unlimited",
|
||||
# which for example for var_uinteger maps to 0 at the user-visible
|
||||
# level, but maps to -1 internally.
|
||||
|
||||
proc test_with {setting values} {
|
||||
foreach val1 $values {
|
||||
foreach val2 $values {
|
||||
gdb_test \
|
||||
"maint with test-settings $setting $val1 -- maint with test-settings $setting $val2 -- p 1" \
|
||||
" = 1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Test "maint with" in the error case. SETTING is the "maint set
|
||||
# test-setting" setting to exercise. TMP_VAL is the value to set the
|
||||
# setting to. EXPECTED_RE is the expected GDB output, which should be
|
||||
# an error of some kind. Also checks that the setting's original
|
||||
# value is preserved across the error.
|
||||
|
||||
proc test_with_error {setting tmp_val expected_re} {
|
||||
global gdb_prompt
|
||||
|
||||
with_test_prefix "$setting, $tmp_val" {
|
||||
set test "save org value"
|
||||
set org_val ""
|
||||
gdb_test_multiple "maint show test-settings $setting" $test {
|
||||
-re "(.*)\r\n$gdb_prompt $" {
|
||||
set org_val $expect_out(1,string)
|
||||
pass $test
|
||||
}
|
||||
}
|
||||
|
||||
gdb_test \
|
||||
"maint with test-settings $setting $tmp_val -- p 1" \
|
||||
$expected_re
|
||||
|
||||
gdb_test "maint show test-settings $setting" "^$org_val" \
|
||||
"value hasn't changed across error"
|
||||
}
|
||||
}
|
||||
|
||||
# Test "with" framework basics, using the internal "maint with
|
||||
# test-settings" subcommands.
|
||||
with_test_prefix "maint" {
|
||||
test_with "auto-boolean" {"on" "off" "auto"}
|
||||
test_with "boolean" {"" "on" "off" "0" "1" "enable" "disable"}
|
||||
test_with "integer" {"0" "1" "-1" "unlimited"}
|
||||
test_with "uinteger" {"0" "1" "unlimited"}
|
||||
test_with "zinteger" {"0" "1" "-1"}
|
||||
test_with "zuinteger" {"0" "1"}
|
||||
test_with "zuinteger-unlimited" {"-1" "unlimited" "0" "1"}
|
||||
test_with "string" {"" "foo" "\"hello world\""}
|
||||
test_with "string-noescape" {"" "foo" "\"hello world\""}
|
||||
test_with "filename" {"/foo" "bar/x/y"}
|
||||
test_with "optional-filename" {"" "/foo" "bar/x/y"}
|
||||
test_with "enum" {"xxx" "yyy"}
|
||||
|
||||
# Check the most important error conditions. E.g., empty,
|
||||
# negative or "unlimited" values for settings that don't accept
|
||||
# those. Exhaustive error coverage of the set/with value parsing
|
||||
# is left to "set" testing, in gdb.base/settings.exp.
|
||||
test_with_error "auto-boolean" "" \
|
||||
"\"on\", \"off\" or \"auto\" expected\\."
|
||||
test_with_error "auto-boolean" "xxx" \
|
||||
"\"on\", \"off\" or \"auto\" expected\\."
|
||||
test_with_error "boolean" "2" "\"on\" or \"off\" expected\\."
|
||||
test_with_error "uinteger" "-1" "integer -1 out of range"
|
||||
test_with_error "uinteger" "" \
|
||||
"Argument required \\(integer to set it to, or \"unlimited\"\\.\\)\\."
|
||||
test_with_error "zuinteger" "-1" "integer -1 out of range"
|
||||
test_with_error "zuinteger" "" \
|
||||
"Argument required \\(integer to set it to\\.\\)\\."
|
||||
test_with_error "zuinteger-unlimited" "-2" \
|
||||
"only -1 is allowed to set as unlimited"
|
||||
test_with_error "zuinteger-unlimited" "" \
|
||||
"Argument required \\(integer to set it to, or \"unlimited\"\\.\\)\\."
|
||||
test_with_error "filename" "" \
|
||||
"Argument required \\(filename to set it to\\.\\)\\."
|
||||
test_with_error "enum" "" \
|
||||
"Requires an argument\\. Valid arguments are xxx, yyy, zzz\\."
|
||||
}
|
||||
|
||||
# Basic/core tests using user-visible commands.
|
||||
with_test_prefix "basics" {
|
||||
gdb_test "print g_s" " = {a = 1, b = 2, c = 3}"
|
||||
gdb_test "with print pretty -- print g_s" \
|
||||
[multi_line \
|
||||
" = {" \
|
||||
" a = 1," \
|
||||
" b = 2," \
|
||||
" c = 3" \
|
||||
"}"]
|
||||
|
||||
# A boolean setting.
|
||||
gdb_test "with non-stop on -- show non-stop" \
|
||||
"Controlling the inferior in non-stop mode is on\\."
|
||||
gdb_test "show non-stop" \
|
||||
"Controlling the inferior in non-stop mode is off\\."
|
||||
|
||||
# Language.
|
||||
gdb_test "with language pascal -- show language" \
|
||||
"The current source language is \"pascal\"\\."
|
||||
|
||||
gdb_test "show language" \
|
||||
"The current source language is \"auto; currently c\"\\."
|
||||
|
||||
gdb_test "with language ada -- print g_s" \
|
||||
" = \\(a => 1, b => 2, c => 3\\)"
|
||||
|
||||
# Nested "with"s.
|
||||
gdb_test "with language ada -- with language c -- print g_s" \
|
||||
" = {a = 1, b = 2, c = 3}"
|
||||
|
||||
# "w" alias.
|
||||
gdb_test "w language pascal -- show language" \
|
||||
"The current source language is \"pascal\"\\." \
|
||||
"w alias works"
|
||||
|
||||
# An early prototype of the "with" command got this wrong.
|
||||
gdb_test \
|
||||
"w print repeats unlimited -- w print repeats 1 -- p \"1223334444\"" \
|
||||
" = \"1\", '2' <repeats 2 times>, '3' <repeats 3 times>, '4' <repeats 4 times>"
|
||||
}
|
||||
|
||||
# Check a user-defined command.
|
||||
with_test_prefix "user-defined" {
|
||||
# A user defined command.
|
||||
set test "define usercmd"
|
||||
gdb_test_multiple "define usercmd" $test {
|
||||
-re "End with" {
|
||||
gdb_test \
|
||||
[multi_line_input \
|
||||
{print g_s} \
|
||||
{end}] \
|
||||
"" \
|
||||
$test
|
||||
}
|
||||
}
|
||||
gdb_test "with language ada -- usercmd" \
|
||||
" = \\(a => 1, b => 2, c => 3\\)"
|
||||
}
|
||||
|
||||
# Check repeating.
|
||||
with_test_prefix "repeat" {
|
||||
clean_restart $binfile
|
||||
|
||||
# "with" with no command reinvokes the previous command.
|
||||
gdb_test "with language ada" \
|
||||
"No previous command to relaunch" \
|
||||
"reinvoke with no previous command to relaunch"
|
||||
|
||||
gdb_test "print g_s" " = {a = 1, b = 2, c = 3}"
|
||||
|
||||
gdb_test "with language ada" \
|
||||
" = \\(a => 1, b => 2, c => 3\\)" \
|
||||
"reinvoke with language"
|
||||
|
||||
# Same, but with "--".
|
||||
gdb_test "with language fortran --" \
|
||||
" = \\( a = 1, b = 2, c = 3 \\)" \
|
||||
"reinvoke with language and --"
|
||||
|
||||
# Repeating repeats the original "print g_s", not the last "with"
|
||||
# command.
|
||||
set test "repeat command line"
|
||||
send_gdb "\n"
|
||||
gdb_test_multiple "" $test {
|
||||
-re " = {a = 1, b = 2, c = 3}\r\n$gdb_prompt $" {
|
||||
pass $test
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Basic run control.
|
||||
with_test_prefix "run control" {
|
||||
clean_restart $binfile
|
||||
|
||||
if ![runto_main] {
|
||||
fail "cannot run to main"
|
||||
return
|
||||
}
|
||||
|
||||
# Check "with" with a synchronous execution command.
|
||||
gdb_test "with disassemble-next-line on -- next" \
|
||||
"return 0;.*=>.*"
|
||||
}
|
||||
|
||||
# Check errors.
|
||||
with_test_prefix "errors" {
|
||||
# Try both an unknown root setting and an unknown prefixed
|
||||
# setting. The errors come from different locations in the
|
||||
# sources.
|
||||
gdb_test "with xxxx yyyy" \
|
||||
"Undefined set command: \"xxxx\". Try \"help set\"\\."
|
||||
gdb_test "with print xxxx yyyy" \
|
||||
"Undefined set print command: \"xxxx yyyy\". Try \"help set print\"\\."
|
||||
# Try one error case for "maint with", to make sure the right
|
||||
# "maintenance with" prefix is shown.
|
||||
gdb_test "maint with xxxx yyyy" \
|
||||
"Undefined maintenance set command: \"xxxx\". Try \"help maintenance set\"\\."
|
||||
|
||||
# Try ambiguous settings.
|
||||
gdb_test "with w" \
|
||||
"Ambiguous set command \"w\": watchdog, width, write\\."
|
||||
gdb_test "with print m" \
|
||||
"Ambiguous set print command \"m\": max-depth, max-symbolic-offset\\."
|
||||
|
||||
gdb_test "with variable xxx=1" \
|
||||
"Cannot use this setting with the \"with\" command"
|
||||
|
||||
gdb_test "with print elements -- p 1" \
|
||||
"Argument required \\(integer to set it to, or \"unlimited\"\\.\\)\\."
|
||||
|
||||
gdb_test "with -- p 1" \
|
||||
"Missing setting before '--' delimiter"
|
||||
|
||||
# Check that the setting is restored even if the command throws.
|
||||
gdb_test "with print elements 1 -- unknowncommand" \
|
||||
"Undefined command: \"unknowncommand\"\\. Try \"help\"\\."
|
||||
gdb_test "show print elements" \
|
||||
"Limit on string chars or array elements to print is 200\\."
|
||||
}
|
||||
|
||||
# Check completion.
|
||||
with_test_prefix "completion" {
|
||||
test_gdb_complete_unique \
|
||||
"with pri" \
|
||||
"with print"
|
||||
|
||||
test_gdb_complete_unique \
|
||||
"with print ele" \
|
||||
"with print elements"
|
||||
|
||||
test_gdb_complete_unique \
|
||||
"with print elements u" \
|
||||
"with print elements unlimited"
|
||||
|
||||
test_gdb_complete_none \
|
||||
"with print elements unlimited "
|
||||
|
||||
test_gdb_completion_offers_commands "with print elements unlimited -- "
|
||||
|
||||
# Check that the completer nests into the nested command line's
|
||||
# completer.
|
||||
test_gdb_complete_unique \
|
||||
"with print elements unlimited -- with print ele" \
|
||||
"with print elements unlimited -- with print elements"
|
||||
|
||||
# Check completion of "maint with". "maint with" and "with"'s
|
||||
# completers share 99% of the code. All we need to care about
|
||||
# here is that the completion word point is computed correctly, so
|
||||
# any simple completion is sufficient.
|
||||
test_gdb_complete_unique \
|
||||
"maint with test-set" \
|
||||
"maint with test-settings"
|
||||
}
|
||||
82
gdb/thread.c
82
gdb/thread.c
@@ -1199,6 +1199,33 @@ print_thread_info (struct ui_out *uiout, const char *requested_threads,
|
||||
print_thread_info_1 (uiout, requested_threads, 1, pid, 0);
|
||||
}
|
||||
|
||||
/* The options for the "info threads" command. */
|
||||
|
||||
struct info_threads_opts
|
||||
{
|
||||
/* For "-gid". */
|
||||
int show_global_ids = 0;
|
||||
};
|
||||
|
||||
static const gdb::option::option_def info_threads_option_defs[] = {
|
||||
|
||||
gdb::option::flag_option_def<info_threads_opts> {
|
||||
"gid",
|
||||
[] (info_threads_opts *opts) { return &opts->show_global_ids; },
|
||||
N_("Show global thread IDs."),
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
/* Create an option_def_group for the "info threads" options, with
|
||||
IT_OPTS as context. */
|
||||
|
||||
static inline gdb::option::option_def_group
|
||||
make_info_threads_options_def_group (info_threads_opts *it_opts)
|
||||
{
|
||||
return {{info_threads_option_defs}, it_opts};
|
||||
}
|
||||
|
||||
/* Implementation of the "info threads" command.
|
||||
|
||||
Note: this has the drawback that it _really_ switches
|
||||
@@ -1208,16 +1235,36 @@ print_thread_info (struct ui_out *uiout, const char *requested_threads,
|
||||
static void
|
||||
info_threads_command (const char *arg, int from_tty)
|
||||
{
|
||||
int show_global_ids = 0;
|
||||
info_threads_opts it_opts;
|
||||
|
||||
if (arg != NULL
|
||||
&& check_for_argument (&arg, "-gid", sizeof ("-gid") - 1))
|
||||
auto grp = make_info_threads_options_def_group (&it_opts);
|
||||
gdb::option::process_options
|
||||
(&arg, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, grp);
|
||||
|
||||
print_thread_info_1 (current_uiout, arg, 0, -1, it_opts.show_global_ids);
|
||||
}
|
||||
|
||||
/* Completer for the "info threads" command. */
|
||||
|
||||
static void
|
||||
info_threads_command_completer (struct cmd_list_element *ignore,
|
||||
completion_tracker &tracker,
|
||||
const char *text, const char *word_ignored)
|
||||
{
|
||||
const auto grp = make_info_threads_options_def_group (nullptr);
|
||||
|
||||
if (gdb::option::complete_options
|
||||
(tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, grp))
|
||||
return;
|
||||
|
||||
/* Convenience to let the user know what the option can accept. */
|
||||
if (*text == '\0')
|
||||
{
|
||||
arg = skip_spaces (arg);
|
||||
show_global_ids = 1;
|
||||
gdb::option::complete_on_all_options (tracker, grp);
|
||||
/* Keep this "ID" in sync with what "help info threads"
|
||||
says. */
|
||||
tracker.add_completion (make_unique_xstrdup ("ID"));
|
||||
}
|
||||
|
||||
print_thread_info_1 (current_uiout, arg, 0, -1, show_global_ids);
|
||||
}
|
||||
|
||||
/* See gdbthread.h. */
|
||||
@@ -2068,12 +2115,23 @@ _initialize_thread (void)
|
||||
static struct cmd_list_element *thread_apply_list = NULL;
|
||||
cmd_list_element *c;
|
||||
|
||||
add_info ("threads", info_threads_command,
|
||||
_("Display currently known threads.\n\
|
||||
Usage: info threads [-gid] [ID]...\n\
|
||||
-gid: Show global thread IDs.\n\
|
||||
const auto info_threads_opts = make_info_threads_options_def_group (nullptr);
|
||||
|
||||
/* Note: keep this "ID" in sync with what "info threads [TAB]"
|
||||
suggests. */
|
||||
static std::string info_threads_help
|
||||
= gdb::option::build_help (_("\
|
||||
Display currently known threads.\n\
|
||||
Usage: info threads [OPTION]... [ID]...\n\
|
||||
\n\
|
||||
Options:\n\
|
||||
%OPTIONS%\
|
||||
If ID is given, it is a space-separated list of IDs of threads to display.\n\
|
||||
Otherwise, all threads are displayed."));
|
||||
Otherwise, all threads are displayed."),
|
||||
info_threads_opts);
|
||||
|
||||
c = add_info ("threads", info_threads_command, info_threads_help.c_str ());
|
||||
set_cmd_completer_handle_brkchars (c, info_threads_command_completer);
|
||||
|
||||
add_prefix_cmd ("thread", class_run, thread_command, _("\
|
||||
Use this command to switch between threads.\n\
|
||||
|
||||
@@ -735,7 +735,7 @@ dont_repeat (void)
|
||||
|
||||
/* See command.h */
|
||||
|
||||
void
|
||||
const char *
|
||||
repeat_previous ()
|
||||
{
|
||||
/* Do not repeat this command, as this command is a repeating command. */
|
||||
@@ -745,6 +745,11 @@ repeat_previous ()
|
||||
so swap it with previous_saved_command_line. */
|
||||
std::swap (previous_saved_command_line, saved_command_line);
|
||||
std::swap (previous_repeat_arguments, repeat_arguments);
|
||||
|
||||
const char *prev = skip_spaces (get_saved_command_line ());
|
||||
if (*prev == '\0')
|
||||
error (_("No previous command to relaunch"));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/* See command.h. */
|
||||
|
||||
Reference in New Issue
Block a user