aboutsummaryrefslogtreecommitdiff
path: root/gdb/cli
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/cli')
-rw-r--r--gdb/cli/cli-cmds.c134
-rw-r--r--gdb/cli/cli-cmds.h15
-rw-r--r--gdb/cli/cli-setshow.c74
-rw-r--r--gdb/cli/cli-setshow.h5
4 files changed, 187 insertions, 41 deletions
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 5124ab3..d1ecd62 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -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 (&current_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. */
@@ -878,12 +988,7 @@ pipe_command (const char *arg, int from_tty)
arg += delim.length (); /* 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')
@@ -1850,6 +1955,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\
diff --git a/gdb/cli/cli-cmds.h b/gdb/cli/cli-cmds.h
index 63b8c40..94e210a 100644
--- a/gdb/cli/cli-cmds.h
+++ b/gdb/cli/cli-cmds.h
@@ -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 */
diff --git a/gdb/cli/cli-setshow.c b/gdb/cli/cli-setshow.c
index d588d04..6fb3244 100644
--- a/gdb/cli/cli-setshow.c
+++ b/gdb/cli/cli-setshow.c
@@ -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 ());
+}
+
+
+/* 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: 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. */
+ /* 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);
diff --git a/gdb/cli/cli-setshow.h b/gdb/cli/cli-setshow.h
index c00a098..8bfe7e8 100644
--- a/gdb/cli/cli-setshow.h
+++ b/gdb/cli/cli-setshow.h
@@ -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);