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 ())
gdb_cmd = repeat_previous ();
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)
{
\n\
With no COMMAND, repeat the last executed command\n\
and send its output to SHELL_COMMAND."));
+ set_cmd_completer_handle_brkchars (c, pipe_command_completer);
add_com_alias ("|", "pipe", class_support, 0);
add_com ("list", class_files, list_command, _("\
# Test that the "shell", "!", "|" and "pipe" commands work.
+load_lib completion-support.exp
+
gdb_exit
gdb_start
# Error handling verifications.
gdb_test "|" "Missing COMMAND" "all missing"
-gdb_test "|-d" "Missing delimiter DELIM after -d" "-d value missing"
-gdb_test "|-d " "Missing delimiter DELIM after -d" "-d spaces value missing"
+gdb_test "|-d" "-d requires an argument" "-d value missing"
+gdb_test "|-d " "-d requires an argument" "-d spaces value missing"
gdb_test "| echo coucou" \
"Missing delimiter before SHELL_COMMAND" \
"| delimiter missing"
"Missing delimiter before SHELL_COMMAND" \
"delimiter missing due to missing space"
+# Completion tests.
+
+test_gdb_complete_unique \
+ "pipe" \
+ "pipe"
+
+# Note that unlike "pipe", "|" doesn't require a space. This checks
+# that completion behaves that way too.
+foreach cmd {"pipe " "| " "|"} {
+ test_gdb_completion_offers_commands "$cmd"
+
+ # There's only one option.
+ test_gdb_complete_unique \
+ "${cmd}-" \
+ "${cmd}-d"
+
+ # Cannot complete "-d"'s argument.
+ test_gdb_complete_none "${cmd}-d "
+ test_gdb_complete_none "${cmd}-d main"
+
+ # Check completing a GDB command, with and without -d.
+ test_gdb_complete_unique \
+ "${cmd}maint set test-se" \
+ "${cmd}maint set test-settings"
+ test_gdb_complete_unique \
+ "${cmd}-d XXX maint set test-se" \
+ "${cmd}-d XXX maint set test-settings"
+
+ # Check that GDB doesn't try to complete the shell command.
+ test_gdb_complete_none \
+ "${cmd}print 1 | "
+
+ # Same, while making sure that the completer understands "-d".
+ test_gdb_complete_unique \
+ "${cmd}-d XXX maint set" \
+ "${cmd}-d XXX maint set"
+ test_gdb_complete_none \
+ "${cmd}-d set maint set"
+ test_gdb_complete_none \
+ "${cmd}-d set maint set "
+}