diff options
Diffstat (limited to 'gdb/cli')
-rw-r--r-- | gdb/cli/cli-cmds.c | 134 | ||||
-rw-r--r-- | gdb/cli/cli-cmds.h | 15 | ||||
-rw-r--r-- | gdb/cli/cli-setshow.c | 74 | ||||
-rw-r--r-- | gdb/cli/cli-setshow.h | 5 |
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 (¤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. */ @@ -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); |