aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/completer.c62
-rw-r--r--gdb/testsuite/gdb.base/filename-completion.exp12
2 files changed, 56 insertions, 18 deletions
diff --git a/gdb/completer.c b/gdb/completer.c
index 7435532..b0e999e 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -48,7 +48,8 @@
/* Forward declarations. */
static const char *completion_find_completion_word (completion_tracker &tracker,
const char *text,
- int *quote_char);
+ int *quote_char,
+ bool *found_any_quoting);
static void set_rl_completer_word_break_characters (const char *break_chars);
@@ -560,7 +561,9 @@ deprecated_filename_completer
boundaries of the current word. QC, if non-null, is set to the
opening quote character if we found an unclosed quoted substring,
'\0' otherwise. DP, if non-null, is set to the value of the
- delimiter character that caused a word break. */
+ delimiter character that caused a word break. FOUND_ANY_QUOTING, if
+ non-null, is set to true if we found any quote characters (single or
+ double quotes, or a backslash) while finding the completion word. */
struct gdb_rl_completion_word_info
{
@@ -571,7 +574,7 @@ struct gdb_rl_completion_word_info
static const char *
gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info,
- int *qc, int *dp,
+ int *qc, int *dp, bool *found_any_quoting,
const char *line_buffer)
{
int scan, end, delimiter, pass_next, isbrk;
@@ -583,6 +586,8 @@ gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info,
the empty string. */
if (point == 0)
{
+ if (found_any_quoting != nullptr)
+ *found_any_quoting = false;
if (qc != NULL)
*qc = '\0';
if (dp != NULL)
@@ -593,6 +598,7 @@ gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info,
end = point;
delimiter = 0;
quote_char = '\0';
+ bool found_quote = false;
brkchars = info->word_break_characters;
@@ -618,6 +624,7 @@ gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info,
if (quote_char != '\'' && line_buffer[scan] == '\\')
{
pass_next = 1;
+ found_quote = true;
continue;
}
@@ -638,6 +645,7 @@ gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info,
/* Found start of a quoted substring. */
quote_char = line_buffer[scan];
point = scan + 1;
+ found_quote = true;
}
}
}
@@ -651,8 +659,22 @@ gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info,
{
scan = line_buffer[point];
- if (strchr (brkchars, scan) != 0)
- break;
+ if (strchr (brkchars, scan) == 0)
+ continue;
+
+ /* Call the application-specific function to tell us whether
+ this word break character is quoted and should be skipped.
+ The const_cast is needed here to comply with the readline
+ API. The only function we register for rl_char_is_quoted_p
+ treats the input buffer as 'const', so we're OK. */
+ if (rl_char_is_quoted_p != nullptr && found_quote
+ && (*rl_char_is_quoted_p) (const_cast<char *> (line_buffer),
+ point))
+ continue;
+
+ /* Convoluted code, but it avoids an n^2 algorithm with calls
+ to char_is_quoted. */
+ break;
}
}
@@ -676,6 +698,8 @@ gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info,
}
}
+ if (found_any_quoting != nullptr)
+ *found_any_quoting = found_quote;
if (qc != NULL)
*qc = quote_char;
if (dp != NULL)
@@ -702,7 +726,7 @@ advance_to_completion_word (completion_tracker &tracker,
int delimiter;
const char *start
- = gdb_rl_find_completion_word (&info, NULL, &delimiter, text);
+ = gdb_rl_find_completion_word (&info, nullptr, &delimiter, nullptr, text);
tracker.advance_custom_word_point_by (start - text);
@@ -775,7 +799,8 @@ complete_nested_command_line (completion_tracker &tracker, const char *text)
int quote_char = '\0';
const char *word = completion_find_completion_word (tracker, text,
- &quote_char);
+ &quote_char,
+ nullptr);
if (tracker.use_custom_word_point ())
{
@@ -1992,8 +2017,11 @@ complete (const char *line, char const **word, int *quote_char)
try
{
+ bool found_any_quoting = false;
+
*word = completion_find_completion_word (tracker_handle_brkchars,
- line, quote_char);
+ line, quote_char,
+ &found_any_quoting);
/* Completers that provide a custom word point in the
handle_brkchars phase also compute their completions then.
@@ -2003,6 +2031,12 @@ complete (const char *line, char const **word, int *quote_char)
tracker = &tracker_handle_brkchars;
else
{
+ /* Setting this global matches what readline does within
+ gen_completion_matches. We need this set correctly in case
+ our completion function calls back into readline to perform
+ completion (e.g. filename_completer does this). */
+ rl_completion_found_quote = found_any_quoting;
+
complete_line (tracker_handle_completions, *word, line, strlen (line));
tracker = &tracker_handle_completions;
}
@@ -2280,7 +2314,7 @@ gdb_completion_word_break_characters () noexcept
static const char *
completion_find_completion_word (completion_tracker &tracker, const char *text,
- int *quote_char)
+ int *quote_char, bool *found_any_quoting)
{
size_t point = strlen (text);
@@ -2290,6 +2324,13 @@ completion_find_completion_word (completion_tracker &tracker, const char *text,
{
gdb_assert (tracker.custom_word_point () > 0);
*quote_char = tracker.quote_char ();
+ /* This isn't really correct, we're ignoring the case where we found
+ a backslash escaping a character. However, this isn't an issue
+ right now as we only rely on *FOUND_ANY_QUOTING being set when
+ performing filename completion, which doesn't go through this
+ path. */
+ if (found_any_quoting != nullptr)
+ *found_any_quoting = *quote_char != '\0';
return text + tracker.custom_word_point ();
}
@@ -2299,7 +2340,8 @@ completion_find_completion_word (completion_tracker &tracker, const char *text,
info.quote_characters = rl_completer_quote_characters;
info.basic_quote_characters = rl_basic_quote_characters;
- return gdb_rl_find_completion_word (&info, quote_char, NULL, text);
+ return gdb_rl_find_completion_word (&info, quote_char, nullptr,
+ found_any_quoting, text);
}
/* See completer.h. */
diff --git a/gdb/testsuite/gdb.base/filename-completion.exp b/gdb/testsuite/gdb.base/filename-completion.exp
index c852b56..a4b411c 100644
--- a/gdb/testsuite/gdb.base/filename-completion.exp
+++ b/gdb/testsuite/gdb.base/filename-completion.exp
@@ -166,10 +166,8 @@ proc run_quoting_and_escaping_tests { root } {
if { $qc eq "'" } {
set dq "\""
- set dq_re "\""
} else {
set dq "\\\""
- set dq_re "\\\\\""
}
test_gdb_complete_filename_multiple "$cmd ${qc}${root}/bb2/" \
@@ -193,8 +191,8 @@ proc run_quoting_and_escaping_tests { root } {
} "" "${qc}" false \
"expand filenames containing quotes"
- test_gdb_complete_tab_unique "$cmd ${qc}${root}/bb1/aa${dq}" \
- "$cmd ${qc}${root}/bb1/aa${dq_re}bb${qc}" " " \
+ test_gdb_complete_unique "$cmd ${qc}${root}/bb1/aa${dq}" \
+ "$cmd ${qc}${root}/bb1/aa${dq}bb${qc}" " " false \
"expand unique filename containing double quotes"
# It is not possible to include a single quote character
@@ -205,14 +203,12 @@ proc run_quoting_and_escaping_tests { root } {
if { $qc ne "'" } {
if { $qc eq "" } {
set sq "\\'"
- set sq_re "\\\\'"
} else {
set sq "'"
- set sq_re "'"
}
- test_gdb_complete_tab_unique "$cmd ${qc}${root}/bb1/aa${sq}" \
- "$cmd ${qc}${root}/bb1/aa${sq_re}bb${qc}" " " \
+ test_gdb_complete_unique "$cmd ${qc}${root}/bb1/aa${sq}" \
+ "$cmd ${qc}${root}/bb1/aa${sq}bb${qc}" " " false \
"expand unique filename containing single quote"
}
}