aboutsummaryrefslogtreecommitdiff
path: root/gdb/cli
diff options
context:
space:
mode:
authorAndrew Burgess <aburgess@redhat.com>2024-09-11 15:25:32 +0100
committerAndrew Burgess <aburgess@redhat.com>2024-11-04 15:56:01 +0000
commit3105b46ed1ed31de8e3cb9768ea181801fc05008 (patch)
treeac9470b1f5c32bb09cc48bef343f2c84d22f4924 /gdb/cli
parent91f8973ba3dff221eb4a3cd2695f3348260972f5 (diff)
downloadbinutils-3105b46ed1ed31de8e3cb9768ea181801fc05008.zip
binutils-3105b46ed1ed31de8e3cb9768ea181801fc05008.tar.gz
binutils-3105b46ed1ed31de8e3cb9768ea181801fc05008.tar.bz2
gdb: add filename option support
This commit adds support for filename options to GDB's option sub-system (see cli/cli-option.{c,h}). The new filename options support quoted and escaped filenames, and tab completion is fully supported. This commit adds the new option, and adds these options to the 'maintenance test-options' command as '-filename', along with some tests that exercise this new option. I've split the -filename testing into two. In gdb.base/options.exp we use the -filename option with some arbitrary strings. This tests that GDB can correctly extract the value from a filename option, and that GDB can complete other options after a filename option. However, these tests don't actually pass real filenames, nor do they test filename completion. In gdb.base/filename-completion.exp I have added some tests that test the -filename option with real filenames, and exercise filename tab completion. This commit doesn't include any real uses of the new filename options, that will come in the next commit.
Diffstat (limited to 'gdb/cli')
-rw-r--r--gdb/cli/cli-option.c90
-rw-r--r--gdb/cli/cli-option.h20
2 files changed, 107 insertions, 3 deletions
diff --git a/gdb/cli/cli-option.c b/gdb/cli/cli-option.c
index 0553928..9eb9ff8 100644
--- a/gdb/cli/cli-option.c
+++ b/gdb/cli/cli-option.c
@@ -43,7 +43,7 @@ union option_value
/* For var_enum options. */
const char *enumeration;
- /* For var_string options. This is malloc-allocated. */
+ /* For var_string and var_filename options. This is allocated with new. */
std::string *string;
};
@@ -85,7 +85,7 @@ struct option_def_and_value
{
if (value.has_value ())
{
- if (option.type == var_string)
+ if (option.type == var_string || option.type == var_filename)
delete value->string;
}
}
@@ -102,7 +102,7 @@ private:
{
if (value.has_value ())
{
- if (option.type == var_string)
+ if (option.type == var_string || option.type == var_filename)
value->string = nullptr;
}
}
@@ -452,6 +452,78 @@ parse_option (gdb::array_view<const option_def_group> options_group,
return option_def_and_value {*match, match_ctx, val};
}
+ case var_filename:
+ {
+ if (check_for_argument (args, "--"))
+ {
+ /* Treat e.g., "maint test-options -filename --" as if there
+ was no argument after "-filename". */
+ error (_("-%s requires an argument"), match->name);
+ }
+
+ const char *arg_start = *args;
+ std::string str = extract_string_maybe_quoted (args);
+
+ /* If we are performing completion, and extracting STR moved ARGS
+ to the end of the line, then the user is trying to complete the
+ filename value.
+
+ If ARGS didn't make it to the end of the line then the filename
+ value is already complete and the user is trying to complete
+ something later on the line. */
+ if (completion != nullptr && **args == '\0')
+ {
+ /* Preserve the current custom word point. If the call to
+ advance_to_filename_maybe_quoted_complete_word_point below
+ skips to the end of the command line then the custom word
+ point will have been updated even though we generate no
+ completions.
+
+ However, *ARGS will also have been updated, and the general
+ option completion code (which we will return too) also
+ updates the custom word point based on the adjustment made
+ to *ARGS.
+
+ And so, if we don't find any completions, we should restore
+ the custom word point value, this leaves the generic option
+ completion code free to make its own adjustments. */
+ int prev_word_pt = completion->tracker.custom_word_point ();
+
+ /* From ARG_START move forward to the start of the completion
+ word, this will skip over any opening quote if there is
+ one.
+
+ If the word to complete is fully quoted, i.e. has an
+ opening and closing quote, then this will skip over the
+ word entirely and leave WORD pointing to the end of the
+ input string. */
+ const char *word
+ = advance_to_filename_maybe_quoted_complete_word_point
+ (completion->tracker, arg_start);
+
+ if (word == arg_start || *word != '\0')
+ {
+ filename_maybe_quoted_completer (nullptr, completion->tracker,
+ arg_start, word);
+
+ if (completion->tracker.have_completions ())
+ return {};
+ }
+
+ /* No completions. Restore the custom word point. See the
+ comment above for why this is needed. */
+ completion->tracker.set_custom_word_point (prev_word_pt);
+ }
+
+ /* Check we did manage to extract something. */
+ if (*args == arg_start)
+ error (_("-%s requires an argument"), match->name);
+
+ option_value val;
+ val.string = new std::string (std::move (str));
+ return option_def_and_value {*match, match_ctx, val};
+ }
+
default:
/* Not yet. */
gdb_assert_not_reached ("option type not supported");
@@ -612,6 +684,7 @@ save_option_value_in_ctx (std::optional<option_def_and_value> &ov)
= ov->value->enumeration;
break;
case var_string:
+ case var_filename:
*ov->option.var_address.string (ov->option, ov->ctx)
= std::move (*ov->value->string);
break;
@@ -701,6 +774,8 @@ get_val_type_str (const option_def &opt, std::string &buffer)
}
case var_string:
return "STRING";
+ case var_filename:
+ return "FILENAME";
default:
return nullptr;
}
@@ -856,6 +931,15 @@ add_setshow_cmds_for_options (command_class cmd_class,
nullptr, option.show_cmd_cb,
set_list, show_list);
}
+ else if (option.type == var_filename)
+ {
+ add_setshow_filename_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");
}
diff --git a/gdb/cli/cli-option.h b/gdb/cli/cli-option.h
index bbe281d..26307a5 100644
--- a/gdb/cli/cli-option.h
+++ b/gdb/cli/cli-option.h
@@ -308,6 +308,26 @@ struct string_option_def : option_def
}
};
+/* A var_filename command line option. */
+
+template<typename Context>
+struct filename_option_def : option_def
+{
+ filename_option_def (const char *long_option_,
+ std::string *(*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_filename, nullptr,
+ (erased_get_var_address_ftype *) get_var_address_cb_,
+ show_cmd_cb_,
+ set_doc_, show_doc_, help_doc_)
+ {
+ var_address.string = detail::get_var_address<std::string, 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