[PATCHv6,09/14] gdb: implement readline rl_directory_rewrite_hook callback

Message ID 57af3bf38f0b7fb55d2e68f0adf1aa43e5d78322.1725017349.git.aburgess@redhat.com
State New
Headers
Series Further filename completion improvements |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Test passed

Commit Message

Andrew Burgess Aug. 30, 2024, 11:33 a.m. UTC
  Implement the readline rl_directory_rewrite_hook callback function,
this is used when readline needs to offer completions from within a
directory.  The important thing is that this function should remove
any escaping, this allows GDB to correctly offer completions in
situations like this:

  (gdb) file /tmp/directory\ with\ spaces/<TAB><TAB>

Note the escaping in 'directory\ with\ spaces'.  Without the
rl_directory_rewrite_hook callback readline will try to open a
directory literally called '/tmp/directory\ with\ spaces' which
obviously doesn't exist.

There are tests added to cover this new functionality.
---
 gdb/completer.c                               | 21 +++++++++++++++++++
 .../gdb.base/filename-completion.exp          | 12 +++++++++++
 2 files changed, 33 insertions(+)
  

Patch

diff --git a/gdb/completer.c b/gdb/completer.c
index b0e999ef514..b80649c5260 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -321,6 +321,26 @@  gdb_completer_file_name_dequote (char *filename, int quote_char)
   return strdup (tmp.c_str ());
 }
 
+/* Implement readline's rl_directory_rewrite_hook.  Remove any quoting from
+   the string *DIRNAME,update *DIRNAME, and return non-zero.  If *DIRNAME
+   doesn't need updating then return zero.  See readline docs for more
+   information.  */
+
+static int
+gdb_completer_directory_rewrite (char **dirname)
+{
+  if (!rl_completion_found_quote)
+    return 0;
+
+  int quote_char = rl_completion_quote_character;
+  char *new_dirname
+    = gdb_completer_file_name_dequote (*dirname, quote_char);
+  free (*dirname);
+  *dirname = new_dirname;
+
+  return 1;
+}
+
 /* Apply character escaping to the filename in TEXT and return a newly
    allocated buffer containing the possibly updated filename.
 
@@ -3416,6 +3436,7 @@  _initialize_completer ()
   rl_filename_quote_characters = " \t\n\\\"'";
   rl_filename_dequoting_function = gdb_completer_file_name_dequote;
   rl_filename_quoting_function = gdb_completer_file_name_quote;
+  rl_directory_rewrite_hook = gdb_completer_directory_rewrite;
 
   add_setshow_zuinteger_unlimited_cmd ("max-completions", no_class,
 				       &max_completions, _("\
diff --git a/gdb/testsuite/gdb.base/filename-completion.exp b/gdb/testsuite/gdb.base/filename-completion.exp
index a4b411c1c67..cf00d007ca7 100644
--- a/gdb/testsuite/gdb.base/filename-completion.exp
+++ b/gdb/testsuite/gdb.base/filename-completion.exp
@@ -170,6 +170,11 @@  proc run_quoting_and_escaping_tests { root } {
 		set dq "\\\""
 	    }
 
+	    test_gdb_complete_unique "${cmd} ${qc}${root}/bb2/dir${sp}1/" \
+		"${cmd} ${qc}${root}/bb2/dir${sp}1/unique${sp}file${qc}" " " \
+		false \
+		"expand a unique file name in a directory containing a space"
+
 	    test_gdb_complete_filename_multiple "$cmd ${qc}${root}/bb2/" \
 		"d" "ir${sp}" {
 		    "dir 1/"
@@ -177,6 +182,13 @@  proc run_quoting_and_escaping_tests { root } {
 		} "" "${qc}" false \
 		"expand multiple directory names containing spaces"
 
+	    test_gdb_complete_filename_multiple "${cmd} ${qc}${root}/bb2/dir${sp}2/" \
+		"f" "ile${sp}" {
+		    "file 1"
+		    "file 2"
+		} "" "${qc}" false \
+		"expand contents of a directory containing a space"
+
 	    test_gdb_complete_filename_multiple "$cmd ${qc}${root}/aaa/" \
 		"a" "a${sp}" {
 		    "aa bb"