[PATCH 04/18] Implement completion limiting for add_filename_to_list.

Keith Seitz keiths@redhat.com
Mon Apr 13 19:23:00 GMT 2015


This patch converts add_filename_to_list to implement completion limiting.
This function is used by both make_source_files_completion_list
and maybe_add_partial_symbol.  Tests have been added for both code
pathways.

gdb/ChangeLog

	* symtab.c (add_filename_to_list): Add completer_data argument.
	Use maybe_add_completion.
	Update all callers.

gdb/testsuite/ChangeLog

	* gdb.base/filesym.c (filesym2): Add external declaration.
	* gdb.base/filesym.exp: Compile newly added files.
	Add tests for completion limiting.
	* gdb.base/filesym2.c, gdb.base/filesym3.c, gdb.base/filesym4.c,
	gdb.base/filesym5.c: New files.
---
 gdb/symtab.c                       |   38 ++++++++++++++--
 gdb/testsuite/gdb.base/filesym.c   |    4 +-
 gdb/testsuite/gdb.base/filesym.exp |   84 +++++++++++++++++++++++++++++++++++-
 gdb/testsuite/gdb.base/filesym2.c  |   24 ++++++++++
 gdb/testsuite/gdb.base/filesym3.c  |   24 ++++++++++
 gdb/testsuite/gdb.base/filesym4.c  |   24 ++++++++++
 gdb/testsuite/gdb.base/filesym5.c  |   22 +++++++++
 7 files changed, 210 insertions(+), 10 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/filesym2.c
 create mode 100644 gdb/testsuite/gdb.base/filesym3.c
 create mode 100644 gdb/testsuite/gdb.base/filesym4.c
 create mode 100644 gdb/testsuite/gdb.base/filesym5.c

diff --git a/gdb/symtab.c b/gdb/symtab.c
index 0736582..d997a33 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -5689,12 +5689,16 @@ make_file_symbol_completion_list (struct completer_data *cdata,
    list as necessary.  */
 
 static void
-add_filename_to_list (const char *fname, const char *text, const char *word,
+add_filename_to_list (struct completer_data *cdata, const char *fname,
+		      const char *text, const char *word,
 		      VEC (char_ptr) **list)
 {
   char *newobj;
   size_t fnlen = strlen (fname);
+  enum maybe_add_completion_enum add_status;
+  struct cleanup *cleanup;
 
+  cleanup = make_cleanup (free_current_contents, &newobj);
   if (word == text)
     {
       /* Return exactly fname.  */
@@ -5715,7 +5719,25 @@ add_filename_to_list (const char *fname, const char *text, const char *word,
       newobj[text - word] = '\0';
       strcat (newobj, fname);
     }
-  VEC_safe_push (char_ptr, *list, newobj);
+
+  add_status = maybe_add_completion (cdata, newobj);
+  switch (add_status)
+    {
+    case MAYBE_ADD_COMPLETION_OK:
+      VEC_safe_push (char_ptr, *list, newobj);
+      discard_cleanups (cleanup);
+      break;
+    case MAYBE_ADD_COMPLETION_OK_MAX_REACHED:
+      VEC_safe_push (char_ptr, *list, newobj);
+      discard_cleanups (cleanup);
+      break;
+    case MAYBE_ADD_COMPLETION_MAX_REACHED:
+      do_cleanups (cleanup);
+      break;
+    case MAYBE_ADD_COMPLETION_DUPLICATE:
+      do_cleanups (cleanup);
+      break;
+    }
 }
 
 static int
@@ -5764,7 +5786,8 @@ maybe_add_partial_symtab_filename (const char *filename, const char *fullname,
     {
       /* This file matches for a completion; add it to the
 	 current list of matches.  */
-      add_filename_to_list (filename, data->text, data->word, data->list);
+      add_filename_to_list (data->completer_data, filename, data->text,
+			    data->word, data->list);
     }
   else
     {
@@ -5773,7 +5796,10 @@ maybe_add_partial_symtab_filename (const char *filename, const char *fullname,
       if (base_name != filename
 	  && !filename_seen (data->filename_seen_cache, base_name, 1)
 	  && filename_ncmp (base_name, data->text, data->text_len) == 0)
-	add_filename_to_list (base_name, data->text, data->word, data->list);
+	{
+	  add_filename_to_list (data->completer_data, base_name, data->text,
+				data->word, data->list);
+	}
     }
 }
 
@@ -5814,7 +5840,7 @@ make_source_files_completion_list (struct completer_data *cdata,
 	{
 	  /* This file matches for a completion; add it to the current
 	     list of matches.  */
-	  add_filename_to_list (s->filename, text, word, &list);
+	  add_filename_to_list (cdata, s->filename, text, word, &list);
 	}
       else
 	{
@@ -5826,7 +5852,7 @@ make_source_files_completion_list (struct completer_data *cdata,
 	  if (base_name != s->filename
 	      && !filename_seen (filename_seen_cache, base_name, 1)
 	      && filename_ncmp (base_name, text, text_len) == 0)
-	    add_filename_to_list (base_name, text, word, &list);
+	    add_filename_to_list (cdata, base_name, text, word, &list);
 	}
     }
 
diff --git a/gdb/testsuite/gdb.base/filesym.c b/gdb/testsuite/gdb.base/filesym.c
index 59093a4..39bf9af 100644
--- a/gdb/testsuite/gdb.base/filesym.c
+++ b/gdb/testsuite/gdb.base/filesym.c
@@ -15,10 +15,12 @@
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
+extern int filesym2 (int arg);
+
 int
 filesym (int arg)
 {
-  return arg;
+  return filesym2 (arg);
 }
 
 int
diff --git a/gdb/testsuite/gdb.base/filesym.exp b/gdb/testsuite/gdb.base/filesym.exp
index 8084710..3b0ede4 100644
--- a/gdb/testsuite/gdb.base/filesym.exp
+++ b/gdb/testsuite/gdb.base/filesym.exp
@@ -16,9 +16,10 @@
 # This series of completion tests checks the completion output
 # on a name which is potentially both a symbol name and a file name.
 
-standard_testfile
+standard_testfile filesym.c filesym2.c filesym3.c filesym4.c filesym5.c
 
-if {[prepare_for_testing $testfile.exp $testfile $srcfile debug]} {
+if {[prepare_for_testing $testfile.exp $testfile \
+	 [list $srcfile $srcfile2 $srcfile3 $srcfile4 $srcfile5] debug]} {
     return -1
 }
 
@@ -40,9 +41,20 @@ gdb_test_multiple "" $tst {
 
 	# Now ask for the completion list
 	set tst "completion list for \"filesym\""
+
+	set expected {\x07\r\n}
+	for {set i 1} {$i <= 5} {incr i} {
+	    if {$i == 1} {
+		append expected "filesym\[ \t\]+"
+		append expected "filesym\\\.c\[ \t\]+"
+	    } else {
+		append expected "filesym$i\[ \t\]+"
+		append expected "filesym${i}\\\.c\[ \t\]+"
+	    }
+	}
 	send_gdb "\t\t"
 	gdb_test_multiple "" $tst {
-	    -re "\\\x07\r\nfilesym\[ \t\]+filesym.c\[ \t\]+\r\n$gdb_prompt " {
+	    -re "$expected\r\n$gdb_prompt " {
 		pass $tst
 
 		# Flush the rest of the output by creating the breakpoint.
@@ -54,4 +66,70 @@ gdb_test_multiple "" $tst {
     }
 }
 
+# Test completion limiting.
+#
+# We cannot assume any order when completion
+# limiting is in effect.  All we know is symbol names are completed
+# first and file names next.  If max-completions is set greater than
+# the number of symbols, we will have all of the symbols and
+# (max-completions - 5) file names in the completion list.
+# We also cannot know which file names will be mentioned -- only the number
+# of source files that should be mentioned.
+
+# The number of symbols/files defined in this test.
+set number_of_symbols 5
+
+# The number of completions to attempt
+set max_completions 7;  # This will give all (5) files and 2 file names
+
+# List of seen files
+set files_seen {}
+
+# List of seen symbols
+set syms_seen {}
+
+# Set the maximum completions.
+gdb_test_no_output "set max-completions $max_completions"
+
+# The terminal at the end of the complete command
+set end "\\\*\\\*\\\* List may be truncated, "
+append end "max-completions reached\\\. \\\*\\\*\\\*"
+
+with_test_prefix "completion limit on files" {
+    gdb_test_multiple "complete break filesy" "" {
+	"complete break filesy" { exp_continue }
+
+	-re "break filesym(\[2-$number_of_symbols\])?(\\\.c)?\r\n" {
+	    set name [string trim $expect_out(0,string) \r\n]
+	    #send_log "seen: $name -- "
+	    if {[string match "*.c" $name]} {
+		#send_log "is file\n"
+		lappend files_seen $name
+	    } else {
+		#send_log "is symbol\n"
+		lappend syms_seen $name
+	    }
+	    exp_continue
+	}
+
+	-re "break filesy $end\r\n$gdb_prompt $" {
+	    set n [llength $syms_seen]
+	    if {$n == $number_of_symbols} {
+		pass "symbols seen"
+	    } else {
+		fail "symbols seen ($n/$number_of_symbols)"
+	    }
+
+	    if {[llength $files_seen] \
+		    == [expr {$max_completions - $number_of_symbols}]} {
+		pass "files seen"
+	    } else {
+		set n [llength $files_seen]
+		set m [expr {$max_completions - $number_of_symbols}]
+		fail "files seen ($n/$m)"
+	    }
+	}
+    }
+}
+
 unset -nocomplain tst
diff --git a/gdb/testsuite/gdb.base/filesym2.c b/gdb/testsuite/gdb.base/filesym2.c
new file mode 100644
index 0000000..e16bb53
--- /dev/null
+++ b/gdb/testsuite/gdb.base/filesym2.c
@@ -0,0 +1,24 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2015 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+extern int filesym3 (int arg);
+
+int
+filesym2 (int arg)
+{
+  return filesym3 (arg);
+}
diff --git a/gdb/testsuite/gdb.base/filesym3.c b/gdb/testsuite/gdb.base/filesym3.c
new file mode 100644
index 0000000..846a488
--- /dev/null
+++ b/gdb/testsuite/gdb.base/filesym3.c
@@ -0,0 +1,24 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2015 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+extern int filesym4 (int arg);
+
+int
+filesym3 (int arg)
+{
+  return filesym4 (arg);
+}
diff --git a/gdb/testsuite/gdb.base/filesym4.c b/gdb/testsuite/gdb.base/filesym4.c
new file mode 100644
index 0000000..2d6e506
--- /dev/null
+++ b/gdb/testsuite/gdb.base/filesym4.c
@@ -0,0 +1,24 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2015 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+extern int filesym5 (int arg);
+
+int
+filesym4 (int arg)
+{
+  return filesym5 (arg);
+}
diff --git a/gdb/testsuite/gdb.base/filesym5.c b/gdb/testsuite/gdb.base/filesym5.c
new file mode 100644
index 0000000..e192da8
--- /dev/null
+++ b/gdb/testsuite/gdb.base/filesym5.c
@@ -0,0 +1,22 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2015 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+int
+filesym5 (int arg)
+{
+  return arg;
+}



More information about the Gdb-patches mailing list