public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v3 09/19] Implement completion limiting for interpreter_completer.
  2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
@ 2015-08-06 19:18 ` Keith Seitz
  2015-08-23  4:03   ` Doug Evans
  2015-08-06 19:20 ` [PATCH v3 12/19] Implement completion limiting for sim_command_completer Keith Seitz
                   ` (18 subsequent siblings)
  19 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-06 19:18 UTC (permalink / raw)
  To: gdb-patches

Differences in this revision:

1. Remove partial copy code from interpreter_completer..

---

This is another simple patch which converts interpreter_completer
to use add_completion and adds some tests to make sure that everything
is working properly.

gdb/ChangeLog

	* interps.c (interpreter_completer): Use add_completion.

gdb/testsuite/ChangeLog

	* gdb.base/completion.exp: Test completion limiting on
	interpreter name with "interpreter-exec".
---
 gdb/interps.c                         |   21 +++------------------
 gdb/testsuite/gdb.base/completion.exp |   16 ++++++++++++++++
 2 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/gdb/interps.c b/gdb/interps.c
index 2cfe92b..9e993c8 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -448,24 +448,9 @@ interpreter_completer (struct completer_data *cdata,
     {
       if (strncmp (interp->name, text, textlen) == 0)
 	{
-	  char *match;
-
-	  match = (char *) xmalloc (strlen (word) + strlen (interp->name) + 1);
-	  if (word == text)
-	    strcpy (match, interp->name);
-	  else if (word > text)
-	    {
-	      /* Return some portion of interp->name.  */
-	      strcpy (match, interp->name + (word - text));
-	    }
-	  else
-	    {
-	      /* Return some of text plus interp->name.  */
-	      strncpy (match, word, text - word);
-	      match[text - word] = '\0';
-	      strcat (match, interp->name);
-	    }
-	  VEC_safe_push (char_ptr, matches, match);
+	  if (add_completion (cdata, &matches, interp->name, text, word)
+	      == ADD_COMPLETION_MAX_REACHED)
+	    break;
 	}
     }
 
diff --git a/gdb/testsuite/gdb.base/completion.exp b/gdb/testsuite/gdb.base/completion.exp
index 884b9f6..41323d2 100644
--- a/gdb/testsuite/gdb.base/completion.exp
+++ b/gdb/testsuite/gdb.base/completion.exp
@@ -1022,6 +1022,22 @@ if {$num_signals > $max_completions} {
     untested $msg
 }
 
+# Test interpreter_completer.  There are only four completions
+# available for this, so temporarily set max-completions to 3.
+with_test_prefix "interpreter_completer" {
+    set old_max $max_completions
+    set max_completions 3
+    gdb_test_no_output "set max-completions $max_completions"
+}
+
+test_completion_limit "interpreter-exec m" \
+    "interpreter-exec mi\[1-3\]?" $max_completions
+
+with_test_prefix "interpreter_completer reset" {
+    set max_completions $old_max
+    gdb_test_no_output "set max-completions $max_completions"
+}
+
 #
 # Test TUI completions
 #

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v3 12/19] Implement completion limiting for sim_command_completer.
  2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
  2015-08-06 19:18 ` [PATCH v3 09/19] Implement completion limiting for interpreter_completer Keith Seitz
@ 2015-08-06 19:20 ` Keith Seitz
  2015-08-23  4:11   ` Doug Evans
  2015-08-06 19:58 ` [PATCH v3 02/19] Remove completion_tracker_t from the public completion API Keith Seitz
                   ` (17 subsequent siblings)
  19 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-06 19:20 UTC (permalink / raw)
  To: gdb-patches

There are no revisions in this version.

--

This patch converts sim_command_completer to use add_completion.
It does not add any tests, since the `sim' command is highly
target-dependent and unimplemented for the majority of simulators.

gdb/ChangeLog

	* remote-sim.c: Include completer.h.
	(sim_command_completer): Use add_completion.
---
 gdb/remote-sim.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c
index 0a8997a..c29d3c5 100644
--- a/gdb/remote-sim.c
+++ b/gdb/remote-sim.c
@@ -40,6 +40,7 @@
 #include "arch-utils.h"
 #include "readline/readline.h"
 #include "gdbthread.h"
+#include "completer.h"
 
 /* Prototypes */
 
@@ -1242,7 +1243,11 @@ sim_command_completer (struct completer_data *cdata,
 
   /* Transform the array into a VEC, and then free the array.  */
   for (i = 0; tmp[i] != NULL; i++)
-    VEC_safe_push (char_ptr, result, tmp[i]);
+    {
+      if (add_completion (cdata, &result, tmp[i], NULL, NULL)
+	  == ADD_COMPLETION_MAX_REACHED)
+	break;
+    }
   xfree (tmp);
 
   return result;

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v3 02/19] Remove completion_tracker_t from the public completion API.
  2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
  2015-08-06 19:18 ` [PATCH v3 09/19] Implement completion limiting for interpreter_completer Keith Seitz
  2015-08-06 19:20 ` [PATCH v3 12/19] Implement completion limiting for sim_command_completer Keith Seitz
@ 2015-08-06 19:58 ` Keith Seitz
  2015-08-23  1:02   ` Doug Evans
  2015-08-06 19:58 ` [PATCH v3 06/19] Implement completion limiting for condition_completer Keith Seitz
                   ` (16 subsequent siblings)
  19 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-06 19:58 UTC (permalink / raw)
  To: gdb-patches

Differences from last version:

1. Removed comments about recording an additional completion from
   add_completion.
2. Removed requirement to xstrdup arg to add_completion; add_completeion
    uses new function completer_strdup.
3. Consolidated (oft-repeated) partial copy code into completer_strdup.
   Removed this code from all completion functions.

---

This patch removes the recently introduced "completion tracker" concept
from the public completion API.  In the previous patch, the completion
tracker was added to the (new) completer_data structure that is now
used by all completion functions.

Since completion_tracker_t is now used entirely inside completer.c, there
is no need to make its type opaque, so the typedef has been removed.

This patch also fixes gdb/17960, which is easily demonstrated:

$ gdb -nx -q gdb
(gdb) b gdb.c:ma<TAB>
./../src/gdb/completer.c:837: internal-error: maybe_add_completion:
Assertion `tracker != NULL' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n)

This occurs because the code path in this case is:
complete_line
- complete_line_internal
-- location_completer

gdb/ChangeLog

	PR gdb/17960
	* completer.c (struct completer_data) <tracker>: Change type to
	htab_t.
	(enum maybe_add_completion_enum): Make private; moved from
	completer.h.
	[DEFAULT_MAX_COMPLETIONS]: Define.
	(new_completion_tracker): Remove function.
	(new_completer_data): New function.
	(free_completion_tracker): Remove function.
	(free_completer_data): New function.
	(make_cleanup_free_completion_tracker): Remove function.
	(maybe_add_completion): Make static.  Update comments.
	Use completer_data instead of completion_tracker_t.
	(completer_strdup): New function.
	(add_completion): New function.
	(complete_line, gdb_completion_word_break_characters): Use
	completer_data instead of completion_tracker.
	* completer.h (completion_tracker_t, new_completion_tracker)
	(make_cleanup_free_completion_tracker, maybe_add_completion)
	(enum maybe_add_completion): Remove declarations.
	(enum add_completion_status): Define.
	(add_completion): Declare.
	* symtab.c (completion_tracker): Remove variable.
	(completion_list_add_name): Use add_completion instead of
	maybe_add_completion and partial copy.
	(default_make_symbol_completion_list_break_on_1): Do not use
	completion_tracker.

gdb/testsuite/ChangeLog

	PR gdb/17960
	* gdb.base/completion.exp: Add some basic tests for the
	location completer, including a regression test for
	the gdb/17960 assertion failure.
---
 gdb/completer.c                       |  231 +++++++++++++++++++++++----------
 gdb/completer.h                       |   66 +++------
 gdb/symtab.c                          |   62 +--------
 gdb/testsuite/gdb.base/completion.exp |   78 +++++++++++
 4 files changed, 260 insertions(+), 177 deletions(-)

diff --git a/gdb/completer.c b/gdb/completer.c
index 476f9f2..bf4137e 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -92,10 +92,31 @@ static char *gdb_completer_quote_characters = "'";
 
 struct completer_data
 {
-  /* The completion tracker being used by the completer.  */
-  completion_tracker_t tracker;
+  /* A hashtable used to track completions.  */
+  htab_t tracker;
 };
 
+/* Return values for maybe_add_completion.  */
+
+enum maybe_add_completion_enum
+{
+  /* NAME has been recorded and max_completions has not been reached,
+     or completion tracking is disabled (max_completions < 0).  */
+  MAYBE_ADD_COMPLETION_OK,
+
+  /* NAME has been recorded and max_completions has been reached
+     (thus the caller can stop searching).  */
+  MAYBE_ADD_COMPLETION_OK_MAX_REACHED,
+
+  /* max-completions entries has been reached.
+     Whether NAME is a duplicate or not is not determined.  */
+  MAYBE_ADD_COMPLETION_MAX_REACHED,
+
+  /* NAME has already been recorded.
+     Note that this is never returned if completion tracking is disabled
+     (max_completions < 0).  */
+  MAYBE_ADD_COMPLETION_DUPLICATE
+};
 \f
 /* Accessor for some completer data that may interest other files.  */
 
@@ -803,48 +824,41 @@ complete_line_internal (struct completer_data *cdata,
 
 /* See completer.h.  */
 
-int max_completions = 200;
+#define DEFAULT_MAX_COMPLETIONS 200
+int max_completions = DEFAULT_MAX_COMPLETIONS;
 
-/* See completer.h.  */
+/* Allocate a new completer data structure.  */
 
-completion_tracker_t
-new_completion_tracker (void)
+static struct completer_data *
+new_completer_data (int size)
 {
-  if (max_completions <= 0)
-    return NULL;
+  struct completer_data *cdata = XCNEW (struct completer_data);
 
-  return htab_create_alloc (max_completions,
-			    htab_hash_string, (htab_eq) streq,
-			    NULL, xcalloc, xfree);
+  cdata->tracker
+    = htab_create_alloc ((size < 0 ? DEFAULT_MAX_COMPLETIONS : size),
+			 htab_hash_string, (htab_eq) streq, NULL,
+			 xcalloc, xfree);
+  return cdata;
 }
 
-/* Cleanup routine to free a completion tracker and reset the pointer
-   to NULL.  */
+/* Free the completion data represented by P.  */
 
 static void
-free_completion_tracker (void *p)
+free_completer_data (void *p)
 {
-  completion_tracker_t *tracker_ptr = p;
+  struct completer_data *cdata = p;
 
-  htab_delete (*tracker_ptr);
-  *tracker_ptr = NULL;
+  htab_delete (cdata->tracker);
+  xfree (cdata);
 }
 
-/* See completer.h.  */
-
-struct cleanup *
-make_cleanup_free_completion_tracker (completion_tracker_t *tracker_ptr)
-{
-  if (*tracker_ptr == NULL)
-    return make_cleanup (null_cleanup, NULL);
-
-  return make_cleanup (free_completion_tracker, tracker_ptr);
-}
-
-/* See completer.h.  */
+/* Add the completion NAME to the list of generated completions if
+   it is not there already.
+   If max_completions is negative, nothing is done, not even watching
+   for duplicates, and MAYBE_ADD_COMPLETION_OK is always returned.  */
 
-enum maybe_add_completion_enum
-maybe_add_completion (completion_tracker_t tracker, char *name)
+static enum maybe_add_completion_enum
+maybe_add_completion (struct completer_data *cdata, char *name)
 {
   void **slot;
 
@@ -853,23 +867,82 @@ maybe_add_completion (completion_tracker_t tracker, char *name)
   if (max_completions == 0)
     return MAYBE_ADD_COMPLETION_MAX_REACHED;
 
-  gdb_assert (tracker != NULL);
-
-  if (htab_elements (tracker) >= max_completions)
+  if (htab_elements (cdata->tracker) >= max_completions)
     return MAYBE_ADD_COMPLETION_MAX_REACHED;
 
-  slot = htab_find_slot (tracker, name, INSERT);
+  slot = htab_find_slot (cdata->tracker, name, INSERT);
 
   if (*slot != HTAB_EMPTY_ENTRY)
     return MAYBE_ADD_COMPLETION_DUPLICATE;
 
   *slot = name;
 
-  return (htab_elements (tracker) < max_completions
+  return (htab_elements (cdata->tracker) < max_completions
 	  ? MAYBE_ADD_COMPLETION_OK
 	  : MAYBE_ADD_COMPLETION_OK_MAX_REACHED);
 }
 
+/* A strdup-like function used by the completer to copy bits of completion
+   strings.  */
+
+static char *
+completer_strdup (const char *match, const char *text, const char *word)
+{
+  char *alloc;
+
+  if (text == NULL || word == NULL || text == word)
+    return xstrdup (match);
+
+  if (word > text)
+    {
+      gdb_assert (strlen (match) > (word - text));
+
+      /* Return some portion of match.  */
+      match += (word - text);
+      alloc = xmalloc (strlen (match) + 1);
+      strcpy (alloc, match);
+    }
+  else
+    {
+      /* Return some of text plus match.  */
+      alloc = xmalloc (strlen (match) + (text - word) + 1);
+      strncpy (alloc, word, text - word);
+      alloc[text - word] = '\0';
+      strcat (alloc, match);
+    }
+
+  return alloc;
+}
+
+/* See completer.h.  */
+
+enum add_completion_status
+add_completion (struct completer_data *cdata, VEC (char_ptr) **result,
+		const char *match, const char *text, const char *word)
+{
+  enum maybe_add_completion_enum add_status;
+  char *alloc = completer_strdup (match, text, word);
+
+  add_status = maybe_add_completion (cdata, alloc);
+  switch (add_status)
+    {
+    case MAYBE_ADD_COMPLETION_OK:
+      VEC_safe_push (char_ptr, *result, alloc);
+      break;
+    case MAYBE_ADD_COMPLETION_OK_MAX_REACHED:
+      VEC_safe_push (char_ptr, *result, alloc);
+      return ADD_COMPLETION_MAX_REACHED;
+    case MAYBE_ADD_COMPLETION_MAX_REACHED:
+      xfree (alloc);
+      return ADD_COMPLETION_MAX_REACHED;
+    case MAYBE_ADD_COMPLETION_DUPLICATE:
+      xfree (alloc);
+      break;
+    }
+
+  return ADD_COMPLETION_OK;
+}
+
 void
 throw_max_completions_reached_error (void)
 {
@@ -894,54 +967,63 @@ complete_line (const char *text, const char *line_buffer, int point)
 {
   VEC (char_ptr) *list;
   VEC (char_ptr) *result = NULL;
-  struct cleanup *cleanups;
-  completion_tracker_t tracker;
+  struct cleanup *cdata_cleanup, *list_cleanup;
   char *candidate;
-  int ix, max_reached;
+  int ix;
+  struct completer_data *cdata;
 
   if (max_completions == 0)
     return NULL;
-  list = complete_line_internal (NULL, text, line_buffer, point,
+
+  cdata = new_completer_data (max_completions);
+  cdata_cleanup = make_cleanup (free_completer_data, cdata);
+  list = complete_line_internal (cdata, text, line_buffer, point,
 				 handle_completions);
   if (max_completions < 0)
-    return list;
-
-  tracker = new_completion_tracker ();
-  cleanups = make_cleanup_free_completion_tracker (&tracker);
-  make_cleanup_free_char_ptr_vec (list);
-
-  /* Do a final test for too many completions.  Individual completers may
-     do some of this, but are not required to.  Duplicates are also removed
-     here.  Otherwise the user is left scratching his/her head: readline and
-     complete_command will remove duplicates, and if removal of duplicates
-     there brings the total under max_completions the user may think gdb quit
-     searching too early.  */
-
-  for (ix = 0, max_reached = 0;
-       !max_reached && VEC_iterate (char_ptr, list, ix, candidate);
-       ++ix)
     {
-      enum maybe_add_completion_enum add_status;
+      do_cleanups (cdata_cleanup);
+      return list;
+    }
+
+  list_cleanup = make_cleanup_free_char_ptr_vec (list);
 
-      add_status = maybe_add_completion (tracker, candidate);
+  /* If complete_line_internal returned more completions than were
+     recorded by the completion tracker, then the completer function that
+     was run does not support completion tracking.  In this case,
+     do a final test for too many completions.
 
-      switch (add_status)
+     Duplicates are also removed here.  Otherwise the user is left
+     scratching his/her head: readline and complete_command will remove
+     duplicates, and if removal of duplicates there brings the total under
+     max_completions the user may think gdb quit searching too early.  */
+
+  if (VEC_length (char_ptr, list) > htab_elements (cdata->tracker))
+    {
+      enum add_completion_status max_reached = ADD_COMPLETION_OK;
+
+      /* Clear the tracker so that we can re-use it to count the number
+	 of returned completions.  */
+      htab_empty (cdata->tracker);
+
+      for (ix = 0; (max_reached == ADD_COMPLETION_OK
+		    && VEC_iterate (char_ptr, list, ix, candidate)); ++ix)
 	{
-	  case MAYBE_ADD_COMPLETION_OK:
-	    VEC_safe_push (char_ptr, result, xstrdup (candidate));
-	    break;
-	  case MAYBE_ADD_COMPLETION_OK_MAX_REACHED:
-	    VEC_safe_push (char_ptr, result, xstrdup (candidate));
-	    max_reached = 1;
-	    break;
-      	  case MAYBE_ADD_COMPLETION_MAX_REACHED:
-	    gdb_assert_not_reached ("more than max completions reached");
-	  case MAYBE_ADD_COMPLETION_DUPLICATE:
-	    break;
+	  max_reached = add_completion (cdata, &result, candidate, NULL, NULL);
 	}
+
+      /* The return result has been assembled and the original list from
+	 complete_line_internal is no longer needed.  Free it.  */
+      do_cleanups (list_cleanup);
+    }
+  else
+    {
+      /* There is a valid tracker for the completion -- simply return
+	 the completed list.  */
+      discard_cleanups (list_cleanup);
+      result = list;
     }
 
-  do_cleanups (cleanups);
+  do_cleanups (cdata_cleanup);
 
   return result;
 }
@@ -1074,9 +1156,14 @@ char *
 gdb_completion_word_break_characters (void)
 {
   VEC (char_ptr) *list;
+  struct completer_data *cdata;
+  struct cleanup *cleanup;
 
-  list = complete_line_internal (NULL, rl_line_buffer, rl_line_buffer,
+  cdata = new_completer_data (max_completions);
+  cleanup = make_cleanup (free_completer_data, cdata);
+  list = complete_line_internal (cdata, rl_line_buffer, rl_line_buffer,
 				 rl_point, handle_brkchars);
+  do_cleanups (cleanup);
   gdb_assert (list == NULL);
   return rl_completer_word_break_characters;
 }
diff --git a/gdb/completer.h b/gdb/completer.h
index 7139c0a..43d1321 100644
--- a/gdb/completer.h
+++ b/gdb/completer.h
@@ -132,59 +132,31 @@ extern const char *skip_quoted (const char *);
 
 extern int max_completions;
 
-/* Object to track how many unique completions have been generated.
-   Used to limit the size of generated completion lists.  */
+/* Return values for add_completion.  */
 
-typedef htab_t completion_tracker_t;
-
-/* Create a new completion tracker.
-   The result is a hash table to track added completions, or NULL
-   if max_completions <= 0.  If max_completions < 0, tracking is disabled.
-   If max_completions == 0, the max is indeed zero.  */
-
-extern completion_tracker_t new_completion_tracker (void);
-
-/* Make a cleanup to free a completion tracker, and reset its pointer
-   to NULL.  */
-
-extern struct cleanup *make_cleanup_free_completion_tracker
-		      (completion_tracker_t *tracker_ptr);
-
-/* Return values for maybe_add_completion.  */
-
-enum maybe_add_completion_enum
+enum add_completion_status
 {
-  /* NAME has been recorded and max_completions has not been reached,
-     or completion tracking is disabled (max_completions < 0).  */
-  MAYBE_ADD_COMPLETION_OK,
-
-  /* NAME has been recorded and max_completions has been reached
-     (thus the caller can stop searching).  */
-  MAYBE_ADD_COMPLETION_OK_MAX_REACHED,
-
-  /* max-completions entries has been reached.
-     Whether NAME is a duplicate or not is not determined.  */
-  MAYBE_ADD_COMPLETION_MAX_REACHED,
-
-  /* NAME has already been recorded.
-     Note that this is never returned if completion tracking is disabled
-     (max_completions < 0).  */
-  MAYBE_ADD_COMPLETION_DUPLICATE
+  /* Completion was added -- keep looking for more.  */
+  ADD_COMPLETION_OK,
+
+  /* Maximum number of completions has been reached or the maximum
+     has already been reached by a previous call to add_completion.
+     Callers can make no assumptions about whether the completion was
+     added or not.  */
+  ADD_COMPLETION_MAX_REACHED
 };
 
-/* Add the completion NAME to the list of generated completions if
-   it is not there already.
-   If max_completions is negative, nothing is done, not even watching
-   for duplicates, and MAYBE_ADD_COMPLETION_OK is always returned.
+/* Add the given MATCH to the completer result in CDATA.
+   Returns one of the above enum add_completion_status codes to indicate
+   whether the caller should continue to look for/compute more completions.
 
-   If MAYBE_ADD_COMPLETION_MAX_REACHED is returned, callers are required to
-   record at least one more completion.  The final list will be pruned to
-   max_completions, but recording at least one more than max_completions is
-   the signal to the completion machinery that too many completions were
-   found.  */
+   If TEXT and WORD are non-NULL, then portions of the strings will be
+   saved into the completion list.  See completer_strdup for more.  */
 
-extern enum maybe_add_completion_enum
-  maybe_add_completion (completion_tracker_t tracker, char *name);
+extern enum add_completion_status
+  add_completion (struct completer_data *cdata,
+		  VEC (char_ptr) **result, const char *match,
+		  const char *text, const char *word);
 
 /* Wrapper to throw MAX_COMPLETIONS_REACHED_ERROR.  */ 
 
diff --git a/gdb/symtab.c b/gdb/symtab.c
index f4407a0..34eb6d7 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -5046,15 +5046,6 @@ static VEC (char_ptr) *return_val;
   completion_list_add_name						\
   (cdata, MSYMBOL_NATURAL_NAME (symbol), (sym_text), (len), (text), (word))
 
-/* Tracker for how many unique completions have been generated.  Used
-   to terminate completion list generation early if the list has grown
-   to a size so large as to be useless.  This helps avoid GDB seeming
-   to lock up in the event the user requests to complete on something
-   vague that necessitates the time consuming expansion of many symbol
-   tables.  */
-
-static completion_tracker_t completion_tracker;
-
 /*  Test to see if the symbol specified by SYMNAME (which is already
    demangled for C++ symbols) matches SYM_TEXT in the first SYM_TEXT_LEN
    characters.  If so, add it to the current completion list.  */
@@ -5070,50 +5061,11 @@ completion_list_add_name (struct completer_data *cdata,
     return;
 
   /* We have a match for a completion, so add SYMNAME to the current list
-     of matches.  Note that the name is moved to freshly malloc'd space.  */
-
-  {
-    char *newobj;
-    enum maybe_add_completion_enum add_status;
-
-    if (word == sym_text)
-      {
-	newobj = xmalloc (strlen (symname) + 5);
-	strcpy (newobj, symname);
-      }
-    else if (word > sym_text)
-      {
-	/* Return some portion of symname.  */
-	newobj = xmalloc (strlen (symname) + 5);
-	strcpy (newobj, symname + (word - sym_text));
-      }
-    else
-      {
-	/* Return some of SYM_TEXT plus symname.  */
-	newobj = xmalloc (strlen (symname) + (sym_text - word) + 5);
-	strncpy (newobj, word, sym_text - word);
-	newobj[sym_text - word] = '\0';
-	strcat (newobj, symname);
-      }
-
-    add_status = maybe_add_completion (completion_tracker, newobj);
+     of matches.  */
 
-    switch (add_status)
-      {
-      case MAYBE_ADD_COMPLETION_OK:
-	VEC_safe_push (char_ptr, return_val, newobj);
-	break;
-      case MAYBE_ADD_COMPLETION_OK_MAX_REACHED:
-	VEC_safe_push (char_ptr, return_val, newobj);
-	throw_max_completions_reached_error ();
-      case MAYBE_ADD_COMPLETION_MAX_REACHED:
-	xfree (newobj);
-	throw_max_completions_reached_error ();
-      case MAYBE_ADD_COMPLETION_DUPLICATE:
-	xfree (newobj);
-	break;
-      }
-  }
+    if (add_completion (cdata, &return_val, symname, sym_text, word)
+	== ADD_COMPLETION_MAX_REACHED)
+      throw_max_completions_reached_error ();
 }
 
 /* ObjC: In case we are completing on a selector, look as the msymbol
@@ -5358,7 +5310,6 @@ default_make_symbol_completion_list_break_on_1 (struct completer_data *cdata,
   /* Length of sym_text.  */
   int sym_text_len;
   struct add_name_data datum;
-  struct cleanup *cleanups;
 
   /* Now look for the symbol we are supposed to complete on.  */
   {
@@ -5429,9 +5380,6 @@ default_make_symbol_completion_list_break_on_1 (struct completer_data *cdata,
     }
   gdb_assert (sym_text[sym_text_len] == '\0' || sym_text[sym_text_len] == '(');
 
-  completion_tracker = new_completion_tracker ();
-  cleanups = make_cleanup_free_completion_tracker (&completion_tracker);
-
   datum.sym_text = sym_text;
   datum.sym_text_len = sym_text_len;
   datum.text = text;
@@ -5549,8 +5497,6 @@ default_make_symbol_completion_list_break_on_1 (struct completer_data *cdata,
       /* User-defined macros are always visible.  */
       macro_for_each (macro_user_macros, add_macro_name, &datum);
     }
-
-  do_cleanups (cleanups);
 }
 
 VEC (char_ptr) *
diff --git a/gdb/testsuite/gdb.base/completion.exp b/gdb/testsuite/gdb.base/completion.exp
index 1eb0fd8..710aac0 100644
--- a/gdb/testsuite/gdb.base/completion.exp
+++ b/gdb/testsuite/gdb.base/completion.exp
@@ -777,6 +777,84 @@ gdb_test_multiple "" "$test" {
 }
 
 #
+# Tests for the location completer
+#
+
+# Turn off pending breakpoint support so that we don't get queried
+# all the time.
+gdb_test_no_output "set breakpoint pending off"
+
+set subsrc [string range $srcfile 0 [expr {[string length $srcfile] - 3}]]
+set test "tab complete break $subsrc"
+send_gdb "break $subsrc\t\t"
+gdb_test_multiple "" $test {
+    -re "break\.c.*break1\.c.*$gdb_prompt " {
+	send_gdb "1\t\n"
+	gdb_test_multiple "" $test {
+	    -re ".*Function \"$srcfile2\" not defined\..*$gdb_prompt " {
+		pass $test
+	    }
+	    -re "$gdb_prompt p$" {
+		fail $test
+	    }
+	}
+    }
+
+    -re "$gdb_prompt p$" {
+	fail $test
+    }
+}
+
+gdb_test "complete break $subsrc" "break\.c.*break1\.c"
+
+# gdb/17960
+set test "tab complete break $srcfile:ma"
+send_gdb "break $srcfile:ma\t"
+gdb_test_multiple "" $test {
+    -re "break $srcfile:main " {
+	send_gdb "\n"
+	gdb_test_multiple "" $test {
+	    -re ".*Breakpoint.*at .*/$srcfile, line .*$gdb_prompt " {
+		pass $test
+		gdb_test_no_output "delete breakpoint \$bpnum" \
+		    "delete breakpoint for $test"
+	    }
+	    -re "$gdb_prompt p$" {
+		fail $test
+	    }
+	}
+    }
+    -re "$gdb_prompt p$" {
+	fail $test
+    }
+}
+
+gdb_test "complete break $srcfile:ma" "break\.c:main"
+
+set test "tab complete break need"
+send_gdb "break need\t"
+gdb_test_multiple "" $test {
+    -re "break need_malloc " {
+	send_gdb "\n"
+	gdb_test_multiple "" $test {
+	    -re ".*Breakpoint.*at .*/$srcfile, line .*$gdb_prompt " {
+		pass $test
+		gdb_test_no_output "delete breakpoint \$bpnum" \
+		    "delete breakpoint for $test"
+	    }
+	    -re "$gdb_prompt p$" {
+		fail $test
+	    }
+	}
+    }
+    -re "$gdb_prompt p$" {
+	fail $test
+    }
+}
+
+gdb_test "complete break need" "need_malloc"
+
+#
 # Completion limiting.
 #
 

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v3 18/19] Use the hashtable to accumulate completion results.
  2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
                   ` (3 preceding siblings ...)
  2015-08-06 19:58 ` [PATCH v3 06/19] Implement completion limiting for condition_completer Keith Seitz
@ 2015-08-06 19:58 ` Keith Seitz
  2015-08-23 17:53   ` Doug Evans
  2015-08-06 19:58 ` [PATCH v3 19/19] Remove the vector return result from the completion API Keith Seitz
                   ` (14 subsequent siblings)
  19 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-06 19:58 UTC (permalink / raw)
  To: gdb-patches

There are no revisions in this version.

--

The completion API now uses a VEC (char_ptr) to collect results of
completion.  The completion tracker is a hashtable whose elements are
the completions.  Both hold essentially the same data, so there is no
need to keep both around.

This patch introduces some API support for removing the vector of
completions altogether.  While it does not remove the vector or
the vector return result from the completer functions, this patch
does not use the results of the vector at all.  Only the results of
the hashtable inside the completer's private data is used.

The vector will be removed in the next patch.

gdb/ChangeLog

	* cli/cli-decode.c (complete_on_cmdlist): Use get_completion_count
	to ascertain if there are any completion results.
	* completer.c (remove_leading_fn_component): New function.
	(location_completer): Use get_completion_count to figure out
	how many symbols and/or file names were found searching for
	possible completions.
	Traverse the completion tracker hashtable to strip leading
	file name components.  Contents moved to remove_leading_fn_component.
	(free_completer_data): Change argument to proper type.
	(free_entry_callback): New function.
	(free_all_completer_data): New function.
	(vectorize_htab): New function.
	(get_completion_list): New function.
	(get_completion_count): New function.
	(maybe_add_completion): Accumulate completions when not limiting
	the number of completions.
	(complete_line): Ignore the return list from complete_line_internal
	and get the completion results from the tracker.
	Do not count/limit the results at all -- it is no longer necessary.
	Use free_all_completer_data to free any allocated memory during
	completion in the case of an exception.
	Use free_completer_data after get_completion_list to free
	completer data structures.
	(gdb_completion_word_break_characters): Ignore the return list
	from complete_line_internal and get the completion results from
	the tracker.
	Use free_completer_data after get_completion_list to free
	completer data structures.
	* completer.h (get_completion_list): Declare.
	(get_completion_count): Declare.
	* python/py-cmd.c (cmdpy_completer): Use get_completion_count
	to ascertain if there are any completion results.
---
 gdb/cli/cli-decode.c |    2 -
 gdb/completer.c      |  176 ++++++++++++++++++++++++++++----------------------
 gdb/completer.h      |    9 +++
 gdb/python/py-cmd.c  |    2 -
 4 files changed, 111 insertions(+), 78 deletions(-)

diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index fa95ee6..9691fd1 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -1781,7 +1781,7 @@ complete_on_cmdlist (struct completer_data *cdata,
      commands.  If we see no matching commands in the first pass, and
      if we did happen to see a matching deprecated command, we do
      another loop to collect those.  */
-  for (pass = 0; matchlist == 0 && pass < 2; ++pass)
+  for (pass = 0; get_completion_count (cdata) == 0 && pass < 2; ++pass)
     {
       for (ptr = list; ptr; ptr = ptr->next)
 	if (!strncmp (ptr->name, text, textlen)
diff --git a/gdb/completer.c b/gdb/completer.c
index 651e9c2..6faed31 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -197,6 +197,20 @@ filename_completer (struct completer_data *cdata,
   return return_val;
 }
 
+/* A hashtable traversal function to remove leading file name
+   components, as required by rl_complete.  See more detailed explanation
+   in location_completer for more.  */
+
+static int
+remove_leading_fn_component (void **slot, void *calldata)
+{
+  char *fn = *slot;
+  int offset = *(int *) calldata;
+
+  memmove (fn, fn + offset, strlen (fn) + 1 - offset);
+  return 1;
+}
+
 /* Complete on locations, which might be of two possible forms:
 
        file:line
@@ -286,21 +300,25 @@ location_completer (struct completer_data *cdata,
     {
       list = make_file_symbol_completion_list (cdata, symbol_start, word,
 					       file_to_match);
+      n_syms = get_completion_count (cdata);
+      n_files = 0;
       xfree (file_to_match);
     }
   else
     {
       list = make_symbol_completion_list (cdata, symbol_start, word);
+      n_syms = get_completion_count (cdata);
+      n_files = 0;
       /* If text includes characters which cannot appear in a file
 	 name, they cannot be asking for completion on files.  */
       if (strcspn (text, 
 		   gdb_completer_file_name_break_characters) == text_len)
-	fn_list = make_source_files_completion_list (cdata, text, text);
+	{
+	  fn_list = make_source_files_completion_list (cdata, text, text);
+	  n_files = get_completion_count (cdata) - n_syms;
+	}
     }
 
-  n_syms = VEC_length (char_ptr, list);
-  n_files = VEC_length (char_ptr, fn_list);
-
   /* Catenate fn_list[] onto the end of list[].  */
   if (!n_syms)
     {
@@ -323,7 +341,7 @@ location_completer (struct completer_data *cdata,
     }
   else if (n_files)
     {
-      char *fn;
+      int offset = word - text;
 
       /* If we only have file names as possible completion, we should
 	 bring them in sync with what rl_complete expects.  The
@@ -338,13 +356,10 @@ location_completer (struct completer_data *cdata,
 	 the full "/foo/bar" and "/foo/baz" strings.  This produces
 	 wrong results when, e.g., there's only one possible
 	 completion, because rl_complete will prepend "/foo/" to each
-	 candidate completion.  The loop below removes that leading
+	 candidate completion.  The callback below removes that leading
 	 part.  */
-      for (ix = 0; VEC_iterate (char_ptr, list, ix, fn); ++ix)
-	{
-	  memmove (fn, fn + (word - text),
-		   strlen (fn) + 1 - (word - text));
-	}
+      htab_traverse (cdata->tracker, remove_leading_fn_component,
+		     &offset);
     }
   else if (!n_syms)
     {
@@ -837,14 +852,67 @@ new_completer_data (int size)
 /* Free the completion data represented by P.  */
 
 static void
-free_completer_data (void *p)
+free_completer_data (struct completer_data *cdata)
 {
-  struct completer_data *cdata = p;
-
   htab_delete (cdata->tracker);
   xfree (cdata);
 }
 
+/* A hashtable traversal function to free the elements of the table.  */
+
+static int
+free_entry_callback (void **slot, void *calldata)
+{
+  char *element = *slot;
+
+  xfree (element);
+  return 1;
+}
+
+/* A cleanup function to free all data associated with the completer_data
+   given by P.  */
+
+static void
+free_all_completer_data (void *p)
+{
+  struct completer_data *cdata = p;
+
+  htab_traverse (cdata->tracker, free_entry_callback, NULL);
+  free_completer_data (cdata);
+}
+
+/* A hashtable traversal function to turn the hashtable keys
+   into a vector.  */
+
+static int
+vectorize_htab (void **slot, void *calldata)
+{
+  char *element = *slot;
+  VEC (char_ptr) **vector = calldata;
+
+  VEC_safe_push (char_ptr, *vector, element);
+  return 1;
+}
+
+/* See completer.h.  */
+
+VEC (char_ptr) *
+get_completion_list (const struct completer_data *cdata)
+{
+  VEC (char_ptr) *result = NULL;
+
+  htab_traverse (cdata->tracker, vectorize_htab, &result);
+  return result;
+}
+
+/* See completer.h.  */
+
+size_t
+get_completion_count (const struct completer_data *cdata)
+{
+  return htab_elements (cdata->tracker);
+}
+
 /* Add the completion NAME to the list of generated completions if
    it is not there already.
    If max_completions is negative, nothing is done, not even watching
@@ -855,12 +923,11 @@ maybe_add_completion (struct completer_data *cdata, char *name)
 {
   void **slot;
 
-  if (max_completions < 0)
-    return MAYBE_ADD_COMPLETION_OK;
   if (max_completions == 0)
     return MAYBE_ADD_COMPLETION_MAX_REACHED;
 
-  if (htab_elements (cdata->tracker) >= max_completions)
+  if (max_completions > 0
+      && htab_elements (cdata->tracker) >= max_completions)
     return MAYBE_ADD_COMPLETION_MAX_REACHED;
 
   slot = htab_find_slot (cdata->tracker, name, INSERT);
@@ -870,7 +937,8 @@ maybe_add_completion (struct completer_data *cdata, char *name)
 
   *slot = name;
 
-  return (htab_elements (cdata->tracker) < max_completions
+  return ((max_completions < 0
+	   || htab_elements (cdata->tracker) < max_completions)
 	  ? MAYBE_ADD_COMPLETION_OK
 	  : MAYBE_ADD_COMPLETION_OK_MAX_REACHED);
 }
@@ -968,66 +1036,20 @@ throw_max_completions_reached_error (void)
 VEC (char_ptr) *
 complete_line (const char *text, const char *line_buffer, int point)
 {
-  VEC (char_ptr) *list;
-  VEC (char_ptr) *result = NULL;
-  struct cleanup *cdata_cleanup, *list_cleanup;
-  char *candidate;
-  int ix;
+  VEC (char_ptr) *result;
+  struct cleanup *cdata_cleanup;
   struct completer_data *cdata;
 
   if (max_completions == 0)
     return NULL;
 
   cdata = new_completer_data (max_completions);
-  cdata_cleanup = make_cleanup (free_completer_data, cdata);
-  list = complete_line_internal (cdata, text, line_buffer, point,
-				 handle_completions);
-  if (max_completions < 0)
-    {
-      do_cleanups (cdata_cleanup);
-      return list;
-    }
-
-  list_cleanup = make_cleanup_free_char_ptr_vec (list);
-
-  /* If complete_line_internal returned more completions than were
-     recorded by the completion tracker, then the completer function that
-     was run does not support completion tracking.  In this case,
-     do a final test for too many completions.
-
-     Duplicates are also removed here.  Otherwise the user is left
-     scratching his/her head: readline and complete_command will remove
-     duplicates, and if removal of duplicates there brings the total under
-     max_completions the user may think gdb quit searching too early.  */
-
-  if (VEC_length (char_ptr, list) > htab_elements (cdata->tracker))
-    {
-      enum add_completion_status max_reached = ADD_COMPLETION_OK;
-
-      /* Clear the tracker so that we can re-use it to count the number
-	 of returned completions.  */
-      htab_empty (cdata->tracker);
-
-      for (ix = 0; (max_reached == ADD_COMPLETION_OK
-		    && VEC_iterate (char_ptr, list, ix, candidate)); ++ix)
-	{
-	  max_reached = add_completion (cdata, &result, candidate, NULL, NULL);
-	}
-
-      /* The return result has been assembled and the original list from
-	 complete_line_internal is no longer needed.  Free it.  */
-      do_cleanups (list_cleanup);
-    }
-  else
-    {
-      /* There is a valid tracker for the completion -- simply return
-	 the completed list.  */
-      discard_cleanups (list_cleanup);
-      result = list;
-    }
-
-  do_cleanups (cdata_cleanup);
-
+  cdata_cleanup = make_cleanup (free_all_completer_data, cdata);
+  complete_line_internal (cdata, text, line_buffer, point,
+			  handle_completions);
+  result = get_completion_list (cdata);
+  discard_cleanups (cdata_cleanup);
+  free_completer_data (cdata);
   return result;
 }
 
@@ -1175,10 +1197,12 @@ gdb_completion_word_break_characters (void)
   struct cleanup *cleanup;
 
   cdata = new_completer_data (max_completions);
-  cleanup = make_cleanup (free_completer_data, cdata);
-  list = complete_line_internal (cdata, rl_line_buffer, rl_line_buffer,
-				 rl_point, handle_brkchars);
-  do_cleanups (cleanup);
+  cleanup = make_cleanup (free_all_completer_data, cdata);
+  complete_line_internal (cdata, rl_line_buffer, rl_line_buffer,
+			  rl_point, handle_brkchars);
+  list = get_completion_list (cdata);
+  discard_cleanups (cleanup);
+  free_completer_data (cdata);
   gdb_assert (list == NULL);
   return rl_completer_word_break_characters;
 }
diff --git a/gdb/completer.h b/gdb/completer.h
index 98b7d14..07c7d93 100644
--- a/gdb/completer.h
+++ b/gdb/completer.h
@@ -132,6 +132,15 @@ extern const char *skip_quoted (const char *);
 
 extern int get_maximum_completions (void);
 
+/* Get the list of completions.  */
+
+extern VEC (char_ptr) *
+  get_completion_list (const struct completer_data *cdata);
+
+/* Get the number of completions in CDATA.  */
+
+extern size_t get_completion_count (const struct completer_data *cdata);
+
 /* Return values for add_completion.  */
 
 enum add_completion_status
diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
index 36e352e..cf76bd1 100644
--- a/gdb/python/py-cmd.c
+++ b/gdb/python/py-cmd.c
@@ -406,7 +406,7 @@ cmdpy_completer (struct completer_data *cdata,
 
       /* If we got some results, ignore problems.  Otherwise, report
 	 the problem.  */
-      if (result != NULL && PyErr_Occurred ())
+      if (get_completion_count (cdata) > 0 && PyErr_Occurred ())
 	PyErr_Clear ();
     }
 

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v3 04/19] Implement completion limiting for add_filename_to_list.
  2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
                   ` (5 preceding siblings ...)
  2015-08-06 19:58 ` [PATCH v3 19/19] Remove the vector return result from the completion API Keith Seitz
@ 2015-08-06 19:58 ` Keith Seitz
  2015-08-23  1:07   ` Doug Evans
  2015-08-06 20:03 ` [PATCH v3 01/19] Add struct completer_data to the completion API Keith Seitz
                   ` (12 subsequent siblings)
  19 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-06 19:58 UTC (permalink / raw)
  To: gdb-patches

Differences in this revision:

1. Remove partial copy code from add_filename_to_list.

---

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 and
	update all callers.
	Use add_completion.

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                       |   40 +++++------------
 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, 189 insertions(+), 33 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 34eb6d7..e24de89 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -5679,33 +5679,11 @@ 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);
-
-  if (word == text)
-    {
-      /* Return exactly fname.  */
-      newobj = xmalloc (fnlen + 5);
-      strcpy (newobj, fname);
-    }
-  else if (word > text)
-    {
-      /* Return some portion of fname.  */
-      newobj = xmalloc (fnlen + 5);
-      strcpy (newobj, fname + (word - text));
-    }
-  else
-    {
-      /* Return some of TEXT plus fname.  */
-      newobj = xmalloc (fnlen + (text - word) + 5);
-      strncpy (newobj, word, text - word);
-      newobj[text - word] = '\0';
-      strcat (newobj, fname);
-    }
-  VEC_safe_push (char_ptr, *list, newobj);
+  (void) add_completion (cdata, list, fname, text, word);
 }
 
 static int
@@ -5754,7 +5732,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
     {
@@ -5763,7 +5742,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);
+	}
     }
 }
 
@@ -5804,7 +5786,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
 	{
@@ -5816,7 +5798,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;
+}

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v3 19/19] Remove the vector return result from the completion API.
  2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
                   ` (4 preceding siblings ...)
  2015-08-06 19:58 ` [PATCH v3 18/19] Use the hashtable to accumulate completion results Keith Seitz
@ 2015-08-06 19:58 ` Keith Seitz
  2015-08-23 18:03   ` Doug Evans
  2015-08-06 19:58 ` [PATCH v3 04/19] Implement completion limiting for add_filename_to_list Keith Seitz
                   ` (13 subsequent siblings)
  19 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-06 19:58 UTC (permalink / raw)
  To: gdb-patches

Differences in this revision:

1. Updated new TUI completion functions.

---

This patch completes the redesign of the completion and completion-
limiting API.  Since the completer's internal data is now responsible
for tracking all completions and the result of the completion operation
no longer uses vectors (except for the final list given to readline),
we can remove the vectors from the API entirely.

gdb/ChangeLog

	* command.h (completer_ftype): Change return type from
	VEC (char_ptr) * to void.  Update all users of this definition.
	* completer.h (add_completion): Remove vector argument.
	All users updated.
	* symtab.c (free_completion_list): Remove.
	(do_free_completion_list): Remove.
	(return_val): Remove global.
---
 gdb/ada-lang.c            |   47 +++++--------
 gdb/break-catch-syscall.c |    8 +-
 gdb/breakpoint.c          |   15 ++--
 gdb/cli/cli-decode.c      |   28 +++-----
 gdb/command.h             |   18 +++--
 gdb/completer.c           |  161 ++++++++++++++++++---------------------------
 gdb/completer.h           |   51 +++++++-------
 gdb/corefile.c            |    4 +
 gdb/cp-abi.c              |    4 +
 gdb/f-lang.c              |    6 +-
 gdb/guile/scm-cmd.c       |   30 +++-----
 gdb/infrun.c              |   12 +--
 gdb/interps.c             |    7 +-
 gdb/language.h            |    2 -
 gdb/python/py-cmd.c       |   10 +--
 gdb/remote-sim.c          |   10 +--
 gdb/symtab.c              |   98 +++++++--------------------
 gdb/symtab.h              |   15 ++--
 gdb/tui/tui-layout.c      |    4 +
 gdb/tui/tui-regs.c        |    9 +--
 gdb/tui/tui-win.c         |   22 +++---
 gdb/value.c               |    7 +-
 gdb/value.h               |    4 +
 23 files changed, 220 insertions(+), 352 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 5df08be..5effb48 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -6199,8 +6199,7 @@ symbol_completion_match (const char *sym_name,
    encoded).  */
 
 static enum add_completion_status
-symbol_completion_add (VEC(char_ptr) **sv,
-		       struct completer_data *cdata,
+symbol_completion_add (struct completer_data *cdata,
                        const char *sym_name,
                        const char *text, int text_len,
                        const char *orig_text, const char *word,
@@ -6213,14 +6212,13 @@ symbol_completion_add (VEC(char_ptr) **sv,
 
   /* We found a match, so add the appropriate completion to the given
      string vector.  */
-  return add_completion (cdata, sv, match, orig_text, word);
+  return add_completion (cdata, match, orig_text, word);
 }
 
 /* An object of this type is passed as the user_data argument to the
    expand_symtabs_matching method.  */
 struct add_partial_datum
 {
-  VEC(char_ptr) **completions;
   const char *text;
   int text_len;
   const char *text0;
@@ -6243,7 +6241,7 @@ ada_complete_symbol_matcher (const char *name, void *user_data)
 /* Return a list of possible symbol names completing TEXT0.  WORD is
    the entire command on which completion is made.  */
 
-static VEC (char_ptr) *
+static void
 ada_make_symbol_completion_list (struct completer_data *cdata,
 				 const char *text0, const char *word,
 				 enum type_code code)
@@ -6252,7 +6250,6 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
   int text_len;
   int wild_match_p;
   int encoded_p;
-  VEC(char_ptr) *completions = VEC_alloc (char_ptr, 128);
   struct symbol *sym;
   struct compunit_symtab *s;
   struct minimal_symbol *msymbol;
@@ -6293,7 +6290,6 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
   {
     struct add_partial_datum data;
 
-    data.completions = &completions;
     data.text = text;
     data.text_len = text_len;
     data.text0 = text0;
@@ -6312,14 +6308,13 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
   ALL_MSYMBOLS (objfile, msymbol)
   {
     QUIT;
-    status = symbol_completion_add (&completions, cdata,
-					 MSYMBOL_LINKAGE_NAME (msymbol),
-					 text, text_len, text0, word,
-					 wild_match_p, encoded_p);
+    status = symbol_completion_add (cdata, MSYMBOL_LINKAGE_NAME (msymbol),
+				    text, text_len, text0, word,
+				    wild_match_p, encoded_p);
     if (status == ADD_COMPLETION_MAX_REACHED)
       {
 	do_cleanups (old_chain);
-	return completions;
+	return;
       }
   }
 
@@ -6333,14 +6328,13 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
 
       ALL_BLOCK_SYMBOLS (b, iter, sym)
       {
-        status = symbol_completion_add (&completions, cdata,
-					     SYMBOL_LINKAGE_NAME (sym),
-					     text, text_len, text0, word,
-					     wild_match_p, encoded_p);
+        status = symbol_completion_add (cdata, SYMBOL_LINKAGE_NAME (sym),
+					text, text_len, text0, word,
+					wild_match_p, encoded_p);
 	if (status == ADD_COMPLETION_MAX_REACHED)
 	  {
 	    do_cleanups (old_chain);
-	    return completions;
+	    return;
 	  }
       }
     }
@@ -6354,14 +6348,13 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
     b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (s), GLOBAL_BLOCK);
     ALL_BLOCK_SYMBOLS (b, iter, sym)
     {
-      status = symbol_completion_add (&completions, cdata,
-					   SYMBOL_LINKAGE_NAME (sym),
-					   text, text_len, text0, word,
-					   wild_match_p, encoded_p);
+      status = symbol_completion_add (cdata,SYMBOL_LINKAGE_NAME (sym),
+				      text, text_len, text0, word,
+				      wild_match_p, encoded_p);
       if (status == ADD_COMPLETION_MAX_REACHED)
 	{
 	  do_cleanups (old_chain);
-	  return completions;
+	  return;
 	}
     }
   }
@@ -6375,20 +6368,18 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
       continue;
     ALL_BLOCK_SYMBOLS (b, iter, sym)
     {
-      status = symbol_completion_add (&completions, cdata,
-					   SYMBOL_LINKAGE_NAME (sym),
-					   text, text_len, text0, word,
-					   wild_match_p, encoded_p);
+      status = symbol_completion_add (cdata, SYMBOL_LINKAGE_NAME (sym),
+				      text, text_len, text0, word,
+				      wild_match_p, encoded_p);
       if (status == ADD_COMPLETION_MAX_REACHED)
 	{
 	  do_cleanups (old_chain);
-	  return completions;
+	  return;
 	}
     }
   }
 
   do_cleanups (old_chain);
-  return completions;
 }
 
                                 /* Field Access */
diff --git a/gdb/break-catch-syscall.c b/gdb/break-catch-syscall.c
index 4677132..a542826 100644
--- a/gdb/break-catch-syscall.c
+++ b/gdb/break-catch-syscall.c
@@ -591,17 +591,17 @@ catching_syscall_number (int syscall_number)
 }
 
 /* Complete syscall names.  Used by "catch syscall".  */
-static VEC (char_ptr) *
+static void
 catch_syscall_completer (struct completer_data *cdata,
 			 struct cmd_list_element *cmd,
                          const char *text, const char *word)
 {
   const char **list = get_syscall_names (get_current_arch ());
-  VEC (char_ptr) *retlist
-    = (list == NULL) ? NULL : complete_on_enum (cdata, list, word, word);
+
+  if (list != NULL)
+    complete_on_enum (cdata, list, word, word);
 
   xfree (list);
-  return retlist;
 }
 
 static void
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 24243c4..08901ae 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -1032,7 +1032,7 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp,
 
 /* Completion for the "condition" command.  */
 
-static VEC (char_ptr) *
+static void
 condition_completer (struct completer_data *cdata,
 		     struct cmd_list_element *cmd,
 		     const char *text, const char *word)
@@ -1045,14 +1045,13 @@ condition_completer (struct completer_data *cdata,
     {
       int len;
       struct breakpoint *b;
-      VEC (char_ptr) *result = NULL;
 
       if (text[0] == '$')
 	{
 	  /* We don't support completion of history indices.  */
-	  if (isdigit (text[1]))
-	    return NULL;
-	  return complete_internalvar (cdata, &text[1]);
+	  if (!isdigit (text[1]))
+	    complete_internalvar (cdata, &text[1]);
+	  return;
 	}
 
       /* We're completing the breakpoint number.  */
@@ -1066,18 +1065,18 @@ condition_completer (struct completer_data *cdata,
 
 	  if (strncmp (number, text, len) == 0)
 	    {
-	      if (add_completion (cdata, &result, number, NULL, NULL)
+	      if (add_completion (cdata, number, NULL, NULL)
 		  == ADD_COMPLETION_MAX_REACHED)
 		break;
 	    }
 	}
 
-      return result;
+      return;
     }
 
   /* We're completing the expression part.  */
   text = skip_spaces_const (space);
-  return expression_completer (cdata, cmd, text, word);
+  expression_completer (cdata, cmd, text, word);
 }
 
 /* condition N EXP -- set break condition of breakpoint N to EXP.  */
diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index 9691fd1..9e7bf80 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -647,7 +647,7 @@ add_setshow_optional_filename_cmd (const char *name, enum command_class theclass
 /* Completes on literal "unlimited".  Used by integer commands that
    support a special "unlimited" value.  */
 
-static VEC (char_ptr) *
+static void
 integer_unlimited_completer (struct completer_data *cdata,
 			     struct cmd_list_element *ignore,
 			     const char *text, const char *word)
@@ -658,7 +658,7 @@ integer_unlimited_completer (struct completer_data *cdata,
       NULL,
     };
 
-  return complete_on_enum (cdata, keywords, text, word);
+  complete_on_enum (cdata, keywords, text, word);
 }
 
 /* Add element named NAME to both the set and show command LISTs (the
@@ -1757,22 +1757,21 @@ lookup_cmd_composition (const char *text,
 
 /* Helper function for SYMBOL_COMPLETION_FUNCTION.  */
 
-/* Return a vector of char pointers which point to the different
-   possible completions in LIST of TEXT.
+/* Add completions to CDATA for the different possible completions
+   in LIST of TEXT.
 
    WORD points in the same buffer as TEXT, and completions should be
    returned relative to this position.  For example, suppose TEXT is
    "foo" and we want to complete to "foobar".  If WORD is "oo", return
    "oobar"; if WORD is "baz/foo", return "baz/foobar".  */
 
-VEC (char_ptr) *
+void
 complete_on_cmdlist (struct completer_data *cdata,
 		     struct cmd_list_element *list,
 		     const char *text, const char *word,
 		     int ignore_help_classes)
 {
   struct cmd_list_element *ptr;
-  VEC (char_ptr) *matchlist = NULL;
   int textlen = strlen (text);
   int pass;
   int saw_deprecated_match = 0;
@@ -1798,35 +1797,32 @@ complete_on_cmdlist (struct completer_data *cdata,
 		  }
 	      }
 
-	    if (add_completion (cdata, &matchlist, ptr->name, text, word)
+	    if (add_completion (cdata, ptr->name, text, word)
 		== ADD_COMPLETION_MAX_REACHED)
-	      return matchlist;
+	      return;
 	  }
       /* If we saw no matching deprecated commands in the first pass,
 	 just bail out.  */
       if (!saw_deprecated_match)
 	break;
     }
-
-  return matchlist;
 }
 
 /* Helper function for SYMBOL_COMPLETION_FUNCTION.  */
 
-/* Return a vector of char pointers which point to the different
-   possible completions in CMD of TEXT.
+/* Add completions to CDATA for the different possible completions in
+   CMD of TEXT.
 
    WORD points in the same buffer as TEXT, and completions should be
    returned relative to this position.  For example, suppose TEXT is "foo"
    and we want to complete to "foobar".  If WORD is "oo", return
    "oobar"; if WORD is "baz/foo", return "baz/foobar".  */
 
-VEC (char_ptr) *
+void
 complete_on_enum (struct completer_data *cdata,
 		  const char *const *enumlist,
 		  const char *text, const char *word)
 {
-  VEC (char_ptr) *matchlist = NULL;
   int textlen = strlen (text);
   int i;
   const char *name;
@@ -1834,12 +1830,10 @@ complete_on_enum (struct completer_data *cdata,
   for (i = 0; (name = enumlist[i]) != NULL; i++)
     if (strncmp (name, text, textlen) == 0)
       {
-	if (add_completion (cdata, &matchlist, name, text, word)
+	if (add_completion (cdata, name, text, word)
 	    == ADD_COMPLETION_MAX_REACHED)
 	  break;
       }
-
-  return matchlist;
 }
 
 
diff --git a/gdb/command.h b/gdb/command.h
index b2aeb30..82872c0 100644
--- a/gdb/command.h
+++ b/gdb/command.h
@@ -158,9 +158,9 @@ typedef void cmd_sfunc_ftype (char *args, int from_tty,
 extern void set_cmd_sfunc (struct cmd_list_element *cmd,
 			   cmd_sfunc_ftype *sfunc);
 
-typedef VEC (char_ptr) *completer_ftype (struct completer_data *,
-					 struct cmd_list_element *,
-					 const char *, const char *);
+typedef void completer_ftype (struct completer_data *,
+			      struct cmd_list_element *,
+			      const char *, const char *);
 
 typedef void completer_ftype_void (struct cmd_list_element *,
 				   const char *, const char *);
@@ -228,13 +228,13 @@ extern struct cmd_list_element *add_info (const char *,
 extern struct cmd_list_element *add_info_alias (const char *, const char *,
 						int);
 
-extern VEC (char_ptr) *complete_on_cmdlist (struct completer_data *,
-					    struct cmd_list_element *,
-					    const char *, const char *, int);
+extern void complete_on_cmdlist (struct completer_data *,
+				 struct cmd_list_element *,
+				 const char *, const char *, int);
 
-extern VEC (char_ptr) *complete_on_enum (struct completer_data *,
-					 const char *const *enumlist,
-					 const char *, const char *);
+extern void complete_on_enum (struct completer_data *,
+			      const char *const *enumlist,
+			      const char *, const char *);
 
 /* Functions that implement commands about CLI commands.  */
 
diff --git a/gdb/completer.c b/gdb/completer.c
index 6faed31..2ca7d2d 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -144,22 +144,23 @@ readline_line_completion_function (const char *text, int matches)
 
 /* This can be used for functions which don't want to complete on
    symbols but don't want to complete on anything else either.  */
-VEC (char_ptr) *
+
+void
 noop_completer (struct completer_data *cdata,
 		struct cmd_list_element *ignore,
 		const char *text, const char *prefix)
 {
-  return NULL;
+  /* Nothing.  */
 }
 
 /* Complete on filenames.  */
-VEC (char_ptr) *
+
+void
 filename_completer (struct completer_data *cdata,
 		    struct cmd_list_element *ignore,
 		    const char *text, const char *word)
 {
   int subsequent_name;
-  VEC (char_ptr) *return_val = NULL;
 
   subsequent_name = 0;
   while (1)
@@ -182,7 +183,7 @@ filename_completer (struct completer_data *cdata,
 	  continue;
 	}
 
-      if (add_completion (cdata, &return_val, p, text, word)
+      if (add_completion (cdata, p, text, word)
 	  == ADD_COMPLETION_MAX_REACHED)
 	break;
     }
@@ -194,7 +195,6 @@ filename_completer (struct completer_data *cdata,
      with respect to inserting quotes.  */
   rl_completer_word_break_characters = "";
 #endif
-  return return_val;
 }
 
 /* A hashtable traversal function to remove leading file name
@@ -220,14 +220,12 @@ remove_leading_fn_component (void **slot, void *calldata)
    This is intended to be used in commands that set breakpoints
    etc.  */
 
-VEC (char_ptr) *
+void
 location_completer (struct completer_data *cdata,
 		    struct cmd_list_element *ignore,
 		    const char *text, const char *word)
 {
   int n_syms, n_files, ix;
-  VEC (char_ptr) *fn_list = NULL;
-  VEC (char_ptr) *list = NULL;
   const char *p;
   int quote_found = 0;
   int quoted = *text == '\'' || *text == '"';
@@ -298,15 +296,15 @@ location_completer (struct completer_data *cdata,
      symbols as well as on files.  */
   if (colon)
     {
-      list = make_file_symbol_completion_list (cdata, symbol_start, word,
-					       file_to_match);
+      make_file_symbol_completion_list (cdata, symbol_start, word,
+					file_to_match);
       n_syms = get_completion_count (cdata);
       n_files = 0;
       xfree (file_to_match);
     }
   else
     {
-      list = make_symbol_completion_list (cdata, symbol_start, word);
+      make_symbol_completion_list (cdata, symbol_start, word);
       n_syms = get_completion_count (cdata);
       n_files = 0;
       /* If text includes characters which cannot appear in a file
@@ -314,27 +312,11 @@ location_completer (struct completer_data *cdata,
       if (strcspn (text, 
 		   gdb_completer_file_name_break_characters) == text_len)
 	{
-	  fn_list = make_source_files_completion_list (cdata, text, text);
+	  make_source_files_completion_list (cdata, text, text);
 	  n_files = get_completion_count (cdata) - n_syms;
 	}
     }
 
-  /* Catenate fn_list[] onto the end of list[].  */
-  if (!n_syms)
-    {
-      VEC_free (char_ptr, list); /* Paranoia.  */
-      list = fn_list;
-      fn_list = NULL;
-    }
-  else
-    {
-      char *fn;
-
-      for (ix = 0; VEC_iterate (char_ptr, fn_list, ix, fn); ++ix)
-	VEC_safe_push (char_ptr, list, fn);
-      VEC_free (char_ptr, fn_list);
-    }
-
   if (n_syms && n_files)
     {
       /* Nothing.  */
@@ -365,18 +347,15 @@ location_completer (struct completer_data *cdata,
     {
       /* No completions at all.  As the final resort, try completing
 	 on the entire text as a symbol.  */
-      list = make_symbol_completion_list (cdata, orig_text, word);
+      make_symbol_completion_list (cdata, orig_text, word);
     }
-
-  return list;
 }
 
 /* Helper for expression_completer which recursively adds field and
    method names from TYPE, a struct or union type, to the array
    OUTPUT.  */
 static void
-add_struct_fields (struct completer_data *cdata,
-		   struct type *type, VEC (char_ptr) **output,
+add_struct_fields (struct completer_data *cdata, struct type *type,
 		   char *fieldname, int namelen)
 {
   int i;
@@ -388,7 +367,7 @@ add_struct_fields (struct completer_data *cdata,
     {
       if (i < TYPE_N_BASECLASSES (type))
 	add_struct_fields (cdata, TYPE_BASECLASS (type, i),
-			   output, fieldname, namelen);
+			   fieldname, namelen);
       else if (TYPE_FIELD_NAME (type, i))
 	{
 	  if (TYPE_FIELD_NAME (type, i)[0] != '\0')
@@ -396,7 +375,7 @@ add_struct_fields (struct completer_data *cdata,
 	      if (! strncmp (TYPE_FIELD_NAME (type, i), 
 			     fieldname, namelen))
 		{
-		  if (add_completion (cdata, output, TYPE_FIELD_NAME (type, i),
+		  if (add_completion (cdata, TYPE_FIELD_NAME (type, i),
 				      NULL, NULL)
 		      == ADD_COMPLETION_MAX_REACHED)
 		    return;
@@ -406,7 +385,7 @@ add_struct_fields (struct completer_data *cdata,
 	    {
 	      /* Recurse into anonymous unions.  */
 	      add_struct_fields (cdata, TYPE_FIELD_TYPE (type, i),
-				 output, fieldname, namelen);
+				 fieldname, namelen);
 	    }
 	}
     }
@@ -425,7 +404,7 @@ add_struct_fields (struct completer_data *cdata,
 	  /* Omit constructors from the completion list.  */
 	  if (!type_name || strcmp (type_name, name))
 	    {
-	      if (add_completion (cdata, output, name, NULL, NULL)
+	      if (add_completion (cdata, name, NULL, NULL)
 		  == ADD_COMPLETION_MAX_REACHED)
 		return;
 	    }
@@ -436,7 +415,8 @@ add_struct_fields (struct completer_data *cdata,
 /* Complete on expressions.  Often this means completing on symbol
    names, but some language parsers also have support for completing
    field names.  */
-VEC (char_ptr) *
+
+void
 expression_completer (struct completer_data *cdata,
 		      struct cmd_list_element *ignore,
 		      const char *text, const char *word)
@@ -455,7 +435,7 @@ expression_completer (struct completer_data *cdata,
     }
   CATCH (except, RETURN_MASK_ERROR)
     {
-      return NULL;
+      return;
     }
   END_CATCH
 
@@ -474,22 +454,19 @@ expression_completer (struct completer_data *cdata,
 	  || TYPE_CODE (type) == TYPE_CODE_STRUCT)
 	{
 	  int flen = strlen (fieldname);
-	  VEC (char_ptr) *result = NULL;
 
-	  add_struct_fields (cdata, type, &result, fieldname, flen);
+	  add_struct_fields (cdata, type, fieldname, flen);
 	  xfree (fieldname);
-	  return result;
+	  return;
 	}
     }
   else if (fieldname && code != TYPE_CODE_UNDEF)
     {
-      VEC (char_ptr) *result;
       struct cleanup *cleanup = make_cleanup (xfree, fieldname);
 
-      result
-	= make_symbol_completion_type (cdata, fieldname, fieldname, code);
+      make_symbol_completion_type (cdata, fieldname, fieldname, code);
       do_cleanups (cleanup);
-      return result;
+      return;
     }
   xfree (fieldname);
 
@@ -501,7 +478,7 @@ expression_completer (struct completer_data *cdata,
     ;
 
   /* Not ideal but it is what we used to do before...  */
-  return location_completer (cdata, ignore, p, word);
+  location_completer (cdata, ignore, p, word);
 }
 
 /* See definition in completer.h.  */
@@ -578,12 +555,11 @@ complete_line_internal_reason;
    once sub-command completions are exhausted, we simply return NULL.
  */
 
-static VEC (char_ptr) *
+static void
 complete_line_internal (struct completer_data *cdata,
 			const char *text, const char *line_buffer, int point,
 			complete_line_internal_reason reason)
 {
-  VEC (char_ptr) *list = NULL;
   char *tmp_command;
   const char *p;
   int ignore_help_classes;
@@ -638,7 +614,7 @@ complete_line_internal (struct completer_data *cdata,
     {
       /* It is an unrecognized command.  So there are no
 	 possible completions.  */
-      list = NULL;
+      return;
     }
   else if (c == CMD_LIST_AMBIGUOUS)
     {
@@ -656,7 +632,7 @@ complete_line_internal (struct completer_data *cdata,
 	     example, "info t " or "info t foo" does not complete
 	     to anything, because "info t" can be "info target" or
 	     "info terminal".  */
-	  list = NULL;
+	  return;
 	}
       else
 	{
@@ -665,14 +641,14 @@ complete_line_internal (struct completer_data *cdata,
 	  if (result_list)
 	    {
 	      if (reason != handle_brkchars)
-		list = complete_on_cmdlist (cdata, *result_list->prefixlist,
-					    p, word, ignore_help_classes);
+		complete_on_cmdlist (cdata, *result_list->prefixlist,
+				     p, word, ignore_help_classes);
 	    }
 	  else
 	    {
 	      if (reason != handle_brkchars)
-		list = complete_on_cmdlist (cdata, cmdlist, p, word,
-					    ignore_help_classes);
+		complete_on_cmdlist (cdata, cmdlist, p, word,
+				     ignore_help_classes);
 	    }
 	  /* Ensure that readline does the right thing with respect to
 	     inserting quotes.  */
@@ -698,8 +674,8 @@ complete_line_internal (struct completer_data *cdata,
 		  /* It is a prefix command; what comes after it is
 		     a subcommand (e.g. "info ").  */
 		  if (reason != handle_brkchars)
-		    list = complete_on_cmdlist (cdata, *c->prefixlist, p,
-						word, ignore_help_classes);
+		    complete_on_cmdlist (cdata, *c->prefixlist, p,
+					 word, ignore_help_classes);
 
 		  /* Ensure that readline does the right thing
 		     with respect to inserting quotes.  */
@@ -707,11 +683,11 @@ complete_line_internal (struct completer_data *cdata,
 		    gdb_completer_command_word_break_characters;
 		}
 	      else if (reason == handle_help)
-		list = NULL;
+		return;
 	      else if (c->enums)
 		{
 		  if (reason != handle_brkchars)
-		    list = complete_on_enum (cdata, c->enums, p, word);
+		    complete_on_enum (cdata, c->enums, p, word);
 		  rl_completer_word_break_characters =
 		    gdb_completer_command_word_break_characters;
 		}
@@ -751,7 +727,7 @@ complete_line_internal (struct completer_data *cdata,
 		      && c->completer_handle_brkchars != NULL)
 		    (*c->completer_handle_brkchars) (c, p, word);
 		  if (reason != handle_brkchars && c->completer != NULL)
-		    list = (*c->completer) (cdata, c, p, word);
+		    (*c->completer) (cdata, c, p, word);
 		}
 	    }
 	  else
@@ -773,8 +749,8 @@ complete_line_internal (struct completer_data *cdata,
 		}
 
 	      if (reason != handle_brkchars)
-		list = complete_on_cmdlist (cdata, result_list, q, word,
-					    ignore_help_classes);
+		complete_on_cmdlist (cdata, result_list, q, word,
+				     ignore_help_classes);
 
 	      /* Ensure that readline does the right thing
 		 with respect to inserting quotes.  */
@@ -783,7 +759,7 @@ complete_line_internal (struct completer_data *cdata,
 	    }
 	}
       else if (reason == handle_help)
-	list = NULL;
+	return;
       else
 	{
 	  /* There is non-whitespace beyond the command.  */
@@ -792,12 +768,12 @@ complete_line_internal (struct completer_data *cdata,
 	    {
 	      /* It is an unrecognized subcommand of a prefix command,
 		 e.g. "info adsfkdj".  */
-	      list = NULL;
+	      return;
 	    }
 	  else if (c->enums)
 	    {
 	      if (reason != handle_brkchars)
-		list = complete_on_enum (cdata, c->enums, p, word);
+		complete_on_enum (cdata, c->enums, p, word);
 	    }
 	  else
 	    {
@@ -827,12 +803,10 @@ complete_line_internal (struct completer_data *cdata,
 		  && c->completer_handle_brkchars != NULL)
 		(*c->completer_handle_brkchars) (c, p, word);
 	      if (reason != handle_brkchars && c->completer != NULL)
-		list = (*c->completer) (cdata, c, p, word);
+		(*c->completer) (cdata, c, p, word);
 	    }
 	}
     }
-
-  return list;
 }
 
 /* Allocate a new completer data structure.  */
@@ -986,8 +960,8 @@ get_maximum_completions (void)
 /* See completer.h.  */
 
 enum add_completion_status
-add_completion (struct completer_data *cdata, VEC (char_ptr) **result,
-		const char *match, const char *text, const char *word)
+add_completion (struct completer_data *cdata, const char *match,
+		const char *text, const char *word)
 {
   enum maybe_add_completion_enum add_status;
   char *alloc = completer_strdup (match, text, word);
@@ -996,10 +970,8 @@ add_completion (struct completer_data *cdata, VEC (char_ptr) **result,
   switch (add_status)
     {
     case MAYBE_ADD_COMPLETION_OK:
-      VEC_safe_push (char_ptr, *result, alloc);
       break;
     case MAYBE_ADD_COMPLETION_OK_MAX_REACHED:
-      VEC_safe_push (char_ptr, *result, alloc);
       return ADD_COMPLETION_MAX_REACHED;
     case MAYBE_ADD_COMPLETION_MAX_REACHED:
       xfree (alloc);
@@ -1054,23 +1026,23 @@ complete_line (const char *text, const char *line_buffer, int point)
 }
 
 /* Complete on command names.  Used by "help".  */
-VEC (char_ptr) *
+
+void
 command_completer (struct completer_data *cdata,
 		   struct cmd_list_element *ignore,
 		   const char *text, const char *word)
 {
-  return complete_line_internal (cdata, word, text,
-				 strlen (text), handle_help);
+  complete_line_internal (cdata, word, text,
+			  strlen (text), handle_help);
 }
 
 /* Complete on signals.  */
 
-VEC (char_ptr) *
+void
 signal_completer (struct completer_data *cdata,
 		  struct cmd_list_element *ignore,
 		  const char *text, const char *word)
 {
-  VEC (char_ptr) *return_val = NULL;
   size_t len = strlen (word);
   int signum;
   const char *signame;
@@ -1089,13 +1061,11 @@ signal_completer (struct completer_data *cdata,
 
       if (strncasecmp (signame, word, len) == 0)
 	{
-	  if (add_completion (cdata, &return_val, signame, NULL, NULL)
+	  if (add_completion (cdata, signame, NULL, NULL)
 	      == ADD_COMPLETION_MAX_REACHED)
 	    break;
 	}
     }
-
-  return return_val;
 }
 
 /* Bit-flags for selecting what the register and/or register-group
@@ -1110,13 +1080,12 @@ enum reg_completer_targets
 /* Complete register names and/or reggroup names based on the value passed
    in TARGETS.  At least one bit in TARGETS must be set.  */
 
-static VEC (char_ptr) *
+static void
 reg_or_group_completer_1 (struct completer_data *cdata,
 			  struct cmd_list_element *ignore,
 			  const char *text, const char *word,
 			  enum reg_completer_targets targets)
 {
-  VEC (char_ptr) *result = NULL;
   size_t len = strlen (word);
   struct gdbarch *gdbarch;
   const char *name;
@@ -1124,6 +1093,8 @@ reg_or_group_completer_1 (struct completer_data *cdata,
   gdb_assert ((targets & (complete_register_names
 			  | complete_reggroup_names)) != 0);
   gdbarch = get_current_arch ();
+  if (!target_has_registers)
+    return;
 
   if ((targets & complete_register_names) != 0)
     {
@@ -1135,9 +1106,9 @@ reg_or_group_completer_1 (struct completer_data *cdata,
 	{
 	  if (*name != '\0' && strncmp (word, name, len) == 0)
 	    {
-	      if (add_completion (cdata, &result, name, NULL, NULL)
+	      if (add_completion (cdata, name, NULL, NULL)
 		  == ADD_COMPLETION_MAX_REACHED)
-		return result;
+		return;
 	    }
 	}
     }
@@ -1153,37 +1124,35 @@ reg_or_group_completer_1 (struct completer_data *cdata,
 	  name = reggroup_name (group);
 	  if (strncmp (word, name, len) == 0)
 	    {
-	      if (add_completion (cdata, &result, name, NULL, NULL)
+	      if (add_completion (cdata, name, NULL, NULL)
 		  == ADD_COMPLETION_MAX_REACHED)
-		return result;
+		return;
 	    }
 	}
     }
-
-  return result;
 }
 
 /* Perform completion on register and reggroup names.  */
 
-VEC (char_ptr) *
+void
 reg_or_group_completer (struct completer_data *cdata,
 			struct cmd_list_element *ignore,
 			const char *text, const char *word)
 {
-  return reg_or_group_completer_1 (cdata, ignore, text, word,
-				   (complete_register_names
-				    | complete_reggroup_names));
+  reg_or_group_completer_1 (cdata, ignore, text, word,
+			    (complete_register_names
+			     | complete_reggroup_names));
 }
 
 /* Perform completion on reggroup names.  */
 
-VEC (char_ptr) *
+void
 reggroup_completer (struct completer_data *cdata,
 		    struct cmd_list_element *ignore,
 		    const char *text, const char *word)
 {
-  return reg_or_group_completer_1 (cdata, ignore, text, word,
-				   complete_reggroup_names);
+  reg_or_group_completer_1 (cdata, ignore, text, word,
+			    complete_reggroup_names);
 }
 
 /* Get the list of chars that are considered as word breaks
diff --git a/gdb/completer.h b/gdb/completer.h
index 07c7d93..cfdca71 100644
--- a/gdb/completer.h
+++ b/gdb/completer.h
@@ -76,37 +76,37 @@ extern VEC (char_ptr) *complete_line (const char *text,
 extern char *readline_line_completion_function (const char *text,
 						int matches);
 
-extern VEC (char_ptr) *noop_completer (struct completer_data *,
-				       struct cmd_list_element *,
-				       const char *, const char *);
+extern void noop_completer (struct completer_data *,
+			    struct cmd_list_element *,
+			    const char *, const char *);
 
-extern VEC (char_ptr) *filename_completer (struct completer_data *,
-					   struct cmd_list_element *,
-					   const char *, const char *);
+extern void filename_completer (struct completer_data *,
+				struct cmd_list_element *,
+				const char *, const char *);
 
-extern VEC (char_ptr) *expression_completer (struct completer_data *,
-					     struct cmd_list_element *,
-					     const char *, const char *);
+extern void expression_completer (struct completer_data *,
+				  struct cmd_list_element *,
+				  const char *, const char *);
 
-extern VEC (char_ptr) *location_completer (struct completer_data *,
-					   struct cmd_list_element *,
-					   const char *, const char *);
+extern void location_completer (struct completer_data *,
+				struct cmd_list_element *,
+				const char *, const char *);
 
-extern VEC (char_ptr) *command_completer (struct completer_data *,
-					  struct cmd_list_element *,
-					  const char *, const char *);
+extern void command_completer (struct completer_data *,
+			       struct cmd_list_element *,
+			       const char *, const char *);
 
-extern VEC (char_ptr) *signal_completer (struct completer_data *,
-					 struct cmd_list_element *,
-					 const char *, const char *);
+extern void signal_completer (struct completer_data *,
+			      struct cmd_list_element *,
+			      const char *, const char *);
 
-extern VEC (char_ptr) *reg_or_group_completer (struct completer_data *,
-					       struct cmd_list_element *,
-					       const char *, const char *);
+extern void reg_or_group_completer (struct completer_data *,
+				    struct cmd_list_element *,
+				    const char *, const char *);
 
-extern VEC (char_ptr) *reggroup_completer (struct completer_data *cdata,
-					   struct cmd_list_element *,
-					   const char *, const char *);
+extern void reggroup_completer (struct completer_data *cdata,
+				struct cmd_list_element *,
+				const char *, const char *);
 
 extern char *get_gdb_completer_quote_characters (void);
 
@@ -163,8 +163,7 @@ enum add_completion_status
    saved into the completion list.  See completer_strdup for more.  */
 
 extern enum add_completion_status
-  add_completion (struct completer_data *cdata,
-		  VEC (char_ptr) **result, const char *match,
+  add_completion (struct completer_data *cdata, const char *match,
 		  const char *text, const char *word);
 
 /* Wrapper to throw MAX_COMPLETIONS_REACHED_ERROR.  */ 
diff --git a/gdb/corefile.c b/gdb/corefile.c
index 41b7cb0..4e5e96a 100644
--- a/gdb/corefile.c
+++ b/gdb/corefile.c
@@ -467,7 +467,7 @@ set_gnutarget_command (char *ignore, int from_tty,
 
 /* A completion function for "set gnutarget".  */
 
-static VEC (char_ptr) *
+static void
 complete_set_gnutarget (struct completer_data *cdata,
 			struct cmd_list_element *cmd,
 			const char *text, const char *word)
@@ -487,7 +487,7 @@ complete_set_gnutarget (struct completer_data *cdata,
       bfd_targets[last + 1] = NULL;
     }
 
-  return complete_on_enum (cdata, bfd_targets, text, word);
+  complete_on_enum (cdata, bfd_targets, text, word);
 }
 
 /* Set the gnutarget.  */
diff --git a/gdb/cp-abi.c b/gdb/cp-abi.c
index 504bb20..cddc382 100644
--- a/gdb/cp-abi.c
+++ b/gdb/cp-abi.c
@@ -358,7 +358,7 @@ set_cp_abi_cmd (char *args, int from_tty)
 
 /* A completion function for "set cp-abi".  */
 
-static VEC (char_ptr) *
+static void
 cp_abi_completer (struct completer_data *cdata,
 		  struct cmd_list_element *ignore,
 		  const char *text, const char *word)
@@ -375,7 +375,7 @@ cp_abi_completer (struct completer_data *cdata,
       cp_abi_names[i] = NULL;
     }
 
-  return complete_on_enum (cdata, cp_abi_names, text, word);
+  complete_on_enum (cdata, cp_abi_names, text, word);
 }
 
 /* Show the currently selected C++ ABI.  */
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index 15c51d9..b5886a6 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -228,13 +228,13 @@ f_word_break_characters (void)
 /* Consider the modules separator :: as a valid symbol name character
    class.  */
 
-static VEC (char_ptr) *
+static void
 f_make_symbol_completion_list (struct completer_data *cdata,
 			       const char *text, const char *word,
 			       enum type_code code)
 {
-  return default_make_symbol_completion_list_break_on (cdata, text, word,
-						       ":", code);
+  default_make_symbol_completion_list_break_on (cdata, text, word,
+						":", code);
 }
 
 const struct language_defn f_language_defn =
diff --git a/gdb/guile/scm-cmd.c b/gdb/guile/scm-cmd.c
index 1544c2b..8816346 100644
--- a/gdb/guile/scm-cmd.c
+++ b/gdb/guile/scm-cmd.c
@@ -348,8 +348,7 @@ cmdscm_bad_completion_result (const char *msg, SCM completion)
    The result is a boolean indicating success.  */
 
 static int
-cmdscm_add_completion (SCM completion, struct completer_data *cdata,
-		       VEC (char_ptr) **result)
+cmdscm_add_completion (SCM completion, struct completer_data *cdata)
 {
   char *item;
   SCM except_scm;
@@ -371,14 +370,14 @@ cmdscm_add_completion (SCM completion, struct completer_data *cdata,
       return 0;
     }
 
-  (void) add_completion (cdata, result, item, NULL, NULL);
+  (void) add_completion (cdata, item, NULL, NULL);
   xfree (item);
   return 1;
 }
 
 /* Called by gdb for command completion.  */
 
-static VEC (char_ptr) *
+static void
 cmdscm_completer (struct completer_data *cdata,
 		  struct cmd_list_element *command,
 		  const char *text, const char *word)
@@ -386,7 +385,6 @@ cmdscm_completer (struct completer_data *cdata,
   command_smob *c_smob/*obj*/ = (command_smob *) get_cmd_context (command);
   SCM completer_result_scm;
   SCM text_scm, word_scm, result_scm;
-  VEC (char_ptr) *result = NULL;
 
   gdb_assert (c_smob != NULL);
   gdb_assert (gdbscm_is_procedure (c_smob->complete));
@@ -408,7 +406,7 @@ cmdscm_completer (struct completer_data *cdata,
     {
       /* Inform the user, but otherwise ignore.  */
       gdbscm_print_gdb_exception (SCM_BOOL_F, completer_result_scm);
-      goto done;
+      return;
     }
 
   if (gdbscm_is_true (scm_list_p (completer_result_scm)))
@@ -419,11 +417,8 @@ cmdscm_completer (struct completer_data *cdata,
 	{
 	  SCM next = scm_car (list);
 
-	  if (!cmdscm_add_completion (next, cdata, &result))
-	    {
-	      VEC_free (char_ptr, result);
-	      goto done;
-	    }
+	  if (!cmdscm_add_completion (next, cdata))
+	    return;
 
 	  list = scm_cdr (list);
 	}
@@ -439,15 +434,11 @@ cmdscm_completer (struct completer_data *cdata,
 	    {
 	      /* Inform the user, but otherwise ignore the entire result.  */
 	      gdbscm_print_gdb_exception (SCM_BOOL_F, completer_result_scm);
-	      VEC_free (char_ptr, result);
-	      goto done;
+	      return;
 	    }
 
-	  if (!cmdscm_add_completion (next, cdata, &result))
-	    {
-	      VEC_free (char_ptr, result);
-	      goto done;
-	    }
+	  if (!cmdscm_add_completion (next, cdata))
+	    return;
 
 	  next = itscm_safe_call_next_x (iter, NULL);
 	}
@@ -458,9 +449,6 @@ cmdscm_completer (struct completer_data *cdata,
       cmdscm_bad_completion_result (_("Bad completer result: "),
 				    completer_result_scm);
     }
-
- done:
-  return result;
 }
 
 /* Helper for gdbscm_make_command which locates the command list to use and
diff --git a/gdb/infrun.c b/gdb/infrun.c
index d858b28..343f9da 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -7065,12 +7065,11 @@ Are you sure you want to change it? "),
 
 /* Complete the "handle" command.  */
 
-static VEC (char_ptr) *
+static void
 handle_completer (struct completer_data *cdata,
 		  struct cmd_list_element *ignore,
 		  const char *text, const char *word)
 {
-  VEC (char_ptr) *vec_signals, *vec_keywords, *return_val;
   static const char * const keywords[] =
     {
       "all",
@@ -7085,13 +7084,8 @@ handle_completer (struct completer_data *cdata,
       NULL,
     };
 
-  vec_signals = signal_completer (cdata, ignore, text, word);
-  vec_keywords = complete_on_enum (cdata, keywords, word, word);
-
-  return_val = VEC_merge (char_ptr, vec_signals, vec_keywords);
-  VEC_free (char_ptr, vec_signals);
-  VEC_free (char_ptr, vec_keywords);
-  return return_val;
+  signal_completer (cdata, ignore, text, word);
+  complete_on_enum (cdata, keywords, word, word);
 }
 
 enum gdb_signal
diff --git a/gdb/interps.c b/gdb/interps.c
index 9e993c8..19cb716 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -434,13 +434,12 @@ interpreter_exec_cmd (char *args, int from_tty)
 }
 
 /* List the possible interpreters which could complete the given text.  */
-static VEC (char_ptr) *
+static void
 interpreter_completer (struct completer_data *cdata,
 		       struct cmd_list_element *ignore,
 		       const char *text, const char *word)
 {
   int textlen;
-  VEC (char_ptr) *matches = NULL;
   struct interp *interp;
 
   textlen = strlen (text);
@@ -448,13 +447,11 @@ interpreter_completer (struct completer_data *cdata,
     {
       if (strncmp (interp->name, text, textlen) == 0)
 	{
-	  if (add_completion (cdata, &matches, interp->name, text, word)
+	  if (add_completion (cdata, interp->name, text, word)
 	      == ADD_COMPLETION_MAX_REACHED)
 	    break;
 	}
     }
-
-  return matches;
 }
 
 struct interp *
diff --git a/gdb/language.h b/gdb/language.h
index 954b4a8..24fb1e8 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -302,7 +302,7 @@ struct language_defn
        completion is being made.  If CODE is TYPE_CODE_UNDEF, then all
        symbols should be examined; otherwise, only STRUCT_DOMAIN
        symbols whose type has a code of CODE should be matched.  */
-    VEC (char_ptr) *
+    void
       (*la_make_symbol_completion_list) (struct completer_data *,
 					 const char *text,
 					 const char *word,
diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
index cf76bd1..7a57349 100644
--- a/gdb/python/py-cmd.c
+++ b/gdb/python/py-cmd.c
@@ -330,13 +330,12 @@ cmdpy_completer_handle_brkchars (struct cmd_list_element *command,
 
 /* Called by gdb for command completion.  */
 
-static VEC (char_ptr) *
+static void
 cmdpy_completer (struct completer_data *cdata,
 		 struct cmd_list_element *command,
 		 const char *text, const char *word)
 {
   PyObject *resultobj = NULL;
-  VEC (char_ptr) *result = NULL;
   struct cleanup *cleanup;
 
   cleanup = ensure_python_env (get_current_arch (), current_language);
@@ -351,7 +350,6 @@ cmdpy_completer (struct completer_data *cdata,
   if (resultobj == NULL)
     goto done;
 
-  result = NULL;
   if (PyInt_Check (resultobj))
     {
       /* User code may also return one of the completion constants,
@@ -364,7 +362,7 @@ cmdpy_completer (struct completer_data *cdata,
 	  PyErr_Clear ();
 	}
       else if (value >= 0 && value < (long) N_COMPLETERS)
-	result = completers[value].completer (cdata, command, text, word);
+	completers[value].completer (cdata, command, text, word);
     }
   else
     {
@@ -393,7 +391,7 @@ cmdpy_completer (struct completer_data *cdata,
 	      continue;
 	    }
 
-	  if (add_completion (cdata, &result, item, NULL, NULL)
+	  if (add_completion (cdata, item, NULL, NULL)
 	      == ADD_COMPLETION_MAX_REACHED)
 	    {
 	      xfree (item);
@@ -414,8 +412,6 @@ cmdpy_completer (struct completer_data *cdata,
 
   Py_XDECREF (resultobj);
   do_cleanups (cleanup);
-
-  return result;
 }
 
 /* Helper for cmdpy_init which locates the command list to use and
diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c
index c29d3c5..862683b 100644
--- a/gdb/remote-sim.c
+++ b/gdb/remote-sim.c
@@ -1223,7 +1223,7 @@ simulator_command (char *args, int from_tty)
   registers_changed ();
 }
 
-static VEC (char_ptr) *
+static void
 sim_command_completer (struct completer_data *cdata,
 		       struct cmd_list_element *ignore, const char *text,
 		       const char *word)
@@ -1235,22 +1235,20 @@ sim_command_completer (struct completer_data *cdata,
 
   sim_data = inferior_data (current_inferior (), sim_inferior_data_key);
   if (sim_data == NULL || sim_data->gdbsim_desc == NULL)
-    return NULL;
+    return;
 
   tmp = sim_complete_command (sim_data->gdbsim_desc, text, word);
   if (tmp == NULL)
-    return NULL;
+    return;
 
   /* Transform the array into a VEC, and then free the array.  */
   for (i = 0; tmp[i] != NULL; i++)
     {
-      if (add_completion (cdata, &result, tmp[i], NULL, NULL)
+      if (add_completion (cdata, tmp[i], NULL, NULL)
 	  == ADD_COMPLETION_MAX_REACHED)
 	break;
     }
   xfree (tmp);
-
-  return result;
 }
 
 /* Check to see if a thread is still alive.  */
diff --git a/gdb/symtab.c b/gdb/symtab.c
index e24de89..18b7619 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -5011,31 +5011,8 @@ compare_symbol_name (const char *name, const char *sym_text, int sym_text_len)
   return 1;
 }
 
-/* Free any memory associated with a completion list.  */
-
-static void
-free_completion_list (VEC (char_ptr) **list_ptr)
-{
-  int i;
-  char *p;
-
-  for (i = 0; VEC_iterate (char_ptr, *list_ptr, i, p); ++i)
-    xfree (p);
-  VEC_free (char_ptr, *list_ptr);
-}
-
-/* Callback for make_cleanup.  */
-
-static void
-do_free_completion_list (void *list)
-{
-  free_completion_list (list);
-}
-
 /* Helper routine for make_symbol_completion_list.  */
 
-static VEC (char_ptr) *return_val;
-
 #define COMPLETION_LIST_ADD_SYMBOL(cdata, symbol, sym_text, len,	\
 				   text, word)				\
   completion_list_add_name						\
@@ -5063,7 +5040,7 @@ completion_list_add_name (struct completer_data *cdata,
   /* We have a match for a completion, so add SYMNAME to the current list
      of matches.  */
 
-    if (add_completion (cdata, &return_val, symname, sym_text, word)
+    if (add_completion (cdata, symname, sym_text, word) 
 	== ADD_COMPLETION_MAX_REACHED)
       throw_max_completions_reached_error ();
 }
@@ -5499,18 +5476,13 @@ default_make_symbol_completion_list_break_on_1 (struct completer_data *cdata,
     }
 }
 
-VEC (char_ptr) *
+void
 default_make_symbol_completion_list_break_on (struct completer_data *cdata,
 					      const char *text,
 					      const char *word,
 					      const char *break_on,
 					      enum type_code code)
 {
-  struct cleanup *back_to;
-
-  return_val = NULL;
-  back_to = make_cleanup (do_free_completion_list, &return_val);
-
   TRY
     {
       default_make_symbol_completion_list_break_on_1 (cdata, text, word,
@@ -5522,61 +5494,56 @@ default_make_symbol_completion_list_break_on (struct completer_data *cdata,
 	throw_exception (except);
     }
   END_CATCH
-
-  discard_cleanups (back_to);
-  return return_val;
 }
 
-VEC (char_ptr) *
+void
 default_make_symbol_completion_list (struct completer_data *cdata,
 				     const char *text, const char *word,
 				     enum type_code code)
 {
-  return default_make_symbol_completion_list_break_on (cdata, text, word, "",
-						       code);
+  default_make_symbol_completion_list_break_on (cdata, text, word, "", code);
 }
 
 /* Return a vector of all symbols (regardless of class) which begin by
    matching TEXT.  If the answer is no symbols, then the return value
    is NULL.  */
 
-VEC (char_ptr) *
+void
 make_symbol_completion_list (struct completer_data *cdata,
 			     const char *text, const char *word)
 {
-  return current_language->la_make_symbol_completion_list (cdata, text, word,
-							   TYPE_CODE_UNDEF);
+  current_language->la_make_symbol_completion_list (cdata, text, word,
+						    TYPE_CODE_UNDEF);
 }
 
 /* Like make_symbol_completion_list, but only return STRUCT_DOMAIN
    symbols whose type code is CODE.  */
 
-VEC (char_ptr) *
+void
 make_symbol_completion_type (struct completer_data *cdata, const char *text,
 			     const char *word, enum type_code code)
 {
   gdb_assert (code == TYPE_CODE_UNION
 	      || code == TYPE_CODE_STRUCT
 	      || code == TYPE_CODE_ENUM);
-  return current_language->la_make_symbol_completion_list (cdata, text, word,
-							   code);
+  current_language->la_make_symbol_completion_list (cdata, text, word, code);
 }
 
 /* Like make_symbol_completion_list, but suitable for use as a
    completion function.  */
 
-VEC (char_ptr) *
+void
 make_symbol_completion_list_fn (struct completer_data *cdata,
 				struct cmd_list_element *ignore,
 				const char *text, const char *word)
 {
-  return make_symbol_completion_list (cdata, text, word);
+  make_symbol_completion_list (cdata, text, word);
 }
 
 /* Like make_symbol_completion_list, but returns a list of symbols
    defined in a source file FILE.  */
 
-VEC (char_ptr) *
+void
 make_file_symbol_completion_list (struct completer_data *cdata,
 				  const char *text, const char *word,
 				  const char *srcfile)
@@ -5624,7 +5591,7 @@ make_file_symbol_completion_list (struct completer_data *cdata,
       /* A double-quoted string is never a symbol, nor does it make sense
          to complete it any other way.  */
       {
-	return NULL;
+	return;
       }
     else
       {
@@ -5635,8 +5602,6 @@ make_file_symbol_completion_list (struct completer_data *cdata,
 
   sym_text_len = strlen (sym_text);
 
-  return_val = NULL;
-
   /* Find the symtab for SRCFILE (this loads it if it was not yet read
      in).  */
   s = lookup_symtab (srcfile);
@@ -5652,7 +5617,7 @@ make_file_symbol_completion_list (struct completer_data *cdata,
 
   /* If we have no symtab for that file, return an empty list.  */
   if (s == NULL)
-    return (return_val);
+    return;
 
   /* Go through this symtab and check the externs and statics for
      symbols which match.  */
@@ -5670,8 +5635,6 @@ make_file_symbol_completion_list (struct completer_data *cdata,
       COMPLETION_LIST_ADD_SYMBOL (cdata, sym, sym_text, sym_text_len,
 				  text, word);
     }
-
-  return (return_val);
 }
 
 /* A helper function for make_source_files_completion_list.  It adds
@@ -5680,10 +5643,9 @@ make_file_symbol_completion_list (struct completer_data *cdata,
 
 static void
 add_filename_to_list (struct completer_data *cdata, const char *fname,
-		      const char *text, const char *word,
-		      VEC (char_ptr) **list)
+		      const char *text, const char *word)
 {
-  (void) add_completion (cdata, list, fname, text, word);
+  (void) add_completion (cdata, fname, text, word);
 }
 
 static int
@@ -5711,7 +5673,6 @@ struct add_partial_filename_data
   const char *text;
   const char *word;
   int text_len;
-  VEC (char_ptr) **list;
 
   /* Completion data used by the completer function.  */
   struct completer_data *completer_data;
@@ -5733,7 +5694,7 @@ 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 (data->completer_data, filename, data->text,
-			    data->word, data->list);
+			    data->word);
     }
   else
     {
@@ -5744,17 +5705,15 @@ maybe_add_partial_symtab_filename (const char *filename, const char *fullname,
 	  && filename_ncmp (base_name, data->text, data->text_len) == 0)
 	{
 	  add_filename_to_list (data->completer_data, base_name, data->text,
-				data->word, data->list);
+				data->word);
 	}
     }
 }
 
-/* Return a vector of all source files whose names begin with matching
-   TEXT.  The file names are looked up in the symbol tables of this
-   program.  If the answer is no matchess, then the return value is
-   NULL.  */
+/* Add all source files whose names begin with matching TEXT to CDATA.
+   The file names are looked up in the symbol tables of this program.  */
 
-VEC (char_ptr) *
+void
 make_source_files_completion_list (struct completer_data *cdata,
 				   const char *text, const char *word)
 {
@@ -5762,16 +5721,13 @@ make_source_files_completion_list (struct completer_data *cdata,
   struct symtab *s;
   struct objfile *objfile;
   size_t text_len = strlen (text);
-  VEC (char_ptr) *list = NULL;
   const char *base_name;
   struct add_partial_filename_data datum;
   struct filename_seen_cache *filename_seen_cache;
-  struct cleanup *back_to, *cache_cleanup;
+  struct cleanup *cache_cleanup;
 
   if (!have_full_symbols () && !have_partial_symbols ())
-    return list;
-
-  back_to = make_cleanup (do_free_completion_list, &list);
+    return;
 
   filename_seen_cache = create_filename_seen_cache ();
   cache_cleanup = make_cleanup (delete_filename_seen_cache,
@@ -5786,7 +5742,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 (cdata, s->filename, text, word, &list);
+	  add_filename_to_list (cdata, s->filename, text, word);
 	}
       else
 	{
@@ -5798,7 +5754,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 (cdata, base_name, text, word, &list);
+	    add_filename_to_list (cdata, base_name, text, word);
 	}
     }
 
@@ -5806,15 +5762,11 @@ make_source_files_completion_list (struct completer_data *cdata,
   datum.text = text;
   datum.word = word;
   datum.text_len = text_len;
-  datum.list = &list;
   datum.completer_data = cdata;
   map_symbol_filenames (maybe_add_partial_symtab_filename, &datum,
 			0 /*need_fullname*/);
 
   do_cleanups (cache_cleanup);
-  discard_cleanups (back_to);
-
-  return list;
 }
 \f
 /* Track MAIN */
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 018852c..755e1d5 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -1454,30 +1454,31 @@ extern void forget_cached_source_info (void);
 
 extern void select_source_symtab (struct symtab *);
 
-extern VEC (char_ptr) *default_make_symbol_completion_list_break_on
+extern void default_make_symbol_completion_list_break_on
  (struct completer_data *cdata, const char *text, const char *word,
   const char *break_on, enum type_code code);
-extern VEC (char_ptr) *
+
+extern void
  default_make_symbol_completion_list (struct completer_data *,
 				      const char *, const char *,
 				      enum type_code);
-extern VEC (char_ptr) *
+extern void
   make_symbol_completion_list (struct completer_data *, const char *,
 			       const char *);
-extern VEC (char_ptr) *
+extern void
   make_symbol_completion_type (struct completer_data *,
 			       const char *, const char *,
 			       enum type_code);
-extern VEC (char_ptr) *
+extern void
   make_symbol_completion_list_fn (struct completer_data *,
 				  struct cmd_list_element *,
 				  const char *, const char *);
 
-extern VEC (char_ptr) *
+extern void
   make_file_symbol_completion_list (struct completer_data *,
 				    const char *, const char *, const char *);
 
-extern VEC (char_ptr) *
+extern void
  make_source_files_completion_list (struct completer_data *, const char *,
 				    const char *);
 
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 8d420894..c4c9cda 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -353,7 +353,7 @@ tui_default_win_viewport_height (enum tui_win_type type,
 /* Complete possible layout names.  TEXT is the complete text entered so
    far, WORD is the word currently being completed.  */
 
-static VEC (char_ptr) *
+static void
 layout_completer (struct completer_data *cdata,
 		  struct cmd_list_element *ignore,
 		  const char *text, const char *word)
@@ -361,7 +361,7 @@ layout_completer (struct completer_data *cdata,
   static const char *layout_names [] =
     { "src", "asm", "split", "regs", "next", "prev", NULL };
 
-  return complete_on_enum (cdata, layout_names, text, word);
+  complete_on_enum (cdata, layout_names, text, word);
 }
 
 /* Function to initialize gdb commands, for tui window layout
diff --git a/gdb/tui/tui-regs.c b/gdb/tui/tui-regs.c
index 17efd9f..bef01e5 100644
--- a/gdb/tui/tui-regs.c
+++ b/gdb/tui/tui-regs.c
@@ -668,29 +668,26 @@ tui_reg_command (char *args, int from_tty)
 /* Complete names of register groups, and add the special "prev" and "next"
    names.  */
 
-static VEC (char_ptr) *
+static void
 tui_reggroup_completer (struct completer_data *cdata,
 			struct cmd_list_element *ignore,
 			const char *text, const char *word)
 {
-  VEC (char_ptr) *result = NULL;
   static const char *extra[] = { "next", "prev", NULL };
   size_t len = strlen (word);
   const char **tmp;
 
-  result = reggroup_completer (cdata, ignore, text, word);
+  reggroup_completer (cdata, ignore, text, word);
 
   for (tmp = extra; *tmp != NULL; ++tmp)
     {
       if (strncmp (word, *tmp, len) == 0)
 	{
-	  if (add_completion (cdata, &result, *tmp, NULL, NULL)
+	  if (add_completion (cdata, *tmp, NULL, NULL)
 	      == ADD_COMPLETION_MAX_REACHED)
 	    break;
 	}
     }
-
-  return result;
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
index 8e7fbd1..4690af1 100644
--- a/gdb/tui/tui-win.c
+++ b/gdb/tui/tui-win.c
@@ -359,13 +359,12 @@ tui_set_var_cmd (char *null_args, int from_tty, struct cmd_list_element *c)
    window names 'next' and 'prev' will also be considered as possible
    completions of the window name.  */
 
-static VEC (char_ptr) *
+static void
 window_name_completer (int include_next_prev_p,
 		       struct completer_data *cdata,
 		       const char *text, const char *word)
 {
   VEC (const_char_ptr) *completion_name_vec = NULL;
-  VEC (char_ptr) *matches_vec;
   int win_type;
 
   for (win_type = SRC_WIN; win_type < MAX_MAJOR_WINDOWS; win_type++)
@@ -399,32 +398,29 @@ window_name_completer (int include_next_prev_p,
     }
 
   VEC_safe_push (const_char_ptr, completion_name_vec, NULL);
-  matches_vec
-    = complete_on_enum (cdata,
-			VEC_address (const_char_ptr, completion_name_vec),
-			text, word);
+  complete_on_enum (cdata,
+		    VEC_address (const_char_ptr, completion_name_vec),
+		    text, word);
 
   VEC_free (const_char_ptr, completion_name_vec);
-
-  return matches_vec;
 }
 
 /* Complete possible window names to focus on.  TEXT is the complete text
    entered so far, WORD is the word currently being completed.  */
 
-static VEC (char_ptr) *
+static void
 focus_completer (struct completer_data *cdata,
 		 struct cmd_list_element *ignore,
 		  const char *text, const char *word)
 {
-  return window_name_completer (1, cdata, text, word);
+  window_name_completer (1, cdata, text, word);
 }
 
 /* Complete possible window names for winheight command.  TEXT is the
    complete text entered so far, WORD is the word currently being
    completed.  */
 
-static VEC (char_ptr) *
+static void
 winheight_completer (struct completer_data *cdata,
 		     struct cmd_list_element *ignore,
 		     const char *text, const char *word)
@@ -432,9 +428,9 @@ winheight_completer (struct completer_data *cdata,
   /* The first word is the window name.  That we can complete.  Subsequent
      words can't be completed.  */
   if (word != text)
-    return NULL;
+    return;
 
-  return window_name_completer (0, cdata, text, word);
+  window_name_completer (0, cdata, text, word);
 }
 
 /* Function to initialize gdb commands, for tui window
diff --git a/gdb/value.c b/gdb/value.c
index 22d392a..b3d4f04 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -2062,10 +2062,9 @@ lookup_only_internalvar (const char *name)
    Returns a vector of newly allocated strings, or NULL if no matches
    were found.  */
 
-VEC (char_ptr) *
+void
 complete_internalvar (struct completer_data *cdata, const char *name)
 {
-  VEC (char_ptr) *result = NULL;
   struct internalvar *var;
   int len;
 
@@ -2074,12 +2073,10 @@ complete_internalvar (struct completer_data *cdata, const char *name)
   for (var = internalvars; var; var = var->next)
     if (strncmp (var->name, name, len) == 0)
       {
-	if (add_completion (cdata, &result, var->name, NULL, NULL)
+	if (add_completion (cdata, var->name, NULL, NULL)
 	    == ADD_COMPLETION_MAX_REACHED)
 	  break;
       }
-
-  return result;
 }
 
 /* Create an internal variable with name NAME and with a void value.
diff --git a/gdb/value.h b/gdb/value.h
index 03df1b7..58c5c26 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -876,8 +876,8 @@ extern struct internalvar *lookup_only_internalvar (const char *name);
 
 extern struct internalvar *create_internalvar (const char *name);
 
-extern VEC (char_ptr) *complete_internalvar (struct completer_data *cdata,
-					     const char *name);
+extern void complete_internalvar (struct completer_data *cdata,
+				  const char *name);
 
 /* An internalvar can be dynamically computed by supplying a vector of
    function pointers to perform various operations.  */

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v3 06/19] Implement completion limiting for condition_completer.
  2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
                   ` (2 preceding siblings ...)
  2015-08-06 19:58 ` [PATCH v3 02/19] Remove completion_tracker_t from the public completion API Keith Seitz
@ 2015-08-06 19:58 ` Keith Seitz
  2015-08-23  3:53   ` Doug Evans
  2015-08-06 19:58 ` [PATCH v3 18/19] Use the hashtable to accumulate completion results Keith Seitz
                   ` (15 subsequent siblings)
  19 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-06 19:58 UTC (permalink / raw)
  To: gdb-patches

There are no changes from the last revision.

--

This patch converts the condition completer to use add_completion.
A side-effect of this is the similar conversion of complete_internalvar.

Tests have been added to exercise this new behavior.

gdb/ChangeLog

	* breakpoint.c (condition_completer): Pass completer_data to
	complete_internalvar.
	Use add_completion.
	* value.c: Include completer.h.
	(complete_internalvar): Add completer_data argument.
	Use add_completion.
	* value.h (complete_internalvar): Add completer_data argument.

gdb/testsuite/ChangeLog

	* gdb.base/condbreak.exp (test_completion): New procedure.
	Add more completion tests, with and without limiting.
---
 gdb/breakpoint.c                     |    8 +++-
 gdb/testsuite/gdb.base/condbreak.exp |   70 ++++++++++++++++++++++++++++++++++
 gdb/value.c                          |    9 ++--
 gdb/value.h                          |    3 +
 4 files changed, 83 insertions(+), 7 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 70569df..24243c4 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -1052,7 +1052,7 @@ condition_completer (struct completer_data *cdata,
 	  /* We don't support completion of history indices.  */
 	  if (isdigit (text[1]))
 	    return NULL;
-	  return complete_internalvar (&text[1]);
+	  return complete_internalvar (cdata, &text[1]);
 	}
 
       /* We're completing the breakpoint number.  */
@@ -1065,7 +1065,11 @@ condition_completer (struct completer_data *cdata,
 	  xsnprintf (number, sizeof (number), "%d", b->number);
 
 	  if (strncmp (number, text, len) == 0)
-	    VEC_safe_push (char_ptr, result, xstrdup (number));
+	    {
+	      if (add_completion (cdata, &result, number, NULL, NULL)
+		  == ADD_COMPLETION_MAX_REACHED)
+		break;
+	    }
 	}
 
       return result;
diff --git a/gdb/testsuite/gdb.base/condbreak.exp b/gdb/testsuite/gdb.base/condbreak.exp
index fa40a5f..5630ede 100644
--- a/gdb/testsuite/gdb.base/condbreak.exp
+++ b/gdb/testsuite/gdb.base/condbreak.exp
@@ -246,3 +246,73 @@ gdb_test "complete cond 1" "cond 1"
 gdb_test "set variable \$var = 1"
 gdb_test "complete cond \$v" "cond \\\$var"
 gdb_test "complete cond 1 values\[0\].a" "cond 1 values.0..a_field"
+
+# Test non-trivial completion and completion-limiting
+
+# Delete all breakpoints and create a bunch of new ones.
+delete_breakpoints
+for {set i 0} {$i < 20} {incr i} {
+    with_test_prefix "set breakpoint $i" {
+	gdb_breakpoint "factorial"
+    }
+}
+
+# While the completer function does traverse breakpoints in the order
+# they were created, don't assume that is required for the test.
+# We only count the number of completions found.  In this case,
+# this test will create breakpoints 9-19, giving "complete cond 1"
+# ten total completion possibilities.
+
+# A convenience procedure to automate test completion lists.
+proc test_completion {cmd exp total {limit 0}} {
+    global gdb_prompt
+
+    if {$limit} {
+	set end "\\\*\\\*\\\* List may be truncated, "
+	append end "max-completions reached\\\. \\\*\\\*\\\*\r\n"
+	set testname "limit '$cmd'"
+    } else {
+	set end ""
+	set testname $cmd
+    }
+
+    set seen 0
+    gdb_test_multiple $cmd $testname {
+	"$cmd\r\n" { exp_continue }
+
+	-re "cond $exp\[0-9\]+\r\n" {
+	    incr seen
+	    exp_continue
+	}
+
+	-re ".*$end$gdb_prompt $" {
+	    if {$seen == $total} {
+		pass $testname
+	    } else {
+		fail "$testname ($seen/$total)"
+	    }
+	}
+    }
+}
+
+# Test completion of breakpoint number.
+with_test_prefix "completion test:" {
+    test_completion "complete cond 1" "1" 10
+}
+
+# Test completion of breakpoint number using internal variable.
+for {set i 0} {$i < 10} {incr i} {
+    gdb_test_no_output "set variable \$var_bp_$i = $i"
+}
+
+test_completion "complete cond \$var_bp" "\\\$var_bp_" 10
+
+# Run the above tests with completion limiting.
+set max_completions 4
+gdb_test_no_output "set max-completions $max_completions"
+
+with_test_prefix "completion test:" {
+    test_completion "complete cond 1" "1" $max_completions 1
+}
+
+test_completion "complete cond \$var_bp" "\\\$var_bp_" $max_completions 1
diff --git a/gdb/value.c b/gdb/value.c
index 63ee94d..22d392a 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -40,6 +40,7 @@
 #include "tracepoint.h"
 #include "cp-abi.h"
 #include "user-regs.h"
+#include "completer.h"
 
 /* Prototypes for exported functions.  */
 
@@ -2062,7 +2063,7 @@ lookup_only_internalvar (const char *name)
    were found.  */
 
 VEC (char_ptr) *
-complete_internalvar (const char *name)
+complete_internalvar (struct completer_data *cdata, const char *name)
 {
   VEC (char_ptr) *result = NULL;
   struct internalvar *var;
@@ -2073,9 +2074,9 @@ complete_internalvar (const char *name)
   for (var = internalvars; var; var = var->next)
     if (strncmp (var->name, name, len) == 0)
       {
-	char *r = xstrdup (var->name);
-
-	VEC_safe_push (char_ptr, result, r);
+	if (add_completion (cdata, &result, var->name, NULL, NULL)
+	    == ADD_COMPLETION_MAX_REACHED)
+	  break;
       }
 
   return result;
diff --git a/gdb/value.h b/gdb/value.h
index 82deaf2..03df1b7 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -876,7 +876,8 @@ extern struct internalvar *lookup_only_internalvar (const char *name);
 
 extern struct internalvar *create_internalvar (const char *name);
 
-extern VEC (char_ptr) *complete_internalvar (const char *name);
+extern VEC (char_ptr) *complete_internalvar (struct completer_data *cdata,
+					     const char *name);
 
 /* An internalvar can be dynamically computed by supplying a vector of
    function pointers to perform various operations.  */

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v3 01/19] Add struct completer_data to the completion API.
  2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
                   ` (6 preceding siblings ...)
  2015-08-06 19:58 ` [PATCH v3 04/19] Implement completion limiting for add_filename_to_list Keith Seitz
@ 2015-08-06 20:03 ` Keith Seitz
  2015-08-23  0:29   ` Doug Evans
  2015-08-06 21:06 ` [PATCH v3 17/19] Make the completion API completely opaque Keith Seitz
                   ` (11 subsequent siblings)
  19 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-06 20:03 UTC (permalink / raw)
  To: gdb-patches

Differences in this revision:

1. Updated new completer[-related] functions reg_or_group_completer_1,
   reg_or_group_completer, layout_completer, tui_reggroup_completer,
   window_name_completer, focus_completer, and winheight_completer.

---

This patch is largely mechanical.  It modifies the completion API so
that all completion functions take a new (pointer to a) structure,
which will (eventually) be used internally by the completer to perform
completion limiting.

gdb/ChangeLog

	* completer.c (struct completer_data): Define.
	* language.h (struct language_defn)
	<la_make_symbol_completion_list>: Add struct completer_data
	to argument list.
	All users updated.
	* symtab.c (COMPLETION_LIST_ADD_SYMBOL): Add CDATA argument.
	Update all callers.
	(MCOMPLETION_LIST_ADD_SYMBOL): Likewise.
	(struct add_name_data) <completer_data>: New field.
	(default_make_symbol_completion_list_break_on_1): Initialize
	the above new field.
	(struct add_partial_filename_data) <completer_data>: New field.
	(make_source_files_completion_list): Initialize the above new
	field.
---
 gdb/ada-lang.c            |    3 +
 gdb/break-catch-syscall.c |    5 +-
 gdb/breakpoint.c          |    5 +-
 gdb/cli/cli-decode.c      |   11 ++--
 gdb/command.h             |   11 +++-
 gdb/completer.c           |   94 ++++++++++++++++++++-------------
 gdb/completer.h           |   25 ++++++---
 gdb/corefile.c            |    5 +-
 gdb/cp-abi.c              |    5 +-
 gdb/f-lang.c              |    6 +-
 gdb/guile/scm-cmd.c       |    3 +
 gdb/infrun.c              |    7 +-
 gdb/interps.c             |    3 +
 gdb/language.h            |    8 ++-
 gdb/python/py-cmd.c       |   12 ++--
 gdb/remote-sim.c          |    3 +
 gdb/symtab.c              |  130 ++++++++++++++++++++++++++++-----------------
 gdb/symtab.h              |   44 +++++++++------
 gdb/tui/tui-layout.c      |    5 +-
 gdb/tui/tui-regs.c        |    5 +-
 gdb/tui/tui-win.c         |   14 +++--
 21 files changed, 252 insertions(+), 152 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 9f9be64..9782b69 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -6266,7 +6266,8 @@ ada_complete_symbol_matcher (const char *name, void *user_data)
    the entire command on which completion is made.  */
 
 static VEC (char_ptr) *
-ada_make_symbol_completion_list (const char *text0, const char *word,
+ada_make_symbol_completion_list (struct completer_data *cdata,
+				 const char *text0, const char *word,
 				 enum type_code code)
 {
   char *text;
diff --git a/gdb/break-catch-syscall.c b/gdb/break-catch-syscall.c
index 1718f49..4677132 100644
--- a/gdb/break-catch-syscall.c
+++ b/gdb/break-catch-syscall.c
@@ -592,12 +592,13 @@ catching_syscall_number (int syscall_number)
 
 /* Complete syscall names.  Used by "catch syscall".  */
 static VEC (char_ptr) *
-catch_syscall_completer (struct cmd_list_element *cmd,
+catch_syscall_completer (struct completer_data *cdata,
+			 struct cmd_list_element *cmd,
                          const char *text, const char *word)
 {
   const char **list = get_syscall_names (get_current_arch ());
   VEC (char_ptr) *retlist
-    = (list == NULL) ? NULL : complete_on_enum (list, word, word);
+    = (list == NULL) ? NULL : complete_on_enum (cdata, list, word, word);
 
   xfree (list);
   return retlist;
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 125b22f..70569df 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -1033,7 +1033,8 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp,
 /* Completion for the "condition" command.  */
 
 static VEC (char_ptr) *
-condition_completer (struct cmd_list_element *cmd,
+condition_completer (struct completer_data *cdata,
+		     struct cmd_list_element *cmd,
 		     const char *text, const char *word)
 {
   const char *space;
@@ -1072,7 +1073,7 @@ condition_completer (struct cmd_list_element *cmd,
 
   /* We're completing the expression part.  */
   text = skip_spaces_const (space);
-  return expression_completer (cmd, text, word);
+  return expression_completer (cdata, cmd, text, word);
 }
 
 /* condition N EXP -- set break condition of breakpoint N to EXP.  */
diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index e406157..3415b77 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -648,7 +648,8 @@ add_setshow_optional_filename_cmd (const char *name, enum command_class theclass
    support a special "unlimited" value.  */
 
 static VEC (char_ptr) *
-integer_unlimited_completer (struct cmd_list_element *ignore,
+integer_unlimited_completer (struct completer_data *cdata,
+			     struct cmd_list_element *ignore,
 			     const char *text, const char *word)
 {
   static const char * const keywords[] =
@@ -657,7 +658,7 @@ integer_unlimited_completer (struct cmd_list_element *ignore,
       NULL,
     };
 
-  return complete_on_enum (keywords, text, word);
+  return complete_on_enum (cdata, keywords, text, word);
 }
 
 /* Add element named NAME to both the set and show command LISTs (the
@@ -1765,7 +1766,8 @@ lookup_cmd_composition (const char *text,
    "oobar"; if WORD is "baz/foo", return "baz/foobar".  */
 
 VEC (char_ptr) *
-complete_on_cmdlist (struct cmd_list_element *list,
+complete_on_cmdlist (struct completer_data *cdata,
+		     struct cmd_list_element *list,
 		     const char *text, const char *word,
 		     int ignore_help_classes)
 {
@@ -1835,7 +1837,8 @@ complete_on_cmdlist (struct cmd_list_element *list,
    "oobar"; if WORD is "baz/foo", return "baz/foobar".  */
 
 VEC (char_ptr) *
-complete_on_enum (const char *const *enumlist,
+complete_on_enum (struct completer_data *cdata,
+		  const char *const *enumlist,
 		  const char *text, const char *word)
 {
   VEC (char_ptr) *matchlist = NULL;
diff --git a/gdb/command.h b/gdb/command.h
index bdf625b..b2aeb30 100644
--- a/gdb/command.h
+++ b/gdb/command.h
@@ -23,6 +23,8 @@
 /* This file defines the public interface for any code wanting to
    create commands.  */
 
+struct completer_data;
+
 /* Command classes are top-level categories into which commands are
    broken down for "help" purposes.
 
@@ -156,7 +158,8 @@ typedef void cmd_sfunc_ftype (char *args, int from_tty,
 extern void set_cmd_sfunc (struct cmd_list_element *cmd,
 			   cmd_sfunc_ftype *sfunc);
 
-typedef VEC (char_ptr) *completer_ftype (struct cmd_list_element *,
+typedef VEC (char_ptr) *completer_ftype (struct completer_data *,
+					 struct cmd_list_element *,
 					 const char *, const char *);
 
 typedef void completer_ftype_void (struct cmd_list_element *,
@@ -225,10 +228,12 @@ extern struct cmd_list_element *add_info (const char *,
 extern struct cmd_list_element *add_info_alias (const char *, const char *,
 						int);
 
-extern VEC (char_ptr) *complete_on_cmdlist (struct cmd_list_element *,
+extern VEC (char_ptr) *complete_on_cmdlist (struct completer_data *,
+					    struct cmd_list_element *,
 					    const char *, const char *, int);
 
-extern VEC (char_ptr) *complete_on_enum (const char *const *enumlist,
+extern VEC (char_ptr) *complete_on_enum (struct completer_data *,
+					 const char *const *enumlist,
 					 const char *, const char *);
 
 /* Functions that implement commands about CLI commands.  */
diff --git a/gdb/completer.c b/gdb/completer.c
index d1ebf67..476f9f2 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -87,6 +87,15 @@ static char *gdb_completer_file_name_break_characters = " \t\n*|\"';:?><";
    we can't include '"' because the gdb C parser treats such quoted
    sequences as strings.  */
 static char *gdb_completer_quote_characters = "'";
+
+/* A structure holding completion-specific call data.  */
+
+struct completer_data
+{
+  /* The completion tracker being used by the completer.  */
+  completion_tracker_t tracker;
+};
+
 \f
 /* Accessor for some completer data that may interest other files.  */
 
@@ -108,7 +117,8 @@ readline_line_completion_function (const char *text, int matches)
 /* This can be used for functions which don't want to complete on
    symbols but don't want to complete on anything else either.  */
 VEC (char_ptr) *
-noop_completer (struct cmd_list_element *ignore, 
+noop_completer (struct completer_data *cdata,
+		struct cmd_list_element *ignore,
 		const char *text, const char *prefix)
 {
   return NULL;
@@ -116,7 +126,8 @@ noop_completer (struct cmd_list_element *ignore,
 
 /* Complete on filenames.  */
 VEC (char_ptr) *
-filename_completer (struct cmd_list_element *ignore, 
+filename_completer (struct completer_data *cdata,
+		    struct cmd_list_element *ignore,
 		    const char *text, const char *word)
 {
   int subsequent_name;
@@ -185,7 +196,8 @@ filename_completer (struct cmd_list_element *ignore,
    etc.  */
 
 VEC (char_ptr) *
-location_completer (struct cmd_list_element *ignore, 
+location_completer (struct completer_data *cdata,
+		    struct cmd_list_element *ignore,
 		    const char *text, const char *word)
 {
   int n_syms, n_files, ix;
@@ -261,18 +273,18 @@ location_completer (struct cmd_list_element *ignore,
      symbols as well as on files.  */
   if (colon)
     {
-      list = make_file_symbol_completion_list (symbol_start, word,
+      list = make_file_symbol_completion_list (cdata, symbol_start, word,
 					       file_to_match);
       xfree (file_to_match);
     }
   else
     {
-      list = make_symbol_completion_list (symbol_start, word);
+      list = make_symbol_completion_list (cdata, symbol_start, word);
       /* If text includes characters which cannot appear in a file
 	 name, they cannot be asking for completion on files.  */
       if (strcspn (text, 
 		   gdb_completer_file_name_break_characters) == text_len)
-	fn_list = make_source_files_completion_list (text, text);
+	fn_list = make_source_files_completion_list (cdata, text, text);
     }
 
   n_syms = VEC_length (char_ptr, list);
@@ -327,7 +339,7 @@ location_completer (struct cmd_list_element *ignore,
     {
       /* No completions at all.  As the final resort, try completing
 	 on the entire text as a symbol.  */
-      list = make_symbol_completion_list (orig_text, word);
+      list = make_symbol_completion_list (cdata, orig_text, word);
     }
 
   return list;
@@ -337,7 +349,8 @@ location_completer (struct cmd_list_element *ignore,
    method names from TYPE, a struct or union type, to the array
    OUTPUT.  */
 static void
-add_struct_fields (struct type *type, VEC (char_ptr) **output,
+add_struct_fields (struct completer_data *cdata,
+		   struct type *type, VEC (char_ptr) **output,
 		   char *fieldname, int namelen)
 {
   int i;
@@ -348,7 +361,7 @@ add_struct_fields (struct type *type, VEC (char_ptr) **output,
   for (i = 0; i < TYPE_NFIELDS (type); ++i)
     {
       if (i < TYPE_N_BASECLASSES (type))
-	add_struct_fields (TYPE_BASECLASS (type, i),
+	add_struct_fields (cdata, TYPE_BASECLASS (type, i),
 			   output, fieldname, namelen);
       else if (TYPE_FIELD_NAME (type, i))
 	{
@@ -362,7 +375,7 @@ add_struct_fields (struct type *type, VEC (char_ptr) **output,
 	  else if (TYPE_CODE (TYPE_FIELD_TYPE (type, i)) == TYPE_CODE_UNION)
 	    {
 	      /* Recurse into anonymous unions.  */
-	      add_struct_fields (TYPE_FIELD_TYPE (type, i),
+	      add_struct_fields (cdata, TYPE_FIELD_TYPE (type, i),
 				 output, fieldname, namelen);
 	    }
 	}
@@ -390,7 +403,8 @@ add_struct_fields (struct type *type, VEC (char_ptr) **output,
    names, but some language parsers also have support for completing
    field names.  */
 VEC (char_ptr) *
-expression_completer (struct cmd_list_element *ignore, 
+expression_completer (struct completer_data *cdata,
+		      struct cmd_list_element *ignore,
 		      const char *text, const char *word)
 {
   struct type *type = NULL;
@@ -428,7 +442,7 @@ expression_completer (struct cmd_list_element *ignore,
 	  int flen = strlen (fieldname);
 	  VEC (char_ptr) *result = NULL;
 
-	  add_struct_fields (type, &result, fieldname, flen);
+	  add_struct_fields (cdata, type, &result, fieldname, flen);
 	  xfree (fieldname);
 	  return result;
 	}
@@ -438,7 +452,8 @@ expression_completer (struct cmd_list_element *ignore,
       VEC (char_ptr) *result;
       struct cleanup *cleanup = make_cleanup (xfree, fieldname);
 
-      result = make_symbol_completion_type (fieldname, fieldname, code);
+      result
+	= make_symbol_completion_type (cdata, fieldname, fieldname, code);
       do_cleanups (cleanup);
       return result;
     }
@@ -452,7 +467,7 @@ expression_completer (struct cmd_list_element *ignore,
     ;
 
   /* Not ideal but it is what we used to do before...  */
-  return location_completer (ignore, p, word);
+  return location_completer (cdata, ignore, p, word);
 }
 
 /* See definition in completer.h.  */
@@ -530,8 +545,8 @@ complete_line_internal_reason;
  */
 
 static VEC (char_ptr) *
-complete_line_internal (const char *text, 
-			const char *line_buffer, int point,
+complete_line_internal (struct completer_data *cdata,
+			const char *text, const char *line_buffer, int point,
 			complete_line_internal_reason reason)
 {
   VEC (char_ptr) *list = NULL;
@@ -616,13 +631,13 @@ complete_line_internal (const char *text,
 	  if (result_list)
 	    {
 	      if (reason != handle_brkchars)
-		list = complete_on_cmdlist (*result_list->prefixlist, p,
-					    word, ignore_help_classes);
+		list = complete_on_cmdlist (cdata, *result_list->prefixlist,
+					    p, word, ignore_help_classes);
 	    }
 	  else
 	    {
 	      if (reason != handle_brkchars)
-		list = complete_on_cmdlist (cmdlist, p, word,
+		list = complete_on_cmdlist (cdata, cmdlist, p, word,
 					    ignore_help_classes);
 	    }
 	  /* Ensure that readline does the right thing with respect to
@@ -649,8 +664,8 @@ complete_line_internal (const char *text,
 		  /* It is a prefix command; what comes after it is
 		     a subcommand (e.g. "info ").  */
 		  if (reason != handle_brkchars)
-		    list = complete_on_cmdlist (*c->prefixlist, p, word,
-						ignore_help_classes);
+		    list = complete_on_cmdlist (cdata, *c->prefixlist, p,
+						word, ignore_help_classes);
 
 		  /* Ensure that readline does the right thing
 		     with respect to inserting quotes.  */
@@ -662,7 +677,7 @@ complete_line_internal (const char *text,
 	      else if (c->enums)
 		{
 		  if (reason != handle_brkchars)
-		    list = complete_on_enum (c->enums, p, word);
+		    list = complete_on_enum (cdata, c->enums, p, word);
 		  rl_completer_word_break_characters =
 		    gdb_completer_command_word_break_characters;
 		}
@@ -702,7 +717,7 @@ complete_line_internal (const char *text,
 		      && c->completer_handle_brkchars != NULL)
 		    (*c->completer_handle_brkchars) (c, p, word);
 		  if (reason != handle_brkchars && c->completer != NULL)
-		    list = (*c->completer) (c, p, word);
+		    list = (*c->completer) (cdata, c, p, word);
 		}
 	    }
 	  else
@@ -724,7 +739,7 @@ complete_line_internal (const char *text,
 		}
 
 	      if (reason != handle_brkchars)
-		list = complete_on_cmdlist (result_list, q, word,
+		list = complete_on_cmdlist (cdata, result_list, q, word,
 					    ignore_help_classes);
 
 	      /* Ensure that readline does the right thing
@@ -748,7 +763,7 @@ complete_line_internal (const char *text,
 	  else if (c->enums)
 	    {
 	      if (reason != handle_brkchars)
-		list = complete_on_enum (c->enums, p, word);
+		list = complete_on_enum (cdata, c->enums, p, word);
 	    }
 	  else
 	    {
@@ -778,7 +793,7 @@ complete_line_internal (const char *text,
 		  && c->completer_handle_brkchars != NULL)
 		(*c->completer_handle_brkchars) (c, p, word);
 	      if (reason != handle_brkchars && c->completer != NULL)
-		list = (*c->completer) (c, p, word);
+		list = (*c->completer) (cdata, c, p, word);
 	    }
 	}
     }
@@ -886,7 +901,7 @@ complete_line (const char *text, const char *line_buffer, int point)
 
   if (max_completions == 0)
     return NULL;
-  list = complete_line_internal (text, line_buffer, point,
+  list = complete_line_internal (NULL, text, line_buffer, point,
 				 handle_completions);
   if (max_completions < 0)
     return list;
@@ -933,17 +948,19 @@ complete_line (const char *text, const char *line_buffer, int point)
 
 /* Complete on command names.  Used by "help".  */
 VEC (char_ptr) *
-command_completer (struct cmd_list_element *ignore, 
+command_completer (struct completer_data *cdata,
+		   struct cmd_list_element *ignore,
 		   const char *text, const char *word)
 {
-  return complete_line_internal (word, text, 
+  return complete_line_internal (cdata, word, text,
 				 strlen (text), handle_help);
 }
 
 /* Complete on signals.  */
 
 VEC (char_ptr) *
-signal_completer (struct cmd_list_element *ignore,
+signal_completer (struct completer_data *cdata,
+		  struct cmd_list_element *ignore,
 		  const char *text, const char *word)
 {
   VEC (char_ptr) *return_val = NULL;
@@ -983,7 +1000,8 @@ enum reg_completer_targets
    in TARGETS.  At least one bit in TARGETS must be set.  */
 
 static VEC (char_ptr) *
-reg_or_group_completer_1 (struct cmd_list_element *ignore,
+reg_or_group_completer_1 (struct completer_data *cdata,
+			  struct cmd_list_element *ignore,
 			  const char *text, const char *word,
 			  enum reg_completer_targets targets)
 {
@@ -1029,10 +1047,11 @@ reg_or_group_completer_1 (struct cmd_list_element *ignore,
 /* Perform completion on register and reggroup names.  */
 
 VEC (char_ptr) *
-reg_or_group_completer (struct cmd_list_element *ignore,
+reg_or_group_completer (struct completer_data *cdata,
+			struct cmd_list_element *ignore,
 			const char *text, const char *word)
 {
-  return reg_or_group_completer_1 (ignore, text, word,
+  return reg_or_group_completer_1 (cdata, ignore, text, word,
 				   (complete_register_names
 				    | complete_reggroup_names));
 }
@@ -1040,10 +1059,11 @@ reg_or_group_completer (struct cmd_list_element *ignore,
 /* Perform completion on reggroup names.  */
 
 VEC (char_ptr) *
-reggroup_completer (struct cmd_list_element *ignore,
+reggroup_completer (struct completer_data *cdata,
+		    struct cmd_list_element *ignore,
 		    const char *text, const char *word)
 {
-  return reg_or_group_completer_1 (ignore, text, word,
+  return reg_or_group_completer_1 (cdata, ignore, text, word,
 				   complete_reggroup_names);
 }
 
@@ -1055,8 +1075,8 @@ gdb_completion_word_break_characters (void)
 {
   VEC (char_ptr) *list;
 
-  list = complete_line_internal (rl_line_buffer, rl_line_buffer, rl_point,
-				 handle_brkchars);
+  list = complete_line_internal (NULL, rl_line_buffer, rl_line_buffer,
+				 rl_point, handle_brkchars);
   gdb_assert (list == NULL);
   return rl_completer_word_break_characters;
 }
diff --git a/gdb/completer.h b/gdb/completer.h
index 6c1f257..7139c0a 100644
--- a/gdb/completer.h
+++ b/gdb/completer.h
@@ -23,6 +23,7 @@
 /* Types of functions in struct match_list_displayer.  */
 
 struct match_list_displayer;
+struct completer_data;
 
 typedef void mld_crlf_ftype (const struct match_list_displayer *);
 typedef void mld_putch_ftype (const struct match_list_displayer *, int);
@@ -75,28 +76,36 @@ extern VEC (char_ptr) *complete_line (const char *text,
 extern char *readline_line_completion_function (const char *text,
 						int matches);
 
-extern VEC (char_ptr) *noop_completer (struct cmd_list_element *,
+extern VEC (char_ptr) *noop_completer (struct completer_data *,
+				       struct cmd_list_element *,
 				       const char *, const char *);
 
-extern VEC (char_ptr) *filename_completer (struct cmd_list_element *,
+extern VEC (char_ptr) *filename_completer (struct completer_data *,
+					   struct cmd_list_element *,
 					   const char *, const char *);
 
-extern VEC (char_ptr) *expression_completer (struct cmd_list_element *,
+extern VEC (char_ptr) *expression_completer (struct completer_data *,
+					     struct cmd_list_element *,
 					     const char *, const char *);
 
-extern VEC (char_ptr) *location_completer (struct cmd_list_element *,
+extern VEC (char_ptr) *location_completer (struct completer_data *,
+					   struct cmd_list_element *,
 					   const char *, const char *);
 
-extern VEC (char_ptr) *command_completer (struct cmd_list_element *,
+extern VEC (char_ptr) *command_completer (struct completer_data *,
+					  struct cmd_list_element *,
 					  const char *, const char *);
 
-extern VEC (char_ptr) *signal_completer (struct cmd_list_element *,
+extern VEC (char_ptr) *signal_completer (struct completer_data *,
+					 struct cmd_list_element *,
 					 const char *, const char *);
 
-extern VEC (char_ptr) *reg_or_group_completer (struct cmd_list_element *,
+extern VEC (char_ptr) *reg_or_group_completer (struct completer_data *,
+					       struct cmd_list_element *,
 					       const char *, const char *);
 
-extern VEC (char_ptr) *reggroup_completer (struct cmd_list_element *,
+extern VEC (char_ptr) *reggroup_completer (struct completer_data *cdata,
+					   struct cmd_list_element *,
 					   const char *, const char *);
 
 extern char *get_gdb_completer_quote_characters (void);
diff --git a/gdb/corefile.c b/gdb/corefile.c
index 5246f71..41b7cb0 100644
--- a/gdb/corefile.c
+++ b/gdb/corefile.c
@@ -468,7 +468,8 @@ set_gnutarget_command (char *ignore, int from_tty,
 /* A completion function for "set gnutarget".  */
 
 static VEC (char_ptr) *
-complete_set_gnutarget (struct cmd_list_element *cmd,
+complete_set_gnutarget (struct completer_data *cdata,
+			struct cmd_list_element *cmd,
 			const char *text, const char *word)
 {
   static const char **bfd_targets;
@@ -486,7 +487,7 @@ complete_set_gnutarget (struct cmd_list_element *cmd,
       bfd_targets[last + 1] = NULL;
     }
 
-  return complete_on_enum (bfd_targets, text, word);
+  return complete_on_enum (cdata, bfd_targets, text, word);
 }
 
 /* Set the gnutarget.  */
diff --git a/gdb/cp-abi.c b/gdb/cp-abi.c
index b8af8f0..504bb20 100644
--- a/gdb/cp-abi.c
+++ b/gdb/cp-abi.c
@@ -359,7 +359,8 @@ set_cp_abi_cmd (char *args, int from_tty)
 /* A completion function for "set cp-abi".  */
 
 static VEC (char_ptr) *
-cp_abi_completer (struct cmd_list_element *ignore,
+cp_abi_completer (struct completer_data *cdata,
+		  struct cmd_list_element *ignore,
 		  const char *text, const char *word)
 {
   static const char **cp_abi_names;
@@ -374,7 +375,7 @@ cp_abi_completer (struct cmd_list_element *ignore,
       cp_abi_names[i] = NULL;
     }
 
-  return complete_on_enum (cp_abi_names, text, word);
+  return complete_on_enum (cdata, cp_abi_names, text, word);
 }
 
 /* Show the currently selected C++ ABI.  */
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index e4deeb9..15c51d9 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -229,10 +229,12 @@ f_word_break_characters (void)
    class.  */
 
 static VEC (char_ptr) *
-f_make_symbol_completion_list (const char *text, const char *word,
+f_make_symbol_completion_list (struct completer_data *cdata,
+			       const char *text, const char *word,
 			       enum type_code code)
 {
-  return default_make_symbol_completion_list_break_on (text, word, ":", code);
+  return default_make_symbol_completion_list_break_on (cdata, text, word,
+						       ":", code);
 }
 
 const struct language_defn f_language_defn =
diff --git a/gdb/guile/scm-cmd.c b/gdb/guile/scm-cmd.c
index 4477b98..58c79c8 100644
--- a/gdb/guile/scm-cmd.c
+++ b/gdb/guile/scm-cmd.c
@@ -378,7 +378,8 @@ cmdscm_add_completion (SCM completion, VEC (char_ptr) **result)
 /* Called by gdb for command completion.  */
 
 static VEC (char_ptr) *
-cmdscm_completer (struct cmd_list_element *command,
+cmdscm_completer (struct completer_data *cdata,
+		  struct cmd_list_element *command,
 		  const char *text, const char *word)
 {
   command_smob *c_smob/*obj*/ = (command_smob *) get_cmd_context (command);
diff --git a/gdb/infrun.c b/gdb/infrun.c
index a2e7cfc..d858b28 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -7066,7 +7066,8 @@ Are you sure you want to change it? "),
 /* Complete the "handle" command.  */
 
 static VEC (char_ptr) *
-handle_completer (struct cmd_list_element *ignore,
+handle_completer (struct completer_data *cdata,
+		  struct cmd_list_element *ignore,
 		  const char *text, const char *word)
 {
   VEC (char_ptr) *vec_signals, *vec_keywords, *return_val;
@@ -7084,8 +7085,8 @@ handle_completer (struct cmd_list_element *ignore,
       NULL,
     };
 
-  vec_signals = signal_completer (ignore, text, word);
-  vec_keywords = complete_on_enum (keywords, word, word);
+  vec_signals = signal_completer (cdata, ignore, text, word);
+  vec_keywords = complete_on_enum (cdata, keywords, word, word);
 
   return_val = VEC_merge (char_ptr, vec_signals, vec_keywords);
   VEC_free (char_ptr, vec_signals);
diff --git a/gdb/interps.c b/gdb/interps.c
index d825e14..2cfe92b 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -435,7 +435,8 @@ interpreter_exec_cmd (char *args, int from_tty)
 
 /* List the possible interpreters which could complete the given text.  */
 static VEC (char_ptr) *
-interpreter_completer (struct cmd_list_element *ignore,
+interpreter_completer (struct completer_data *cdata,
+		       struct cmd_list_element *ignore,
 		       const char *text, const char *word)
 {
   int textlen;
diff --git a/gdb/language.h b/gdb/language.h
index 4ecb103..954b4a8 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -302,9 +302,11 @@ struct language_defn
        completion is being made.  If CODE is TYPE_CODE_UNDEF, then all
        symbols should be examined; otherwise, only STRUCT_DOMAIN
        symbols whose type has a code of CODE should be matched.  */
-    VEC (char_ptr) *(*la_make_symbol_completion_list) (const char *text,
-						       const char *word,
-						       enum type_code code);
+    VEC (char_ptr) *
+      (*la_make_symbol_completion_list) (struct completer_data *,
+					 const char *text,
+					 const char *word,
+					 enum type_code code);
 
     /* The per-architecture (OS/ABI) language information.  */
     void (*la_language_arch_info) (struct gdbarch *,
diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
index b11fc32..21d842e 100644
--- a/gdb/python/py-cmd.c
+++ b/gdb/python/py-cmd.c
@@ -237,7 +237,8 @@ cmdpy_function (struct cmd_list_element *command, char *args, int from_tty)
    call.  */
 
 static PyObject *
-cmdpy_completer_helper (struct cmd_list_element *command,
+cmdpy_completer_helper (struct completer_data *cdata,
+			struct cmd_list_element *command,
 			const char *text, const char *word)
 {
   cmdpy_object *obj = (cmdpy_object *) get_cmd_context (command);
@@ -293,7 +294,7 @@ cmdpy_completer_handle_brkchars (struct cmd_list_element *command,
 
   /* Calling our helper to obtain the PyObject of the Python
      function.  */
-  resultobj = cmdpy_completer_helper (command, text, word);
+  resultobj = cmdpy_completer_helper (NULL, command, text, word);
 
   /* Check if there was an error.  */
   if (resultobj == NULL)
@@ -330,7 +331,8 @@ cmdpy_completer_handle_brkchars (struct cmd_list_element *command,
 /* Called by gdb for command completion.  */
 
 static VEC (char_ptr) *
-cmdpy_completer (struct cmd_list_element *command,
+cmdpy_completer (struct completer_data *cdata,
+		 struct cmd_list_element *command,
 		 const char *text, const char *word)
 {
   PyObject *resultobj = NULL;
@@ -341,7 +343,7 @@ cmdpy_completer (struct cmd_list_element *command,
 
   /* Calling our helper to obtain the PyObject of the Python
      function.  */
-  resultobj = cmdpy_completer_helper (command, text, word);
+  resultobj = cmdpy_completer_helper (cdata, command, text, word);
 
   /* If the result object of calling the Python function is NULL, it
      means that there was an error.  In this case, just give up and
@@ -362,7 +364,7 @@ cmdpy_completer (struct cmd_list_element *command,
 	  PyErr_Clear ();
 	}
       else if (value >= 0 && value < (long) N_COMPLETERS)
-	result = completers[value].completer (command, text, word);
+	result = completers[value].completer (cdata, command, text, word);
     }
   else
     {
diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c
index 82c129d..0a8997a 100644
--- a/gdb/remote-sim.c
+++ b/gdb/remote-sim.c
@@ -1223,7 +1223,8 @@ simulator_command (char *args, int from_tty)
 }
 
 static VEC (char_ptr) *
-sim_command_completer (struct cmd_list_element *ignore, const char *text,
+sim_command_completer (struct completer_data *cdata,
+		       struct cmd_list_element *ignore, const char *text,
 		       const char *word)
 {
   struct sim_inferior_data *sim_data;
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 8aeabe86..f4407a0 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -5036,13 +5036,15 @@ do_free_completion_list (void *list)
 
 static VEC (char_ptr) *return_val;
 
-#define COMPLETION_LIST_ADD_SYMBOL(symbol, sym_text, len, text, word) \
-      completion_list_add_name \
-	(SYMBOL_NATURAL_NAME (symbol), (sym_text), (len), (text), (word))
+#define COMPLETION_LIST_ADD_SYMBOL(cdata, symbol, sym_text, len,	\
+				   text, word)				\
+  completion_list_add_name						\
+  ((cdata), SYMBOL_NATURAL_NAME (symbol), (sym_text), (len), (text), (word))
 
-#define MCOMPLETION_LIST_ADD_SYMBOL(symbol, sym_text, len, text, word) \
-      completion_list_add_name \
-	(MSYMBOL_NATURAL_NAME (symbol), (sym_text), (len), (text), (word))
+#define MCOMPLETION_LIST_ADD_SYMBOL(cdata, symbol, sym_text, len,	\
+				    text, word)				\
+  completion_list_add_name						\
+  (cdata, MSYMBOL_NATURAL_NAME (symbol), (sym_text), (len), (text), (word))
 
 /* Tracker for how many unique completions have been generated.  Used
    to terminate completion list generation early if the list has grown
@@ -5058,7 +5060,8 @@ static completion_tracker_t completion_tracker;
    characters.  If so, add it to the current completion list.  */
 
 static void
-completion_list_add_name (const char *symname,
+completion_list_add_name (struct completer_data *cdata,
+			  const char *symname,
 			  const char *sym_text, int sym_text_len,
 			  const char *text, const char *word)
 {
@@ -5117,7 +5120,8 @@ completion_list_add_name (const char *symname,
    again and feed all the selectors into the mill.  */
 
 static void
-completion_list_objc_symbol (struct minimal_symbol *msymbol,
+completion_list_objc_symbol (struct completer_data *cdata,
+			     struct minimal_symbol *msymbol,
 			     const char *sym_text, int sym_text_len,
 			     const char *text, const char *word)
 {
@@ -5135,7 +5139,8 @@ completion_list_objc_symbol (struct minimal_symbol *msymbol,
 
   if (sym_text[0] == '[')
     /* Complete on shortened method method.  */
-    completion_list_add_name (method + 1, sym_text, sym_text_len, text, word);
+    completion_list_add_name (cdata, method + 1, sym_text, sym_text_len,
+			      text, word);
 
   while ((strlen (method) + 1) >= tmplen)
     {
@@ -5156,9 +5161,11 @@ completion_list_objc_symbol (struct minimal_symbol *msymbol,
       memcpy (tmp, method, (category - method));
       tmp[category - method] = ' ';
       memcpy (tmp + (category - method) + 1, selector, strlen (selector) + 1);
-      completion_list_add_name (tmp, sym_text, sym_text_len, text, word);
+      completion_list_add_name (cdata, tmp, sym_text, sym_text_len,
+				text, word);
       if (sym_text[0] == '[')
-	completion_list_add_name (tmp + 1, sym_text, sym_text_len, text, word);
+	completion_list_add_name (cdata, tmp + 1, sym_text, sym_text_len,
+				  text, word);
     }
 
   if (selector != NULL)
@@ -5169,7 +5176,8 @@ completion_list_objc_symbol (struct minimal_symbol *msymbol,
       if (tmp2 != NULL)
 	*tmp2 = '\0';
 
-      completion_list_add_name (tmp, sym_text, sym_text_len, text, word);
+      completion_list_add_name (cdata, tmp, sym_text, sym_text_len,
+				text, word);
     }
 }
 
@@ -5220,7 +5228,8 @@ language_search_unquoted_string (const char *text, const char *p)
 }
 
 static void
-completion_list_add_fields (struct symbol *sym, const char *sym_text,
+completion_list_add_fields (struct completer_data *cdata,
+			    struct symbol *sym, const char *sym_text,
 			    int sym_text_len, const char *text,
 			    const char *word)
 {
@@ -5233,7 +5242,7 @@ completion_list_add_fields (struct symbol *sym, const char *sym_text,
       if (c == TYPE_CODE_UNION || c == TYPE_CODE_STRUCT)
 	for (j = TYPE_N_BASECLASSES (t); j < TYPE_NFIELDS (t); j++)
 	  if (TYPE_FIELD_NAME (t, j))
-	    completion_list_add_name (TYPE_FIELD_NAME (t, j),
+	    completion_list_add_name (cdata, TYPE_FIELD_NAME (t, j),
 				      sym_text, sym_text_len, text, word);
     }
 }
@@ -5249,6 +5258,9 @@ struct add_name_data
   const char *text;
   const char *word;
 
+  /* Completion data used by the completer function.  */
+  struct completer_data *completer_data;
+
   /* Extra argument required for add_symtab_completions.  */
   enum type_code code;
 };
@@ -5263,7 +5275,7 @@ add_macro_name (const char *name, const struct macro_definition *ignore,
 {
   struct add_name_data *datum = (struct add_name_data *) user_data;
 
-  completion_list_add_name (name,
+  completion_list_add_name (datum->completer_data, name,
 			    datum->sym_text, datum->sym_text_len,
 			    datum->text, datum->word);
 }
@@ -5281,7 +5293,8 @@ symbol_completion_matcher (const char *name, void *user_data)
 /* Add matching symbols from SYMTAB to the current completion list.  */
 
 static void
-add_symtab_completions (struct compunit_symtab *cust,
+add_symtab_completions (struct completer_data *cdata,
+			struct compunit_symtab *cust,
 			const char *sym_text, int sym_text_len,
 			const char *text, const char *word,
 			enum type_code code)
@@ -5300,7 +5313,7 @@ add_symtab_completions (struct compunit_symtab *cust,
 	  if (code == TYPE_CODE_UNDEF
 	      || (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
 		  && TYPE_CODE (SYMBOL_TYPE (sym)) == code))
-	    COMPLETION_LIST_ADD_SYMBOL (sym,
+	    COMPLETION_LIST_ADD_SYMBOL (cdata, sym,
 					sym_text, sym_text_len,
 					text, word);
 	}
@@ -5316,14 +5329,15 @@ symtab_expansion_callback (struct compunit_symtab *symtab,
 {
   struct add_name_data *datum = (struct add_name_data *) user_data;
 
-  add_symtab_completions (symtab,
+  add_symtab_completions (datum->completer_data, symtab,
 			  datum->sym_text, datum->sym_text_len,
 			  datum->text, datum->word,
 			  datum->code);
 }
 
 static void
-default_make_symbol_completion_list_break_on_1 (const char *text,
+default_make_symbol_completion_list_break_on_1 (struct completer_data *cdata,
+						const char *text,
 						const char *word,
 						const char *break_on,
 						enum type_code code)
@@ -5423,6 +5437,7 @@ default_make_symbol_completion_list_break_on_1 (const char *text,
   datum.text = text;
   datum.word = word;
   datum.code = code;
+  datum.completer_data = cdata;
 
   /* At this point scan through the misc symbol vectors and add each
      symbol you find to the list.  Eventually we want to ignore
@@ -5434,17 +5449,17 @@ default_make_symbol_completion_list_break_on_1 (const char *text,
       ALL_MSYMBOLS (objfile, msymbol)
 	{
 	  QUIT;
-	  MCOMPLETION_LIST_ADD_SYMBOL (msymbol, sym_text, sym_text_len, text,
-				       word);
+	  MCOMPLETION_LIST_ADD_SYMBOL (cdata, msymbol, sym_text, sym_text_len,
+				       text, word);
 
-	  completion_list_objc_symbol (msymbol, sym_text, sym_text_len, text,
-				       word);
+	  completion_list_objc_symbol (cdata, msymbol, sym_text, sym_text_len,
+				       text, word);
 	}
     }
 
   /* Add completions for all currently loaded symbol tables.  */
   ALL_COMPUNITS (objfile, cust)
-    add_symtab_completions (cust, sym_text, sym_text_len, text, word,
+    add_symtab_completions (cdata, cust, sym_text, sym_text_len, text, word,
 			    code);
 
   /* Look through the partial symtabs for all symbols which begin
@@ -5472,15 +5487,15 @@ default_make_symbol_completion_list_break_on_1 (const char *text,
 	  {
 	    if (code == TYPE_CODE_UNDEF)
 	      {
-		COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text,
-					    word);
-		completion_list_add_fields (sym, sym_text, sym_text_len, text,
-					    word);
+		COMPLETION_LIST_ADD_SYMBOL (cdata, sym, sym_text,
+					    sym_text_len, text, word);
+		completion_list_add_fields (cdata, sym, sym_text,
+					    sym_text_len, text, word);
 	      }
 	    else if (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
 		     && TYPE_CODE (SYMBOL_TYPE (sym)) == code)
-	      COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text,
-					  word);
+	      COMPLETION_LIST_ADD_SYMBOL (cdata, sym, sym_text, sym_text_len,
+					  text, word);
 	  }
 
 	/* Stop when we encounter an enclosing function.  Do not stop for
@@ -5497,11 +5512,16 @@ default_make_symbol_completion_list_break_on_1 (const char *text,
     {
       if (surrounding_static_block != NULL)
 	ALL_BLOCK_SYMBOLS (surrounding_static_block, iter, sym)
-	  completion_list_add_fields (sym, sym_text, sym_text_len, text, word);
-
+	  {
+	    completion_list_add_fields (cdata, sym, sym_text, sym_text_len,
+					text, word);
+	  }
       if (surrounding_global_block != NULL)
 	ALL_BLOCK_SYMBOLS (surrounding_global_block, iter, sym)
-	  completion_list_add_fields (sym, sym_text, sym_text_len, text, word);
+	  {
+	    completion_list_add_fields (cdata, sym, sym_text, sym_text_len,
+					text, word);
+	  }
     }
 
   /* Skip macros if we are completing a struct tag -- arguable but
@@ -5534,7 +5554,8 @@ default_make_symbol_completion_list_break_on_1 (const char *text,
 }
 
 VEC (char_ptr) *
-default_make_symbol_completion_list_break_on (const char *text,
+default_make_symbol_completion_list_break_on (struct completer_data *cdata,
+					      const char *text,
 					      const char *word,
 					      const char *break_on,
 					      enum type_code code)
@@ -5546,7 +5567,7 @@ default_make_symbol_completion_list_break_on (const char *text,
 
   TRY
     {
-      default_make_symbol_completion_list_break_on_1 (text, word,
+      default_make_symbol_completion_list_break_on_1 (cdata, text, word,
 						      break_on, code);
     }
   CATCH (except, RETURN_MASK_ERROR)
@@ -5561,10 +5582,12 @@ default_make_symbol_completion_list_break_on (const char *text,
 }
 
 VEC (char_ptr) *
-default_make_symbol_completion_list (const char *text, const char *word,
+default_make_symbol_completion_list (struct completer_data *cdata,
+				     const char *text, const char *word,
 				     enum type_code code)
 {
-  return default_make_symbol_completion_list_break_on (text, word, "", code);
+  return default_make_symbol_completion_list_break_on (cdata, text, word, "",
+						       code);
 }
 
 /* Return a vector of all symbols (regardless of class) which begin by
@@ -5572,9 +5595,10 @@ default_make_symbol_completion_list (const char *text, const char *word,
    is NULL.  */
 
 VEC (char_ptr) *
-make_symbol_completion_list (const char *text, const char *word)
+make_symbol_completion_list (struct completer_data *cdata,
+			     const char *text, const char *word)
 {
-  return current_language->la_make_symbol_completion_list (text, word,
+  return current_language->la_make_symbol_completion_list (cdata, text, word,
 							   TYPE_CODE_UNDEF);
 }
 
@@ -5582,30 +5606,33 @@ make_symbol_completion_list (const char *text, const char *word)
    symbols whose type code is CODE.  */
 
 VEC (char_ptr) *
-make_symbol_completion_type (const char *text, const char *word,
-			     enum type_code code)
+make_symbol_completion_type (struct completer_data *cdata, const char *text,
+			     const char *word, enum type_code code)
 {
   gdb_assert (code == TYPE_CODE_UNION
 	      || code == TYPE_CODE_STRUCT
 	      || code == TYPE_CODE_ENUM);
-  return current_language->la_make_symbol_completion_list (text, word, code);
+  return current_language->la_make_symbol_completion_list (cdata, text, word,
+							   code);
 }
 
 /* Like make_symbol_completion_list, but suitable for use as a
    completion function.  */
 
 VEC (char_ptr) *
-make_symbol_completion_list_fn (struct cmd_list_element *ignore,
+make_symbol_completion_list_fn (struct completer_data *cdata,
+				struct cmd_list_element *ignore,
 				const char *text, const char *word)
 {
-  return make_symbol_completion_list (text, word);
+  return make_symbol_completion_list (cdata, text, word);
 }
 
 /* Like make_symbol_completion_list, but returns a list of symbols
    defined in a source file FILE.  */
 
 VEC (char_ptr) *
-make_file_symbol_completion_list (const char *text, const char *word,
+make_file_symbol_completion_list (struct completer_data *cdata,
+				  const char *text, const char *word,
 				  const char *srcfile)
 {
   struct symbol *sym;
@@ -5687,13 +5714,15 @@ make_file_symbol_completion_list (const char *text, const char *word,
   b = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (s), GLOBAL_BLOCK);
   ALL_BLOCK_SYMBOLS (b, iter, sym)
     {
-      COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
+      COMPLETION_LIST_ADD_SYMBOL (cdata, sym, sym_text, sym_text_len,
+				  text, word);
     }
 
   b = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (s), STATIC_BLOCK);
   ALL_BLOCK_SYMBOLS (b, iter, sym)
     {
-      COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
+      COMPLETION_LIST_ADD_SYMBOL (cdata, sym, sym_text, sym_text_len,
+				  text, word);
     }
 
   return (return_val);
@@ -5759,6 +5788,9 @@ struct add_partial_filename_data
   const char *word;
   int text_len;
   VEC (char_ptr) **list;
+
+  /* Completion data used by the completer function.  */
+  struct completer_data *completer_data;
 };
 
 /* A callback for map_partial_symbol_filenames.  */
@@ -5795,7 +5827,8 @@ maybe_add_partial_symtab_filename (const char *filename, const char *fullname,
    NULL.  */
 
 VEC (char_ptr) *
-make_source_files_completion_list (const char *text, const char *word)
+make_source_files_completion_list (struct completer_data *cdata,
+				   const char *text, const char *word)
 {
   struct compunit_symtab *cu;
   struct symtab *s;
@@ -5846,6 +5879,7 @@ make_source_files_completion_list (const char *text, const char *word)
   datum.word = word;
   datum.text_len = text_len;
   datum.list = &list;
+  datum.completer_data = cdata;
   map_symbol_filenames (maybe_add_partial_symtab_filename, &datum,
 			0 /*need_fullname*/);
 
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 61fc8c5..018852c 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -38,6 +38,7 @@ struct program_space;
 struct language_defn;
 struct probe;
 struct common_block;
+struct completer_data;
 
 /* Some of the structures in this file are space critical.
    The space-critical structures are:
@@ -1454,24 +1455,31 @@ extern void forget_cached_source_info (void);
 extern void select_source_symtab (struct symtab *);
 
 extern VEC (char_ptr) *default_make_symbol_completion_list_break_on
-  (const char *text, const char *word, const char *break_on,
-   enum type_code code);
-extern VEC (char_ptr) *default_make_symbol_completion_list (const char *,
-							    const char *,
-							    enum type_code);
-extern VEC (char_ptr) *make_symbol_completion_list (const char *, const char *);
-extern VEC (char_ptr) *make_symbol_completion_type (const char *, const char *,
-						    enum type_code);
-extern VEC (char_ptr) *make_symbol_completion_list_fn (struct cmd_list_element *,
-						       const char *,
-						       const char *);
-
-extern VEC (char_ptr) *make_file_symbol_completion_list (const char *,
-							 const char *,
-							 const char *);
-
-extern VEC (char_ptr) *make_source_files_completion_list (const char *,
-							  const char *);
+ (struct completer_data *cdata, const char *text, const char *word,
+  const char *break_on, enum type_code code);
+extern VEC (char_ptr) *
+ default_make_symbol_completion_list (struct completer_data *,
+				      const char *, const char *,
+				      enum type_code);
+extern VEC (char_ptr) *
+  make_symbol_completion_list (struct completer_data *, const char *,
+			       const char *);
+extern VEC (char_ptr) *
+  make_symbol_completion_type (struct completer_data *,
+			       const char *, const char *,
+			       enum type_code);
+extern VEC (char_ptr) *
+  make_symbol_completion_list_fn (struct completer_data *,
+				  struct cmd_list_element *,
+				  const char *, const char *);
+
+extern VEC (char_ptr) *
+  make_file_symbol_completion_list (struct completer_data *,
+				    const char *, const char *, const char *);
+
+extern VEC (char_ptr) *
+ make_source_files_completion_list (struct completer_data *, const char *,
+				    const char *);
 
 /* symtab.c */
 
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 0255c39..8d420894 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -354,13 +354,14 @@ tui_default_win_viewport_height (enum tui_win_type type,
    far, WORD is the word currently being completed.  */
 
 static VEC (char_ptr) *
-layout_completer (struct cmd_list_element *ignore,
+layout_completer (struct completer_data *cdata,
+		  struct cmd_list_element *ignore,
 		  const char *text, const char *word)
 {
   static const char *layout_names [] =
     { "src", "asm", "split", "regs", "next", "prev", NULL };
 
-  return complete_on_enum (layout_names, text, word);
+  return complete_on_enum (cdata, layout_names, text, word);
 }
 
 /* Function to initialize gdb commands, for tui window layout
diff --git a/gdb/tui/tui-regs.c b/gdb/tui/tui-regs.c
index a61fadb..756f598 100644
--- a/gdb/tui/tui-regs.c
+++ b/gdb/tui/tui-regs.c
@@ -669,7 +669,8 @@ tui_reg_command (char *args, int from_tty)
    names.  */
 
 static VEC (char_ptr) *
-tui_reggroup_completer (struct cmd_list_element *ignore,
+tui_reggroup_completer (struct completer_data *cdata,
+			struct cmd_list_element *ignore,
 			const char *text, const char *word)
 {
   VEC (char_ptr) *result = NULL;
@@ -677,7 +678,7 @@ tui_reggroup_completer (struct cmd_list_element *ignore,
   size_t len = strlen (word);
   const char **tmp;
 
-  result = reggroup_completer (ignore, text, word);
+  result = reggroup_completer (cdata, ignore, text, word);
 
   for (tmp = extra; *tmp != NULL; ++tmp)
     {
diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
index 29ad279..8e7fbd1 100644
--- a/gdb/tui/tui-win.c
+++ b/gdb/tui/tui-win.c
@@ -361,6 +361,7 @@ tui_set_var_cmd (char *null_args, int from_tty, struct cmd_list_element *c)
 
 static VEC (char_ptr) *
 window_name_completer (int include_next_prev_p,
+		       struct completer_data *cdata,
 		       const char *text, const char *word)
 {
   VEC (const_char_ptr) *completion_name_vec = NULL;
@@ -399,7 +400,8 @@ window_name_completer (int include_next_prev_p,
 
   VEC_safe_push (const_char_ptr, completion_name_vec, NULL);
   matches_vec
-    = complete_on_enum (VEC_address (const_char_ptr, completion_name_vec),
+    = complete_on_enum (cdata,
+			VEC_address (const_char_ptr, completion_name_vec),
 			text, word);
 
   VEC_free (const_char_ptr, completion_name_vec);
@@ -411,10 +413,11 @@ window_name_completer (int include_next_prev_p,
    entered so far, WORD is the word currently being completed.  */
 
 static VEC (char_ptr) *
-focus_completer (struct cmd_list_element *ignore,
+focus_completer (struct completer_data *cdata,
+		 struct cmd_list_element *ignore,
 		  const char *text, const char *word)
 {
-  return window_name_completer (1, text, word);
+  return window_name_completer (1, cdata, text, word);
 }
 
 /* Complete possible window names for winheight command.  TEXT is the
@@ -422,7 +425,8 @@ focus_completer (struct cmd_list_element *ignore,
    completed.  */
 
 static VEC (char_ptr) *
-winheight_completer (struct cmd_list_element *ignore,
+winheight_completer (struct completer_data *cdata,
+		     struct cmd_list_element *ignore,
 		     const char *text, const char *word)
 {
   /* The first word is the window name.  That we can complete.  Subsequent
@@ -430,7 +434,7 @@ winheight_completer (struct cmd_list_element *ignore,
   if (word != text)
     return NULL;
 
-  return window_name_completer (0, text, word);
+  return window_name_completer (0, cdata, text, word);
 }
 
 /* Function to initialize gdb commands, for tui window

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v3 17/19] Make the completion API completely opaque.
  2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
                   ` (7 preceding siblings ...)
  2015-08-06 20:03 ` [PATCH v3 01/19] Add struct completer_data to the completion API Keith Seitz
@ 2015-08-06 21:06 ` Keith Seitz
  2015-08-23 15:14   ` Doug Evans
  2015-08-06 21:06 ` [PATCH v3 05/19] Implement completion limiting for ada_make_symbol_completion_list Keith Seitz
                   ` (10 subsequent siblings)
  19 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-06 21:06 UTC (permalink / raw)
  To: gdb-patches

There are no revisions in this version.

--

Now that the completion API is passing around a structure holding
its internal data, there is no need to expose any of this data and
other settings to other modules.

This patch removes global access to max_completions and
introduces a new API function,  get_maximum_completions (void), which
other modules may use to query the current completion maximum.

The API will be expanded as necessary in subsequent patches.

gdb/ChangeLog

	* cli/cli-cmds.c (complete_command): Use get_maximum_completions
	instead of accessing the global max_completions.
	* completer.c (max_completions): Move definition earlier and
	make static.
	(get_maximum_completions): New function.
	(throw_max_completions_reached_error): Add comment.
	* completer.h (max_completions): Remove declaration.
	(get_maximum_completions): New declaration.
---
 gdb/cli/cli-cmds.c |    4 ++--
 gdb/completer.c    |   22 +++++++++++++++++-----
 gdb/completer.h    |    8 ++++----
 3 files changed, 23 insertions(+), 11 deletions(-)

diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 2ec2dd3..a73a655 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -248,7 +248,7 @@ complete_command (char *arg, int from_tty)
 
   dont_repeat ();
 
-  if (max_completions == 0)
+  if (get_maximum_completions () == 0)
     {
       /* Only print this for non-mi frontends.  An MI frontend may not
 	 be able to handle this.  */
@@ -307,7 +307,7 @@ complete_command (char *arg, int from_tty)
       xfree (prev);
       VEC_free (char_ptr, completions);
 
-      if (size == max_completions)
+      if (size == get_maximum_completions ())
 	{
 	  /* ARG_PREFIX and POINT are included in the output so that emacs
 	     will include the message in the output.  */
diff --git a/gdb/completer.c b/gdb/completer.c
index 134a3c2..651e9c2 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -43,6 +43,13 @@
 
 #include "completer.h"
 
+/* Maximum number of candidates to consider before the completer
+   bails by throwing MAX_COMPLETIONS_REACHED_ERROR.  Negative values
+   disable limiting.  */
+
+#define DEFAULT_MAX_COMPLETIONS 200
+static int max_completions = DEFAULT_MAX_COMPLETIONS;
+
 /* Prototypes for local functions.  */
 static
 char *line_completion_function (const char *text, int matches, 
@@ -813,11 +820,6 @@ complete_line_internal (struct completer_data *cdata,
   return list;
 }
 
-/* See completer.h.  */
-
-#define DEFAULT_MAX_COMPLETIONS 200
-int max_completions = DEFAULT_MAX_COMPLETIONS;
-
 /* Allocate a new completer data structure.  */
 
 static struct completer_data *
@@ -907,6 +909,14 @@ completer_strdup (const char *match, const char *text, const char *word)
 
 /* See completer.h.  */
 
+int
+get_maximum_completions (void)
+{
+  return max_completions;
+}
+
+/* See completer.h.  */
+
 enum add_completion_status
 add_completion (struct completer_data *cdata, VEC (char_ptr) **result,
 		const char *match, const char *text, const char *word)
@@ -934,6 +944,8 @@ add_completion (struct completer_data *cdata, VEC (char_ptr) **result,
   return ADD_COMPLETION_OK;
 }
 
+/* See completer.h.  */
+
 void
 throw_max_completions_reached_error (void)
 {
diff --git a/gdb/completer.h b/gdb/completer.h
index 43d1321..98b7d14 100644
--- a/gdb/completer.h
+++ b/gdb/completer.h
@@ -126,11 +126,11 @@ extern const char *skip_quoted_chars (const char *, const char *,
 
 extern const char *skip_quoted (const char *);
 
-/* Maximum number of candidates to consider before the completer
-   bails by throwing MAX_COMPLETIONS_REACHED_ERROR.  Negative values
-   disable limiting.  */
+/* Get the maximum number of completions that are permitted before the
+   completer throws a MAX_COMPLETIONS_REACHED_ERROR.  Negative values
+   mean completion limiting is entirely disabled.  */
 
-extern int max_completions;
+extern int get_maximum_completions (void);
 
 /* Return values for add_completion.  */
 

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v3 05/19] Implement completion limiting for ada_make_symbol_completion_list.
  2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
                   ` (8 preceding siblings ...)
  2015-08-06 21:06 ` [PATCH v3 17/19] Make the completion API completely opaque Keith Seitz
@ 2015-08-06 21:06 ` Keith Seitz
  2015-08-23  3:47   ` Doug Evans
  2015-08-06 22:03 ` [PATCH v3 16/19] Implement completion limiting for tui_reggroup_completer Keith Seitz
                   ` (9 subsequent siblings)
  19 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-06 21:06 UTC (permalink / raw)
  To: gdb-patches

Differences in this revision:

1. Remove partial copy code from symbol_completion_add.

---

This patch converts the one Ada completion(-related) function,
symbol_completion_add, to use maybe_add_completion, and tests have
been added to exercise this newly implemented behavior.

gdb/ChangeLog

	* ada-lang.c (symbol_completion_add): Return
	add_completion_status instead of void.
	Use add_completion and return the status of this function.
	(ada_make_symbol_completion_list): If symbol_completion_add
	returns that maximum completions have been reached, stop
	looking for completions and return the list.

gdb/testsuite/ChangeLog

	* gdb.ada/complete.exp (limit_multi_line): New procedure.
	Update existing tests for source changes.
	Add additional tests for new types.
	Add tests for completion limiting.
	* gdb.ada/complete/foo.adb (Repeat_Variable_1, Repeat_Variable_2,
	Repeat_Variable_3, Repeat_Variable_4): Define.
	* gdb.ada/complete/pck.ads (Repeat_Variable_1, Repeat_Variable_2)
	(Repeat_Variable_3, Repeat_Variable_4): Declare.
	(Repeated_1, Repeated_2, Repeated_3, Repeated_4): Define.
---
 gdb/ada-lang.c                         |   79 +++++++++---------
 gdb/testsuite/gdb.ada/complete.exp     |  144 ++++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.ada/complete/foo.adb |    4 +
 gdb/testsuite/gdb.ada/complete/pck.ads |   12 +++
 4 files changed, 199 insertions(+), 40 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 9782b69..5df08be 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -6198,8 +6198,9 @@ symbol_completion_match (const char *sym_name,
    encoded formed (in which case the completion should also be
    encoded).  */
 
-static void
+static enum add_completion_status
 symbol_completion_add (VEC(char_ptr) **sv,
+		       struct completer_data *cdata,
                        const char *sym_name,
                        const char *text, int text_len,
                        const char *orig_text, const char *word,
@@ -6207,35 +6208,12 @@ symbol_completion_add (VEC(char_ptr) **sv,
 {
   const char *match = symbol_completion_match (sym_name, text, text_len,
                                                wild_match_p, encoded_p);
-  char *completion;
-
   if (match == NULL)
-    return;
+    return ADD_COMPLETION_OK;
 
   /* We found a match, so add the appropriate completion to the given
      string vector.  */
-
-  if (word == orig_text)
-    {
-      completion = xmalloc (strlen (match) + 5);
-      strcpy (completion, match);
-    }
-  else if (word > orig_text)
-    {
-      /* Return some portion of sym_name.  */
-      completion = xmalloc (strlen (match) + 5);
-      strcpy (completion, match + (word - orig_text));
-    }
-  else
-    {
-      /* Return some of ORIG_TEXT plus sym_name.  */
-      completion = xmalloc (strlen (match) + (orig_text - word) + 5);
-      strncpy (completion, word, orig_text - word);
-      completion[orig_text - word] = '\0';
-      strcat (completion, match);
-    }
-
-  VEC_safe_push (char_ptr, *sv, completion);
+  return add_completion (cdata, sv, match, orig_text, word);
 }
 
 /* An object of this type is passed as the user_data argument to the
@@ -6283,6 +6261,7 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
   int i;
   struct block_iterator iter;
   struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
+  enum add_completion_status status;
 
   gdb_assert (code == TYPE_CODE_UNDEF);
 
@@ -6333,9 +6312,15 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
   ALL_MSYMBOLS (objfile, msymbol)
   {
     QUIT;
-    symbol_completion_add (&completions, MSYMBOL_LINKAGE_NAME (msymbol),
-			   text, text_len, text0, word, wild_match_p,
-			   encoded_p);
+    status = symbol_completion_add (&completions, cdata,
+					 MSYMBOL_LINKAGE_NAME (msymbol),
+					 text, text_len, text0, word,
+					 wild_match_p, encoded_p);
+    if (status == ADD_COMPLETION_MAX_REACHED)
+      {
+	do_cleanups (old_chain);
+	return completions;
+      }
   }
 
   /* Search upwards from currently selected frame (so that we can
@@ -6348,9 +6333,15 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
 
       ALL_BLOCK_SYMBOLS (b, iter, sym)
       {
-        symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (sym),
-                               text, text_len, text0, word,
-                               wild_match_p, encoded_p);
+        status = symbol_completion_add (&completions, cdata,
+					     SYMBOL_LINKAGE_NAME (sym),
+					     text, text_len, text0, word,
+					     wild_match_p, encoded_p);
+	if (status == ADD_COMPLETION_MAX_REACHED)
+	  {
+	    do_cleanups (old_chain);
+	    return completions;
+	  }
       }
     }
 
@@ -6363,9 +6354,15 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
     b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (s), GLOBAL_BLOCK);
     ALL_BLOCK_SYMBOLS (b, iter, sym)
     {
-      symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (sym),
-                             text, text_len, text0, word,
-                             wild_match_p, encoded_p);
+      status = symbol_completion_add (&completions, cdata,
+					   SYMBOL_LINKAGE_NAME (sym),
+					   text, text_len, text0, word,
+					   wild_match_p, encoded_p);
+      if (status == ADD_COMPLETION_MAX_REACHED)
+	{
+	  do_cleanups (old_chain);
+	  return completions;
+	}
     }
   }
 
@@ -6378,9 +6375,15 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
       continue;
     ALL_BLOCK_SYMBOLS (b, iter, sym)
     {
-      symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (sym),
-                             text, text_len, text0, word,
-                             wild_match_p, encoded_p);
+      status = symbol_completion_add (&completions, cdata,
+					   SYMBOL_LINKAGE_NAME (sym),
+					   text, text_len, text0, word,
+					   wild_match_p, encoded_p);
+      if (status == ADD_COMPLETION_MAX_REACHED)
+	{
+	  do_cleanups (old_chain);
+	  return completions;
+	}
     }
   }
 
diff --git a/gdb/testsuite/gdb.ada/complete.exp b/gdb/testsuite/gdb.ada/complete.exp
index 9919bdf..b4efc68 100644
--- a/gdb/testsuite/gdb.ada/complete.exp
+++ b/gdb/testsuite/gdb.ada/complete.exp
@@ -44,6 +44,29 @@ proc test_gdb_no_completion { expr } {
     gdb_test_no_output "complete p $expr"
 }
 
+# A convenience function that joins all the arguments together,
+# with a regexp that matches zero-or-more end of lines in between
+# each argument.  This function is ideal to write the expected output
+# of a GDB command that generates more than a couple of lines, as
+# this allows us to write each line as a separate string, which is
+# easier to read by a human being.
+
+proc multi_line { args } {
+    return [join $args "\[\r\n\]*"]
+}
+
+# Like multi_line above, but limiting the return result to MAX
+# elements and adding the completer's truncation message.
+
+proc limit_multi_line { max args } {
+    set result [join [lrange $args 0 [expr {$max - 1}]] "\[\r\n\]*"]
+    if {$max <= [llength $args]} {
+	append result ".*\\\*\\\*\\\* List may be truncated, "
+	append result "max-completions reached\\\. \\\*\\\*\\\*"
+    }
+    return $result
+}
+
 # Try a global variable, only one match should be found:
 
 test_gdb_complete "my_glob" \
@@ -145,7 +168,11 @@ test_gdb_complete "pck" \
                               "p pck.local_identical_one" \
                               "p pck.local_identical_two" \
                               "p pck.my_global_variable" \
-                              "p pck.proc" ]
+                              "p pck.proc" \
+                              "p pck.repeat_variable_1" \
+                              "p pck.repeat_variable_2" \
+                              "p pck.repeat_variable_3" \
+                              "p pck.repeat_variable_4" ]
 
 # Complete on the name of a package followed by a dot:
 test_gdb_complete "pck." \
@@ -156,12 +183,125 @@ test_gdb_complete "pck." \
                               "p pck.local_identical_one" \
                               "p pck.local_identical_two" \
                               "p pck.my_global_variable" \
-                              "p pck.proc" ]
+                              "p pck.proc" \
+                              "p pck.repeat_variable_1" \
+                              "p pck.repeat_variable_2" \
+                              "p pck.repeat_variable_3" \
+                              "p pck.repeat_variable_4" ]
+
+# Complete on a repeated global name:
+test_gdb_complete "repeat_" \
+                 [multi_line "p repeat_variable_1" \
+                             "p repeat_variable_2" \
+                             "p repeat_variable_3" \
+                             "p repeat_variable_4" ]
+
+# Complete a mangled symbol name, but using the '<...>' notation:
+test_gdb_complete "<pck__repeat_" \
+                  [multi_line "p <pck__repeat_variable_1>" \
+                              "p <pck__repeat_variable_2>" \
+                              "p <pck__repeat_variable_3>" \
+                              "p <pck__repeat_variable_4>" ]
+
+# Complete on repeated mangled name, using '<...>' notation:
+test_gdb_complete "<Repeated_" \
+                  [multi_line "p <Repeated_1>" \
+                              "p <Repeated_2>" \
+                              "p <Repeated_3>" \
+                              "p <Repeated_4>" ]
 
 # Complete a mangled symbol name, but using the '<...>' notation.
 test_gdb_complete "<pck__my" \
                   "p <pck__my_global_variable>"
 
+# Test completion limiting.
+set max_completions 2
+gdb_test_no_output "set max-completions $max_completions"
+with_test_prefix "limit completion" {
+    # Two matches, from the global scope:
+    test_gdb_complete "local_ident" \
+	[limit_multi_line $max_completions \
+	     "p local_identical_one" \
+	     "p local_identical_two" ]
+
+    # Two matches, from the global scope, but using fully qualified names:
+    test_gdb_complete "pck.local_ident" \
+	[limit_multi_line $max_completions "p pck.local_identical_one" \
+	     "p pck.local_identical_two" ]
+
+    # Two matches, from the global scope, but using mangled fully qualified
+    # names:
+    test_gdb_complete "pck__local_ident" \
+	[limit_multi_line $max_completions \
+	     "p pck__local_identical_one" \
+	     "p pck__local_identical_two" ]
+
+    # Two matches, one from the global scope, the other from the local
+    # scope:
+    test_gdb_complete "external_ident" \
+	[limit_multi_line $max_completions \
+	     "p external_identical_one" \
+	     "p external_identical_two" ]
+
+    # Complete on the name of package.
+    test_gdb_complete "pck" \
+	[limit_multi_line $max_completions \
+	     "(p pck\\.ad\[sb\])?" \
+	     "(p pck\\.ad\[sb\])?" \
+	     "p pck.external_identical_one" \
+	     "p pck.inner.inside_variable" \
+	     "p pck.local_identical_one" \
+	     "p pck.local_identical_two" \
+	     "p pck.my_global_variable" \
+	     "p pck.proc" \
+	     "p pck.repeat_variable_1" \
+	     "p pck.repeat_variable_2" \
+	     "p pck.repeat_variable_3" \
+	     "p pck.repeat_variable_4" ]
+
+    # Complete on the name of a package followed by a dot:
+    test_gdb_complete "pck." \
+	[limit_multi_line $max_completions \
+	     "(p pck\\.ad\[sb\])?" \
+	     "(p pck\\.ad\[sb\])?" \
+	     "p pck.external_identical_one" \
+	     "p pck.inner.inside_variable" \
+	     "p pck.local_identical_one" \
+	     "p pck.local_identical_two" \
+	     "p pck.my_global_variable" \
+	     "p pck.proc" \
+	     "p pck.repeat_variable_1" \
+	     "p pck.repeat_variable_2" \
+	     "p pck.repeat_variable_3" \
+	     "p pck.repeat_variable_4"]
+
+    # Complete on a repeated global name:
+    test_gdb_complete "repeat_" \
+	[limit_multi_line $max_completions \
+	     "p repeat_variable_1" \
+	     "p repeat_variable_2" \
+	     "p repeat_variable_3" \
+	     "p repeat_variable_4" ]
+    # Complete a mangled symbol name, but using the '<...>' notation:
+    test_gdb_complete "<pck__repeat_" \
+	[limit_multi_line $max_completions \
+	     "p <pck__repeat_variable_1>" \
+	     "p <pck__repeat_variable_2>" \
+	     "p <pck__repeat_variable_3>" \
+	     "p <pck__repeat_variable_4>" ]
+
+    # Complete on repeated mangled name, using '<...>' notation:
+    test_gdb_complete "<Repeated_" \
+	[limit_multi_line $max_completions \
+	     "p <Repeated_1>" \
+	     "p <Repeated_2>" \
+	     "p <Repeated_3>" \
+	     "p <Repeated_4>" ]
+}
+
+# Reset completion-limiting to its default.
+gdb_test_no_output "set max-completions 200"
+
 # Very simple completion, but using the interactive form, this time.
 # The verification we are trying to make involves the event loop,
 # and using the "complete" command is not sufficient to reproduce
diff --git a/gdb/testsuite/gdb.ada/complete/foo.adb b/gdb/testsuite/gdb.ada/complete/foo.adb
index 58d0ee3..ad6b5ec 100644
--- a/gdb/testsuite/gdb.ada/complete/foo.adb
+++ b/gdb/testsuite/gdb.ada/complete/foo.adb
@@ -20,6 +20,10 @@ procedure Foo is
    External_Identical_Two : Integer := 74;
 begin
    My_Global_Variable := Some_Local_Variable + 1; -- START
+   Repeat_Variable_1 := My_Global_Variable + 1;
+   Repeat_Variable_2 := Repeat_Variable_1 + 1;
+   Repeat_Variable_3 := Repeat_Variable_2 + 1;
+   Repeat_Variable_4 := Repeat_Variable_3 + 1;
    Proc (External_Identical_Two);
 end Foo;
 
diff --git a/gdb/testsuite/gdb.ada/complete/pck.ads b/gdb/testsuite/gdb.ada/complete/pck.ads
index ab2c47b..5595f7f 100644
--- a/gdb/testsuite/gdb.ada/complete/pck.ads
+++ b/gdb/testsuite/gdb.ada/complete/pck.ads
@@ -16,9 +16,21 @@
 package Pck is
 
    My_Global_Variable : Integer := 1;
+   Repeat_Variable_1 : Integer := 1;
+   Repeat_Variable_2 : Integer := 1;
+   Repeat_Variable_3 : Integer := 1;
+   Repeat_Variable_4 : Integer := 1;
 
    Exported_Capitalized : Integer := 2;
    pragma Export (C, Exported_Capitalized, "Exported_Capitalized");
+   Repeated_1 : Integer := 21;
+   pragma Export (C, Repeated_1, "Repeated_1");
+   Repeated_2 : Integer := 22;
+   pragma Export (C, Repeated_2, "Repeated_2");
+   Repeated_3 : Integer := 23;
+   pragma Export (C, Repeated_3, "Repeated_3");
+   Repeated_4 : Integer := 24;
+   pragma Export (C, Repeated_4, "Repeated_4");
 
    Local_Identical_One : Integer := 4;
    Local_Identical_Two : Integer := 8;

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v3 07/19] Implement completion limiting for filename_completer.
  2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
                   ` (10 preceding siblings ...)
  2015-08-06 22:03 ` [PATCH v3 16/19] Implement completion limiting for tui_reggroup_completer Keith Seitz
@ 2015-08-06 22:03 ` Keith Seitz
  2015-08-23  3:58   ` Doug Evans
  2015-08-06 22:03 ` [PATCH v3 13/19] Implement completion limiting for complete_on_enum Keith Seitz
                   ` (7 subsequent siblings)
  19 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-06 22:03 UTC (permalink / raw)
  To: gdb-patches

Differences in this revision:

1. Remove partial copy code from filename_completer.

---

This patch converts filename_completer to using add_completion
and adds some tests to exercise this new behavior.

gdb/ChangeLog

	* completer.c (filename_completer): Use add_completion.

gdb/testsuite/ChangeLog

	* gdb.base/completion.exp: Put completion truncation message
	into a variable for use by other tests.  Update existing tests.
	(test_completion_limit): New procedure.
	Add tests for completion limiting on file names.
---
 gdb/completer.c                       |   25 ++----------
 gdb/testsuite/gdb.base/completion.exp |   69 +++++++++++++++++++++++++++++++--
 2 files changed, 69 insertions(+), 25 deletions(-)

diff --git a/gdb/completer.c b/gdb/completer.c
index bf4137e..6aa8d35 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -157,7 +157,7 @@ filename_completer (struct completer_data *cdata,
   subsequent_name = 0;
   while (1)
     {
-      char *p, *q;
+      char *p;
 
       p = rl_filename_completion_function (text, subsequent_name);
       if (p == NULL)
@@ -175,26 +175,9 @@ filename_completer (struct completer_data *cdata,
 	  continue;
 	}
 
-      if (word == text)
-	/* Return exactly p.  */
-	q = p;
-      else if (word > text)
-	{
-	  /* Return some portion of p.  */
-	  q = xmalloc (strlen (p) + 5);
-	  strcpy (q, p + (word - text));
-	  xfree (p);
-	}
-      else
-	{
-	  /* Return some of TEXT plus p.  */
-	  q = xmalloc (strlen (p) + (text - word) + 5);
-	  strncpy (q, word, text - word);
-	  q[text - word] = '\0';
-	  strcat (q, p);
-	  xfree (p);
-	}
-      VEC_safe_push (char_ptr, return_val, q);
+      if (add_completion (cdata, &return_val, p, text, word)
+	  == ADD_COMPLETION_MAX_REACHED)
+	break;
     }
 #if 0
   /* There is no way to do this just long enough to affect quote
diff --git a/gdb/testsuite/gdb.base/completion.exp b/gdb/testsuite/gdb.base/completion.exp
index 710aac0..f0b7f2c 100644
--- a/gdb/testsuite/gdb.base/completion.exp
+++ b/gdb/testsuite/gdb.base/completion.exp
@@ -858,6 +858,10 @@ gdb_test "complete break need" "need_malloc"
 # Completion limiting.
 #
 
+# The terminal at the end of the complete command
+set end "\\\*\\\*\\\* List may be truncated, "
+append end "max-completions reached\\\. \\\*\\\*\\\*"
+
 gdb_test_no_output "set max-completions 5"
 
 set test "command-name completion limiting using tab character"
@@ -866,7 +870,7 @@ gdb_test_multiple "" "$test" {
     -re "^p\\\x07$" {
 	send_gdb "\t"
 	gdb_test_multiple "" "$test" {
-	    -re "List may be truncated, max-completions reached.*\r\n$gdb_prompt p$" {
+	    -re "$end\r\n$gdb_prompt p$" {
 		# Complete the command and ignore the output to resync
 		# gdb for the next test.
 		send_gdb "\n"
@@ -898,7 +902,8 @@ gdb_test_multiple "" "$test" {
     }
 }
 
-gdb_test_no_output "set max-completions 3"
+set max_completions 3
+gdb_test_no_output "set max-completions $max_completions"
 
 set test "symbol-name completion limiting using tab character"
 send_gdb "p marker\t"
@@ -906,7 +911,7 @@ gdb_test_multiple "" "$test" {
     -re "^p marker\\\x07$" {
 	send_gdb "\t"
 	gdb_test_multiple "" "$test" {
-	    -re "List may be truncated, max-completions reached.*\r\n$gdb_prompt p marker$" {
+	    -re "$end\r\n$gdb_prompt p marker$" {
 		# Complete the command and ignore the output to resync
 		# gdb for the next test.
 		send_gdb "\n"
@@ -933,11 +938,67 @@ gdb_test_multiple "" "$test" {
 set test "symbol-name completion limiting using complete command"
 send_gdb "complete p mark\n"
 gdb_test_multiple "" "$test" {
-    -re "List may be truncated, max-completions reached.*\r\n$gdb_prompt $" {
+    -re "$end\r\n$gdb_prompt $" {
 	pass "$test"
     }
 }
 
+# A convenience function for testing completion limiting.
+# CMD is a GDB command to to run with "complete".
+# PATTERN is a regexp pattern matching the expected output
+#   of completion items "seen" in the output.
+# NUM is the number of maximum completions expected.
+#
+# The test will use the test name "limit complete CMD"
+# and will only count the number of completion items matching
+# PATTERN.  No assumptions are made on the order of the items
+# seen in GDB's output.
+#
+# If NUM items are seen before the truncation message, the test
+# passes, otherwise it fails.  The test can also fail if no
+# truncation message is seen at all, in which case the test
+# failure message will say "(unlimited)".
+
+proc test_completion_limit {cmd pattern num} {
+    global gdb_prompt
+
+    # The terminal at the end of the complete command
+    set end "\\\*\\\*\\\* List may be truncated, "
+    append end "max-completions reached\\\. \\\*\\\*\\\*"
+
+    set cmdr [string_to_regexp $cmd]
+    set seen 0
+    gdb_test_multiple "complete $cmd" "limit complete $cmd" {
+	"complete $cmdr" { exp_continue }
+	-re "$pattern\r\n" {
+	    incr seen
+	    exp_continue
+	}
+	-re ".*$end\r\n$gdb_prompt $" {
+	    if {$seen == $num} {
+		pass "limit complete $cmd"
+	    } else {
+		fail "limit complete $cmd ($seen/$num)"
+	    }
+	}
+	-re ".*$gdb_prompt $" {
+	    fail "limit complete $cmd (unlimited)"
+	}
+    }
+}
+
+test_completion_limit "file ./gdb.base/jit-s" \
+    "file \\\./gdb\\\.base/jit-s(imple|olib|o)(\\\.c|\\\.exp)?" \
+    $max_completions
+
+# same as above but completing on directory names.
+test_completion_limit "file ./gdb.a" "file \\\./gdb\\\.a(da|rch|sm)" \
+    $max_completions
+
+#
+# Test TUI completions
+#
+
 gdb_test_no_output "set max-completions unlimited"
 
 if {![skip_tui_tests]} {

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v3 16/19] Implement completion limiting for tui_reggroup_completer.
  2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
                   ` (9 preceding siblings ...)
  2015-08-06 21:06 ` [PATCH v3 05/19] Implement completion limiting for ada_make_symbol_completion_list Keith Seitz
@ 2015-08-06 22:03 ` Keith Seitz
  2015-08-23  4:25   ` Doug Evans
  2015-08-06 22:03 ` [PATCH v3 07/19] Implement completion limiting for filename_completer Keith Seitz
                   ` (8 subsequent siblings)
  19 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-06 22:03 UTC (permalink / raw)
  To: gdb-patches

This is a new patch in the series.

--

This patch converts the (recently introduced) TUI register/group
completer, tui_reggroup_completer, to use add_completion.

gdb/ChangeLog

	* tui/tui-regs.c (tui_reggroup_completer): Use add_completion
	to add completions to the completion list.

gdb/testsuite/ChangeLog

	* completion.exp: Add a completion-limit test for "tui reg".
---
 gdb/testsuite/gdb.base/completion.exp |    5 +++++
 gdb/tui/tui-regs.c                    |    6 +++++-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/gdb/testsuite/gdb.base/completion.exp b/gdb/testsuite/gdb.base/completion.exp
index 1036af5..07ce660 100644
--- a/gdb/testsuite/gdb.base/completion.exp
+++ b/gdb/testsuite/gdb.base/completion.exp
@@ -1058,6 +1058,11 @@ if {$signal_to_use != ""} {
 test_completion_limit "print field_test_global.a" \
     "print field_test_global\\\.a\[1-9\]_field" $max_completions
 
+# Test TUI's reg completer
+if {![skip_tui_tests]} {
+    test_completion_limit "tui reg " "tui reg \[a-z\]+" $max_completions
+}
+
 #
 # Test TUI completions
 #
diff --git a/gdb/tui/tui-regs.c b/gdb/tui/tui-regs.c
index 756f598..17efd9f 100644
--- a/gdb/tui/tui-regs.c
+++ b/gdb/tui/tui-regs.c
@@ -683,7 +683,11 @@ tui_reggroup_completer (struct completer_data *cdata,
   for (tmp = extra; *tmp != NULL; ++tmp)
     {
       if (strncmp (word, *tmp, len) == 0)
-	VEC_safe_push (char_ptr, result, xstrdup (*tmp));
+	{
+	  if (add_completion (cdata, &result, *tmp, NULL, NULL)
+	      == ADD_COMPLETION_MAX_REACHED)
+	    break;
+	}
     }
 
   return result;

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v3 13/19] Implement completion limiting for complete_on_enum.
  2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
                   ` (11 preceding siblings ...)
  2015-08-06 22:03 ` [PATCH v3 07/19] Implement completion limiting for filename_completer Keith Seitz
@ 2015-08-06 22:03 ` Keith Seitz
  2015-08-23  4:19   ` Doug Evans
  2015-08-06 22:03 ` [PATCH v3 11/19] Implement completion limiting for reg_or_group_completer Keith Seitz
                   ` (6 subsequent siblings)
  19 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-06 22:03 UTC (permalink / raw)
  To: gdb-patches

Differences in this revision:

1. Remove partial copy code from complete_on_enum

---

This is another patch to push along the conversion of location_completer
toward using add_completion.  In this patch, complete_on_enum is
converted.  This function is also used by several other commands, such as
integer_unlimited_completer, handle_completer, cp_abi_completer, etc.

gdb/ChangeLog

	* cli/cli-decode.c (complete_on_enum): Use add_completion.

gdb/testsuite/ChangeLog

	* gdb.base/completion.exp: Add tests for complete_on_enum
	completion limiting using "handle signal".
---
 gdb/cli/cli-decode.c                  |   21 +++------------------
 gdb/testsuite/gdb.base/completion.exp |   12 ++++++++++++
 2 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index 3cecc90..fa95ee6 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -1834,24 +1834,9 @@ complete_on_enum (struct completer_data *cdata,
   for (i = 0; (name = enumlist[i]) != NULL; i++)
     if (strncmp (name, text, textlen) == 0)
       {
-	char *match;
-
-	match = (char *) xmalloc (strlen (word) + strlen (name) + 1);
-	if (word == text)
-	  strcpy (match, name);
-	else if (word > text)
-	  {
-	    /* Return some portion of name.  */
-	    strcpy (match, name + (word - text));
-	  }
-	else
-	  {
-	    /* Return some of text plus name.  */
-	    strncpy (match, word, text - word);
-	    match[text - word] = '\0';
-	    strcat (match, name);
-	  }
-	VEC_safe_push (char_ptr, matchlist, match);
+	if (add_completion (cdata, &matchlist, name, text, word)
+	    == ADD_COMPLETION_MAX_REACHED)
+	  break;
       }
 
   return matchlist;
diff --git a/gdb/testsuite/gdb.base/completion.exp b/gdb/testsuite/gdb.base/completion.exp
index 3f56a13..6c81505 100644
--- a/gdb/testsuite/gdb.base/completion.exp
+++ b/gdb/testsuite/gdb.base/completion.exp
@@ -1042,6 +1042,18 @@ with_test_prefix "interpreter_completer reset" {
 test_completion_limit "info registers " \
     "info registers \[a-zA-Z0-9\]+" $max_completions
 
+# Test complete_on_enum.
+set signal_to_use ""
+set signal_list [split \
+		     [capture_command_output "complete handle signal " ""] \
+		     \r\n]
+catch {lindex [split [lindex $signal_list 0]] 2} signal_to_use
+if {$signal_to_use != ""} {
+    test_completion_limit "handle signal $signal_to_use n" \
+	"handle signal $signal_to_use n\[a-z\]+" \
+	$max_completions
+}
+
 #
 # Test TUI completions
 #

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v3 08/19] Implement completion limiting for signal_completer.
  2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
                   ` (13 preceding siblings ...)
  2015-08-06 22:03 ` [PATCH v3 11/19] Implement completion limiting for reg_or_group_completer Keith Seitz
@ 2015-08-06 22:03 ` Keith Seitz
  2015-08-23  3:59   ` Doug Evans
  2015-08-06 22:12 ` [PATCH v3 14/19] Implement completion limiting in add_struct_fields Keith Seitz
                   ` (4 subsequent siblings)
  19 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-06 22:03 UTC (permalink / raw)
  To: gdb-patches

There are no revisions in this version.

---

This patch converts signal_completer to use add_completion
and adds some tests to cover this new behavior.

gdb/ChangeLog

	* completer.c (signal_completer): Use add_completion.

gdb/testsuite/ChangeLog

	* gdb.base/completion.exp: Add completion limiting tests
	for "handle signal".
---
 gdb/completer.c                       |    6 +++++-
 gdb/testsuite/gdb.base/completion.exp |   27 +++++++++++++++++++++++++++
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/gdb/completer.c b/gdb/completer.c
index 6aa8d35..bf85efe 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -1046,7 +1046,11 @@ signal_completer (struct completer_data *cdata,
 	continue;
 
       if (strncasecmp (signame, word, len) == 0)
-	VEC_safe_push (char_ptr, return_val, xstrdup (signame));
+	{
+	  if (add_completion (cdata, &return_val, signame, NULL, NULL)
+	      == ADD_COMPLETION_MAX_REACHED)
+	    break;
+	}
     }
 
   return return_val;
diff --git a/gdb/testsuite/gdb.base/completion.exp b/gdb/testsuite/gdb.base/completion.exp
index f0b7f2c..884b9f6 100644
--- a/gdb/testsuite/gdb.base/completion.exp
+++ b/gdb/testsuite/gdb.base/completion.exp
@@ -995,6 +995,33 @@ test_completion_limit "file ./gdb.base/jit-s" \
 test_completion_limit "file ./gdb.a" "file \\\./gdb\\\.a(da|rch|sm)" \
     $max_completions
 
+# Test completion limiting in signal_completer.
+with_test_prefix "signal_completer" {
+    gdb_test_no_output "set max-completions unlimited"
+    set num_signals 0
+    gdb_test_multiple "complete handle signal SIG10" "" {
+	"complete handle signal SIG10" { exp_continue }
+	-re "handle signal SIG10\[0-9\]\r\n" {
+	    incr num_signals
+	    exp_continue
+	}
+	-re "$gdb_prompt $" {
+	    pass "count available signals"
+	}
+    }
+
+    gdb_test_no_output "set max-completions $max_completions"
+}
+
+if {$num_signals > $max_completions} {
+    test_completion_limit "handle signal SIG10" \
+	"handle signal SIG10\[0-9\]" $max_completions
+} else {
+    set msg "insufficient signals to test completion "
+    append msg "limiting in signal_handler ($num_signals)"
+    untested $msg
+}
+
 #
 # Test TUI completions
 #

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v3 11/19] Implement completion limiting for reg_or_group_completer.
  2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
                   ` (12 preceding siblings ...)
  2015-08-06 22:03 ` [PATCH v3 13/19] Implement completion limiting for complete_on_enum Keith Seitz
@ 2015-08-06 22:03 ` Keith Seitz
  2015-08-23  4:09   ` Doug Evans
  2015-08-06 22:03 ` [PATCH v3 08/19] Implement completion limiting for signal_completer Keith Seitz
                   ` (5 subsequent siblings)
  19 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-06 22:03 UTC (permalink / raw)
  To: gdb-patches

There are no revisions in this version.

--

This patch converts reg_or_group_completer to use add_completion
and adds tests for this new behavior.

gdb/ChangeLog

	* completer.c (reg_or_group_completer): Use add_completion.

gdb/testsuite/ChangeLog

	* gdb.base/completion.exp: Add tests for limit completing
	"info reigsters".
---
 gdb/completer.c                       |   12 ++++++++++--
 gdb/testsuite/gdb.base/completion.exp |    4 ++++
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/gdb/completer.c b/gdb/completer.c
index bf85efe..7ede0f9 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -1092,7 +1092,11 @@ reg_or_group_completer_1 (struct completer_data *cdata,
 	   i++)
 	{
 	  if (*name != '\0' && strncmp (word, name, len) == 0)
-	    VEC_safe_push (char_ptr, result, xstrdup (name));
+	    {
+	      if (add_completion (cdata, &result, name, NULL, NULL)
+		  == ADD_COMPLETION_MAX_REACHED)
+		return result;
+	    }
 	}
     }
 
@@ -1106,7 +1110,11 @@ reg_or_group_completer_1 (struct completer_data *cdata,
 	{
 	  name = reggroup_name (group);
 	  if (strncmp (word, name, len) == 0)
-	    VEC_safe_push (char_ptr, result, xstrdup (name));
+	    {
+	      if (add_completion (cdata, &result, name, NULL, NULL)
+		  == ADD_COMPLETION_MAX_REACHED)
+		return result;
+	    }
 	}
     }
 
diff --git a/gdb/testsuite/gdb.base/completion.exp b/gdb/testsuite/gdb.base/completion.exp
index 41323d2..3f56a13 100644
--- a/gdb/testsuite/gdb.base/completion.exp
+++ b/gdb/testsuite/gdb.base/completion.exp
@@ -1038,6 +1038,10 @@ with_test_prefix "interpreter_completer reset" {
     gdb_test_no_output "set max-completions $max_completions"
 }
 
+# Test reg_or_group_completer.
+test_completion_limit "info registers " \
+    "info registers \[a-zA-Z0-9\]+" $max_completions
+
 #
 # Test TUI completions
 #

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v3 14/19] Implement completion limiting in add_struct_fields.
  2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
                   ` (14 preceding siblings ...)
  2015-08-06 22:03 ` [PATCH v3 08/19] Implement completion limiting for signal_completer Keith Seitz
@ 2015-08-06 22:12 ` Keith Seitz
  2015-08-23  4:23   ` Doug Evans
  2015-08-06 22:12 ` [PATCH v3 10/19] Implement completion limiting for cmdpy_completer Keith Seitz
                   ` (3 subsequent siblings)
  19 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-06 22:12 UTC (permalink / raw)
  To: gdb-patches

There are no revisions in this version.

---

This patch converts add_struct_fields (used by expression_completer) to use
add_completion and adds (coverage) tests for this new behavior.

break.exp contains two overly greedy regexp patterns which required
tweaking, too.

gdb/ChangeLog

	* completer.c (add_struct_fields): Use add_completion.

gdb/testsuite/ChangeLog

	* gdb.base/break.c (struct field_test): New structure.
	(field_test_global): New global variable.
	* gdb.base/break.exp: Add srcfile to otherwise too greedy regexp
	for tests "check disable with history value" and "check disable
	with convenience values".
	* gdb.base/completion.exp: Add completion limiting tests for
	add_struct_fields using the print command.
	* gdb.cp/cpcompletion.exp (test_completion_limit): New procedure.
	Add completion limiting tests for C++-specific parts of
	add_struct_fields using the print command.
	* gdb.cp/pr9694.cc (class Foo) <repeated1, repeated2, repeated3,
	repeated4, repeated5, repeated6, repeated7, repeated8>: New members.
	(Foo::Foo): Add initializer for new members.
	(main): Add new methods method1, method2, method3, method4, method5,
	method6, method7, and method8 to anonymous structure and make
	sure they are not optimized away.
---
 gdb/completer.c                       |   14 +++++++-
 gdb/testsuite/gdb.base/break.c        |   14 ++++++++
 gdb/testsuite/gdb.base/break.exp      |    4 +-
 gdb/testsuite/gdb.base/completion.exp |    4 ++
 gdb/testsuite/gdb.cp/cpcompletion.exp |   55 +++++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.cp/pr9594.cc        |   28 ++++++++++++++++-
 6 files changed, 113 insertions(+), 6 deletions(-)

diff --git a/gdb/completer.c b/gdb/completer.c
index 7ede0f9..134a3c2 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -373,8 +373,12 @@ add_struct_fields (struct completer_data *cdata,
 	    {
 	      if (! strncmp (TYPE_FIELD_NAME (type, i), 
 			     fieldname, namelen))
-		VEC_safe_push (char_ptr, *output,
-			       xstrdup (TYPE_FIELD_NAME (type, i)));
+		{
+		  if (add_completion (cdata, output, TYPE_FIELD_NAME (type, i),
+				      NULL, NULL)
+		      == ADD_COMPLETION_MAX_REACHED)
+		    return;
+		}
 	    }
 	  else if (TYPE_CODE (TYPE_FIELD_TYPE (type, i)) == TYPE_CODE_UNION)
 	    {
@@ -398,7 +402,11 @@ add_struct_fields (struct completer_data *cdata,
 	    }
 	  /* Omit constructors from the completion list.  */
 	  if (!type_name || strcmp (type_name, name))
-	    VEC_safe_push (char_ptr, *output, xstrdup (name));
+	    {
+	      if (add_completion (cdata, output, name, NULL, NULL)
+		  == ADD_COMPLETION_MAX_REACHED)
+		return;
+	    }
 	}
     }
 }
diff --git a/gdb/testsuite/gdb.base/break.c b/gdb/testsuite/gdb.base/break.c
index d017a91..8ee11b1 100644
--- a/gdb/testsuite/gdb.base/break.c
+++ b/gdb/testsuite/gdb.base/break.c
@@ -30,6 +30,20 @@ void *need_malloc ()
   return malloc (1);
 }
 
+/* A structure for testing add_struct_fields.  */
+struct field_test
+{
+  int a1_field;
+  int a2_field;
+  int a3_field;
+  int a4_field;
+  int a5_field;
+  int a6_field;
+  int a7_field;
+};
+
+struct field_test field_test_global = {1, 2, 3, 4, 5, 6, 7};
+
 /*
  *	This simple classical example of recursion is useful for
  *	testing stack backtraces and such.
diff --git a/gdb/testsuite/gdb.base/break.exp b/gdb/testsuite/gdb.base/break.exp
index f879bc8..5344533 100644
--- a/gdb/testsuite/gdb.base/break.exp
+++ b/gdb/testsuite/gdb.base/break.exp
@@ -249,7 +249,7 @@ set see5 0
 set see6 0
 
 gdb_test_multiple "info break" "check disable with history values" {
-    -re "1\[\t \]+breakpoint *keep y.* in main at .*:$main_line\[^\r\n\]*" {
+    -re "1\[\t \]+breakpoint *keep y.* at .*$srcfile:$main_line\[\r\n\]*" {
 	set see1 1
 	exp_continue
     }
@@ -295,7 +295,7 @@ set see5 0
 set see6 0
 
 gdb_test_multiple "info break" "check disable with convenience values" {
-    -re "1\[\t \]+breakpoint *keep y.* in main at .*:$main_line\[^\r\n\]*" {
+    -re "1\[\t \]+breakpoint *keep y.* in main at .*$srcfile:$main_line\[^\r\n\]*" {
 	set see1 1
 	exp_continue
     }
diff --git a/gdb/testsuite/gdb.base/completion.exp b/gdb/testsuite/gdb.base/completion.exp
index 6c81505..1036af5 100644
--- a/gdb/testsuite/gdb.base/completion.exp
+++ b/gdb/testsuite/gdb.base/completion.exp
@@ -1054,6 +1054,10 @@ if {$signal_to_use != ""} {
 	$max_completions
 }
 
+# Test add_struct_fields.
+test_completion_limit "print field_test_global.a" \
+    "print field_test_global\\\.a\[1-9\]_field" $max_completions
+
 #
 # Test TUI completions
 #
diff --git a/gdb/testsuite/gdb.cp/cpcompletion.exp b/gdb/testsuite/gdb.cp/cpcompletion.exp
index 023c261..a1bc6d8 100644
--- a/gdb/testsuite/gdb.cp/cpcompletion.exp
+++ b/gdb/testsuite/gdb.cp/cpcompletion.exp
@@ -85,3 +85,58 @@ gdb_test "complete p foo1.Fo" "p foo1\\.Foofoo"
 
 # Test completion with an anonymous struct.
 gdb_test "complete p a.g" "p a\\.get"
+
+# Test completion limiting (add_struct_fields)
+set max_completions 3
+gdb_test_no_output "set max-completions $max_completions"
+
+# A convenience function for testing completion limiting.
+# CMD is a GDB command to to run with "complete".
+# PATTERN is a regexp pattern matching the expected output
+#   of completion items "seen" in the output.
+# NUM is the number of maximum completions expected.
+#
+# The test will use the test name "limit complete CMD"
+# and will only count the number of completion items matching
+# PATTERN.  No assumptions are made on the order of the items
+# seen in GDB's output.
+#
+# If NUM items are seen before the truncation message, the test
+# passes, otherwise it fails.  The test can also fail if no
+# truncation message is seen at all, in which case the test
+# failure message will say "(unlimited)".
+
+proc test_completion_limit {cmd pattern num} {
+    global gdb_prompt
+
+    # The terminal at the end of the complete command
+    set end "\\\*\\\*\\\* List may be truncated, "
+    append end "max-completions reached\\\. \\\*\\\*\\\*"
+
+    set cmdr [string_to_regexp $cmd]
+    set seen 0
+    gdb_test_multiple "complete $cmd" "limit complete $cmd" {
+	"complete $cmdr" { exp_continue }
+	-re "$pattern\r\n" {
+	    incr seen
+	    exp_continue
+	}
+	-re ".*$end\r\n$gdb_prompt $" {
+	    if {$seen == $num} {
+		pass "limit complete $cmd"
+	    } else {
+		fail "limit complete $cmd ($seen/$num)"
+	    }
+	}
+	-re ".*$gdb_prompt $" {
+	    fail "limit complete $cmd (unlimited)"
+	}
+    }
+}
+
+# Completion limiting tests for add_struct_fields.
+test_completion_limit "print a.meth" "print a\\\.method\[1-8\]" \
+    $max_completions
+
+test_completion_limit "print foo1.repeat" \
+    "print foo1\\\.repeated\[1-8\]" $max_completions
diff --git a/gdb/testsuite/gdb.cp/pr9594.cc b/gdb/testsuite/gdb.cp/pr9594.cc
index 8fdee84..e4b49ce 100644
--- a/gdb/testsuite/gdb.cp/pr9594.cc
+++ b/gdb/testsuite/gdb.cp/pr9594.cc
@@ -11,9 +11,19 @@ class Foo : public Base
 
 private:
   int foo_value;
+  int repeated1;
+  int repeated2;
+  int repeated3;
+  int repeated4;
+  int repeated5;
+  int repeated6;
+  int repeated7;
+  int repeated8;
 
 public:
-  Foo () { foo_value = 0;}
+  Foo () : foo_value (0), repeated1 (1), repeated2 (2), repeated3 (3),
+	   repeated4 (4), repeated5 (5), repeated6 (6), repeated7 (7),
+	   repeated8 (8) {}
   Foo (int i) { foo_value = i;}
   ~Foo () { }
   void set_foo (int value);
@@ -44,9 +54,25 @@ int main ()
   // Anonymous struct with method.
   struct {
     int get() { return 5; }
+    int method1 (void) { return 1; }
+    int method2 (void) { return 2; }
+    int method3 (void) { return 3; }
+    int method4 (void) { return 4; }
+    int method5 (void) { return 5; }
+    int method6 (void) { return 6; }
+    int method7 (void) { return 7; }
+    int method8 (void) { return 8; }
   } a;
   Foo foo1;
   foo1.set_foo (42);		// Set breakpoint here.
   a.get();			// Prevent compiler from throwing 'a' away.
+  a.method1 ();
+  a.method2 ();
+  a.method3 ();
+  a.method4 ();
+  a.method5 ();
+  a.method6 ();
+  a.method7 ();
+  a.method8 ();
   return 0;
 }

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v3 10/19] Implement completion limiting for cmdpy_completer.
  2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
                   ` (15 preceding siblings ...)
  2015-08-06 22:12 ` [PATCH v3 14/19] Implement completion limiting in add_struct_fields Keith Seitz
@ 2015-08-06 22:12 ` Keith Seitz
  2015-08-23  4:07   ` Doug Evans
  2015-08-06 22:36 ` [PATCH v3 03/19] Implement completion-limiting for complete_on_cmdlist Keith Seitz
                   ` (2 subsequent siblings)
  19 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-06 22:12 UTC (permalink / raw)
  To: gdb-patches

Differences in this revision:

1. Free string memory after passing to add_completion.

---

This patch converts cmdpy_completer, used by commands written in
python.  It also adds tests for some untested python functionality
related to completion.

gdb/ChangeLog

	* python/py-cmd.c (cmdpy_completer) Use add_completion.
	Free memory associated with `item'.

gdb/testsuite/ChangeLog

	* gdb.python/py-completion.exp: Test completion functions,
	with and without completion limiting.
---
 gdb/python/py-cmd.c                        |    9 +++++-
 gdb/testsuite/gdb.python/py-completion.exp |   45 ++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
index 21d842e..36e352e 100644
--- a/gdb/python/py-cmd.c
+++ b/gdb/python/py-cmd.c
@@ -392,7 +392,14 @@ cmdpy_completer (struct completer_data *cdata,
 	      PyErr_Clear ();
 	      continue;
 	    }
-	  VEC_safe_push (char_ptr, result, item);
+
+	  if (add_completion (cdata, &result, item, NULL, NULL)
+	      == ADD_COMPLETION_MAX_REACHED)
+	    {
+	      xfree (item);
+	      break;
+	    }
+	  xfree (item);
 	}
 
       Py_DECREF (iter);
diff --git a/gdb/testsuite/gdb.python/py-completion.exp b/gdb/testsuite/gdb.python/py-completion.exp
index 5e45087..f7f23a3 100644
--- a/gdb/testsuite/gdb.python/py-completion.exp
+++ b/gdb/testsuite/gdb.python/py-completion.exp
@@ -128,3 +128,48 @@ if {[readline_is_used]} {
 	    "completelimit2 cl29"
 	}
 }
+
+# The terminal at the end of the complete command
+set end "\\\*\\\*\\\* List may be truncated, "
+append end "max-completions reached\\\. \\\*\\\*\\\*"
+
+set max_completions 3
+gdb_test_no_output "set max-completions $max_completions"
+set seen 0
+
+set testname "limit completions of 'complete completel'"
+gdb_test_multiple "complete completel" $testname {
+    "complete completel" { exp_continue }
+
+    -re "completelimit\[1-9\]+\r\n" {
+	incr seen
+	exp_continue
+    }
+
+    -re "completel $end\r\n$gdb_prompt $" {
+	if {$seen == $max_completions} {
+	    pass $testname
+	} else {
+	    fail "$testname ($seen/$max_completions)"
+	}
+    }
+}
+
+set testname "limit completions of 'complete completelimit1 c'"
+set seen 0
+gdb_test_multiple "complete completelimit1 c" $testname {
+    "complete completelimit1 c" { exp_continue }
+
+    -re "completelimit1 cl1\[1-9\]+\r\n" {
+	incr seen
+	exp_continue
+    }
+
+    -re "completelimit1 c $end\r\n$gdb_prompt $" {
+	if {$seen == $max_completions} {
+	    pass $testname
+	} else {
+	    fail "$testname ($seen/$max_completions)"
+	}
+    }
+}

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v3 03/19] Implement completion-limiting for complete_on_cmdlist.
  2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
                   ` (16 preceding siblings ...)
  2015-08-06 22:12 ` [PATCH v3 10/19] Implement completion limiting for cmdpy_completer Keith Seitz
@ 2015-08-06 22:36 ` Keith Seitz
  2015-08-23  1:05   ` Doug Evans
  2015-08-07  2:37 ` [PATCH v3 15/19] Implement completion limiting for scmcmd_add_completion Keith Seitz
  2015-08-07 22:57 ` [PATCH v3 00/19] New completer API Andrew Burgess
  19 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-06 22:36 UTC (permalink / raw)
  To: gdb-patches

Differences in this revision:

1. Remove partial copy code from complete_on_cmdlist.

---

This is the first of a series of smaller patches to switch over
all completion functions to using add_completion to add
completions to the completion list to be presented to the user.

Note that in order to verify that this patch works as intended,
one must override the backup completion counting in complete_line.
[This backup code will be permanently removed in a later patch.]
During testing, I have verified all patches with this planned code
removal to verify that it works.

First up is complete_on_cmdlist.  Completion-limiting is already tested
in gdb.base/completion.exp, so there are no new tests.

gdb/ChangeLog

	* cli/cli-decode.c (complete_on_cmdlist): Use add_completion
	to determine whether to continue looking for completions.
---
 gdb/cli/cli-decode.c |   21 +++------------------
 1 file changed, 3 insertions(+), 18 deletions(-)

diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index 3415b77..3cecc90 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -1789,8 +1789,6 @@ complete_on_cmdlist (struct completer_data *cdata,
 	    && (!ignore_help_classes || ptr->func
 		|| ptr->prefixlist))
 	  {
-	    char *match;
-
 	    if (pass == 0)
 	      {
 		if (ptr->cmd_deprecated)
@@ -1800,22 +1798,9 @@ complete_on_cmdlist (struct completer_data *cdata,
 		  }
 	      }
 
-	    match = (char *) xmalloc (strlen (word) + strlen (ptr->name) + 1);
-	    if (word == text)
-	      strcpy (match, ptr->name);
-	    else if (word > text)
-	      {
-		/* Return some portion of ptr->name.  */
-		strcpy (match, ptr->name + (word - text));
-	      }
-	    else
-	      {
-		/* Return some of text plus ptr->name.  */
-		strncpy (match, word, text - word);
-		match[text - word] = '\0';
-		strcat (match, ptr->name);
-	      }
-	    VEC_safe_push (char_ptr, matchlist, match);
+	    if (add_completion (cdata, &matchlist, ptr->name, text, word)
+		== ADD_COMPLETION_MAX_REACHED)
+	      return matchlist;
 	  }
       /* If we saw no matching deprecated commands in the first pass,
 	 just bail out.  */

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v3 15/19] Implement completion limiting for scmcmd_add_completion.
  2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
                   ` (17 preceding siblings ...)
  2015-08-06 22:36 ` [PATCH v3 03/19] Implement completion-limiting for complete_on_cmdlist Keith Seitz
@ 2015-08-07  2:37 ` Keith Seitz
  2015-08-23  4:24   ` Doug Evans
  2015-08-07 22:57 ` [PATCH v3 00/19] New completer API Andrew Burgess
  19 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-07  2:37 UTC (permalink / raw)
  To: gdb-patches

Differences in this revision:

1. Free string memory after passing to add_completion.

---

This patch converts scmcmd_add_completion to use add_completion and
adds some tests for this new behavior.

gdb/ChangeLog

	* guile/scm-cmd.c (cmdscm_add_completion): Add completer_data
	argument.  All callers updated.
	Use add_completion.
	Free memory associated with `item'.

gdb/testsuite/ChangeLog

	* gdb.guile/scm-cmd.exp: Add completion limiting tests.
---
 gdb/guile/scm-cmd.c                 |   11 ++++++-----
 gdb/testsuite/gdb.guile/scm-cmd.exp |   24 ++++++++++++++++++++++++
 2 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/gdb/guile/scm-cmd.c b/gdb/guile/scm-cmd.c
index 58c79c8..1544c2b 100644
--- a/gdb/guile/scm-cmd.c
+++ b/gdb/guile/scm-cmd.c
@@ -348,7 +348,8 @@ cmdscm_bad_completion_result (const char *msg, SCM completion)
    The result is a boolean indicating success.  */
 
 static int
-cmdscm_add_completion (SCM completion, VEC (char_ptr) **result)
+cmdscm_add_completion (SCM completion, struct completer_data *cdata,
+		       VEC (char_ptr) **result)
 {
   char *item;
   SCM except_scm;
@@ -370,8 +371,8 @@ cmdscm_add_completion (SCM completion, VEC (char_ptr) **result)
       return 0;
     }
 
-  VEC_safe_push (char_ptr, *result, item);
-
+  (void) add_completion (cdata, result, item, NULL, NULL);
+  xfree (item);
   return 1;
 }
 
@@ -418,7 +419,7 @@ cmdscm_completer (struct completer_data *cdata,
 	{
 	  SCM next = scm_car (list);
 
-	  if (!cmdscm_add_completion (next, &result))
+	  if (!cmdscm_add_completion (next, cdata, &result))
 	    {
 	      VEC_free (char_ptr, result);
 	      goto done;
@@ -442,7 +443,7 @@ cmdscm_completer (struct completer_data *cdata,
 	      goto done;
 	    }
 
-	  if (!cmdscm_add_completion (next, &result))
+	  if (!cmdscm_add_completion (next, cdata, &result))
 	    {
 	      VEC_free (char_ptr, result);
 	      goto done;
diff --git a/gdb/testsuite/gdb.guile/scm-cmd.exp b/gdb/testsuite/gdb.guile/scm-cmd.exp
index 53c0fdf..ac721c3 100644
--- a/gdb/testsuite/gdb.guile/scm-cmd.exp
+++ b/gdb/testsuite/gdb.guile/scm-cmd.exp
@@ -196,6 +196,30 @@ gdb_test "test-scheme-error-cmd ugh" \
     "Error occurred in Scheme-implemented GDB command." \
     "call scheme-error command"
 
+# Test completion limiting.
+set max_completions 2
+gdb_test_no_output "set max-completions $max_completions"
+set end "\\\*\\\*\\\* List may be truncated, "
+append end "max-completions reached\\\. \\\*\\\*\\\*"
+set test "limit complete completer-as-function 42\."
+gdb_test_multiple "complete completer-as-function 42\." $test {
+    "complete completer-as-function 42\\\." { exp_continue }
+    -re "completer-as-function 42\\\.\[1-3\]\r\n" {
+	incr seen
+	exp_continue
+    }
+    -re ".*$end\r\n$gdb_prompt $" {
+	if {$seen == $max_completions} {
+	    pass $test
+	} else {
+	    fail "$test ($seen/$max_completions)"
+	}
+    }
+    -re ".*$gdb_prompt $" {
+	fail "$test (unlimited)"
+    }
+}
+
 # If there is a problem with object management, this can often trigger it.
 # It is useful to do this last, after we've created a bunch of command objects.
 

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v3 00/19] New completer API
@ 2015-08-07  2:37 Keith Seitz
  2015-08-06 19:18 ` [PATCH v3 09/19] Implement completion limiting for interpreter_completer Keith Seitz
                   ` (19 more replies)
  0 siblings, 20 replies; 45+ messages in thread
From: Keith Seitz @ 2015-08-07  2:37 UTC (permalink / raw)
  To: gdb-patches

This series (v3) of patches contains numerous little fixes, plus two major
additions:

1) Since v2, new TUI completion functions have been introduced. These have
   been updated/converted to the new API.
2) Many completion functions used to do a "partial copy" of the matching
   text.  This oft-repeated code has been removed from all the completion
   functions and incorporated internally to the API.

---

Currently completer functions are not required to implement completion-
limiting.  These functions will compute all possible completions and then
rely on complete_line to limit the result.

The main goal of this patchset is to require completer functions to
implement proper completion-limiting using maybe_add_completion.  This
actually cleans up the completer API significantly and fixes at least one
serious bug (an assertion failure, gdb/17960).

The new API requires all completions to be added to the completion
list using maybe_add_completion:

void
my_completer_function (struct completer_data *cdata,
                       struct cmd_list_element *cmd,
                       const char *text, const char *word)
{
    while (/* there are more completions to look for */)
    {
      char *match = xstrdup (a_completion_match);

      if (add_completion (cdata, match, text /* or NULL */,
                          word /* or NULL */))
          == ADD_COMPLETION_MAX_REACHED)
	return;
    }
}

All patches have been regression tested for buildbot.

---

Keith Seitz (19):
      Add struct completer_data to the completion API.
      Remove completion_tracker_t from the public completion API.
      Implement completion-limiting for complete_on_cmdlist.
      Implement completion limiting for add_filename_to_list.
      Implement completion limiting for ada_make_symbol_completion_list.
      Implement completion limiting for condition_completer.
      Implement completion limiting for filename_completer.
      Implement completion limiting for signal_completer.
      Implement completion limiting for interpreter_completer.
      Implement completion limiting for cmdpy_completer.
      Implement completion limiting for reg_or_group_completer.
      Implement completion limiting for sim_command_completer.
      Implement completion limiting for complete_on_enum.
      Implement completion limiting in add_struct_fields.
      Implement completion limiting for scmcmd_add_completion.
      Implement completion limiting for tui_reggroup_completer.
      Make the completion API completely opaque.
      Use the hashtable to accumulate completion results.
      Remove the vector return result from the completion API.


 gdb/ada-lang.c                             |   85 ++--
 gdb/break-catch-syscall.c                  |   11 -
 gdb/breakpoint.c                           |   22 +
 gdb/cli/cli-cmds.c                         |    4 
 gdb/cli/cli-decode.c                       |   75 +---
 gdb/command.h                              |   17 +
 gdb/completer.c                            |  537 +++++++++++++++++-----------
 gdb/completer.h                            |  115 +++---
 gdb/corefile.c                             |    7 
 gdb/cp-abi.c                               |    7 
 gdb/f-lang.c                               |    8 
 gdb/guile/scm-cmd.c                        |   34 +-
 gdb/infrun.c                               |   15 -
 gdb/interps.c                              |   29 --
 gdb/language.h                             |    8 
 gdb/python/py-cmd.c                        |   29 +-
 gdb/remote-sim.c                           |   18 +
 gdb/symtab.c                               |  304 ++++++----------
 gdb/symtab.h                               |   47 +-
 gdb/testsuite/gdb.ada/complete.exp         |  144 +++++++-
 gdb/testsuite/gdb.ada/complete/foo.adb     |    4 
 gdb/testsuite/gdb.ada/complete/pck.ads     |   12 +
 gdb/testsuite/gdb.base/break.c             |   14 +
 gdb/testsuite/gdb.base/break.exp           |    4 
 gdb/testsuite/gdb.base/completion.exp      |  215 +++++++++++
 gdb/testsuite/gdb.base/condbreak.exp       |   70 ++++
 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 +
 gdb/testsuite/gdb.cp/cpcompletion.exp      |   55 +++
 gdb/testsuite/gdb.cp/pr9594.cc             |   28 +
 gdb/testsuite/gdb.guile/scm-cmd.exp        |   24 +
 gdb/testsuite/gdb.python/py-completion.exp |   45 ++
 gdb/tui/tui-layout.c                       |    7 
 gdb/tui/tui-regs.c                         |   16 -
 gdb/tui/tui-win.c                          |   28 +
 gdb/value.c                                |   14 -
 gdb/value.h                                |    3 
 41 files changed, 1496 insertions(+), 741 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

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 00/19] New completer API
  2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
                   ` (18 preceding siblings ...)
  2015-08-07  2:37 ` [PATCH v3 15/19] Implement completion limiting for scmcmd_add_completion Keith Seitz
@ 2015-08-07 22:57 ` Andrew Burgess
  2015-08-08  0:04   ` Keith Seitz
  19 siblings, 1 reply; 45+ messages in thread
From: Andrew Burgess @ 2015-08-07 22:57 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

* Keith Seitz <keiths@redhat.com> [2015-08-06 12:14:29 -0700]:

> Currently completer functions are not required to implement completion-
> limiting.  These functions will compute all possible completions and then
> rely on complete_line to limit the result.
> 
> The main goal of this patchset is to require completer functions to
> implement proper completion-limiting using maybe_add_completion.  This
> actually cleans up the completer API significantly and fixes at least one
> serious bug (an assertion failure, gdb/17960).
> 
> The new API requires all completions to be added to the completion
> list using maybe_add_completion:

I think that the above text is out of date w.r.t. the example below,
in the above you talk about maybe_add_completion, but in the example
below you use the add_completion wrapper.  A small detail and
unimportant detail; unless I'm missing something, in which case
... I'm confused!

> void
> my_completer_function (struct completer_data *cdata,
>                        struct cmd_list_element *cmd,
>                        const char *text, const char *word)
> {
>     while (/* there are more completions to look for */)
>     {
>       char *match = xstrdup (a_completion_match);
> 
>       if (add_completion (cdata, match, text /* or NULL */,
>                           word /* or NULL */))
>           == ADD_COMPLETION_MAX_REACHED)
> 	return;
>     }
> }

This pattern of calling add_completion and comparing to
ADD_COMPLETION_MAX_REACHED is repeated throughout the patch set.

I wonder, looking at add_completion, do users _care_ about the reason?
Of all the possible return codes from add_completion, I think we can
classify them as either "stop trying to add completions please", or
"feel free to add more completions".

Could the add_completion interface be simplified to simply return a
bool, true if more completions can be added, false if not?

Just a thought.

Thanks,
Andrew

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 00/19] New completer API
  2015-08-07 22:57 ` [PATCH v3 00/19] New completer API Andrew Burgess
@ 2015-08-08  0:04   ` Keith Seitz
  2015-08-08  6:44     ` Andrew Burgess
  0 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-08  0:04 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

On 08/07/2015 03:56 PM, Andrew Burgess wrote:
> I think that the above text is out of date w.r.t. the example below,
> in the above you talk about maybe_add_completion, but in the example
> below you use the add_completion wrapper.  A small detail and
> unimportant detail; unless I'm missing something, in which case
> ... I'm confused!
> 

Yup, you're right. s/maybe_add_completion/add_completion/g.

> I wonder, looking at add_completion, do users _care_ about the reason?

Users? No. Developers? Yes. add_completion either returns ..._OK,
meaning that more completions may be added. ..._MAX_REACHED meaning that
no more completions should be added (but will just waste cycles).

The return value does not indicate whether the addition was successful.
Just whether more may be added.

> Of all the possible return codes from add_completion, I think we can
> classify them as either "stop trying to add completions please", or
> "feel free to add more completions".

Yup.

> Could the add_completion interface be simplified to simply return a
> bool, true if more completions can be added, false if not?

I don't like boolean return values in this case. Forget knowing what
happens under the covers (or now that you've read the proposed API).
Just by reading "bool add_completion (struct completer_data *, const
char *);" can you tell what the boolean return value means?

My first reading of that would be "the addition was successfully
completed," but that's not what it means in this specific case, because
the return value indicates something entirely different.

But now I wonder if I am missing something. Is defining an enum going to
choke some compiler? Does it violate, or is it ambiguous in, the
language? Or is it simply a matter of style?

Keith

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 00/19] New completer API
  2015-08-08  0:04   ` Keith Seitz
@ 2015-08-08  6:44     ` Andrew Burgess
  2015-08-08 16:25       ` Keith Seitz
  0 siblings, 1 reply; 45+ messages in thread
From: Andrew Burgess @ 2015-08-08  6:44 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

* Keith Seitz <keiths@redhat.com> [2015-08-07 17:04:08 -0700]:

> On 08/07/2015 03:56 PM, Andrew Burgess wrote:
> > I think that the above text is out of date w.r.t. the example below,
> > in the above you talk about maybe_add_completion, but in the example
> > below you use the add_completion wrapper.  A small detail and
> > unimportant detail; unless I'm missing something, in which case
> > ... I'm confused!
> > 
> 
> Yup, you're right. s/maybe_add_completion/add_completion/g.
> 
> > I wonder, looking at add_completion, do users _care_ about the reason?
> 
> Users? No. Developers? Yes. add_completion either returns ..._OK,

Sorry, I should have said "users of the API".

> I don't like boolean return values in this case. Forget knowing what
> happens under the covers (or now that you've read the proposed API).
> Just by reading "bool add_completion (struct completer_data *, const
> char *);" can you tell what the boolean return value means?

No. But you could rename to
add_completion_then_should_more_completions_be_added (he jokes)
(though maybe add_completion_and_continue would work?).  But
I would have just assumed a good comment was enough.

> My first reading of that would be "the addition was successfully
> completed," but that's not what it means in this specific case, because
> the return value indicates something entirely different.

I agree with that point.

> But now I wonder if I am missing something. Is defining an enum going to
> choke some compiler? Does it violate, or is it ambiguous in, the
> language? Or is it simply a matter of style?

My response was certainly _not_ on any technical grounds, simply a
matter of style.  As a general rule when I see every use of a
function be:

   function_call (args) == SAME_VALUE

I tend to think, can't we just push the comparison (effectively) up
into the function_call.

Anyway, it was just a passing thought based on a mild interest in this
code, having recently touched it, I don't think it's a big issue.

Thanks
Andrew

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 00/19] New completer API
  2015-08-08  6:44     ` Andrew Burgess
@ 2015-08-08 16:25       ` Keith Seitz
  2015-08-22 22:25         ` Doug Evans
  0 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2015-08-08 16:25 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

On 08/07/2015 11:44 PM, Andrew Burgess wrote:
>> I don't like boolean return values in this case. Forget knowing what
>> happens under the covers (or now that you've read the proposed API).
>> Just by reading "bool add_completion (struct completer_data *, const
>> char *);" can you tell what the boolean return value means?
> 
> No. But you could rename to
> add_completion_then_should_more_completions_be_added (he jokes)
> (though maybe add_completion_and_continue would work?).  But
> I would have just assumed a good comment was enough.

I'll have to try and sneak something like that past Doug on some other
series. :-)

>> But now I wonder if I am missing something. Is defining an enum going to
>> choke some compiler? Does it violate, or is it ambiguous in, the
>> language? Or is it simply a matter of style?
> 
> My response was certainly _not_ on any technical grounds, simply a
> matter of style.  As a general rule when I see every use of a
> function be:
> 
>    function_call (args) == SAME_VALUE
> 
> I tend to think, can't we just push the comparison (effectively) up
> into the function_call.

That's a valid point. Thank you for reminding me of that. With large
patches like this (with multiple revisions), I can sometimes not see the
proverbial forest, or I forget it's even there.

> Anyway, it was just a passing thought based on a mild interest in this
> code, having recently touched it, I don't think it's a big issue.

I appreciate your comments. Keep 'em coming!

Keith

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 00/19] New completer API
  2015-08-08 16:25       ` Keith Seitz
@ 2015-08-22 22:25         ` Doug Evans
  0 siblings, 0 replies; 45+ messages in thread
From: Doug Evans @ 2015-08-22 22:25 UTC (permalink / raw)
  To: Keith Seitz; +Cc: Andrew Burgess, gdb-patches

Keith Seitz <keiths@redhat.com> writes:
> On 08/07/2015 11:44 PM, Andrew Burgess wrote:
>>> I don't like boolean return values in this case. Forget knowing what
>>> happens under the covers (or now that you've read the proposed API).
>>> Just by reading "bool add_completion (struct completer_data *, const
>>> char *);" can you tell what the boolean return value means?
>> 
>> No. But you could rename to
>> add_completion_then_should_more_completions_be_added (he jokes)
>> (though maybe add_completion_and_continue would work?).  But
>> I would have just assumed a good comment was enough.
>
> I'll have to try and sneak something like that past Doug on some other
> series. :-)

Heh. :-)

fyi, reviewing this patchset is one of my projects for this weekend.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 01/19] Add struct completer_data to the completion API.
  2015-08-06 20:03 ` [PATCH v3 01/19] Add struct completer_data to the completion API Keith Seitz
@ 2015-08-23  0:29   ` Doug Evans
  0 siblings, 0 replies; 45+ messages in thread
From: Doug Evans @ 2015-08-23  0:29 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

Keith Seitz <keiths@redhat.com> writes:
> Differences in this revision:
>
> 1. Updated new completer[-related] functions reg_or_group_completer_1,
>    reg_or_group_completer, layout_completer, tui_reggroup_completer,
>    window_name_completer, focus_completer, and winheight_completer.
>
> ---
>
> This patch is largely mechanical.  It modifies the completion API so
> that all completion functions take a new (pointer to a) structure,
> which will (eventually) be used internally by the completer to perform
> completion limiting.
>
> gdb/ChangeLog
>
> 	* completer.c (struct completer_data): Define.
> 	* language.h (struct language_defn)
> 	<la_make_symbol_completion_list>: Add struct completer_data
> 	to argument list.
> 	All users updated.
> 	* symtab.c (COMPLETION_LIST_ADD_SYMBOL): Add CDATA argument.
> 	Update all callers.
> 	(MCOMPLETION_LIST_ADD_SYMBOL): Likewise.
> 	(struct add_name_data) <completer_data>: New field.
> 	(default_make_symbol_completion_list_break_on_1): Initialize
> 	the above new field.
> 	(struct add_partial_filename_data) <completer_data>: New field.
> 	(make_source_files_completion_list): Initialize the above new
> 	field.

LGTM.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 02/19] Remove completion_tracker_t from the public completion API.
  2015-08-06 19:58 ` [PATCH v3 02/19] Remove completion_tracker_t from the public completion API Keith Seitz
@ 2015-08-23  1:02   ` Doug Evans
  2015-08-24 16:06     ` Doug Evans
  0 siblings, 1 reply; 45+ messages in thread
From: Doug Evans @ 2015-08-23  1:02 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

Keith Seitz <keiths@redhat.com> writes:
> Differences from last version:
>
> 1. Removed comments about recording an additional completion from
>    add_completion.
> 2. Removed requirement to xstrdup arg to add_completion; add_completeion
>     uses new function completer_strdup.
> 3. Consolidated (oft-repeated) partial copy code into completer_strdup.
>    Removed this code from all completion functions.
>
> ---
>
> This patch removes the recently introduced "completion tracker" concept
> from the public completion API.  In the previous patch, the completion
> tracker was added to the (new) completer_data structure that is now
> used by all completion functions.
>
> Since completion_tracker_t is now used entirely inside completer.c, there
> is no need to make its type opaque, so the typedef has been removed.
>
> This patch also fixes gdb/17960, which is easily demonstrated:
>
> $ gdb -nx -q gdb
> (gdb) b gdb.c:ma<TAB>
> ./../src/gdb/completer.c:837: internal-error: maybe_add_completion:
> Assertion `tracker != NULL' failed.
> A problem internal to GDB has been detected,
> further debugging may prove unreliable.
> Quit this debugging session? (y or n)
>
> This occurs because the code path in this case is:
> complete_line
> - complete_line_internal
> -- location_completer
>
> gdb/ChangeLog
>
> 	PR gdb/17960
> 	* completer.c (struct completer_data) <tracker>: Change type to
> 	htab_t.
> 	(enum maybe_add_completion_enum): Make private; moved from
> 	completer.h.
> 	[DEFAULT_MAX_COMPLETIONS]: Define.
> 	(new_completion_tracker): Remove function.
> 	(new_completer_data): New function.
> 	(free_completion_tracker): Remove function.
> 	(free_completer_data): New function.
> 	(make_cleanup_free_completion_tracker): Remove function.
> 	(maybe_add_completion): Make static.  Update comments.
> 	Use completer_data instead of completion_tracker_t.
> 	(completer_strdup): New function.
> 	(add_completion): New function.
> 	(complete_line, gdb_completion_word_break_characters): Use
> 	completer_data instead of completion_tracker.
> 	* completer.h (completion_tracker_t, new_completion_tracker)
> 	(make_cleanup_free_completion_tracker, maybe_add_completion)
> 	(enum maybe_add_completion): Remove declarations.
> 	(enum add_completion_status): Define.
> 	(add_completion): Declare.
> 	* symtab.c (completion_tracker): Remove variable.
> 	(completion_list_add_name): Use add_completion instead of
> 	maybe_add_completion and partial copy.
> 	(default_make_symbol_completion_list_break_on_1): Do not use
> 	completion_tracker.
>
> gdb/testsuite/ChangeLog
>
> 	PR gdb/17960
> 	* gdb.base/completion.exp: Add some basic tests for the
> 	location completer, including a regression test for
> 	the gdb/17960 assertion failure.

Hi.
A few nits, grep for ^====.

> ---
>  gdb/completer.c                       |  231 +++++++++++++++++++++++----------
>  gdb/completer.h                       |   66 +++------
>  gdb/symtab.c                          |   62 +--------
>  gdb/testsuite/gdb.base/completion.exp |   78 +++++++++++
>  4 files changed, 260 insertions(+), 177 deletions(-)
>
> diff --git a/gdb/completer.c b/gdb/completer.c
> index 476f9f2..bf4137e 100644
> --- a/gdb/completer.c
> +++ b/gdb/completer.c
> @@ -92,10 +92,31 @@ static char *gdb_completer_quote_characters = "'";
>  
>  struct completer_data
>  {
> -  /* The completion tracker being used by the completer.  */
> -  completion_tracker_t tracker;
> +  /* A hashtable used to track completions.  */
> +  htab_t tracker;
>  };
>  
> +/* Return values for maybe_add_completion.  */
> +
> +enum maybe_add_completion_enum
> +{
> +  /* NAME has been recorded and max_completions has not been reached,
> +     or completion tracking is disabled (max_completions < 0).  */
> +  MAYBE_ADD_COMPLETION_OK,
> +
> +  /* NAME has been recorded and max_completions has been reached
> +     (thus the caller can stop searching).  */
> +  MAYBE_ADD_COMPLETION_OK_MAX_REACHED,
> +
> +  /* max-completions entries has been reached.
> +     Whether NAME is a duplicate or not is not determined.  */
> +  MAYBE_ADD_COMPLETION_MAX_REACHED,
> +
> +  /* NAME has already been recorded.
> +     Note that this is never returned if completion tracking is disabled
> +     (max_completions < 0).  */
> +  MAYBE_ADD_COMPLETION_DUPLICATE
> +};
>  \f
>  /* Accessor for some completer data that may interest other files.  */
>  
> @@ -803,48 +824,41 @@ complete_line_internal (struct completer_data *cdata,
>  
>  /* See completer.h.  */
>  
> -int max_completions = 200;
> +#define DEFAULT_MAX_COMPLETIONS 200
> +int max_completions = DEFAULT_MAX_COMPLETIONS;
>  
> -/* See completer.h.  */
> +/* Allocate a new completer data structure.  */
>  
> -completion_tracker_t
> -new_completion_tracker (void)
> +static struct completer_data *
> +new_completer_data (int size)
>  {
> -  if (max_completions <= 0)
> -    return NULL;
> +  struct completer_data *cdata = XCNEW (struct completer_data);
>  
> -  return htab_create_alloc (max_completions,
> -			    htab_hash_string, (htab_eq) streq,
> -			    NULL, xcalloc, xfree);
> +  cdata->tracker
> +    = htab_create_alloc ((size < 0 ? DEFAULT_MAX_COMPLETIONS : size),
> +			 htab_hash_string, (htab_eq) streq, NULL,

====
One can argue the cast makes things fragile (however slightly).
I'm slightly ambivalent on the point, but I do lean towards removing
the cast and having a wrapper function for streq so the cast isn't
needed.  Let's do the latter.
[IWBN if hashtab itself provided one, but that's another patch for
another day.]
 
I'm also slightly ambivalent on creating the hash table if
max_completions is disabled (<= 0), and leaning towards not creating it
to avoid potential confusion.
Let's do the latter (pending reading the rest of the patchset - maybe
there's a good reason to always create it).

> +			 xcalloc, xfree);
> +  return cdata;
>  }
>  
> -/* Cleanup routine to free a completion tracker and reset the pointer
> -   to NULL.  */
> +/* Free the completion data represented by P.  */
>  
>  static void
> -free_completion_tracker (void *p)
> +free_completer_data (void *p)
>  {
> -  completion_tracker_t *tracker_ptr = p;
> +  struct completer_data *cdata = p;
>  
> -  htab_delete (*tracker_ptr);
> -  *tracker_ptr = NULL;
> +  htab_delete (cdata->tracker);
> +  xfree (cdata);
>  }
>  
> -/* See completer.h.  */
> -
> -struct cleanup *
> -make_cleanup_free_completion_tracker (completion_tracker_t *tracker_ptr)
> -{
> -  if (*tracker_ptr == NULL)
> -    return make_cleanup (null_cleanup, NULL);
> -
> -  return make_cleanup (free_completion_tracker, tracker_ptr);
> -}
> -
> -/* See completer.h.  */
> +/* Add the completion NAME to the list of generated completions if
> +   it is not there already.
> +   If max_completions is negative, nothing is done, not even watching
> +   for duplicates, and MAYBE_ADD_COMPLETION_OK is always returned.  */
>  
> -enum maybe_add_completion_enum
> -maybe_add_completion (completion_tracker_t tracker, char *name)
> +static enum maybe_add_completion_enum
> +maybe_add_completion (struct completer_data *cdata, char *name)
>  {
>    void **slot;
>  
> @@ -853,23 +867,82 @@ maybe_add_completion (completion_tracker_t tracker, char *name)
>    if (max_completions == 0)
>      return MAYBE_ADD_COMPLETION_MAX_REACHED;
>  
> -  gdb_assert (tracker != NULL);

====
Let's keep this assert (assuming we're going with not creating the
hashtab if we don't have to, i.e., if max_completions <= 0).

> -
> -  if (htab_elements (tracker) >= max_completions)
> +  if (htab_elements (cdata->tracker) >= max_completions)
>      return MAYBE_ADD_COMPLETION_MAX_REACHED;
>  
> -  slot = htab_find_slot (tracker, name, INSERT);
> +  slot = htab_find_slot (cdata->tracker, name, INSERT);
>  
>    if (*slot != HTAB_EMPTY_ENTRY)
>      return MAYBE_ADD_COMPLETION_DUPLICATE;
>  
>    *slot = name;
>  
> -  return (htab_elements (tracker) < max_completions
> +  return (htab_elements (cdata->tracker) < max_completions
>  	  ? MAYBE_ADD_COMPLETION_OK
>  	  : MAYBE_ADD_COMPLETION_OK_MAX_REACHED);
>  }
>  
> +/* A strdup-like function used by the completer to copy bits of completion
> +   strings.  */
> +
> +static char *
> +completer_strdup (const char *match, const char *text, const char *word)
> +{
> +  char *alloc;
> +
> +  if (text == NULL || word == NULL || text == word)
> +    return xstrdup (match);
> +
> +  if (word > text)
> +    {
> +      gdb_assert (strlen (match) > (word - text));
> +
> +      /* Return some portion of match.  */
> +      match += (word - text);
> +      alloc = xmalloc (strlen (match) + 1);
> +      strcpy (alloc, match);

====
This can still use xstrdup (right?).

> +    }
> +  else
> +    {
> +      /* Return some of text plus match.  */
> +      alloc = xmalloc (strlen (match) + (text - word) + 1);
> +      strncpy (alloc, word, text - word);
> +      alloc[text - word] = '\0';
> +      strcat (alloc, match);
> +    }
> +
> +  return alloc;
> +}

====
I didn't review this function too closely to confirm it's correct.
I'm going to assume it is for the moment.
IWBN to have a description of each parameter in the function comment.
I realize the terms match,text,word have very specific meanings
in this file. Just a WBN.

> +
> +/* See completer.h.  */
> +
> +enum add_completion_status
> +add_completion (struct completer_data *cdata, VEC (char_ptr) **result,
> +		const char *match, const char *text, const char *word)
> +{
> +  enum maybe_add_completion_enum add_status;
> +  char *alloc = completer_strdup (match, text, word);
> +
> +  add_status = maybe_add_completion (cdata, alloc);
> +  switch (add_status)
> +    {
> +    case MAYBE_ADD_COMPLETION_OK:
> +      VEC_safe_push (char_ptr, *result, alloc);
> +      break;
> +    case MAYBE_ADD_COMPLETION_OK_MAX_REACHED:
> +      VEC_safe_push (char_ptr, *result, alloc);
> +      return ADD_COMPLETION_MAX_REACHED;
> +    case MAYBE_ADD_COMPLETION_MAX_REACHED:
> +      xfree (alloc);
> +      return ADD_COMPLETION_MAX_REACHED;
> +    case MAYBE_ADD_COMPLETION_DUPLICATE:
> +      xfree (alloc);
> +      break;
> +    }
> +
> +  return ADD_COMPLETION_OK;
> +}
> +
>  void
>  throw_max_completions_reached_error (void)
>  {
> @@ -894,54 +967,63 @@ complete_line (const char *text, const char *line_buffer, int point)
>  {
>    VEC (char_ptr) *list;
>    VEC (char_ptr) *result = NULL;
> -  struct cleanup *cleanups;
> -  completion_tracker_t tracker;
> +  struct cleanup *cdata_cleanup, *list_cleanup;
>    char *candidate;
> -  int ix, max_reached;
> +  int ix;
> +  struct completer_data *cdata;
>  
>    if (max_completions == 0)
>      return NULL;
> -  list = complete_line_internal (NULL, text, line_buffer, point,
> +
> +  cdata = new_completer_data (max_completions);
> +  cdata_cleanup = make_cleanup (free_completer_data, cdata);
> +  list = complete_line_internal (cdata, text, line_buffer, point,
>  				 handle_completions);
>    if (max_completions < 0)
> -    return list;
> -
> -  tracker = new_completion_tracker ();
> -  cleanups = make_cleanup_free_completion_tracker (&tracker);
> -  make_cleanup_free_char_ptr_vec (list);
> -
> -  /* Do a final test for too many completions.  Individual completers may
> -     do some of this, but are not required to.  Duplicates are also removed
> -     here.  Otherwise the user is left scratching his/her head: readline and
> -     complete_command will remove duplicates, and if removal of duplicates
> -     there brings the total under max_completions the user may think gdb quit
> -     searching too early.  */
> -
> -  for (ix = 0, max_reached = 0;
> -       !max_reached && VEC_iterate (char_ptr, list, ix, candidate);
> -       ++ix)
>      {
> -      enum maybe_add_completion_enum add_status;
> +      do_cleanups (cdata_cleanup);
> +      return list;
> +    }
> +
> +  list_cleanup = make_cleanup_free_char_ptr_vec (list);
>  
> -      add_status = maybe_add_completion (tracker, candidate);
> +  /* If complete_line_internal returned more completions than were
> +     recorded by the completion tracker, then the completer function that
> +     was run does not support completion tracking.  In this case,
> +     do a final test for too many completions.
>  
> -      switch (add_status)
> +     Duplicates are also removed here.  Otherwise the user is left
> +     scratching his/her head: readline and complete_command will remove
> +     duplicates, and if removal of duplicates there brings the total under
> +     max_completions the user may think gdb quit searching too early.  */
> +
> +  if (VEC_length (char_ptr, list) > htab_elements (cdata->tracker))
> +    {
> +      enum add_completion_status max_reached = ADD_COMPLETION_OK;
> +
> +      /* Clear the tracker so that we can re-use it to count the number
> +	 of returned completions.  */
> +      htab_empty (cdata->tracker);
> +
> +      for (ix = 0; (max_reached == ADD_COMPLETION_OK
> +		    && VEC_iterate (char_ptr, list, ix, candidate)); ++ix)
>  	{
> -	  case MAYBE_ADD_COMPLETION_OK:
> -	    VEC_safe_push (char_ptr, result, xstrdup (candidate));
> -	    break;
> -	  case MAYBE_ADD_COMPLETION_OK_MAX_REACHED:
> -	    VEC_safe_push (char_ptr, result, xstrdup (candidate));
> -	    max_reached = 1;
> -	    break;
> -      	  case MAYBE_ADD_COMPLETION_MAX_REACHED:
> -	    gdb_assert_not_reached ("more than max completions reached");
> -	  case MAYBE_ADD_COMPLETION_DUPLICATE:
> -	    break;
> +	  max_reached = add_completion (cdata, &result, candidate, NULL, NULL);
>  	}
> +
> +      /* The return result has been assembled and the original list from
> +	 complete_line_internal is no longer needed.  Free it.  */
> +      do_cleanups (list_cleanup);
> +    }
> +  else
> +    {
> +      /* There is a valid tracker for the completion -- simply return
> +	 the completed list.  */
> +      discard_cleanups (list_cleanup);
> +      result = list;
>      }
>  
> -  do_cleanups (cleanups);
> +  do_cleanups (cdata_cleanup);
>  
>    return result;
>  }
> @@ -1074,9 +1156,14 @@ char *
>  gdb_completion_word_break_characters (void)
>  {
>    VEC (char_ptr) *list;
> +  struct completer_data *cdata;
> +  struct cleanup *cleanup;
>  
> -  list = complete_line_internal (NULL, rl_line_buffer, rl_line_buffer,
> +  cdata = new_completer_data (max_completions);
> +  cleanup = make_cleanup (free_completer_data, cdata);
> +  list = complete_line_internal (cdata, rl_line_buffer, rl_line_buffer,
>  				 rl_point, handle_brkchars);
> +  do_cleanups (cleanup);
>    gdb_assert (list == NULL);
>    return rl_completer_word_break_characters;
>  }
> diff --git a/gdb/completer.h b/gdb/completer.h
> index 7139c0a..43d1321 100644
> --- a/gdb/completer.h
> +++ b/gdb/completer.h
> @@ -132,59 +132,31 @@ extern const char *skip_quoted (const char *);
>  
>  extern int max_completions;
>  
> -/* Object to track how many unique completions have been generated.
> -   Used to limit the size of generated completion lists.  */
> +/* Return values for add_completion.  */
>  
> -typedef htab_t completion_tracker_t;
> -
> -/* Create a new completion tracker.
> -   The result is a hash table to track added completions, or NULL
> -   if max_completions <= 0.  If max_completions < 0, tracking is disabled.
> -   If max_completions == 0, the max is indeed zero.  */
> -
> -extern completion_tracker_t new_completion_tracker (void);
> -
> -/* Make a cleanup to free a completion tracker, and reset its pointer
> -   to NULL.  */
> -
> -extern struct cleanup *make_cleanup_free_completion_tracker
> -		      (completion_tracker_t *tracker_ptr);
> -
> -/* Return values for maybe_add_completion.  */
> -
> -enum maybe_add_completion_enum
> +enum add_completion_status
>  {
> -  /* NAME has been recorded and max_completions has not been reached,
> -     or completion tracking is disabled (max_completions < 0).  */
> -  MAYBE_ADD_COMPLETION_OK,
> -
> -  /* NAME has been recorded and max_completions has been reached
> -     (thus the caller can stop searching).  */
> -  MAYBE_ADD_COMPLETION_OK_MAX_REACHED,
> -
> -  /* max-completions entries has been reached.
> -     Whether NAME is a duplicate or not is not determined.  */
> -  MAYBE_ADD_COMPLETION_MAX_REACHED,
> -
> -  /* NAME has already been recorded.
> -     Note that this is never returned if completion tracking is disabled
> -     (max_completions < 0).  */
> -  MAYBE_ADD_COMPLETION_DUPLICATE
> +  /* Completion was added -- keep looking for more.  */
> +  ADD_COMPLETION_OK,
> +
> +  /* Maximum number of completions has been reached or the maximum
> +     has already been reached by a previous call to add_completion.
> +     Callers can make no assumptions about whether the completion was
> +     added or not.  */
> +  ADD_COMPLETION_MAX_REACHED
>  };
>  
> -/* Add the completion NAME to the list of generated completions if
> -   it is not there already.
> -   If max_completions is negative, nothing is done, not even watching
> -   for duplicates, and MAYBE_ADD_COMPLETION_OK is always returned.
> +/* Add the given MATCH to the completer result in CDATA.
> +   Returns one of the above enum add_completion_status codes to indicate
> +   whether the caller should continue to look for/compute more completions.
>  
> -   If MAYBE_ADD_COMPLETION_MAX_REACHED is returned, callers are required to
> -   record at least one more completion.  The final list will be pruned to
> -   max_completions, but recording at least one more than max_completions is
> -   the signal to the completion machinery that too many completions were
> -   found.  */
> +   If TEXT and WORD are non-NULL, then portions of the strings will be
> +   saved into the completion list.  See completer_strdup for more.  */
>  
> -extern enum maybe_add_completion_enum
> -  maybe_add_completion (completion_tracker_t tracker, char *name);
> +extern enum add_completion_status
> +  add_completion (struct completer_data *cdata,
> +		  VEC (char_ptr) **result, const char *match,
> +		  const char *text, const char *word);
>  
>  /* Wrapper to throw MAX_COMPLETIONS_REACHED_ERROR.  */ 
>  
> diff --git a/gdb/symtab.c b/gdb/symtab.c
> index f4407a0..34eb6d7 100644
> --- a/gdb/symtab.c
> +++ b/gdb/symtab.c
> @@ -5046,15 +5046,6 @@ static VEC (char_ptr) *return_val;
>    completion_list_add_name						\
>    (cdata, MSYMBOL_NATURAL_NAME (symbol), (sym_text), (len), (text), (word))
>  
> -/* Tracker for how many unique completions have been generated.  Used
> -   to terminate completion list generation early if the list has grown
> -   to a size so large as to be useless.  This helps avoid GDB seeming
> -   to lock up in the event the user requests to complete on something
> -   vague that necessitates the time consuming expansion of many symbol
> -   tables.  */
> -
> -static completion_tracker_t completion_tracker;
> -
>  /*  Test to see if the symbol specified by SYMNAME (which is already
>     demangled for C++ symbols) matches SYM_TEXT in the first SYM_TEXT_LEN
>     characters.  If so, add it to the current completion list.  */
> @@ -5070,50 +5061,11 @@ completion_list_add_name (struct completer_data *cdata,
>      return;
>  
>    /* We have a match for a completion, so add SYMNAME to the current list
> -     of matches.  Note that the name is moved to freshly malloc'd space.  */
> -
> -  {
> -    char *newobj;
> -    enum maybe_add_completion_enum add_status;
> -
> -    if (word == sym_text)
> -      {
> -	newobj = xmalloc (strlen (symname) + 5);
> -	strcpy (newobj, symname);
> -      }
> -    else if (word > sym_text)
> -      {
> -	/* Return some portion of symname.  */
> -	newobj = xmalloc (strlen (symname) + 5);
> -	strcpy (newobj, symname + (word - sym_text));
> -      }
> -    else
> -      {
> -	/* Return some of SYM_TEXT plus symname.  */
> -	newobj = xmalloc (strlen (symname) + (sym_text - word) + 5);
> -	strncpy (newobj, word, sym_text - word);
> -	newobj[sym_text - word] = '\0';
> -	strcat (newobj, symname);
> -      }
> -
> -    add_status = maybe_add_completion (completion_tracker, newobj);
> +     of matches.  */
>  
> -    switch (add_status)
> -      {
> -      case MAYBE_ADD_COMPLETION_OK:
> -	VEC_safe_push (char_ptr, return_val, newobj);
> -	break;
> -      case MAYBE_ADD_COMPLETION_OK_MAX_REACHED:
> -	VEC_safe_push (char_ptr, return_val, newobj);
> -	throw_max_completions_reached_error ();
> -      case MAYBE_ADD_COMPLETION_MAX_REACHED:
> -	xfree (newobj);
> -	throw_max_completions_reached_error ();
> -      case MAYBE_ADD_COMPLETION_DUPLICATE:
> -	xfree (newobj);
> -	break;
> -      }
> -  }
> +    if (add_completion (cdata, &return_val, symname, sym_text, word)
> +	== ADD_COMPLETION_MAX_REACHED)
> +      throw_max_completions_reached_error ();
>  }
>  
>  /* ObjC: In case we are completing on a selector, look as the msymbol
> @@ -5358,7 +5310,6 @@ default_make_symbol_completion_list_break_on_1 (struct completer_data *cdata,
>    /* Length of sym_text.  */
>    int sym_text_len;
>    struct add_name_data datum;
> -  struct cleanup *cleanups;
>  
>    /* Now look for the symbol we are supposed to complete on.  */
>    {
> @@ -5429,9 +5380,6 @@ default_make_symbol_completion_list_break_on_1 (struct completer_data *cdata,
>      }
>    gdb_assert (sym_text[sym_text_len] == '\0' || sym_text[sym_text_len] == '(');
>  
> -  completion_tracker = new_completion_tracker ();
> -  cleanups = make_cleanup_free_completion_tracker (&completion_tracker);
> -
>    datum.sym_text = sym_text;
>    datum.sym_text_len = sym_text_len;
>    datum.text = text;
> @@ -5549,8 +5497,6 @@ default_make_symbol_completion_list_break_on_1 (struct completer_data *cdata,
>        /* User-defined macros are always visible.  */
>        macro_for_each (macro_user_macros, add_macro_name, &datum);
>      }
> -
> -  do_cleanups (cleanups);
>  }
>  
>  VEC (char_ptr) *
> diff --git a/gdb/testsuite/gdb.base/completion.exp b/gdb/testsuite/gdb.base/completion.exp
> index 1eb0fd8..710aac0 100644
> --- a/gdb/testsuite/gdb.base/completion.exp
> +++ b/gdb/testsuite/gdb.base/completion.exp
> @@ -777,6 +777,84 @@ gdb_test_multiple "" "$test" {
>  }
>  
>  #
> +# Tests for the location completer
> +#
> +
> +# Turn off pending breakpoint support so that we don't get queried
> +# all the time.
> +gdb_test_no_output "set breakpoint pending off"
> +
> +set subsrc [string range $srcfile 0 [expr {[string length $srcfile] - 3}]]
> +set test "tab complete break $subsrc"
> +send_gdb "break $subsrc\t\t"
> +gdb_test_multiple "" $test {
> +    -re "break\.c.*break1\.c.*$gdb_prompt " {
> +	send_gdb "1\t\n"
> +	gdb_test_multiple "" $test {
> +	    -re ".*Function \"$srcfile2\" not defined\..*$gdb_prompt " {
> +		pass $test
> +	    }
> +	    -re "$gdb_prompt p$" {
> +		fail $test
> +	    }
> +	}
> +    }
> +
> +    -re "$gdb_prompt p$" {
> +	fail $test
> +    }
> +}
> +
> +gdb_test "complete break $subsrc" "break\.c.*break1\.c"
> +
> +# gdb/17960
> +set test "tab complete break $srcfile:ma"
> +send_gdb "break $srcfile:ma\t"
> +gdb_test_multiple "" $test {
> +    -re "break $srcfile:main " {
> +	send_gdb "\n"
> +	gdb_test_multiple "" $test {
> +	    -re ".*Breakpoint.*at .*/$srcfile, line .*$gdb_prompt " {
> +		pass $test
> +		gdb_test_no_output "delete breakpoint \$bpnum" \
> +		    "delete breakpoint for $test"
> +	    }
> +	    -re "$gdb_prompt p$" {
> +		fail $test
> +	    }
> +	}
> +    }
> +    -re "$gdb_prompt p$" {
> +	fail $test
> +    }
> +}
> +
> +gdb_test "complete break $srcfile:ma" "break\.c:main"
> +
> +set test "tab complete break need"
> +send_gdb "break need\t"
> +gdb_test_multiple "" $test {
> +    -re "break need_malloc " {
> +	send_gdb "\n"
> +	gdb_test_multiple "" $test {
> +	    -re ".*Breakpoint.*at .*/$srcfile, line .*$gdb_prompt " {
> +		pass $test
> +		gdb_test_no_output "delete breakpoint \$bpnum" \
> +		    "delete breakpoint for $test"
> +	    }
> +	    -re "$gdb_prompt p$" {
> +		fail $test
> +	    }
> +	}
> +    }
> +    -re "$gdb_prompt p$" {
> +	fail $test
> +    }
> +}
> +
> +gdb_test "complete break need" "need_malloc"
> +
> +#
>  # Completion limiting.
>  #
>  

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 03/19] Implement completion-limiting for complete_on_cmdlist.
  2015-08-06 22:36 ` [PATCH v3 03/19] Implement completion-limiting for complete_on_cmdlist Keith Seitz
@ 2015-08-23  1:05   ` Doug Evans
  0 siblings, 0 replies; 45+ messages in thread
From: Doug Evans @ 2015-08-23  1:05 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

Keith Seitz <keiths@redhat.com> writes:
> Differences in this revision:
>
> 1. Remove partial copy code from complete_on_cmdlist.
>
> ---
>
> This is the first of a series of smaller patches to switch over
> all completion functions to using add_completion to add
> completions to the completion list to be presented to the user.
>
> Note that in order to verify that this patch works as intended,
> one must override the backup completion counting in complete_line.
> [This backup code will be permanently removed in a later patch.]
> During testing, I have verified all patches with this planned code
> removal to verify that it works.
>
> First up is complete_on_cmdlist.  Completion-limiting is already tested
> in gdb.base/completion.exp, so there are no new tests.
>
> gdb/ChangeLog
>
> 	* cli/cli-decode.c (complete_on_cmdlist): Use add_completion
> 	to determine whether to continue looking for completions.

LGTM

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 04/19] Implement completion limiting for add_filename_to_list.
  2015-08-06 19:58 ` [PATCH v3 04/19] Implement completion limiting for add_filename_to_list Keith Seitz
@ 2015-08-23  1:07   ` Doug Evans
  0 siblings, 0 replies; 45+ messages in thread
From: Doug Evans @ 2015-08-23  1:07 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

Keith Seitz <keiths@redhat.com> writes:
> Differences in this revision:
>
> 1. Remove partial copy code from add_filename_to_list.
>
> ---
>
> 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 and
> 	update all callers.
> 	Use add_completion.
>
> 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.

LGTM

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 05/19] Implement completion limiting for ada_make_symbol_completion_list.
  2015-08-06 21:06 ` [PATCH v3 05/19] Implement completion limiting for ada_make_symbol_completion_list Keith Seitz
@ 2015-08-23  3:47   ` Doug Evans
  0 siblings, 0 replies; 45+ messages in thread
From: Doug Evans @ 2015-08-23  3:47 UTC (permalink / raw)
  To: Keith Seitz, brobecker; +Cc: gdb-patches

Keith Seitz <keiths@redhat.com> writes:
> Differences in this revision:
>
> 1. Remove partial copy code from symbol_completion_add.
>
> ---
>
> This patch converts the one Ada completion(-related) function,
> symbol_completion_add, to use maybe_add_completion, and tests have
> been added to exercise this newly implemented behavior.
>
> gdb/ChangeLog
>
> 	* ada-lang.c (symbol_completion_add): Return
> 	add_completion_status instead of void.
> 	Use add_completion and return the status of this function.
> 	(ada_make_symbol_completion_list): If symbol_completion_add
> 	returns that maximum completions have been reached, stop
> 	looking for completions and return the list.
>
> gdb/testsuite/ChangeLog
>
> 	* gdb.ada/complete.exp (limit_multi_line): New procedure.
> 	Update existing tests for source changes.
> 	Add additional tests for new types.
> 	Add tests for completion limiting.
> 	* gdb.ada/complete/foo.adb (Repeat_Variable_1, Repeat_Variable_2,
> 	Repeat_Variable_3, Repeat_Variable_4): Define.
> 	* gdb.ada/complete/pck.ads (Repeat_Variable_1, Repeat_Variable_2)
> 	(Repeat_Variable_3, Repeat_Variable_4): Declare.
> 	(Repeated_1, Repeated_2, Repeated_3, Repeated_4): Define.

LGTM.
I didn't study the ada tests too closely,
but they seemed ok.
Adding Joel to the To list as a "heads up".

> diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
> index 9782b69..5df08be 100644
> --- a/gdb/ada-lang.c
> +++ b/gdb/ada-lang.c
> @@ -6198,8 +6198,9 @@ symbol_completion_match (const char *sym_name,
>     encoded formed (in which case the completion should also be
>     encoded).  */
>  
> -static void
> +static enum add_completion_status
>  symbol_completion_add (VEC(char_ptr) **sv,
> +		       struct completer_data *cdata,
>                         const char *sym_name,
>                         const char *text, int text_len,
>                         const char *orig_text, const char *word,
> @@ -6207,35 +6208,12 @@ symbol_completion_add (VEC(char_ptr) **sv,
>  {
>    const char *match = symbol_completion_match (sym_name, text, text_len,
>                                                 wild_match_p, encoded_p);
> -  char *completion;
> -
>    if (match == NULL)
> -    return;
> +    return ADD_COMPLETION_OK;
>  
>    /* We found a match, so add the appropriate completion to the given
>       string vector.  */
> -
> -  if (word == orig_text)
> -    {
> -      completion = xmalloc (strlen (match) + 5);
> -      strcpy (completion, match);
> -    }
> -  else if (word > orig_text)
> -    {
> -      /* Return some portion of sym_name.  */
> -      completion = xmalloc (strlen (match) + 5);
> -      strcpy (completion, match + (word - orig_text));
> -    }
> -  else
> -    {
> -      /* Return some of ORIG_TEXT plus sym_name.  */
> -      completion = xmalloc (strlen (match) + (orig_text - word) + 5);
> -      strncpy (completion, word, orig_text - word);
> -      completion[orig_text - word] = '\0';
> -      strcat (completion, match);
> -    }
> -
> -  VEC_safe_push (char_ptr, *sv, completion);
> +  return add_completion (cdata, sv, match, orig_text, word);
>  }
>  
>  /* An object of this type is passed as the user_data argument to the
> @@ -6283,6 +6261,7 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
>    int i;
>    struct block_iterator iter;
>    struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
> +  enum add_completion_status status;
>  
>    gdb_assert (code == TYPE_CODE_UNDEF);
>  
> @@ -6333,9 +6312,15 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
>    ALL_MSYMBOLS (objfile, msymbol)
>    {
>      QUIT;
> -    symbol_completion_add (&completions, MSYMBOL_LINKAGE_NAME (msymbol),
> -			   text, text_len, text0, word, wild_match_p,
> -			   encoded_p);
> +    status = symbol_completion_add (&completions, cdata,
> +					 MSYMBOL_LINKAGE_NAME (msymbol),
> +					 text, text_len, text0, word,
> +					 wild_match_p, encoded_p);
> +    if (status == ADD_COMPLETION_MAX_REACHED)
> +      {
> +	do_cleanups (old_chain);
> +	return completions;
> +      }
>    }
>  
>    /* Search upwards from currently selected frame (so that we can
> @@ -6348,9 +6333,15 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
>  
>        ALL_BLOCK_SYMBOLS (b, iter, sym)
>        {
> -        symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (sym),
> -                               text, text_len, text0, word,
> -                               wild_match_p, encoded_p);
> +        status = symbol_completion_add (&completions, cdata,
> +					     SYMBOL_LINKAGE_NAME (sym),
> +					     text, text_len, text0, word,
> +					     wild_match_p, encoded_p);
> +	if (status == ADD_COMPLETION_MAX_REACHED)
> +	  {
> +	    do_cleanups (old_chain);
> +	    return completions;
> +	  }
>        }
>      }
>  
> @@ -6363,9 +6354,15 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
>      b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (s), GLOBAL_BLOCK);
>      ALL_BLOCK_SYMBOLS (b, iter, sym)
>      {
> -      symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (sym),
> -                             text, text_len, text0, word,
> -                             wild_match_p, encoded_p);
> +      status = symbol_completion_add (&completions, cdata,
> +					   SYMBOL_LINKAGE_NAME (sym),
> +					   text, text_len, text0, word,
> +					   wild_match_p, encoded_p);
> +      if (status == ADD_COMPLETION_MAX_REACHED)
> +	{
> +	  do_cleanups (old_chain);
> +	  return completions;
> +	}
>      }
>    }
>  
> @@ -6378,9 +6375,15 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
>        continue;
>      ALL_BLOCK_SYMBOLS (b, iter, sym)
>      {
> -      symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (sym),
> -                             text, text_len, text0, word,
> -                             wild_match_p, encoded_p);
> +      status = symbol_completion_add (&completions, cdata,
> +					   SYMBOL_LINKAGE_NAME (sym),
> +					   text, text_len, text0, word,
> +					   wild_match_p, encoded_p);
> +      if (status == ADD_COMPLETION_MAX_REACHED)
> +	{
> +	  do_cleanups (old_chain);
> +	  return completions;
> +	}
>      }
>    }
>  
> diff --git a/gdb/testsuite/gdb.ada/complete.exp b/gdb/testsuite/gdb.ada/complete.exp
> index 9919bdf..b4efc68 100644
> --- a/gdb/testsuite/gdb.ada/complete.exp
> +++ b/gdb/testsuite/gdb.ada/complete.exp
> @@ -44,6 +44,29 @@ proc test_gdb_no_completion { expr } {
>      gdb_test_no_output "complete p $expr"
>  }
>  
> +# A convenience function that joins all the arguments together,
> +# with a regexp that matches zero-or-more end of lines in between
> +# each argument.  This function is ideal to write the expected output
> +# of a GDB command that generates more than a couple of lines, as
> +# this allows us to write each line as a separate string, which is
> +# easier to read by a human being.
> +
> +proc multi_line { args } {
> +    return [join $args "\[\r\n\]*"]
> +}
> +
> +# Like multi_line above, but limiting the return result to MAX
> +# elements and adding the completer's truncation message.
> +
> +proc limit_multi_line { max args } {
> +    set result [join [lrange $args 0 [expr {$max - 1}]] "\[\r\n\]*"]
> +    if {$max <= [llength $args]} {
> +	append result ".*\\\*\\\*\\\* List may be truncated, "
> +	append result "max-completions reached\\\. \\\*\\\*\\\*"
> +    }
> +    return $result
> +}
> +
>  # Try a global variable, only one match should be found:
>  
>  test_gdb_complete "my_glob" \
> @@ -145,7 +168,11 @@ test_gdb_complete "pck" \
>                                "p pck.local_identical_one" \
>                                "p pck.local_identical_two" \
>                                "p pck.my_global_variable" \
> -                              "p pck.proc" ]
> +                              "p pck.proc" \
> +                              "p pck.repeat_variable_1" \
> +                              "p pck.repeat_variable_2" \
> +                              "p pck.repeat_variable_3" \
> +                              "p pck.repeat_variable_4" ]
>  
>  # Complete on the name of a package followed by a dot:
>  test_gdb_complete "pck." \
> @@ -156,12 +183,125 @@ test_gdb_complete "pck." \
>                                "p pck.local_identical_one" \
>                                "p pck.local_identical_two" \
>                                "p pck.my_global_variable" \
> -                              "p pck.proc" ]
> +                              "p pck.proc" \
> +                              "p pck.repeat_variable_1" \
> +                              "p pck.repeat_variable_2" \
> +                              "p pck.repeat_variable_3" \
> +                              "p pck.repeat_variable_4" ]
> +
> +# Complete on a repeated global name:
> +test_gdb_complete "repeat_" \
> +                 [multi_line "p repeat_variable_1" \
> +                             "p repeat_variable_2" \
> +                             "p repeat_variable_3" \
> +                             "p repeat_variable_4" ]
> +
> +# Complete a mangled symbol name, but using the '<...>' notation:
> +test_gdb_complete "<pck__repeat_" \
> +                  [multi_line "p <pck__repeat_variable_1>" \
> +                              "p <pck__repeat_variable_2>" \
> +                              "p <pck__repeat_variable_3>" \
> +                              "p <pck__repeat_variable_4>" ]
> +
> +# Complete on repeated mangled name, using '<...>' notation:
> +test_gdb_complete "<Repeated_" \
> +                  [multi_line "p <Repeated_1>" \
> +                              "p <Repeated_2>" \
> +                              "p <Repeated_3>" \
> +                              "p <Repeated_4>" ]
>  
>  # Complete a mangled symbol name, but using the '<...>' notation.
>  test_gdb_complete "<pck__my" \
>                    "p <pck__my_global_variable>"
>  
> +# Test completion limiting.
> +set max_completions 2
> +gdb_test_no_output "set max-completions $max_completions"
> +with_test_prefix "limit completion" {
> +    # Two matches, from the global scope:
> +    test_gdb_complete "local_ident" \
> +	[limit_multi_line $max_completions \
> +	     "p local_identical_one" \
> +	     "p local_identical_two" ]
> +
> +    # Two matches, from the global scope, but using fully qualified names:
> +    test_gdb_complete "pck.local_ident" \
> +	[limit_multi_line $max_completions "p pck.local_identical_one" \
> +	     "p pck.local_identical_two" ]
> +
> +    # Two matches, from the global scope, but using mangled fully qualified
> +    # names:
> +    test_gdb_complete "pck__local_ident" \
> +	[limit_multi_line $max_completions \
> +	     "p pck__local_identical_one" \
> +	     "p pck__local_identical_two" ]
> +
> +    # Two matches, one from the global scope, the other from the local
> +    # scope:
> +    test_gdb_complete "external_ident" \
> +	[limit_multi_line $max_completions \
> +	     "p external_identical_one" \
> +	     "p external_identical_two" ]
> +
> +    # Complete on the name of package.
> +    test_gdb_complete "pck" \
> +	[limit_multi_line $max_completions \
> +	     "(p pck\\.ad\[sb\])?" \
> +	     "(p pck\\.ad\[sb\])?" \
> +	     "p pck.external_identical_one" \
> +	     "p pck.inner.inside_variable" \
> +	     "p pck.local_identical_one" \
> +	     "p pck.local_identical_two" \
> +	     "p pck.my_global_variable" \
> +	     "p pck.proc" \
> +	     "p pck.repeat_variable_1" \
> +	     "p pck.repeat_variable_2" \
> +	     "p pck.repeat_variable_3" \
> +	     "p pck.repeat_variable_4" ]
> +
> +    # Complete on the name of a package followed by a dot:
> +    test_gdb_complete "pck." \
> +	[limit_multi_line $max_completions \
> +	     "(p pck\\.ad\[sb\])?" \
> +	     "(p pck\\.ad\[sb\])?" \
> +	     "p pck.external_identical_one" \
> +	     "p pck.inner.inside_variable" \
> +	     "p pck.local_identical_one" \
> +	     "p pck.local_identical_two" \
> +	     "p pck.my_global_variable" \
> +	     "p pck.proc" \
> +	     "p pck.repeat_variable_1" \
> +	     "p pck.repeat_variable_2" \
> +	     "p pck.repeat_variable_3" \
> +	     "p pck.repeat_variable_4"]
> +
> +    # Complete on a repeated global name:
> +    test_gdb_complete "repeat_" \
> +	[limit_multi_line $max_completions \
> +	     "p repeat_variable_1" \
> +	     "p repeat_variable_2" \
> +	     "p repeat_variable_3" \
> +	     "p repeat_variable_4" ]
> +    # Complete a mangled symbol name, but using the '<...>' notation:
> +    test_gdb_complete "<pck__repeat_" \
> +	[limit_multi_line $max_completions \
> +	     "p <pck__repeat_variable_1>" \
> +	     "p <pck__repeat_variable_2>" \
> +	     "p <pck__repeat_variable_3>" \
> +	     "p <pck__repeat_variable_4>" ]
> +
> +    # Complete on repeated mangled name, using '<...>' notation:
> +    test_gdb_complete "<Repeated_" \
> +	[limit_multi_line $max_completions \
> +	     "p <Repeated_1>" \
> +	     "p <Repeated_2>" \
> +	     "p <Repeated_3>" \
> +	     "p <Repeated_4>" ]
> +}
> +
> +# Reset completion-limiting to its default.
> +gdb_test_no_output "set max-completions 200"
> +
>  # Very simple completion, but using the interactive form, this time.
>  # The verification we are trying to make involves the event loop,
>  # and using the "complete" command is not sufficient to reproduce
> diff --git a/gdb/testsuite/gdb.ada/complete/foo.adb b/gdb/testsuite/gdb.ada/complete/foo.adb
> index 58d0ee3..ad6b5ec 100644
> --- a/gdb/testsuite/gdb.ada/complete/foo.adb
> +++ b/gdb/testsuite/gdb.ada/complete/foo.adb
> @@ -20,6 +20,10 @@ procedure Foo is
>     External_Identical_Two : Integer := 74;
>  begin
>     My_Global_Variable := Some_Local_Variable + 1; -- START
> +   Repeat_Variable_1 := My_Global_Variable + 1;
> +   Repeat_Variable_2 := Repeat_Variable_1 + 1;
> +   Repeat_Variable_3 := Repeat_Variable_2 + 1;
> +   Repeat_Variable_4 := Repeat_Variable_3 + 1;
>     Proc (External_Identical_Two);
>  end Foo;
>  
> diff --git a/gdb/testsuite/gdb.ada/complete/pck.ads b/gdb/testsuite/gdb.ada/complete/pck.ads
> index ab2c47b..5595f7f 100644
> --- a/gdb/testsuite/gdb.ada/complete/pck.ads
> +++ b/gdb/testsuite/gdb.ada/complete/pck.ads
> @@ -16,9 +16,21 @@
>  package Pck is
>  
>     My_Global_Variable : Integer := 1;
> +   Repeat_Variable_1 : Integer := 1;
> +   Repeat_Variable_2 : Integer := 1;
> +   Repeat_Variable_3 : Integer := 1;
> +   Repeat_Variable_4 : Integer := 1;
>  
>     Exported_Capitalized : Integer := 2;
>     pragma Export (C, Exported_Capitalized, "Exported_Capitalized");
> +   Repeated_1 : Integer := 21;
> +   pragma Export (C, Repeated_1, "Repeated_1");
> +   Repeated_2 : Integer := 22;
> +   pragma Export (C, Repeated_2, "Repeated_2");
> +   Repeated_3 : Integer := 23;
> +   pragma Export (C, Repeated_3, "Repeated_3");
> +   Repeated_4 : Integer := 24;
> +   pragma Export (C, Repeated_4, "Repeated_4");
>  
>     Local_Identical_One : Integer := 4;
>     Local_Identical_Two : Integer := 8;

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 06/19] Implement completion limiting for condition_completer.
  2015-08-06 19:58 ` [PATCH v3 06/19] Implement completion limiting for condition_completer Keith Seitz
@ 2015-08-23  3:53   ` Doug Evans
  0 siblings, 0 replies; 45+ messages in thread
From: Doug Evans @ 2015-08-23  3:53 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

Keith Seitz <keiths@redhat.com> writes:
> There are no changes from the last revision.
>
> --
>
> This patch converts the condition completer to use add_completion.
> A side-effect of this is the similar conversion of complete_internalvar.
>
> Tests have been added to exercise this new behavior.
>
> gdb/ChangeLog
>
> 	* breakpoint.c (condition_completer): Pass completer_data to
> 	complete_internalvar.
> 	Use add_completion.
> 	* value.c: Include completer.h.
> 	(complete_internalvar): Add completer_data argument.
> 	Use add_completion.
> 	* value.h (complete_internalvar): Add completer_data argument.
>
> gdb/testsuite/ChangeLog
>
> 	* gdb.base/condbreak.exp (test_completion): New procedure.
> 	Add more completion tests, with and without limiting.

====
One nit.
Ok with that fixed.

> ---
>  gdb/breakpoint.c                     |    8 +++-
>  gdb/testsuite/gdb.base/condbreak.exp |   70 ++++++++++++++++++++++++++++++++++
>  gdb/value.c                          |    9 ++--
>  gdb/value.h                          |    3 +
>  4 files changed, 83 insertions(+), 7 deletions(-)
>
> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
> index 70569df..24243c4 100644
> --- a/gdb/breakpoint.c
> +++ b/gdb/breakpoint.c
> @@ -1052,7 +1052,7 @@ condition_completer (struct completer_data *cdata,
>  	  /* We don't support completion of history indices.  */
>  	  if (isdigit (text[1]))
>  	    return NULL;
> -	  return complete_internalvar (&text[1]);
> +	  return complete_internalvar (cdata, &text[1]);
>  	}
>  
>        /* We're completing the breakpoint number.  */
> @@ -1065,7 +1065,11 @@ condition_completer (struct completer_data *cdata,
>  	  xsnprintf (number, sizeof (number), "%d", b->number);
>  
>  	  if (strncmp (number, text, len) == 0)
> -	    VEC_safe_push (char_ptr, result, xstrdup (number));
> +	    {
> +	      if (add_completion (cdata, &result, number, NULL, NULL)
> +		  == ADD_COMPLETION_MAX_REACHED)
> +		break;
> +	    }
>  	}
>  
>        return result;
> diff --git a/gdb/testsuite/gdb.base/condbreak.exp b/gdb/testsuite/gdb.base/condbreak.exp
> index fa40a5f..5630ede 100644
> --- a/gdb/testsuite/gdb.base/condbreak.exp
> +++ b/gdb/testsuite/gdb.base/condbreak.exp
> @@ -246,3 +246,73 @@ gdb_test "complete cond 1" "cond 1"
>  gdb_test "set variable \$var = 1"
>  gdb_test "complete cond \$v" "cond \\\$var"
>  gdb_test "complete cond 1 values\[0\].a" "cond 1 values.0..a_field"
> +
> +# Test non-trivial completion and completion-limiting
> +
> +# Delete all breakpoints and create a bunch of new ones.
> +delete_breakpoints
> +for {set i 0} {$i < 20} {incr i} {
> +    with_test_prefix "set breakpoint $i" {
> +	gdb_breakpoint "factorial"
> +    }
> +}
> +
> +# While the completer function does traverse breakpoints in the order
> +# they were created, don't assume that is required for the test.
> +# We only count the number of completions found.  In this case,
> +# this test will create breakpoints 9-19, giving "complete cond 1"
> +# ten total completion possibilities.
> +
> +# A convenience procedure to automate test completion lists.
> +proc test_completion {cmd exp total {limit 0}} {
> +    global gdb_prompt
> +
> +    if {$limit} {
> +	set end "\\\*\\\*\\\* List may be truncated, "
> +	append end "max-completions reached\\\. \\\*\\\*\\\*\r\n"
> +	set testname "limit '$cmd'"
> +    } else {
> +	set end ""
> +	set testname $cmd
> +    }
> +
> +    set seen 0
> +    gdb_test_multiple $cmd $testname {
> +	"$cmd\r\n" { exp_continue }
> +
> +	-re "cond $exp\[0-9\]+\r\n" {
> +	    incr seen
> +	    exp_continue
> +	}
> +
> +	-re ".*$end$gdb_prompt $" {
> +	    if {$seen == $total} {
> +		pass $testname
> +	    } else {
> +		fail "$testname ($seen/$total)"
> +	    }
> +	}
> +    }
> +}

====
Nice test.

> +
> +# Test completion of breakpoint number.
> +with_test_prefix "completion test:" {
> +    test_completion "complete cond 1" "1" 10
> +}
> +
> +# Test completion of breakpoint number using internal variable.
> +for {set i 0} {$i < 10} {incr i} {
> +    gdb_test_no_output "set variable \$var_bp_$i = $i"
> +}
> +
> +test_completion "complete cond \$var_bp" "\\\$var_bp_" 10
> +
> +# Run the above tests with completion limiting.
> +set max_completions 4
> +gdb_test_no_output "set max-completions $max_completions"
> +
> +with_test_prefix "completion test:" {
> +    test_completion "complete cond 1" "1" $max_completions 1
> +}
> +
> +test_completion "complete cond \$var_bp" "\\\$var_bp_" $max_completions 1
> diff --git a/gdb/value.c b/gdb/value.c
> index 63ee94d..22d392a 100644
> --- a/gdb/value.c
> +++ b/gdb/value.c
> @@ -40,6 +40,7 @@
>  #include "tracepoint.h"
>  #include "cp-abi.h"
>  #include "user-regs.h"
> +#include "completer.h"
>  
>  /* Prototypes for exported functions.  */
>  
> @@ -2062,7 +2063,7 @@ lookup_only_internalvar (const char *name)
>     were found.  */
>  
>  VEC (char_ptr) *
> -complete_internalvar (const char *name)
> +complete_internalvar (struct completer_data *cdata, const char *name)
>  {
>    VEC (char_ptr) *result = NULL;
>    struct internalvar *var;
> @@ -2073,9 +2074,9 @@ complete_internalvar (const char *name)
>    for (var = internalvars; var; var = var->next)
>      if (strncmp (var->name, name, len) == 0)
>        {
> -	char *r = xstrdup (var->name);
> -
> -	VEC_safe_push (char_ptr, result, r);
> +	if (add_completion (cdata, &result, var->name, NULL, NULL)
> +	    == ADD_COMPLETION_MAX_REACHED)
> +	  break;
>        }
>  
>    return result;
> diff --git a/gdb/value.h b/gdb/value.h
> index 82deaf2..03df1b7 100644
> --- a/gdb/value.h
> +++ b/gdb/value.h
> @@ -876,7 +876,8 @@ extern struct internalvar *lookup_only_internalvar (const char *name);
>  
>  extern struct internalvar *create_internalvar (const char *name);
>  
> -extern VEC (char_ptr) *complete_internalvar (const char *name);
> +extern VEC (char_ptr) *complete_internalvar (struct completer_data *cdata,
> +					     const char *name);

====
Add a forward decl for struct completer_cdata.

>  
>  /* An internalvar can be dynamically computed by supplying a vector of
>     function pointers to perform various operations.  */

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 07/19] Implement completion limiting for filename_completer.
  2015-08-06 22:03 ` [PATCH v3 07/19] Implement completion limiting for filename_completer Keith Seitz
@ 2015-08-23  3:58   ` Doug Evans
  0 siblings, 0 replies; 45+ messages in thread
From: Doug Evans @ 2015-08-23  3:58 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

Keith Seitz <keiths@redhat.com> writes:
> Differences in this revision:
>
> 1. Remove partial copy code from filename_completer.
>
> ---
>
> This patch converts filename_completer to using add_completion
> and adds some tests to exercise this new behavior.
>
> gdb/ChangeLog
>
> 	* completer.c (filename_completer): Use add_completion.
>
> gdb/testsuite/ChangeLog
>
> 	* gdb.base/completion.exp: Put completion truncation message
> 	into a variable for use by other tests.  Update existing tests.
> 	(test_completion_limit): New procedure.
> 	Add tests for completion limiting on file names.

LGTM.
One comment, grep for ===

> ---
>  gdb/completer.c                       |   25 ++----------
>  gdb/testsuite/gdb.base/completion.exp |   69 +++++++++++++++++++++++++++++++--
>  2 files changed, 69 insertions(+), 25 deletions(-)
>
> diff --git a/gdb/completer.c b/gdb/completer.c
> index bf4137e..6aa8d35 100644
> --- a/gdb/completer.c
> +++ b/gdb/completer.c
> @@ -157,7 +157,7 @@ filename_completer (struct completer_data *cdata,
>    subsequent_name = 0;
>    while (1)
>      {
> -      char *p, *q;
> +      char *p;
>  
>        p = rl_filename_completion_function (text, subsequent_name);
>        if (p == NULL)
> @@ -175,26 +175,9 @@ filename_completer (struct completer_data *cdata,
>  	  continue;
>  	}
>  
> -      if (word == text)
> -	/* Return exactly p.  */
> -	q = p;
> -      else if (word > text)
> -	{
> -	  /* Return some portion of p.  */
> -	  q = xmalloc (strlen (p) + 5);
> -	  strcpy (q, p + (word - text));
> -	  xfree (p);
> -	}
> -      else
> -	{
> -	  /* Return some of TEXT plus p.  */
> -	  q = xmalloc (strlen (p) + (text - word) + 5);
> -	  strncpy (q, word, text - word);
> -	  q[text - word] = '\0';
> -	  strcat (q, p);
> -	  xfree (p);
> -	}
> -      VEC_safe_push (char_ptr, return_val, q);
> +      if (add_completion (cdata, &return_val, p, text, word)
> +	  == ADD_COMPLETION_MAX_REACHED)
> +	break;
>      }
>  #if 0
>    /* There is no way to do this just long enough to affect quote
> diff --git a/gdb/testsuite/gdb.base/completion.exp b/gdb/testsuite/gdb.base/completion.exp
> index 710aac0..f0b7f2c 100644
> --- a/gdb/testsuite/gdb.base/completion.exp
> +++ b/gdb/testsuite/gdb.base/completion.exp
> @@ -858,6 +858,10 @@ gdb_test "complete break need" "need_malloc"
>  # Completion limiting.
>  #
>  
> +# The terminal at the end of the complete command
> +set end "\\\*\\\*\\\* List may be truncated, "
> +append end "max-completions reached\\\. \\\*\\\*\\\*"
> +
>  gdb_test_no_output "set max-completions 5"
>  
>  set test "command-name completion limiting using tab character"
> @@ -866,7 +870,7 @@ gdb_test_multiple "" "$test" {
>      -re "^p\\\x07$" {
>  	send_gdb "\t"
>  	gdb_test_multiple "" "$test" {
> -	    -re "List may be truncated, max-completions reached.*\r\n$gdb_prompt p$" {
> +	    -re "$end\r\n$gdb_prompt p$" {
>  		# Complete the command and ignore the output to resync
>  		# gdb for the next test.
>  		send_gdb "\n"
> @@ -898,7 +902,8 @@ gdb_test_multiple "" "$test" {
>      }
>  }
>  
> -gdb_test_no_output "set max-completions 3"
> +set max_completions 3
> +gdb_test_no_output "set max-completions $max_completions"
>  
>  set test "symbol-name completion limiting using tab character"
>  send_gdb "p marker\t"
> @@ -906,7 +911,7 @@ gdb_test_multiple "" "$test" {
>      -re "^p marker\\\x07$" {
>  	send_gdb "\t"
>  	gdb_test_multiple "" "$test" {
> -	    -re "List may be truncated, max-completions reached.*\r\n$gdb_prompt p marker$" {
> +	    -re "$end\r\n$gdb_prompt p marker$" {
>  		# Complete the command and ignore the output to resync
>  		# gdb for the next test.
>  		send_gdb "\n"
> @@ -933,11 +938,67 @@ gdb_test_multiple "" "$test" {
>  set test "symbol-name completion limiting using complete command"
>  send_gdb "complete p mark\n"
>  gdb_test_multiple "" "$test" {
> -    -re "List may be truncated, max-completions reached.*\r\n$gdb_prompt $" {
> +    -re "$end\r\n$gdb_prompt $" {
>  	pass "$test"
>      }
>  }
>  
> +# A convenience function for testing completion limiting.
> +# CMD is a GDB command to to run with "complete".
> +# PATTERN is a regexp pattern matching the expected output
> +#   of completion items "seen" in the output.
> +# NUM is the number of maximum completions expected.
> +#
> +# The test will use the test name "limit complete CMD"
> +# and will only count the number of completion items matching
> +# PATTERN.  No assumptions are made on the order of the items
> +# seen in GDB's output.
> +#
> +# If NUM items are seen before the truncation message, the test
> +# passes, otherwise it fails.  The test can also fail if no
> +# truncation message is seen at all, in which case the test
> +# failure message will say "(unlimited)".
> +
> +proc test_completion_limit {cmd pattern num} {
> +    global gdb_prompt
> +
> +    # The terminal at the end of the complete command
> +    set end "\\\*\\\*\\\* List may be truncated, "
> +    append end "max-completions reached\\\. \\\*\\\*\\\*"
> +
> +    set cmdr [string_to_regexp $cmd]
> +    set seen 0
> +    gdb_test_multiple "complete $cmd" "limit complete $cmd" {
> +	"complete $cmdr" { exp_continue }
> +	-re "$pattern\r\n" {
> +	    incr seen
> +	    exp_continue
> +	}
> +	-re ".*$end\r\n$gdb_prompt $" {
> +	    if {$seen == $num} {
> +		pass "limit complete $cmd"
> +	    } else {
> +		fail "limit complete $cmd ($seen/$num)"
> +	    }
> +	}
> +	-re ".*$gdb_prompt $" {
> +	    fail "limit complete $cmd (unlimited)"
> +	}
> +    }
> +}

====
IWBN to combine this function with test_completion in
gdb.base/condbreak.exp, and I suppose put the function in gdb.exp.
Only if it's easy though.

> +
> +test_completion_limit "file ./gdb.base/jit-s" \
> +    "file \\\./gdb\\\.base/jit-s(imple|olib|o)(\\\.c|\\\.exp)?" \
> +    $max_completions
> +
> +# same as above but completing on directory names.
> +test_completion_limit "file ./gdb.a" "file \\\./gdb\\\.a(da|rch|sm)" \
> +    $max_completions
> +
> +#
> +# Test TUI completions
> +#
> +
>  gdb_test_no_output "set max-completions unlimited"
>  
>  if {![skip_tui_tests]} {

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 08/19] Implement completion limiting for signal_completer.
  2015-08-06 22:03 ` [PATCH v3 08/19] Implement completion limiting for signal_completer Keith Seitz
@ 2015-08-23  3:59   ` Doug Evans
  0 siblings, 0 replies; 45+ messages in thread
From: Doug Evans @ 2015-08-23  3:59 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

Keith Seitz <keiths@redhat.com> writes:
> There are no revisions in this version.
>
> ---
>
> This patch converts signal_completer to use add_completion
> and adds some tests to cover this new behavior.
>
> gdb/ChangeLog
>
> 	* completer.c (signal_completer): Use add_completion.
>
> gdb/testsuite/ChangeLog
>
> 	* gdb.base/completion.exp: Add completion limiting tests
> 	for "handle signal".

LGTM

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 09/19] Implement completion limiting for interpreter_completer.
  2015-08-06 19:18 ` [PATCH v3 09/19] Implement completion limiting for interpreter_completer Keith Seitz
@ 2015-08-23  4:03   ` Doug Evans
  0 siblings, 0 replies; 45+ messages in thread
From: Doug Evans @ 2015-08-23  4:03 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

Keith Seitz <keiths@redhat.com> writes:
> Differences in this revision:
>
> 1. Remove partial copy code from interpreter_completer..
>
> ---
>
> This is another simple patch which converts interpreter_completer
> to use add_completion and adds some tests to make sure that everything
> is working properly.
>
> gdb/ChangeLog
>
> 	* interps.c (interpreter_completer): Use add_completion.
>
> gdb/testsuite/ChangeLog
>
> 	* gdb.base/completion.exp: Test completion limiting on
> 	interpreter name with "interpreter-exec".

LGTM with one nit below fixed.

I'm really liking all this removal of duplicate code.
Thanks!

> ---
>  gdb/interps.c                         |   21 +++------------------
>  gdb/testsuite/gdb.base/completion.exp |   16 ++++++++++++++++
>  2 files changed, 19 insertions(+), 18 deletions(-)
>
> diff --git a/gdb/interps.c b/gdb/interps.c
> index 2cfe92b..9e993c8 100644
> --- a/gdb/interps.c
> +++ b/gdb/interps.c
> @@ -448,24 +448,9 @@ interpreter_completer (struct completer_data *cdata,
>      {
>        if (strncmp (interp->name, text, textlen) == 0)
>  	{
> -	  char *match;
> -
> -	  match = (char *) xmalloc (strlen (word) + strlen (interp->name) + 1);
> -	  if (word == text)
> -	    strcpy (match, interp->name);
> -	  else if (word > text)
> -	    {
> -	      /* Return some portion of interp->name.  */
> -	      strcpy (match, interp->name + (word - text));
> -	    }
> -	  else
> -	    {
> -	      /* Return some of text plus interp->name.  */
> -	      strncpy (match, word, text - word);
> -	      match[text - word] = '\0';
> -	      strcat (match, interp->name);
> -	    }
> -	  VEC_safe_push (char_ptr, matches, match);
> +	  if (add_completion (cdata, &matches, interp->name, text, word)
> +	      == ADD_COMPLETION_MAX_REACHED)
> +	    break;
>  	}
>      }
>  
> diff --git a/gdb/testsuite/gdb.base/completion.exp b/gdb/testsuite/gdb.base/completion.exp
> index 884b9f6..41323d2 100644
> --- a/gdb/testsuite/gdb.base/completion.exp
> +++ b/gdb/testsuite/gdb.base/completion.exp
> @@ -1022,6 +1022,22 @@ if {$num_signals > $max_completions} {
>      untested $msg
>  }
>  
> +# Test interpreter_completer.  There are only four completions
> +# available for this, so temporarily set max-completions to 3.
> +with_test_prefix "interpreter_completer" {
> +    set old_max $max_completions

====
There is save_vars now to handle restoring variables
to their previous values.

save_vars { max_completions } {
    ...
}

> +    set max_completions 3
> +    gdb_test_no_output "set max-completions $max_completions"
> +}
> +
> +test_completion_limit "interpreter-exec m" \
> +    "interpreter-exec mi\[1-3\]?" $max_completions
> +
> +with_test_prefix "interpreter_completer reset" {
> +    set max_completions $old_max
> +    gdb_test_no_output "set max-completions $max_completions"
> +}
> +
>  #
>  # Test TUI completions
>  #

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 10/19] Implement completion limiting for cmdpy_completer.
  2015-08-06 22:12 ` [PATCH v3 10/19] Implement completion limiting for cmdpy_completer Keith Seitz
@ 2015-08-23  4:07   ` Doug Evans
  0 siblings, 0 replies; 45+ messages in thread
From: Doug Evans @ 2015-08-23  4:07 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

Keith Seitz <keiths@redhat.com> writes:
> Differences in this revision:
>
> 1. Free string memory after passing to add_completion.
>
> ---
>
> This patch converts cmdpy_completer, used by commands written in
> python.  It also adds tests for some untested python functionality
> related to completion.
>
> gdb/ChangeLog
>
> 	* python/py-cmd.c (cmdpy_completer) Use add_completion.
> 	Free memory associated with `item'.
>
> gdb/testsuite/ChangeLog
>
> 	* gdb.python/py-completion.exp: Test completion functions,
> 	with and without completion limiting.

LGTM, but see comment below.

> ---
>  gdb/python/py-cmd.c                        |    9 +++++-
>  gdb/testsuite/gdb.python/py-completion.exp |   45 ++++++++++++++++++++++++++++
>  2 files changed, 53 insertions(+), 1 deletion(-)
>
> diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
> index 21d842e..36e352e 100644
> --- a/gdb/python/py-cmd.c
> +++ b/gdb/python/py-cmd.c
> @@ -392,7 +392,14 @@ cmdpy_completer (struct completer_data *cdata,
>  	      PyErr_Clear ();
>  	      continue;
>  	    }
> -	  VEC_safe_push (char_ptr, result, item);
> +
> +	  if (add_completion (cdata, &result, item, NULL, NULL)
> +	      == ADD_COMPLETION_MAX_REACHED)
> +	    {
> +	      xfree (item);
> +	      break;
> +	    }
> +	  xfree (item);
>  	}
>  
>        Py_DECREF (iter);
> diff --git a/gdb/testsuite/gdb.python/py-completion.exp b/gdb/testsuite/gdb.python/py-completion.exp
> index 5e45087..f7f23a3 100644
> --- a/gdb/testsuite/gdb.python/py-completion.exp
> +++ b/gdb/testsuite/gdb.python/py-completion.exp
> @@ -128,3 +128,48 @@ if {[readline_is_used]} {
>  	    "completelimit2 cl29"
>  	}
>  }
> +
> +# The terminal at the end of the complete command
> +set end "\\\*\\\*\\\* List may be truncated, "
> +append end "max-completions reached\\\. \\\*\\\*\\\*"

====
Another case where it'd be nice to just call a function
(test_completion_limit?) and have this regexp live there?
It may be that each case is sufficiently different that such
a function would be too complex to handle all its potential callers,
I didn't study each case too thoroughly.
Just wanted to bring the issue up.

> +
> +set max_completions 3
> +gdb_test_no_output "set max-completions $max_completions"
> +set seen 0
> +
> +set testname "limit completions of 'complete completel'"
> +gdb_test_multiple "complete completel" $testname {
> +    "complete completel" { exp_continue }
> +
> +    -re "completelimit\[1-9\]+\r\n" {
> +	incr seen
> +	exp_continue
> +    }
> +
> +    -re "completel $end\r\n$gdb_prompt $" {
> +	if {$seen == $max_completions} {
> +	    pass $testname
> +	} else {
> +	    fail "$testname ($seen/$max_completions)"
> +	}
> +    }
> +}
> +
> +set testname "limit completions of 'complete completelimit1 c'"
> +set seen 0
> +gdb_test_multiple "complete completelimit1 c" $testname {
> +    "complete completelimit1 c" { exp_continue }
> +
> +    -re "completelimit1 cl1\[1-9\]+\r\n" {
> +	incr seen
> +	exp_continue
> +    }
> +
> +    -re "completelimit1 c $end\r\n$gdb_prompt $" {
> +	if {$seen == $max_completions} {
> +	    pass $testname
> +	} else {
> +	    fail "$testname ($seen/$max_completions)"
> +	}
> +    }
> +}

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 11/19] Implement completion limiting for reg_or_group_completer.
  2015-08-06 22:03 ` [PATCH v3 11/19] Implement completion limiting for reg_or_group_completer Keith Seitz
@ 2015-08-23  4:09   ` Doug Evans
  0 siblings, 0 replies; 45+ messages in thread
From: Doug Evans @ 2015-08-23  4:09 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

Keith Seitz <keiths@redhat.com> writes:
> There are no revisions in this version.
>
> --
>
> This patch converts reg_or_group_completer to use add_completion
> and adds tests for this new behavior.
>
> gdb/ChangeLog
>
> 	* completer.c (reg_or_group_completer): Use add_completion.
>
> gdb/testsuite/ChangeLog
>
> 	* gdb.base/completion.exp: Add tests for limit completing
> 	"info reigsters".

LGTM.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 12/19] Implement completion limiting for sim_command_completer.
  2015-08-06 19:20 ` [PATCH v3 12/19] Implement completion limiting for sim_command_completer Keith Seitz
@ 2015-08-23  4:11   ` Doug Evans
  0 siblings, 0 replies; 45+ messages in thread
From: Doug Evans @ 2015-08-23  4:11 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

Keith Seitz <keiths@redhat.com> writes:
> There are no revisions in this version.
>
> --
>
> This patch converts sim_command_completer to use add_completion.
> It does not add any tests, since the `sim' command is highly
> target-dependent and unimplemented for the majority of simulators.
>
> gdb/ChangeLog
>
> 	* remote-sim.c: Include completer.h.
> 	(sim_command_completer): Use add_completion.

LGTM

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 13/19] Implement completion limiting for complete_on_enum.
  2015-08-06 22:03 ` [PATCH v3 13/19] Implement completion limiting for complete_on_enum Keith Seitz
@ 2015-08-23  4:19   ` Doug Evans
  0 siblings, 0 replies; 45+ messages in thread
From: Doug Evans @ 2015-08-23  4:19 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

Keith Seitz <keiths@redhat.com> writes:
> Differences in this revision:
>
> 1. Remove partial copy code from complete_on_enum
>
> ---
>
> This is another patch to push along the conversion of location_completer
> toward using add_completion.  In this patch, complete_on_enum is
> converted.  This function is also used by several other commands, such as
> integer_unlimited_completer, handle_completer, cp_abi_completer, etc.
>
> gdb/ChangeLog
>
> 	* cli/cli-decode.c (complete_on_enum): Use add_completion.
>
> gdb/testsuite/ChangeLog
>
> 	* gdb.base/completion.exp: Add tests for complete_on_enum
> 	completion limiting using "handle signal".

LGTM

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 14/19] Implement completion limiting in add_struct_fields.
  2015-08-06 22:12 ` [PATCH v3 14/19] Implement completion limiting in add_struct_fields Keith Seitz
@ 2015-08-23  4:23   ` Doug Evans
  0 siblings, 0 replies; 45+ messages in thread
From: Doug Evans @ 2015-08-23  4:23 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

Keith Seitz <keiths@redhat.com> writes:
> There are no revisions in this version.
>
> ---
>
> This patch converts add_struct_fields (used by expression_completer) to use
> add_completion and adds (coverage) tests for this new behavior.
>
> break.exp contains two overly greedy regexp patterns which required
> tweaking, too.
>
> gdb/ChangeLog
>
> 	* completer.c (add_struct_fields): Use add_completion.
>
> gdb/testsuite/ChangeLog
>
> 	* gdb.base/break.c (struct field_test): New structure.
> 	(field_test_global): New global variable.
> 	* gdb.base/break.exp: Add srcfile to otherwise too greedy regexp
> 	for tests "check disable with history value" and "check disable
> 	with convenience values".
> 	* gdb.base/completion.exp: Add completion limiting tests for
> 	add_struct_fields using the print command.
> 	* gdb.cp/cpcompletion.exp (test_completion_limit): New procedure.
> 	Add completion limiting tests for C++-specific parts of
> 	add_struct_fields using the print command.
> 	* gdb.cp/pr9694.cc (class Foo) <repeated1, repeated2, repeated3,
> 	repeated4, repeated5, repeated6, repeated7, repeated8>: New members.
> 	(Foo::Foo): Add initializer for new members.
> 	(main): Add new methods method1, method2, method3, method4, method5,
> 	method6, method7, and method8 to anonymous structure and make
> 	sure they are not optimized away.

LGTM, but see comment below.

> diff --git a/gdb/completer.c b/gdb/completer.c
> index 7ede0f9..134a3c2 100644
> --- a/gdb/completer.c
> +++ b/gdb/completer.c
> @@ -373,8 +373,12 @@ add_struct_fields (struct completer_data *cdata,
>  	    {
>  	      if (! strncmp (TYPE_FIELD_NAME (type, i), 
>  			     fieldname, namelen))
> -		VEC_safe_push (char_ptr, *output,
> -			       xstrdup (TYPE_FIELD_NAME (type, i)));
> +		{
> +		  if (add_completion (cdata, output, TYPE_FIELD_NAME (type, i),
> +				      NULL, NULL)
> +		      == ADD_COMPLETION_MAX_REACHED)
> +		    return;
> +		}
>  	    }
>  	  else if (TYPE_CODE (TYPE_FIELD_TYPE (type, i)) == TYPE_CODE_UNION)
>  	    {
> @@ -398,7 +402,11 @@ add_struct_fields (struct completer_data *cdata,
>  	    }
>  	  /* Omit constructors from the completion list.  */
>  	  if (!type_name || strcmp (type_name, name))
> -	    VEC_safe_push (char_ptr, *output, xstrdup (name));
> +	    {
> +	      if (add_completion (cdata, output, name, NULL, NULL)
> +		  == ADD_COMPLETION_MAX_REACHED)
> +		return;
> +	    }
>  	}
>      }
>  }
> diff --git a/gdb/testsuite/gdb.base/break.c b/gdb/testsuite/gdb.base/break.c
> index d017a91..8ee11b1 100644
> --- a/gdb/testsuite/gdb.base/break.c
> +++ b/gdb/testsuite/gdb.base/break.c
> @@ -30,6 +30,20 @@ void *need_malloc ()
>    return malloc (1);
>  }
>  
> +/* A structure for testing add_struct_fields.  */
> +struct field_test
> +{
> +  int a1_field;
> +  int a2_field;
> +  int a3_field;
> +  int a4_field;
> +  int a5_field;
> +  int a6_field;
> +  int a7_field;
> +};
> +
> +struct field_test field_test_global = {1, 2, 3, 4, 5, 6, 7};
> +
>  /*
>   *	This simple classical example of recursion is useful for
>   *	testing stack backtraces and such.
> diff --git a/gdb/testsuite/gdb.base/break.exp b/gdb/testsuite/gdb.base/break.exp
> index f879bc8..5344533 100644
> --- a/gdb/testsuite/gdb.base/break.exp
> +++ b/gdb/testsuite/gdb.base/break.exp
> @@ -249,7 +249,7 @@ set see5 0
>  set see6 0
>  
>  gdb_test_multiple "info break" "check disable with history values" {
> -    -re "1\[\t \]+breakpoint *keep y.* in main at .*:$main_line\[^\r\n\]*" {
> +    -re "1\[\t \]+breakpoint *keep y.* at .*$srcfile:$main_line\[\r\n\]*" {
>  	set see1 1
>  	exp_continue
>      }
> @@ -295,7 +295,7 @@ set see5 0
>  set see6 0
>  
>  gdb_test_multiple "info break" "check disable with convenience values" {
> -    -re "1\[\t \]+breakpoint *keep y.* in main at .*:$main_line\[^\r\n\]*" {
> +    -re "1\[\t \]+breakpoint *keep y.* in main at .*$srcfile:$main_line\[^\r\n\]*" {
>  	set see1 1
>  	exp_continue
>      }
> diff --git a/gdb/testsuite/gdb.base/completion.exp b/gdb/testsuite/gdb.base/completion.exp
> index 6c81505..1036af5 100644
> --- a/gdb/testsuite/gdb.base/completion.exp
> +++ b/gdb/testsuite/gdb.base/completion.exp
> @@ -1054,6 +1054,10 @@ if {$signal_to_use != ""} {
>  	$max_completions
>  }
>  
> +# Test add_struct_fields.
> +test_completion_limit "print field_test_global.a" \
> +    "print field_test_global\\\.a\[1-9\]_field" $max_completions
> +
>  #
>  # Test TUI completions
>  #
> diff --git a/gdb/testsuite/gdb.cp/cpcompletion.exp b/gdb/testsuite/gdb.cp/cpcompletion.exp
> index 023c261..a1bc6d8 100644
> --- a/gdb/testsuite/gdb.cp/cpcompletion.exp
> +++ b/gdb/testsuite/gdb.cp/cpcompletion.exp
> @@ -85,3 +85,58 @@ gdb_test "complete p foo1.Fo" "p foo1\\.Foofoo"
>  
>  # Test completion with an anonymous struct.
>  gdb_test "complete p a.g" "p a\\.get"
> +
> +# Test completion limiting (add_struct_fields)
> +set max_completions 3
> +gdb_test_no_output "set max-completions $max_completions"
> +
> +# A convenience function for testing completion limiting.
> +# CMD is a GDB command to to run with "complete".
> +# PATTERN is a regexp pattern matching the expected output
> +#   of completion items "seen" in the output.
> +# NUM is the number of maximum completions expected.
> +#
> +# The test will use the test name "limit complete CMD"
> +# and will only count the number of completion items matching
> +# PATTERN.  No assumptions are made on the order of the items
> +# seen in GDB's output.
> +#
> +# If NUM items are seen before the truncation message, the test
> +# passes, otherwise it fails.  The test can also fail if no
> +# truncation message is seen at all, in which case the test
> +# failure message will say "(unlimited)".
> +
> +proc test_completion_limit {cmd pattern num} {

====
Note: Another version of test_completion_limit.

> +    global gdb_prompt
> +
> +    # The terminal at the end of the complete command
> +    set end "\\\*\\\*\\\* List may be truncated, "
> +    append end "max-completions reached\\\. \\\*\\\*\\\*"
> +
> +    set cmdr [string_to_regexp $cmd]
> +    set seen 0
> +    gdb_test_multiple "complete $cmd" "limit complete $cmd" {
> +	"complete $cmdr" { exp_continue }
> +	-re "$pattern\r\n" {
> +	    incr seen
> +	    exp_continue
> +	}
> +	-re ".*$end\r\n$gdb_prompt $" {
> +	    if {$seen == $num} {
> +		pass "limit complete $cmd"
> +	    } else {
> +		fail "limit complete $cmd ($seen/$num)"
> +	    }
> +	}
> +	-re ".*$gdb_prompt $" {
> +	    fail "limit complete $cmd (unlimited)"
> +	}
> +    }
> +}
> +
> +# Completion limiting tests for add_struct_fields.
> +test_completion_limit "print a.meth" "print a\\\.method\[1-8\]" \
> +    $max_completions
> +
> +test_completion_limit "print foo1.repeat" \
> +    "print foo1\\\.repeated\[1-8\]" $max_completions
> diff --git a/gdb/testsuite/gdb.cp/pr9594.cc b/gdb/testsuite/gdb.cp/pr9594.cc
> index 8fdee84..e4b49ce 100644
> --- a/gdb/testsuite/gdb.cp/pr9594.cc
> +++ b/gdb/testsuite/gdb.cp/pr9594.cc
> @@ -11,9 +11,19 @@ class Foo : public Base
>  
>  private:
>    int foo_value;
> +  int repeated1;
> +  int repeated2;
> +  int repeated3;
> +  int repeated4;
> +  int repeated5;
> +  int repeated6;
> +  int repeated7;
> +  int repeated8;
>  
>  public:
> -  Foo () { foo_value = 0;}
> +  Foo () : foo_value (0), repeated1 (1), repeated2 (2), repeated3 (3),
> +	   repeated4 (4), repeated5 (5), repeated6 (6), repeated7 (7),
> +	   repeated8 (8) {}
>    Foo (int i) { foo_value = i;}
>    ~Foo () { }
>    void set_foo (int value);
> @@ -44,9 +54,25 @@ int main ()
>    // Anonymous struct with method.
>    struct {
>      int get() { return 5; }
> +    int method1 (void) { return 1; }
> +    int method2 (void) { return 2; }
> +    int method3 (void) { return 3; }
> +    int method4 (void) { return 4; }
> +    int method5 (void) { return 5; }
> +    int method6 (void) { return 6; }
> +    int method7 (void) { return 7; }
> +    int method8 (void) { return 8; }
>    } a;
>    Foo foo1;
>    foo1.set_foo (42);		// Set breakpoint here.
>    a.get();			// Prevent compiler from throwing 'a' away.
> +  a.method1 ();
> +  a.method2 ();
> +  a.method3 ();
> +  a.method4 ();
> +  a.method5 ();
> +  a.method6 ();
> +  a.method7 ();
> +  a.method8 ();
>    return 0;
>  }

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 15/19] Implement completion limiting for scmcmd_add_completion.
  2015-08-07  2:37 ` [PATCH v3 15/19] Implement completion limiting for scmcmd_add_completion Keith Seitz
@ 2015-08-23  4:24   ` Doug Evans
  0 siblings, 0 replies; 45+ messages in thread
From: Doug Evans @ 2015-08-23  4:24 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

Keith Seitz <keiths@redhat.com> writes:
> Differences in this revision:
>
> 1. Free string memory after passing to add_completion.
>
> ---
>
> This patch converts scmcmd_add_completion to use add_completion and
> adds some tests for this new behavior.
>
> gdb/ChangeLog
>
> 	* guile/scm-cmd.c (cmdscm_add_completion): Add completer_data
> 	argument.  All callers updated.
> 	Use add_completion.
> 	Free memory associated with `item'.
>
> gdb/testsuite/ChangeLog
>
> 	* gdb.guile/scm-cmd.exp: Add completion limiting tests.

LGTM.
Another case for using common test_completion_limit?

> ---
>  gdb/guile/scm-cmd.c                 |   11 ++++++-----
>  gdb/testsuite/gdb.guile/scm-cmd.exp |   24 ++++++++++++++++++++++++
>  2 files changed, 30 insertions(+), 5 deletions(-)
>
> diff --git a/gdb/guile/scm-cmd.c b/gdb/guile/scm-cmd.c
> index 58c79c8..1544c2b 100644
> --- a/gdb/guile/scm-cmd.c
> +++ b/gdb/guile/scm-cmd.c
> @@ -348,7 +348,8 @@ cmdscm_bad_completion_result (const char *msg, SCM completion)
>     The result is a boolean indicating success.  */
>  
>  static int
> -cmdscm_add_completion (SCM completion, VEC (char_ptr) **result)
> +cmdscm_add_completion (SCM completion, struct completer_data *cdata,
> +		       VEC (char_ptr) **result)
>  {
>    char *item;
>    SCM except_scm;
> @@ -370,8 +371,8 @@ cmdscm_add_completion (SCM completion, VEC (char_ptr) **result)
>        return 0;
>      }
>  
> -  VEC_safe_push (char_ptr, *result, item);
> -
> +  (void) add_completion (cdata, result, item, NULL, NULL);
> +  xfree (item);
>    return 1;
>  }
>  
> @@ -418,7 +419,7 @@ cmdscm_completer (struct completer_data *cdata,
>  	{
>  	  SCM next = scm_car (list);
>  
> -	  if (!cmdscm_add_completion (next, &result))
> +	  if (!cmdscm_add_completion (next, cdata, &result))
>  	    {
>  	      VEC_free (char_ptr, result);
>  	      goto done;
> @@ -442,7 +443,7 @@ cmdscm_completer (struct completer_data *cdata,
>  	      goto done;
>  	    }
>  
> -	  if (!cmdscm_add_completion (next, &result))
> +	  if (!cmdscm_add_completion (next, cdata, &result))
>  	    {
>  	      VEC_free (char_ptr, result);
>  	      goto done;
> diff --git a/gdb/testsuite/gdb.guile/scm-cmd.exp b/gdb/testsuite/gdb.guile/scm-cmd.exp
> index 53c0fdf..ac721c3 100644
> --- a/gdb/testsuite/gdb.guile/scm-cmd.exp
> +++ b/gdb/testsuite/gdb.guile/scm-cmd.exp
> @@ -196,6 +196,30 @@ gdb_test "test-scheme-error-cmd ugh" \
>      "Error occurred in Scheme-implemented GDB command." \
>      "call scheme-error command"
>  
> +# Test completion limiting.
> +set max_completions 2
> +gdb_test_no_output "set max-completions $max_completions"
> +set end "\\\*\\\*\\\* List may be truncated, "
> +append end "max-completions reached\\\. \\\*\\\*\\\*"
> +set test "limit complete completer-as-function 42\."
> +gdb_test_multiple "complete completer-as-function 42\." $test {
> +    "complete completer-as-function 42\\\." { exp_continue }
> +    -re "completer-as-function 42\\\.\[1-3\]\r\n" {
> +	incr seen
> +	exp_continue
> +    }
> +    -re ".*$end\r\n$gdb_prompt $" {
> +	if {$seen == $max_completions} {
> +	    pass $test
> +	} else {
> +	    fail "$test ($seen/$max_completions)"
> +	}
> +    }
> +    -re ".*$gdb_prompt $" {
> +	fail "$test (unlimited)"
> +    }
> +}
> +
>  # If there is a problem with object management, this can often trigger it.
>  # It is useful to do this last, after we've created a bunch of command objects.
>  

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 16/19] Implement completion limiting for tui_reggroup_completer.
  2015-08-06 22:03 ` [PATCH v3 16/19] Implement completion limiting for tui_reggroup_completer Keith Seitz
@ 2015-08-23  4:25   ` Doug Evans
  0 siblings, 0 replies; 45+ messages in thread
From: Doug Evans @ 2015-08-23  4:25 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

Keith Seitz <keiths@redhat.com> writes:
> This is a new patch in the series.
>
> --
>
> This patch converts the (recently introduced) TUI register/group
> completer, tui_reggroup_completer, to use add_completion.
>
> gdb/ChangeLog
>
> 	* tui/tui-regs.c (tui_reggroup_completer): Use add_completion
> 	to add completions to the completion list.
>
> gdb/testsuite/ChangeLog
>
> 	* completion.exp: Add a completion-limit test for "tui reg".

LGTM

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 17/19] Make the completion API completely opaque.
  2015-08-06 21:06 ` [PATCH v3 17/19] Make the completion API completely opaque Keith Seitz
@ 2015-08-23 15:14   ` Doug Evans
  0 siblings, 0 replies; 45+ messages in thread
From: Doug Evans @ 2015-08-23 15:14 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

Keith Seitz <keiths@redhat.com> writes:
> There are no revisions in this version.
>
> --
>
> Now that the completion API is passing around a structure holding
> its internal data, there is no need to expose any of this data and
> other settings to other modules.
>
> This patch removes global access to max_completions and
> introduces a new API function,  get_maximum_completions (void), which
> other modules may use to query the current completion maximum.
>
> The API will be expanded as necessary in subsequent patches.
>
> gdb/ChangeLog
>
> 	* cli/cli-cmds.c (complete_command): Use get_maximum_completions
> 	instead of accessing the global max_completions.
> 	* completer.c (max_completions): Move definition earlier and
> 	make static.
> 	(get_maximum_completions): New function.
> 	(throw_max_completions_reached_error): Add comment.
> 	* completer.h (max_completions): Remove declaration.
> 	(get_maximum_completions): New declaration.

IIUC, we generally don't export accessors for parameters,
we just export the parameter. But I don't know if that's
a hard and fast rule.

It'd be nice if grep max_completions found both
the variable and the function.
Ok with that change.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 18/19] Use the hashtable to accumulate completion results.
  2015-08-06 19:58 ` [PATCH v3 18/19] Use the hashtable to accumulate completion results Keith Seitz
@ 2015-08-23 17:53   ` Doug Evans
  0 siblings, 0 replies; 45+ messages in thread
From: Doug Evans @ 2015-08-23 17:53 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

Keith Seitz <keiths@redhat.com> writes:
> There are no revisions in this version.
>
> --
>
> The completion API now uses a VEC (char_ptr) to collect results of
> completion.  The completion tracker is a hashtable whose elements are
> the completions.  Both hold essentially the same data, so there is no
> need to keep both around.
>
> This patch introduces some API support for removing the vector of
> completions altogether.  While it does not remove the vector or
> the vector return result from the completer functions, this patch
> does not use the results of the vector at all.  Only the results of
> the hashtable inside the completer's private data is used.
>
> The vector will be removed in the next patch.
>
> gdb/ChangeLog
>
> 	* cli/cli-decode.c (complete_on_cmdlist): Use get_completion_count
> 	to ascertain if there are any completion results.
> 	* completer.c (remove_leading_fn_component): New function.
> 	(location_completer): Use get_completion_count to figure out
> 	how many symbols and/or file names were found searching for
> 	possible completions.
> 	Traverse the completion tracker hashtable to strip leading
> 	file name components.  Contents moved to remove_leading_fn_component.
> 	(free_completer_data): Change argument to proper type.
> 	(free_entry_callback): New function.
> 	(free_all_completer_data): New function.
> 	(vectorize_htab): New function.
> 	(get_completion_list): New function.
> 	(get_completion_count): New function.
> 	(maybe_add_completion): Accumulate completions when not limiting
> 	the number of completions.
> 	(complete_line): Ignore the return list from complete_line_internal
> 	and get the completion results from the tracker.
> 	Do not count/limit the results at all -- it is no longer necessary.
> 	Use free_all_completer_data to free any allocated memory during
> 	completion in the case of an exception.
> 	Use free_completer_data after get_completion_list to free
> 	completer data structures.
> 	(gdb_completion_word_break_characters): Ignore the return list
> 	from complete_line_internal and get the completion results from
> 	the tracker.
> 	Use free_completer_data after get_completion_list to free
> 	completer data structures.
> 	* completer.h (get_completion_list): Declare.
> 	(get_completion_count): Declare.
> 	* python/py-cmd.c (cmdpy_completer): Use get_completion_count
> 	to ascertain if there are any completion results.

Hi.
A few nits.

> diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
> index fa95ee6..9691fd1 100644
> --- a/gdb/cli/cli-decode.c
> +++ b/gdb/cli/cli-decode.c
> @@ -1781,7 +1781,7 @@ complete_on_cmdlist (struct completer_data *cdata,
>       commands.  If we see no matching commands in the first pass, and
>       if we did happen to see a matching deprecated command, we do
>       another loop to collect those.  */
> -  for (pass = 0; matchlist == 0 && pass < 2; ++pass)
> +  for (pass = 0; get_completion_count (cdata) == 0 && pass < 2; ++pass)
>      {
>        for (ptr = list; ptr; ptr = ptr->next)
>  	if (!strncmp (ptr->name, text, textlen)
> diff --git a/gdb/completer.c b/gdb/completer.c
> index 651e9c2..6faed31 100644
> --- a/gdb/completer.c
> +++ b/gdb/completer.c
> @@ -197,6 +197,20 @@ filename_completer (struct completer_data *cdata,
>    return return_val;
>  }
>  
> +/* A hashtable traversal function to remove leading file name
> +   components, as required by rl_complete.  See more detailed explanation
> +   in location_completer for more.  */
> +
> +static int
> +remove_leading_fn_component (void **slot, void *calldata)
> +{
> +  char *fn = *slot;
> +  int offset = *(int *) calldata;
> +
> +  memmove (fn, fn + offset, strlen (fn) + 1 - offset);
> +  return 1;
> +}
> +
>  /* Complete on locations, which might be of two possible forms:
>  
>         file:line
> @@ -286,21 +300,25 @@ location_completer (struct completer_data *cdata,
>      {
>        list = make_file_symbol_completion_list (cdata, symbol_start, word,
>  					       file_to_match);
> +      n_syms = get_completion_count (cdata);
> +      n_files = 0;
>        xfree (file_to_match);
>      }
>    else
>      {
>        list = make_symbol_completion_list (cdata, symbol_start, word);
> +      n_syms = get_completion_count (cdata);
> +      n_files = 0;
>        /* If text includes characters which cannot appear in a file
>  	 name, they cannot be asking for completion on files.  */
>        if (strcspn (text, 
>  		   gdb_completer_file_name_break_characters) == text_len)
> -	fn_list = make_source_files_completion_list (cdata, text, text);
> +	{
> +	  fn_list = make_source_files_completion_list (cdata, text, text);
> +	  n_files = get_completion_count (cdata) - n_syms;
> +	}
>      }
>  
> -  n_syms = VEC_length (char_ptr, list);
> -  n_files = VEC_length (char_ptr, fn_list);
> -
>    /* Catenate fn_list[] onto the end of list[].  */
>    if (!n_syms)
>      {
> @@ -323,7 +341,7 @@ location_completer (struct completer_data *cdata,
>      }
>    else if (n_files)
>      {
> -      char *fn;
> +      int offset = word - text;
>  
>        /* If we only have file names as possible completion, we should
>  	 bring them in sync with what rl_complete expects.  The
> @@ -338,13 +356,10 @@ location_completer (struct completer_data *cdata,
>  	 the full "/foo/bar" and "/foo/baz" strings.  This produces
>  	 wrong results when, e.g., there's only one possible
>  	 completion, because rl_complete will prepend "/foo/" to each
> -	 candidate completion.  The loop below removes that leading
> +	 candidate completion.  The callback below removes that leading
>  	 part.  */
> -      for (ix = 0; VEC_iterate (char_ptr, list, ix, fn); ++ix)
> -	{
> -	  memmove (fn, fn + (word - text),
> -		   strlen (fn) + 1 - (word - text));
> -	}
> +      htab_traverse (cdata->tracker, remove_leading_fn_component,
> +		     &offset);

====
I don't know that it'd make a difference, technically,
but use htab_traverse_noresize throughout here just to obviate the need
for the reader to have to think about it?

>      }
>    else if (!n_syms)
>      {
> @@ -837,14 +852,67 @@ new_completer_data (int size)
>  /* Free the completion data represented by P.  */
>  
>  static void
> -free_completer_data (void *p)
> +free_completer_data (struct completer_data *cdata)
>  {
> -  struct completer_data *cdata = p;
> -
>    htab_delete (cdata->tracker);
>    xfree (cdata);
>  }
>  
> +/* A hashtable traversal function to free the elements of the table.  */
> +
> +static int
> +free_entry_callback (void **slot, void *calldata)
> +{
> +  char *element = *slot;
> +
> +  xfree (element);
> +  return 1;
> +}
> +
> +/* A cleanup function to free all data associated with the completer_data
> +   given by P.  */
> +
> +static void
> +free_all_completer_data (void *p)
> +{
> +  struct completer_data *cdata = p;
> +
> +  htab_traverse (cdata->tracker, free_entry_callback, NULL);

====
This isn't needed if one specifies a function for the del_f parameter
to htab_create_alloc, which is a good thing to have in general now that
the hashtable "owns" the strings.

> +  free_completer_data (cdata);
> +}
> +
> +/* A hashtable traversal function to turn the hashtable keys
> +   into a vector.  */
> +
> +static int
> +vectorize_htab (void **slot, void *calldata)
> +{
> +  char *element = *slot;
> +  VEC (char_ptr) **vector = calldata;
> +
> +  VEC_safe_push (char_ptr, *vector, element);
> +  return 1;
> +}
> +
> +/* See completer.h.  */
> +
> +VEC (char_ptr) *
> +get_completion_list (const struct completer_data *cdata)
> +{
> +  VEC (char_ptr) *result = NULL;
> +
> +  htab_traverse (cdata->tracker, vectorize_htab, &result);
> +  return result;
> +}
> +
> +/* See completer.h.  */
> +
> +size_t
> +get_completion_count (const struct completer_data *cdata)
> +{
> +  return htab_elements (cdata->tracker);
> +}
> +
>  /* Add the completion NAME to the list of generated completions if
>     it is not there already.
>     If max_completions is negative, nothing is done, not even watching
> @@ -855,12 +923,11 @@ maybe_add_completion (struct completer_data *cdata, char *name)
>  {
>    void **slot;
>  
> -  if (max_completions < 0)
> -    return MAYBE_ADD_COMPLETION_OK;
>    if (max_completions == 0)
>      return MAYBE_ADD_COMPLETION_MAX_REACHED;
>  
> -  if (htab_elements (cdata->tracker) >= max_completions)
> +  if (max_completions > 0
> +      && htab_elements (cdata->tracker) >= max_completions)
>      return MAYBE_ADD_COMPLETION_MAX_REACHED;
>  
>    slot = htab_find_slot (cdata->tracker, name, INSERT);
> @@ -870,7 +937,8 @@ maybe_add_completion (struct completer_data *cdata, char *name)
>  
>    *slot = name;
>  
> -  return (htab_elements (cdata->tracker) < max_completions
> +  return ((max_completions < 0
> +	   || htab_elements (cdata->tracker) < max_completions)
>  	  ? MAYBE_ADD_COMPLETION_OK
>  	  : MAYBE_ADD_COMPLETION_OK_MAX_REACHED);
>  }
> @@ -968,66 +1036,20 @@ throw_max_completions_reached_error (void)
>  VEC (char_ptr) *
>  complete_line (const char *text, const char *line_buffer, int point)
>  {
> -  VEC (char_ptr) *list;
> -  VEC (char_ptr) *result = NULL;
> -  struct cleanup *cdata_cleanup, *list_cleanup;
> -  char *candidate;
> -  int ix;
> +  VEC (char_ptr) *result;
> +  struct cleanup *cdata_cleanup;
>    struct completer_data *cdata;
>  
>    if (max_completions == 0)
>      return NULL;
>  
>    cdata = new_completer_data (max_completions);
> -  cdata_cleanup = make_cleanup (free_completer_data, cdata);
> -  list = complete_line_internal (cdata, text, line_buffer, point,
> -				 handle_completions);
> -  if (max_completions < 0)
> -    {
> -      do_cleanups (cdata_cleanup);
> -      return list;
> -    }
> -
> -  list_cleanup = make_cleanup_free_char_ptr_vec (list);
> -
> -  /* If complete_line_internal returned more completions than were
> -     recorded by the completion tracker, then the completer function that
> -     was run does not support completion tracking.  In this case,
> -     do a final test for too many completions.
> -
> -     Duplicates are also removed here.  Otherwise the user is left
> -     scratching his/her head: readline and complete_command will remove
> -     duplicates, and if removal of duplicates there brings the total under
> -     max_completions the user may think gdb quit searching too early.  */

====
I'd like to keep this comment in some form.
I think it's important to document why we remove duplicates.

> -
> -  if (VEC_length (char_ptr, list) > htab_elements (cdata->tracker))
> -    {
> -      enum add_completion_status max_reached = ADD_COMPLETION_OK;
> -
> -      /* Clear the tracker so that we can re-use it to count the number
> -	 of returned completions.  */
> -      htab_empty (cdata->tracker);
> -
> -      for (ix = 0; (max_reached == ADD_COMPLETION_OK
> -		    && VEC_iterate (char_ptr, list, ix, candidate)); ++ix)
> -	{
> -	  max_reached = add_completion (cdata, &result, candidate, NULL, NULL);
> -	}
> -
> -      /* The return result has been assembled and the original list from
> -	 complete_line_internal is no longer needed.  Free it.  */
> -      do_cleanups (list_cleanup);
> -    }
> -  else
> -    {
> -      /* There is a valid tracker for the completion -- simply return
> -	 the completed list.  */
> -      discard_cleanups (list_cleanup);
> -      result = list;
> -    }
> -
> -  do_cleanups (cdata_cleanup);
> -
> +  cdata_cleanup = make_cleanup (free_all_completer_data, cdata);
> +  complete_line_internal (cdata, text, line_buffer, point,
> +			  handle_completions);
> +  result = get_completion_list (cdata);
> +  discard_cleanups (cdata_cleanup);
> +  free_completer_data (cdata);
>    return result;
>  }
>  
> @@ -1175,10 +1197,12 @@ gdb_completion_word_break_characters (void)
>    struct cleanup *cleanup;
>  
>    cdata = new_completer_data (max_completions);
> -  cleanup = make_cleanup (free_completer_data, cdata);
> -  list = complete_line_internal (cdata, rl_line_buffer, rl_line_buffer,
> -				 rl_point, handle_brkchars);
> -  do_cleanups (cleanup);
> +  cleanup = make_cleanup (free_all_completer_data, cdata);
> +  complete_line_internal (cdata, rl_line_buffer, rl_line_buffer,
> +			  rl_point, handle_brkchars);
> +  list = get_completion_list (cdata);
> +  discard_cleanups (cleanup);
> +  free_completer_data (cdata);
>    gdb_assert (list == NULL);
>    return rl_completer_word_break_characters;
>  }
> diff --git a/gdb/completer.h b/gdb/completer.h
> index 98b7d14..07c7d93 100644
> --- a/gdb/completer.h
> +++ b/gdb/completer.h
> @@ -132,6 +132,15 @@ extern const char *skip_quoted (const char *);
>  
>  extern int get_maximum_completions (void);
>  
> +/* Get the list of completions.  */
> +
> +extern VEC (char_ptr) *
> +  get_completion_list (const struct completer_data *cdata);
> +
> +/* Get the number of completions in CDATA.  */
> +
> +extern size_t get_completion_count (const struct completer_data *cdata);
> +
>  /* Return values for add_completion.  */
>  
>  enum add_completion_status
> diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
> index 36e352e..cf76bd1 100644
> --- a/gdb/python/py-cmd.c
> +++ b/gdb/python/py-cmd.c
> @@ -406,7 +406,7 @@ cmdpy_completer (struct completer_data *cdata,
>  
>        /* If we got some results, ignore problems.  Otherwise, report
>  	 the problem.  */
> -      if (result != NULL && PyErr_Occurred ())
> +      if (get_completion_count (cdata) > 0 && PyErr_Occurred ())
>  	PyErr_Clear ();
>      }
>  

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 19/19] Remove the vector return result from the completion API.
  2015-08-06 19:58 ` [PATCH v3 19/19] Remove the vector return result from the completion API Keith Seitz
@ 2015-08-23 18:03   ` Doug Evans
  0 siblings, 0 replies; 45+ messages in thread
From: Doug Evans @ 2015-08-23 18:03 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

Keith Seitz <keiths@redhat.com> writes:
> Differences in this revision:
>
> 1. Updated new TUI completion functions.
>
> ---
>
> This patch completes the redesign of the completion and completion-
> limiting API.  Since the completer's internal data is now responsible
> for tracking all completions and the result of the completion operation
> no longer uses vectors (except for the final list given to readline),
> we can remove the vectors from the API entirely.
>
> gdb/ChangeLog
>
> 	* command.h (completer_ftype): Change return type from
> 	VEC (char_ptr) * to void.  Update all users of this definition.
> 	* completer.h (add_completion): Remove vector argument.
> 	All users updated.
> 	* symtab.c (free_completion_list): Remove.
> 	(do_free_completion_list): Remove.
> 	(return_val): Remove global.

Hi.
Just a couple of nits.

> diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
> index 5df08be..5effb48 100644
> --- a/gdb/ada-lang.c
> +++ b/gdb/ada-lang.c
> @@ -6199,8 +6199,7 @@ symbol_completion_match (const char *sym_name,
>     encoded).  */
>  
>  static enum add_completion_status
> -symbol_completion_add (VEC(char_ptr) **sv,
> -		       struct completer_data *cdata,
> +symbol_completion_add (struct completer_data *cdata,
>                         const char *sym_name,
>                         const char *text, int text_len,
>                         const char *orig_text, const char *word,
> @@ -6213,14 +6212,13 @@ symbol_completion_add (VEC(char_ptr) **sv,
>  
>    /* We found a match, so add the appropriate completion to the given
>       string vector.  */
> -  return add_completion (cdata, sv, match, orig_text, word);
> +  return add_completion (cdata, match, orig_text, word);
>  }
>  
>  /* An object of this type is passed as the user_data argument to the
>     expand_symtabs_matching method.  */
>  struct add_partial_datum
>  {
> -  VEC(char_ptr) **completions;
>    const char *text;
>    int text_len;
>    const char *text0;
> @@ -6243,7 +6241,7 @@ ada_complete_symbol_matcher (const char *name, void *user_data)
>  /* Return a list of possible symbol names completing TEXT0.  WORD is
>     the entire command on which completion is made.  */
>  
> -static VEC (char_ptr) *
> +static void
>  ada_make_symbol_completion_list (struct completer_data *cdata,
>  				 const char *text0, const char *word,
>  				 enum type_code code)
> @@ -6252,7 +6250,6 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
>    int text_len;
>    int wild_match_p;
>    int encoded_p;
> -  VEC(char_ptr) *completions = VEC_alloc (char_ptr, 128);
>    struct symbol *sym;
>    struct compunit_symtab *s;
>    struct minimal_symbol *msymbol;
> @@ -6293,7 +6290,6 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
>    {
>      struct add_partial_datum data;
>  
> -    data.completions = &completions;
>      data.text = text;
>      data.text_len = text_len;
>      data.text0 = text0;
> @@ -6312,14 +6308,13 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
>    ALL_MSYMBOLS (objfile, msymbol)
>    {
>      QUIT;
> -    status = symbol_completion_add (&completions, cdata,
> -					 MSYMBOL_LINKAGE_NAME (msymbol),
> -					 text, text_len, text0, word,
> -					 wild_match_p, encoded_p);
> +    status = symbol_completion_add (cdata, MSYMBOL_LINKAGE_NAME (msymbol),
> +				    text, text_len, text0, word,
> +				    wild_match_p, encoded_p);
>      if (status == ADD_COMPLETION_MAX_REACHED)
>        {
>  	do_cleanups (old_chain);
> -	return completions;
> +	return;
>        }
>    }
>  
> @@ -6333,14 +6328,13 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
>  
>        ALL_BLOCK_SYMBOLS (b, iter, sym)
>        {
> -        status = symbol_completion_add (&completions, cdata,
> -					     SYMBOL_LINKAGE_NAME (sym),
> -					     text, text_len, text0, word,
> -					     wild_match_p, encoded_p);
> +        status = symbol_completion_add (cdata, SYMBOL_LINKAGE_NAME (sym),
> +					text, text_len, text0, word,
> +					wild_match_p, encoded_p);
>  	if (status == ADD_COMPLETION_MAX_REACHED)
>  	  {
>  	    do_cleanups (old_chain);
> -	    return completions;
> +	    return;
>  	  }
>        }
>      }
> @@ -6354,14 +6348,13 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
>      b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (s), GLOBAL_BLOCK);
>      ALL_BLOCK_SYMBOLS (b, iter, sym)
>      {
> -      status = symbol_completion_add (&completions, cdata,
> -					   SYMBOL_LINKAGE_NAME (sym),
> -					   text, text_len, text0, word,
> -					   wild_match_p, encoded_p);
> +      status = symbol_completion_add (cdata,SYMBOL_LINKAGE_NAME (sym),
> +				      text, text_len, text0, word,
> +				      wild_match_p, encoded_p);
>        if (status == ADD_COMPLETION_MAX_REACHED)
>  	{
>  	  do_cleanups (old_chain);
> -	  return completions;
> +	  return;
>  	}
>      }
>    }
> @@ -6375,20 +6368,18 @@ ada_make_symbol_completion_list (struct completer_data *cdata,
>        continue;
>      ALL_BLOCK_SYMBOLS (b, iter, sym)
>      {
> -      status = symbol_completion_add (&completions, cdata,
> -					   SYMBOL_LINKAGE_NAME (sym),
> -					   text, text_len, text0, word,
> -					   wild_match_p, encoded_p);
> +      status = symbol_completion_add (cdata, SYMBOL_LINKAGE_NAME (sym),
> +				      text, text_len, text0, word,
> +				      wild_match_p, encoded_p);
>        if (status == ADD_COMPLETION_MAX_REACHED)
>  	{
>  	  do_cleanups (old_chain);
> -	  return completions;
> +	  return;
>  	}
>      }
>    }
>  
>    do_cleanups (old_chain);
> -  return completions;
>  }
>  
>                                  /* Field Access */
> diff --git a/gdb/break-catch-syscall.c b/gdb/break-catch-syscall.c
> index 4677132..a542826 100644
> --- a/gdb/break-catch-syscall.c
> +++ b/gdb/break-catch-syscall.c
> @@ -591,17 +591,17 @@ catching_syscall_number (int syscall_number)
>  }
>  
>  /* Complete syscall names.  Used by "catch syscall".  */
> -static VEC (char_ptr) *
> +static void
>  catch_syscall_completer (struct completer_data *cdata,
>  			 struct cmd_list_element *cmd,
>                           const char *text, const char *word)
>  {
>    const char **list = get_syscall_names (get_current_arch ());
> -  VEC (char_ptr) *retlist
> -    = (list == NULL) ? NULL : complete_on_enum (cdata, list, word, word);
> +
> +  if (list != NULL)
> +    complete_on_enum (cdata, list, word, word);
>  
>    xfree (list);
> -  return retlist;
>  }
>  
>  static void
> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
> index 24243c4..08901ae 100644
> --- a/gdb/breakpoint.c
> +++ b/gdb/breakpoint.c
> @@ -1032,7 +1032,7 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp,
>  
>  /* Completion for the "condition" command.  */
>  
> -static VEC (char_ptr) *
> +static void
>  condition_completer (struct completer_data *cdata,
>  		     struct cmd_list_element *cmd,
>  		     const char *text, const char *word)
> @@ -1045,14 +1045,13 @@ condition_completer (struct completer_data *cdata,
>      {
>        int len;
>        struct breakpoint *b;
> -      VEC (char_ptr) *result = NULL;
>  
>        if (text[0] == '$')
>  	{
>  	  /* We don't support completion of history indices.  */
> -	  if (isdigit (text[1]))
> -	    return NULL;
> -	  return complete_internalvar (cdata, &text[1]);
> +	  if (!isdigit (text[1]))
> +	    complete_internalvar (cdata, &text[1]);
> +	  return;
>  	}
>  
>        /* We're completing the breakpoint number.  */
> @@ -1066,18 +1065,18 @@ condition_completer (struct completer_data *cdata,
>  
>  	  if (strncmp (number, text, len) == 0)
>  	    {
> -	      if (add_completion (cdata, &result, number, NULL, NULL)
> +	      if (add_completion (cdata, number, NULL, NULL)
>  		  == ADD_COMPLETION_MAX_REACHED)
>  		break;
>  	    }
>  	}
>  
> -      return result;
> +      return;
>      }
>  
>    /* We're completing the expression part.  */
>    text = skip_spaces_const (space);
> -  return expression_completer (cdata, cmd, text, word);
> +  expression_completer (cdata, cmd, text, word);
>  }
>  
>  /* condition N EXP -- set break condition of breakpoint N to EXP.  */
> diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
> index 9691fd1..9e7bf80 100644
> --- a/gdb/cli/cli-decode.c
> +++ b/gdb/cli/cli-decode.c
> @@ -647,7 +647,7 @@ add_setshow_optional_filename_cmd (const char *name, enum command_class theclass
>  /* Completes on literal "unlimited".  Used by integer commands that
>     support a special "unlimited" value.  */
>  
> -static VEC (char_ptr) *
> +static void
>  integer_unlimited_completer (struct completer_data *cdata,
>  			     struct cmd_list_element *ignore,
>  			     const char *text, const char *word)
> @@ -658,7 +658,7 @@ integer_unlimited_completer (struct completer_data *cdata,
>        NULL,
>      };
>  
> -  return complete_on_enum (cdata, keywords, text, word);
> +  complete_on_enum (cdata, keywords, text, word);
>  }
>  
>  /* Add element named NAME to both the set and show command LISTs (the
> @@ -1757,22 +1757,21 @@ lookup_cmd_composition (const char *text,
>  
>  /* Helper function for SYMBOL_COMPLETION_FUNCTION.  */
>  
> -/* Return a vector of char pointers which point to the different
> -   possible completions in LIST of TEXT.
> +/* Add completions to CDATA for the different possible completions
> +   in LIST of TEXT.
>  
>     WORD points in the same buffer as TEXT, and completions should be
>     returned relative to this position.  For example, suppose TEXT is
>     "foo" and we want to complete to "foobar".  If WORD is "oo", return
>     "oobar"; if WORD is "baz/foo", return "baz/foobar".  */
>  
> -VEC (char_ptr) *
> +void
>  complete_on_cmdlist (struct completer_data *cdata,
>  		     struct cmd_list_element *list,
>  		     const char *text, const char *word,
>  		     int ignore_help_classes)
>  {
>    struct cmd_list_element *ptr;
> -  VEC (char_ptr) *matchlist = NULL;
>    int textlen = strlen (text);
>    int pass;
>    int saw_deprecated_match = 0;
> @@ -1798,35 +1797,32 @@ complete_on_cmdlist (struct completer_data *cdata,
>  		  }
>  	      }
>  
> -	    if (add_completion (cdata, &matchlist, ptr->name, text, word)
> +	    if (add_completion (cdata, ptr->name, text, word)
>  		== ADD_COMPLETION_MAX_REACHED)
> -	      return matchlist;
> +	      return;
>  	  }
>        /* If we saw no matching deprecated commands in the first pass,
>  	 just bail out.  */
>        if (!saw_deprecated_match)
>  	break;
>      }
> -
> -  return matchlist;
>  }
>  
>  /* Helper function for SYMBOL_COMPLETION_FUNCTION.  */
>  
> -/* Return a vector of char pointers which point to the different
> -   possible completions in CMD of TEXT.
> +/* Add completions to CDATA for the different possible completions in
> +   CMD of TEXT.
>  
>     WORD points in the same buffer as TEXT, and completions should be
>     returned relative to this position.  For example, suppose TEXT is "foo"
>     and we want to complete to "foobar".  If WORD is "oo", return
>     "oobar"; if WORD is "baz/foo", return "baz/foobar".  */
>  
> -VEC (char_ptr) *
> +void
>  complete_on_enum (struct completer_data *cdata,
>  		  const char *const *enumlist,
>  		  const char *text, const char *word)
>  {
> -  VEC (char_ptr) *matchlist = NULL;
>    int textlen = strlen (text);
>    int i;
>    const char *name;
> @@ -1834,12 +1830,10 @@ complete_on_enum (struct completer_data *cdata,
>    for (i = 0; (name = enumlist[i]) != NULL; i++)
>      if (strncmp (name, text, textlen) == 0)
>        {
> -	if (add_completion (cdata, &matchlist, name, text, word)
> +	if (add_completion (cdata, name, text, word)
>  	    == ADD_COMPLETION_MAX_REACHED)
>  	  break;
>        }
> -
> -  return matchlist;
>  }
>  
>  
> diff --git a/gdb/command.h b/gdb/command.h
> index b2aeb30..82872c0 100644
> --- a/gdb/command.h
> +++ b/gdb/command.h
> @@ -158,9 +158,9 @@ typedef void cmd_sfunc_ftype (char *args, int from_tty,
>  extern void set_cmd_sfunc (struct cmd_list_element *cmd,
>  			   cmd_sfunc_ftype *sfunc);
>  
> -typedef VEC (char_ptr) *completer_ftype (struct completer_data *,
> -					 struct cmd_list_element *,
> -					 const char *, const char *);
> +typedef void completer_ftype (struct completer_data *,
> +			      struct cmd_list_element *,
> +			      const char *, const char *);
>  
>  typedef void completer_ftype_void (struct cmd_list_element *,
>  				   const char *, const char *);
> @@ -228,13 +228,13 @@ extern struct cmd_list_element *add_info (const char *,
>  extern struct cmd_list_element *add_info_alias (const char *, const char *,
>  						int);
>  
> -extern VEC (char_ptr) *complete_on_cmdlist (struct completer_data *,
> -					    struct cmd_list_element *,
> -					    const char *, const char *, int);
> +extern void complete_on_cmdlist (struct completer_data *,
> +				 struct cmd_list_element *,
> +				 const char *, const char *, int);
>  
> -extern VEC (char_ptr) *complete_on_enum (struct completer_data *,
> -					 const char *const *enumlist,
> -					 const char *, const char *);
> +extern void complete_on_enum (struct completer_data *,
> +			      const char *const *enumlist,
> +			      const char *, const char *);
>  
>  /* Functions that implement commands about CLI commands.  */
>  
> diff --git a/gdb/completer.c b/gdb/completer.c
> index 6faed31..2ca7d2d 100644
> --- a/gdb/completer.c
> +++ b/gdb/completer.c
> @@ -144,22 +144,23 @@ readline_line_completion_function (const char *text, int matches)
>  
>  /* This can be used for functions which don't want to complete on
>     symbols but don't want to complete on anything else either.  */
> -VEC (char_ptr) *
> +
> +void
>  noop_completer (struct completer_data *cdata,
>  		struct cmd_list_element *ignore,
>  		const char *text, const char *prefix)
>  {
> -  return NULL;
> +  /* Nothing.  */
>  }
>  
>  /* Complete on filenames.  */
> -VEC (char_ptr) *
> +
> +void
>  filename_completer (struct completer_data *cdata,
>  		    struct cmd_list_element *ignore,
>  		    const char *text, const char *word)
>  {
>    int subsequent_name;
> -  VEC (char_ptr) *return_val = NULL;
>  
>    subsequent_name = 0;
>    while (1)
> @@ -182,7 +183,7 @@ filename_completer (struct completer_data *cdata,
>  	  continue;
>  	}
>  
> -      if (add_completion (cdata, &return_val, p, text, word)
> +      if (add_completion (cdata, p, text, word)
>  	  == ADD_COMPLETION_MAX_REACHED)
>  	break;
>      }
> @@ -194,7 +195,6 @@ filename_completer (struct completer_data *cdata,
>       with respect to inserting quotes.  */
>    rl_completer_word_break_characters = "";
>  #endif
> -  return return_val;
>  }
>  
>  /* A hashtable traversal function to remove leading file name
> @@ -220,14 +220,12 @@ remove_leading_fn_component (void **slot, void *calldata)
>     This is intended to be used in commands that set breakpoints
>     etc.  */
>  
> -VEC (char_ptr) *
> +void
>  location_completer (struct completer_data *cdata,
>  		    struct cmd_list_element *ignore,
>  		    const char *text, const char *word)
>  {
>    int n_syms, n_files, ix;
> -  VEC (char_ptr) *fn_list = NULL;
> -  VEC (char_ptr) *list = NULL;
>    const char *p;
>    int quote_found = 0;
>    int quoted = *text == '\'' || *text == '"';
> @@ -298,15 +296,15 @@ location_completer (struct completer_data *cdata,
>       symbols as well as on files.  */
>    if (colon)
>      {
> -      list = make_file_symbol_completion_list (cdata, symbol_start, word,
> -					       file_to_match);
> +      make_file_symbol_completion_list (cdata, symbol_start, word,
> +					file_to_match);
>        n_syms = get_completion_count (cdata);
>        n_files = 0;
>        xfree (file_to_match);
>      }
>    else
>      {
> -      list = make_symbol_completion_list (cdata, symbol_start, word);
> +      make_symbol_completion_list (cdata, symbol_start, word);
>        n_syms = get_completion_count (cdata);
>        n_files = 0;
>        /* If text includes characters which cannot appear in a file
> @@ -314,27 +312,11 @@ location_completer (struct completer_data *cdata,
>        if (strcspn (text, 
>  		   gdb_completer_file_name_break_characters) == text_len)
>  	{
> -	  fn_list = make_source_files_completion_list (cdata, text, text);
> +	  make_source_files_completion_list (cdata, text, text);
>  	  n_files = get_completion_count (cdata) - n_syms;
>  	}
>      }
>  
> -  /* Catenate fn_list[] onto the end of list[].  */
> -  if (!n_syms)
> -    {
> -      VEC_free (char_ptr, list); /* Paranoia.  */
> -      list = fn_list;
> -      fn_list = NULL;
> -    }
> -  else
> -    {
> -      char *fn;
> -
> -      for (ix = 0; VEC_iterate (char_ptr, fn_list, ix, fn); ++ix)
> -	VEC_safe_push (char_ptr, list, fn);
> -      VEC_free (char_ptr, fn_list);
> -    }
> -
>    if (n_syms && n_files)
>      {
>        /* Nothing.  */
> @@ -365,18 +347,15 @@ location_completer (struct completer_data *cdata,
>      {
>        /* No completions at all.  As the final resort, try completing
>  	 on the entire text as a symbol.  */
> -      list = make_symbol_completion_list (cdata, orig_text, word);
> +      make_symbol_completion_list (cdata, orig_text, word);
>      }
> -
> -  return list;
>  }
>  
>  /* Helper for expression_completer which recursively adds field and
>     method names from TYPE, a struct or union type, to the array
>     OUTPUT.  */

====
Function comment needs updating.

>  static void
> -add_struct_fields (struct completer_data *cdata,
> -		   struct type *type, VEC (char_ptr) **output,
> +add_struct_fields (struct completer_data *cdata, struct type *type,
>  		   char *fieldname, int namelen)
>  {
>    int i;
> @@ -388,7 +367,7 @@ add_struct_fields (struct completer_data *cdata,
>      {
>        if (i < TYPE_N_BASECLASSES (type))
>  	add_struct_fields (cdata, TYPE_BASECLASS (type, i),
> -			   output, fieldname, namelen);
> +			   fieldname, namelen);
>        else if (TYPE_FIELD_NAME (type, i))
>  	{
>  	  if (TYPE_FIELD_NAME (type, i)[0] != '\0')
> @@ -396,7 +375,7 @@ add_struct_fields (struct completer_data *cdata,
>  	      if (! strncmp (TYPE_FIELD_NAME (type, i), 
>  			     fieldname, namelen))
>  		{
> -		  if (add_completion (cdata, output, TYPE_FIELD_NAME (type, i),
> +		  if (add_completion (cdata, TYPE_FIELD_NAME (type, i),
>  				      NULL, NULL)
>  		      == ADD_COMPLETION_MAX_REACHED)
>  		    return;
> @@ -406,7 +385,7 @@ add_struct_fields (struct completer_data *cdata,
>  	    {
>  	      /* Recurse into anonymous unions.  */
>  	      add_struct_fields (cdata, TYPE_FIELD_TYPE (type, i),
> -				 output, fieldname, namelen);
> +				 fieldname, namelen);
>  	    }
>  	}
>      }
> @@ -425,7 +404,7 @@ add_struct_fields (struct completer_data *cdata,
>  	  /* Omit constructors from the completion list.  */
>  	  if (!type_name || strcmp (type_name, name))
>  	    {
> -	      if (add_completion (cdata, output, name, NULL, NULL)
> +	      if (add_completion (cdata, name, NULL, NULL)
>  		  == ADD_COMPLETION_MAX_REACHED)
>  		return;
>  	    }
> @@ -436,7 +415,8 @@ add_struct_fields (struct completer_data *cdata,
>  /* Complete on expressions.  Often this means completing on symbol
>     names, but some language parsers also have support for completing
>     field names.  */
> -VEC (char_ptr) *
> +
> +void
>  expression_completer (struct completer_data *cdata,
>  		      struct cmd_list_element *ignore,
>  		      const char *text, const char *word)
> @@ -455,7 +435,7 @@ expression_completer (struct completer_data *cdata,
>      }
>    CATCH (except, RETURN_MASK_ERROR)
>      {
> -      return NULL;
> +      return;
>      }
>    END_CATCH
>  
> @@ -474,22 +454,19 @@ expression_completer (struct completer_data *cdata,
>  	  || TYPE_CODE (type) == TYPE_CODE_STRUCT)
>  	{
>  	  int flen = strlen (fieldname);
> -	  VEC (char_ptr) *result = NULL;
>  
> -	  add_struct_fields (cdata, type, &result, fieldname, flen);
> +	  add_struct_fields (cdata, type, fieldname, flen);
>  	  xfree (fieldname);
> -	  return result;
> +	  return;
>  	}
>      }
>    else if (fieldname && code != TYPE_CODE_UNDEF)
>      {
> -      VEC (char_ptr) *result;
>        struct cleanup *cleanup = make_cleanup (xfree, fieldname);
>  
> -      result
> -	= make_symbol_completion_type (cdata, fieldname, fieldname, code);
> +      make_symbol_completion_type (cdata, fieldname, fieldname, code);
>        do_cleanups (cleanup);
> -      return result;
> +      return;
>      }
>    xfree (fieldname);
>  
> @@ -501,7 +478,7 @@ expression_completer (struct completer_data *cdata,
>      ;
>  
>    /* Not ideal but it is what we used to do before...  */
> -  return location_completer (cdata, ignore, p, word);
> +  location_completer (cdata, ignore, p, word);
>  }
>  
>  /* See definition in completer.h.  */
> @@ -578,12 +555,11 @@ complete_line_internal_reason;
>     once sub-command completions are exhausted, we simply return NULL.
>   */
>  
> -static VEC (char_ptr) *
> +static void
>  complete_line_internal (struct completer_data *cdata,
>  			const char *text, const char *line_buffer, int point,
>  			complete_line_internal_reason reason)
>  {
> -  VEC (char_ptr) *list = NULL;
>    char *tmp_command;
>    const char *p;
>    int ignore_help_classes;
> @@ -638,7 +614,7 @@ complete_line_internal (struct completer_data *cdata,
>      {
>        /* It is an unrecognized command.  So there are no
>  	 possible completions.  */
> -      list = NULL;
> +      return;
>      }
>    else if (c == CMD_LIST_AMBIGUOUS)
>      {
> @@ -656,7 +632,7 @@ complete_line_internal (struct completer_data *cdata,
>  	     example, "info t " or "info t foo" does not complete
>  	     to anything, because "info t" can be "info target" or
>  	     "info terminal".  */
> -	  list = NULL;
> +	  return;
>  	}
>        else
>  	{
> @@ -665,14 +641,14 @@ complete_line_internal (struct completer_data *cdata,
>  	  if (result_list)
>  	    {
>  	      if (reason != handle_brkchars)
> -		list = complete_on_cmdlist (cdata, *result_list->prefixlist,
> -					    p, word, ignore_help_classes);
> +		complete_on_cmdlist (cdata, *result_list->prefixlist,
> +				     p, word, ignore_help_classes);
>  	    }
>  	  else
>  	    {
>  	      if (reason != handle_brkchars)
> -		list = complete_on_cmdlist (cdata, cmdlist, p, word,
> -					    ignore_help_classes);
> +		complete_on_cmdlist (cdata, cmdlist, p, word,
> +				     ignore_help_classes);
>  	    }
>  	  /* Ensure that readline does the right thing with respect to
>  	     inserting quotes.  */
> @@ -698,8 +674,8 @@ complete_line_internal (struct completer_data *cdata,
>  		  /* It is a prefix command; what comes after it is
>  		     a subcommand (e.g. "info ").  */
>  		  if (reason != handle_brkchars)
> -		    list = complete_on_cmdlist (cdata, *c->prefixlist, p,
> -						word, ignore_help_classes);
> +		    complete_on_cmdlist (cdata, *c->prefixlist, p,
> +					 word, ignore_help_classes);
>  
>  		  /* Ensure that readline does the right thing
>  		     with respect to inserting quotes.  */
> @@ -707,11 +683,11 @@ complete_line_internal (struct completer_data *cdata,
>  		    gdb_completer_command_word_break_characters;
>  		}
>  	      else if (reason == handle_help)
> -		list = NULL;
> +		return;
>  	      else if (c->enums)
>  		{
>  		  if (reason != handle_brkchars)
> -		    list = complete_on_enum (cdata, c->enums, p, word);
> +		    complete_on_enum (cdata, c->enums, p, word);
>  		  rl_completer_word_break_characters =
>  		    gdb_completer_command_word_break_characters;
>  		}
> @@ -751,7 +727,7 @@ complete_line_internal (struct completer_data *cdata,
>  		      && c->completer_handle_brkchars != NULL)
>  		    (*c->completer_handle_brkchars) (c, p, word);
>  		  if (reason != handle_brkchars && c->completer != NULL)
> -		    list = (*c->completer) (cdata, c, p, word);
> +		    (*c->completer) (cdata, c, p, word);
>  		}
>  	    }
>  	  else
> @@ -773,8 +749,8 @@ complete_line_internal (struct completer_data *cdata,
>  		}
>  
>  	      if (reason != handle_brkchars)
> -		list = complete_on_cmdlist (cdata, result_list, q, word,
> -					    ignore_help_classes);
> +		complete_on_cmdlist (cdata, result_list, q, word,
> +				     ignore_help_classes);
>  
>  	      /* Ensure that readline does the right thing
>  		 with respect to inserting quotes.  */
> @@ -783,7 +759,7 @@ complete_line_internal (struct completer_data *cdata,
>  	    }
>  	}
>        else if (reason == handle_help)
> -	list = NULL;
> +	return;
>        else
>  	{
>  	  /* There is non-whitespace beyond the command.  */
> @@ -792,12 +768,12 @@ complete_line_internal (struct completer_data *cdata,
>  	    {
>  	      /* It is an unrecognized subcommand of a prefix command,
>  		 e.g. "info adsfkdj".  */
> -	      list = NULL;
> +	      return;
>  	    }
>  	  else if (c->enums)
>  	    {
>  	      if (reason != handle_brkchars)
> -		list = complete_on_enum (cdata, c->enums, p, word);
> +		complete_on_enum (cdata, c->enums, p, word);
>  	    }
>  	  else
>  	    {
> @@ -827,12 +803,10 @@ complete_line_internal (struct completer_data *cdata,
>  		  && c->completer_handle_brkchars != NULL)
>  		(*c->completer_handle_brkchars) (c, p, word);
>  	      if (reason != handle_brkchars && c->completer != NULL)
> -		list = (*c->completer) (cdata, c, p, word);
> +		(*c->completer) (cdata, c, p, word);
>  	    }
>  	}
>      }
> -
> -  return list;
>  }
>  
>  /* Allocate a new completer data structure.  */
> @@ -986,8 +960,8 @@ get_maximum_completions (void)
>  /* See completer.h.  */
>  
>  enum add_completion_status
> -add_completion (struct completer_data *cdata, VEC (char_ptr) **result,
> -		const char *match, const char *text, const char *word)
> +add_completion (struct completer_data *cdata, const char *match,
> +		const char *text, const char *word)
>  {
>    enum maybe_add_completion_enum add_status;
>    char *alloc = completer_strdup (match, text, word);
> @@ -996,10 +970,8 @@ add_completion (struct completer_data *cdata, VEC (char_ptr) **result,
>    switch (add_status)
>      {
>      case MAYBE_ADD_COMPLETION_OK:
> -      VEC_safe_push (char_ptr, *result, alloc);
>        break;
>      case MAYBE_ADD_COMPLETION_OK_MAX_REACHED:
> -      VEC_safe_push (char_ptr, *result, alloc);
>        return ADD_COMPLETION_MAX_REACHED;
>      case MAYBE_ADD_COMPLETION_MAX_REACHED:
>        xfree (alloc);
> @@ -1054,23 +1026,23 @@ complete_line (const char *text, const char *line_buffer, int point)
>  }
>  
>  /* Complete on command names.  Used by "help".  */
> -VEC (char_ptr) *
> +
> +void
>  command_completer (struct completer_data *cdata,
>  		   struct cmd_list_element *ignore,
>  		   const char *text, const char *word)
>  {
> -  return complete_line_internal (cdata, word, text,
> -				 strlen (text), handle_help);
> +  complete_line_internal (cdata, word, text,
> +			  strlen (text), handle_help);
>  }
>  
>  /* Complete on signals.  */
>  
> -VEC (char_ptr) *
> +void
>  signal_completer (struct completer_data *cdata,
>  		  struct cmd_list_element *ignore,
>  		  const char *text, const char *word)
>  {
> -  VEC (char_ptr) *return_val = NULL;
>    size_t len = strlen (word);
>    int signum;
>    const char *signame;
> @@ -1089,13 +1061,11 @@ signal_completer (struct completer_data *cdata,
>  
>        if (strncasecmp (signame, word, len) == 0)
>  	{
> -	  if (add_completion (cdata, &return_val, signame, NULL, NULL)
> +	  if (add_completion (cdata, signame, NULL, NULL)
>  	      == ADD_COMPLETION_MAX_REACHED)
>  	    break;
>  	}
>      }
> -
> -  return return_val;
>  }
>  
>  /* Bit-flags for selecting what the register and/or register-group
> @@ -1110,13 +1080,12 @@ enum reg_completer_targets
>  /* Complete register names and/or reggroup names based on the value passed
>     in TARGETS.  At least one bit in TARGETS must be set.  */
>  
> -static VEC (char_ptr) *
> +static void
>  reg_or_group_completer_1 (struct completer_data *cdata,
>  			  struct cmd_list_element *ignore,
>  			  const char *text, const char *word,
>  			  enum reg_completer_targets targets)
>  {
> -  VEC (char_ptr) *result = NULL;
>    size_t len = strlen (word);
>    struct gdbarch *gdbarch;
>    const char *name;
> @@ -1124,6 +1093,8 @@ reg_or_group_completer_1 (struct completer_data *cdata,
>    gdb_assert ((targets & (complete_register_names
>  			  | complete_reggroup_names)) != 0);
>    gdbarch = get_current_arch ();
> +  if (!target_has_registers)
> +    return;

====
This change probably belongs in a separate patchset.
I could be missing something though.

>  
>    if ((targets & complete_register_names) != 0)
>      {
> @@ -1135,9 +1106,9 @@ reg_or_group_completer_1 (struct completer_data *cdata,
>  	{
>  	  if (*name != '\0' && strncmp (word, name, len) == 0)
>  	    {
> -	      if (add_completion (cdata, &result, name, NULL, NULL)
> +	      if (add_completion (cdata, name, NULL, NULL)
>  		  == ADD_COMPLETION_MAX_REACHED)
> -		return result;
> +		return;
>  	    }
>  	}
>      }
> @@ -1153,37 +1124,35 @@ reg_or_group_completer_1 (struct completer_data *cdata,
>  	  name = reggroup_name (group);
>  	  if (strncmp (word, name, len) == 0)
>  	    {
> -	      if (add_completion (cdata, &result, name, NULL, NULL)
> +	      if (add_completion (cdata, name, NULL, NULL)
>  		  == ADD_COMPLETION_MAX_REACHED)
> -		return result;
> +		return;
>  	    }
>  	}
>      }
> -
> -  return result;
>  }
>  
>  /* Perform completion on register and reggroup names.  */
>  
> -VEC (char_ptr) *
> +void
>  reg_or_group_completer (struct completer_data *cdata,
>  			struct cmd_list_element *ignore,
>  			const char *text, const char *word)
>  {
> -  return reg_or_group_completer_1 (cdata, ignore, text, word,
> -				   (complete_register_names
> -				    | complete_reggroup_names));
> +  reg_or_group_completer_1 (cdata, ignore, text, word,
> +			    (complete_register_names
> +			     | complete_reggroup_names));
>  }
>  
>  /* Perform completion on reggroup names.  */
>  
> -VEC (char_ptr) *
> +void
>  reggroup_completer (struct completer_data *cdata,
>  		    struct cmd_list_element *ignore,
>  		    const char *text, const char *word)
>  {
> -  return reg_or_group_completer_1 (cdata, ignore, text, word,
> -				   complete_reggroup_names);
> +  reg_or_group_completer_1 (cdata, ignore, text, word,
> +			    complete_reggroup_names);
>  }
>  
>  /* Get the list of chars that are considered as word breaks
> diff --git a/gdb/completer.h b/gdb/completer.h
> index 07c7d93..cfdca71 100644
> --- a/gdb/completer.h
> +++ b/gdb/completer.h
> @@ -76,37 +76,37 @@ extern VEC (char_ptr) *complete_line (const char *text,
>  extern char *readline_line_completion_function (const char *text,
>  						int matches);
>  
> -extern VEC (char_ptr) *noop_completer (struct completer_data *,
> -				       struct cmd_list_element *,
> -				       const char *, const char *);
> +extern void noop_completer (struct completer_data *,
> +			    struct cmd_list_element *,
> +			    const char *, const char *);
>  
> -extern VEC (char_ptr) *filename_completer (struct completer_data *,
> -					   struct cmd_list_element *,
> -					   const char *, const char *);
> +extern void filename_completer (struct completer_data *,
> +				struct cmd_list_element *,
> +				const char *, const char *);
>  
> -extern VEC (char_ptr) *expression_completer (struct completer_data *,
> -					     struct cmd_list_element *,
> -					     const char *, const char *);
> +extern void expression_completer (struct completer_data *,
> +				  struct cmd_list_element *,
> +				  const char *, const char *);
>  
> -extern VEC (char_ptr) *location_completer (struct completer_data *,
> -					   struct cmd_list_element *,
> -					   const char *, const char *);
> +extern void location_completer (struct completer_data *,
> +				struct cmd_list_element *,
> +				const char *, const char *);
>  
> -extern VEC (char_ptr) *command_completer (struct completer_data *,
> -					  struct cmd_list_element *,
> -					  const char *, const char *);
> +extern void command_completer (struct completer_data *,
> +			       struct cmd_list_element *,
> +			       const char *, const char *);
>  
> -extern VEC (char_ptr) *signal_completer (struct completer_data *,
> -					 struct cmd_list_element *,
> -					 const char *, const char *);
> +extern void signal_completer (struct completer_data *,
> +			      struct cmd_list_element *,
> +			      const char *, const char *);
>  
> -extern VEC (char_ptr) *reg_or_group_completer (struct completer_data *,
> -					       struct cmd_list_element *,
> -					       const char *, const char *);
> +extern void reg_or_group_completer (struct completer_data *,
> +				    struct cmd_list_element *,
> +				    const char *, const char *);
>  
> -extern VEC (char_ptr) *reggroup_completer (struct completer_data *cdata,
> -					   struct cmd_list_element *,
> -					   const char *, const char *);
> +extern void reggroup_completer (struct completer_data *cdata,
> +				struct cmd_list_element *,
> +				const char *, const char *);
>  
>  extern char *get_gdb_completer_quote_characters (void);
>  
> @@ -163,8 +163,7 @@ enum add_completion_status
>     saved into the completion list.  See completer_strdup for more.  */
>  
>  extern enum add_completion_status
> -  add_completion (struct completer_data *cdata,
> -		  VEC (char_ptr) **result, const char *match,
> +  add_completion (struct completer_data *cdata, const char *match,
>  		  const char *text, const char *word);
>  
>  /* Wrapper to throw MAX_COMPLETIONS_REACHED_ERROR.  */ 
> diff --git a/gdb/corefile.c b/gdb/corefile.c
> index 41b7cb0..4e5e96a 100644
> --- a/gdb/corefile.c
> +++ b/gdb/corefile.c
> @@ -467,7 +467,7 @@ set_gnutarget_command (char *ignore, int from_tty,
>  
>  /* A completion function for "set gnutarget".  */
>  
> -static VEC (char_ptr) *
> +static void
>  complete_set_gnutarget (struct completer_data *cdata,
>  			struct cmd_list_element *cmd,
>  			const char *text, const char *word)
> @@ -487,7 +487,7 @@ complete_set_gnutarget (struct completer_data *cdata,
>        bfd_targets[last + 1] = NULL;
>      }
>  
> -  return complete_on_enum (cdata, bfd_targets, text, word);
> +  complete_on_enum (cdata, bfd_targets, text, word);
>  }
>  
>  /* Set the gnutarget.  */
> diff --git a/gdb/cp-abi.c b/gdb/cp-abi.c
> index 504bb20..cddc382 100644
> --- a/gdb/cp-abi.c
> +++ b/gdb/cp-abi.c
> @@ -358,7 +358,7 @@ set_cp_abi_cmd (char *args, int from_tty)
>  
>  /* A completion function for "set cp-abi".  */
>  
> -static VEC (char_ptr) *
> +static void
>  cp_abi_completer (struct completer_data *cdata,
>  		  struct cmd_list_element *ignore,
>  		  const char *text, const char *word)
> @@ -375,7 +375,7 @@ cp_abi_completer (struct completer_data *cdata,
>        cp_abi_names[i] = NULL;
>      }
>  
> -  return complete_on_enum (cdata, cp_abi_names, text, word);
> +  complete_on_enum (cdata, cp_abi_names, text, word);
>  }
>  
>  /* Show the currently selected C++ ABI.  */
> diff --git a/gdb/f-lang.c b/gdb/f-lang.c
> index 15c51d9..b5886a6 100644
> --- a/gdb/f-lang.c
> +++ b/gdb/f-lang.c
> @@ -228,13 +228,13 @@ f_word_break_characters (void)
>  /* Consider the modules separator :: as a valid symbol name character
>     class.  */
>  
> -static VEC (char_ptr) *
> +static void
>  f_make_symbol_completion_list (struct completer_data *cdata,
>  			       const char *text, const char *word,
>  			       enum type_code code)
>  {
> -  return default_make_symbol_completion_list_break_on (cdata, text, word,
> -						       ":", code);
> +  default_make_symbol_completion_list_break_on (cdata, text, word,
> +						":", code);
>  }
>  
>  const struct language_defn f_language_defn =
> diff --git a/gdb/guile/scm-cmd.c b/gdb/guile/scm-cmd.c
> index 1544c2b..8816346 100644
> --- a/gdb/guile/scm-cmd.c
> +++ b/gdb/guile/scm-cmd.c
> @@ -348,8 +348,7 @@ cmdscm_bad_completion_result (const char *msg, SCM completion)
>     The result is a boolean indicating success.  */
>  
>  static int
> -cmdscm_add_completion (SCM completion, struct completer_data *cdata,
> -		       VEC (char_ptr) **result)
> +cmdscm_add_completion (SCM completion, struct completer_data *cdata)
>  {
>    char *item;
>    SCM except_scm;
> @@ -371,14 +370,14 @@ cmdscm_add_completion (SCM completion, struct completer_data *cdata,
>        return 0;
>      }
>  
> -  (void) add_completion (cdata, result, item, NULL, NULL);
> +  (void) add_completion (cdata, item, NULL, NULL);
>    xfree (item);
>    return 1;
>  }
>  
>  /* Called by gdb for command completion.  */
>  
> -static VEC (char_ptr) *
> +static void
>  cmdscm_completer (struct completer_data *cdata,
>  		  struct cmd_list_element *command,
>  		  const char *text, const char *word)
> @@ -386,7 +385,6 @@ cmdscm_completer (struct completer_data *cdata,
>    command_smob *c_smob/*obj*/ = (command_smob *) get_cmd_context (command);
>    SCM completer_result_scm;
>    SCM text_scm, word_scm, result_scm;
> -  VEC (char_ptr) *result = NULL;
>  
>    gdb_assert (c_smob != NULL);
>    gdb_assert (gdbscm_is_procedure (c_smob->complete));
> @@ -408,7 +406,7 @@ cmdscm_completer (struct completer_data *cdata,
>      {
>        /* Inform the user, but otherwise ignore.  */
>        gdbscm_print_gdb_exception (SCM_BOOL_F, completer_result_scm);
> -      goto done;
> +      return;
>      }
>  
>    if (gdbscm_is_true (scm_list_p (completer_result_scm)))
> @@ -419,11 +417,8 @@ cmdscm_completer (struct completer_data *cdata,
>  	{
>  	  SCM next = scm_car (list);
>  
> -	  if (!cmdscm_add_completion (next, cdata, &result))
> -	    {
> -	      VEC_free (char_ptr, result);
> -	      goto done;
> -	    }
> +	  if (!cmdscm_add_completion (next, cdata))
> +	    return;
>  
>  	  list = scm_cdr (list);
>  	}
> @@ -439,15 +434,11 @@ cmdscm_completer (struct completer_data *cdata,
>  	    {
>  	      /* Inform the user, but otherwise ignore the entire result.  */
>  	      gdbscm_print_gdb_exception (SCM_BOOL_F, completer_result_scm);
> -	      VEC_free (char_ptr, result);
> -	      goto done;
> +	      return;
>  	    }
>  
> -	  if (!cmdscm_add_completion (next, cdata, &result))
> -	    {
> -	      VEC_free (char_ptr, result);
> -	      goto done;
> -	    }
> +	  if (!cmdscm_add_completion (next, cdata))
> +	    return;
>  
>  	  next = itscm_safe_call_next_x (iter, NULL);
>  	}
> @@ -458,9 +449,6 @@ cmdscm_completer (struct completer_data *cdata,
>        cmdscm_bad_completion_result (_("Bad completer result: "),
>  				    completer_result_scm);
>      }
> -
> - done:
> -  return result;
>  }
>  
>  /* Helper for gdbscm_make_command which locates the command list to use and
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index d858b28..343f9da 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -7065,12 +7065,11 @@ Are you sure you want to change it? "),
>  
>  /* Complete the "handle" command.  */
>  
> -static VEC (char_ptr) *
> +static void
>  handle_completer (struct completer_data *cdata,
>  		  struct cmd_list_element *ignore,
>  		  const char *text, const char *word)
>  {
> -  VEC (char_ptr) *vec_signals, *vec_keywords, *return_val;
>    static const char * const keywords[] =
>      {
>        "all",
> @@ -7085,13 +7084,8 @@ handle_completer (struct completer_data *cdata,
>        NULL,
>      };
>  
> -  vec_signals = signal_completer (cdata, ignore, text, word);
> -  vec_keywords = complete_on_enum (cdata, keywords, word, word);
> -
> -  return_val = VEC_merge (char_ptr, vec_signals, vec_keywords);
> -  VEC_free (char_ptr, vec_signals);
> -  VEC_free (char_ptr, vec_keywords);
> -  return return_val;
> +  signal_completer (cdata, ignore, text, word);
> +  complete_on_enum (cdata, keywords, word, word);
>  }
>  
>  enum gdb_signal
> diff --git a/gdb/interps.c b/gdb/interps.c
> index 9e993c8..19cb716 100644
> --- a/gdb/interps.c
> +++ b/gdb/interps.c
> @@ -434,13 +434,12 @@ interpreter_exec_cmd (char *args, int from_tty)
>  }
>  
>  /* List the possible interpreters which could complete the given text.  */
> -static VEC (char_ptr) *
> +static void
>  interpreter_completer (struct completer_data *cdata,
>  		       struct cmd_list_element *ignore,
>  		       const char *text, const char *word)
>  {
>    int textlen;
> -  VEC (char_ptr) *matches = NULL;
>    struct interp *interp;
>  
>    textlen = strlen (text);
> @@ -448,13 +447,11 @@ interpreter_completer (struct completer_data *cdata,
>      {
>        if (strncmp (interp->name, text, textlen) == 0)
>  	{
> -	  if (add_completion (cdata, &matches, interp->name, text, word)
> +	  if (add_completion (cdata, interp->name, text, word)
>  	      == ADD_COMPLETION_MAX_REACHED)
>  	    break;
>  	}
>      }
> -
> -  return matches;
>  }
>  
>  struct interp *
> diff --git a/gdb/language.h b/gdb/language.h
> index 954b4a8..24fb1e8 100644
> --- a/gdb/language.h
> +++ b/gdb/language.h
> @@ -302,7 +302,7 @@ struct language_defn
>         completion is being made.  If CODE is TYPE_CODE_UNDEF, then all
>         symbols should be examined; otherwise, only STRUCT_DOMAIN
>         symbols whose type has a code of CODE should be matched.  */
> -    VEC (char_ptr) *
> +    void
>        (*la_make_symbol_completion_list) (struct completer_data *,
>  					 const char *text,
>  					 const char *word,
> diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
> index cf76bd1..7a57349 100644
> --- a/gdb/python/py-cmd.c
> +++ b/gdb/python/py-cmd.c
> @@ -330,13 +330,12 @@ cmdpy_completer_handle_brkchars (struct cmd_list_element *command,
>  
>  /* Called by gdb for command completion.  */
>  
> -static VEC (char_ptr) *
> +static void
>  cmdpy_completer (struct completer_data *cdata,
>  		 struct cmd_list_element *command,
>  		 const char *text, const char *word)
>  {
>    PyObject *resultobj = NULL;
> -  VEC (char_ptr) *result = NULL;
>    struct cleanup *cleanup;
>  
>    cleanup = ensure_python_env (get_current_arch (), current_language);
> @@ -351,7 +350,6 @@ cmdpy_completer (struct completer_data *cdata,
>    if (resultobj == NULL)
>      goto done;
>  
> -  result = NULL;
>    if (PyInt_Check (resultobj))
>      {
>        /* User code may also return one of the completion constants,
> @@ -364,7 +362,7 @@ cmdpy_completer (struct completer_data *cdata,
>  	  PyErr_Clear ();
>  	}
>        else if (value >= 0 && value < (long) N_COMPLETERS)
> -	result = completers[value].completer (cdata, command, text, word);
> +	completers[value].completer (cdata, command, text, word);
>      }
>    else
>      {
> @@ -393,7 +391,7 @@ cmdpy_completer (struct completer_data *cdata,
>  	      continue;
>  	    }
>  
> -	  if (add_completion (cdata, &result, item, NULL, NULL)
> +	  if (add_completion (cdata, item, NULL, NULL)
>  	      == ADD_COMPLETION_MAX_REACHED)
>  	    {
>  	      xfree (item);
> @@ -414,8 +412,6 @@ cmdpy_completer (struct completer_data *cdata,
>  
>    Py_XDECREF (resultobj);
>    do_cleanups (cleanup);
> -
> -  return result;
>  }
>  
>  /* Helper for cmdpy_init which locates the command list to use and
> diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c
> index c29d3c5..862683b 100644
> --- a/gdb/remote-sim.c
> +++ b/gdb/remote-sim.c
> @@ -1223,7 +1223,7 @@ simulator_command (char *args, int from_tty)
>    registers_changed ();
>  }
>  
> -static VEC (char_ptr) *
> +static void
>  sim_command_completer (struct completer_data *cdata,
>  		       struct cmd_list_element *ignore, const char *text,
>  		       const char *word)
> @@ -1235,22 +1235,20 @@ sim_command_completer (struct completer_data *cdata,
>  
>    sim_data = inferior_data (current_inferior (), sim_inferior_data_key);
>    if (sim_data == NULL || sim_data->gdbsim_desc == NULL)
> -    return NULL;
> +    return;
>  
>    tmp = sim_complete_command (sim_data->gdbsim_desc, text, word);
>    if (tmp == NULL)
> -    return NULL;
> +    return;
>  
>    /* Transform the array into a VEC, and then free the array.  */
>    for (i = 0; tmp[i] != NULL; i++)
>      {
> -      if (add_completion (cdata, &result, tmp[i], NULL, NULL)
> +      if (add_completion (cdata, tmp[i], NULL, NULL)
>  	  == ADD_COMPLETION_MAX_REACHED)
>  	break;
>      }
>    xfree (tmp);
> -
> -  return result;
>  }
>  
>  /* Check to see if a thread is still alive.  */
> diff --git a/gdb/symtab.c b/gdb/symtab.c
> index e24de89..18b7619 100644
> --- a/gdb/symtab.c
> +++ b/gdb/symtab.c
> @@ -5011,31 +5011,8 @@ compare_symbol_name (const char *name, const char *sym_text, int sym_text_len)
>    return 1;
>  }
>  
> -/* Free any memory associated with a completion list.  */
> -
> -static void
> -free_completion_list (VEC (char_ptr) **list_ptr)
> -{
> -  int i;
> -  char *p;
> -
> -  for (i = 0; VEC_iterate (char_ptr, *list_ptr, i, p); ++i)
> -    xfree (p);
> -  VEC_free (char_ptr, *list_ptr);
> -}
> -
> -/* Callback for make_cleanup.  */
> -
> -static void
> -do_free_completion_list (void *list)
> -{
> -  free_completion_list (list);
> -}
> -
>  /* Helper routine for make_symbol_completion_list.  */
>  
> -static VEC (char_ptr) *return_val;
> -
>  #define COMPLETION_LIST_ADD_SYMBOL(cdata, symbol, sym_text, len,	\
>  				   text, word)				\
>    completion_list_add_name						\
> @@ -5063,7 +5040,7 @@ completion_list_add_name (struct completer_data *cdata,
>    /* We have a match for a completion, so add SYMNAME to the current list
>       of matches.  */
>  
> -    if (add_completion (cdata, &return_val, symname, sym_text, word)
> +    if (add_completion (cdata, symname, sym_text, word) 
>  	== ADD_COMPLETION_MAX_REACHED)
>        throw_max_completions_reached_error ();
>  }
> @@ -5499,18 +5476,13 @@ default_make_symbol_completion_list_break_on_1 (struct completer_data *cdata,
>      }
>  }
>  
> -VEC (char_ptr) *
> +void
>  default_make_symbol_completion_list_break_on (struct completer_data *cdata,
>  					      const char *text,
>  					      const char *word,
>  					      const char *break_on,
>  					      enum type_code code)
>  {
> -  struct cleanup *back_to;
> -
> -  return_val = NULL;
> -  back_to = make_cleanup (do_free_completion_list, &return_val);
> -
>    TRY
>      {
>        default_make_symbol_completion_list_break_on_1 (cdata, text, word,
> @@ -5522,61 +5494,56 @@ default_make_symbol_completion_list_break_on (struct completer_data *cdata,
>  	throw_exception (except);
>      }
>    END_CATCH
> -
> -  discard_cleanups (back_to);
> -  return return_val;
>  }
>  
> -VEC (char_ptr) *
> +void
>  default_make_symbol_completion_list (struct completer_data *cdata,
>  				     const char *text, const char *word,
>  				     enum type_code code)
>  {
> -  return default_make_symbol_completion_list_break_on (cdata, text, word, "",
> -						       code);
> +  default_make_symbol_completion_list_break_on (cdata, text, word, "", code);
>  }
>  
>  /* Return a vector of all symbols (regardless of class) which begin by
>     matching TEXT.  If the answer is no symbols, then the return value
>     is NULL.  */
>  
> -VEC (char_ptr) *
> +void
>  make_symbol_completion_list (struct completer_data *cdata,
>  			     const char *text, const char *word)
>  {
> -  return current_language->la_make_symbol_completion_list (cdata, text, word,
> -							   TYPE_CODE_UNDEF);
> +  current_language->la_make_symbol_completion_list (cdata, text, word,
> +						    TYPE_CODE_UNDEF);
>  }
>  
>  /* Like make_symbol_completion_list, but only return STRUCT_DOMAIN
>     symbols whose type code is CODE.  */
>  
> -VEC (char_ptr) *
> +void
>  make_symbol_completion_type (struct completer_data *cdata, const char *text,
>  			     const char *word, enum type_code code)
>  {
>    gdb_assert (code == TYPE_CODE_UNION
>  	      || code == TYPE_CODE_STRUCT
>  	      || code == TYPE_CODE_ENUM);
> -  return current_language->la_make_symbol_completion_list (cdata, text, word,
> -							   code);
> +  current_language->la_make_symbol_completion_list (cdata, text, word, code);
>  }
>  
>  /* Like make_symbol_completion_list, but suitable for use as a
>     completion function.  */
>  
> -VEC (char_ptr) *
> +void
>  make_symbol_completion_list_fn (struct completer_data *cdata,
>  				struct cmd_list_element *ignore,
>  				const char *text, const char *word)
>  {
> -  return make_symbol_completion_list (cdata, text, word);
> +  make_symbol_completion_list (cdata, text, word);
>  }
>  
>  /* Like make_symbol_completion_list, but returns a list of symbols
>     defined in a source file FILE.  */
>  
> -VEC (char_ptr) *
> +void
>  make_file_symbol_completion_list (struct completer_data *cdata,
>  				  const char *text, const char *word,
>  				  const char *srcfile)
> @@ -5624,7 +5591,7 @@ make_file_symbol_completion_list (struct completer_data *cdata,
>        /* A double-quoted string is never a symbol, nor does it make sense
>           to complete it any other way.  */
>        {
> -	return NULL;
> +	return;
>        }
>      else
>        {
> @@ -5635,8 +5602,6 @@ make_file_symbol_completion_list (struct completer_data *cdata,
>  
>    sym_text_len = strlen (sym_text);
>  
> -  return_val = NULL;
> -
>    /* Find the symtab for SRCFILE (this loads it if it was not yet read
>       in).  */
>    s = lookup_symtab (srcfile);
> @@ -5652,7 +5617,7 @@ make_file_symbol_completion_list (struct completer_data *cdata,
>  
>    /* If we have no symtab for that file, return an empty list.  */
>    if (s == NULL)
> -    return (return_val);
> +    return;
>  
>    /* Go through this symtab and check the externs and statics for
>       symbols which match.  */
> @@ -5670,8 +5635,6 @@ make_file_symbol_completion_list (struct completer_data *cdata,
>        COMPLETION_LIST_ADD_SYMBOL (cdata, sym, sym_text, sym_text_len,
>  				  text, word);
>      }
> -
> -  return (return_val);
>  }
>  
>  /* A helper function for make_source_files_completion_list.  It adds
> @@ -5680,10 +5643,9 @@ make_file_symbol_completion_list (struct completer_data *cdata,
>  
>  static void
>  add_filename_to_list (struct completer_data *cdata, const char *fname,
> -		      const char *text, const char *word,
> -		      VEC (char_ptr) **list)
> +		      const char *text, const char *word)
>  {
> -  (void) add_completion (cdata, list, fname, text, word);
> +  (void) add_completion (cdata, fname, text, word);
>  }
>  
>  static int
> @@ -5711,7 +5673,6 @@ struct add_partial_filename_data
>    const char *text;
>    const char *word;
>    int text_len;
> -  VEC (char_ptr) **list;
>  
>    /* Completion data used by the completer function.  */
>    struct completer_data *completer_data;
> @@ -5733,7 +5694,7 @@ 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 (data->completer_data, filename, data->text,
> -			    data->word, data->list);
> +			    data->word);
>      }
>    else
>      {
> @@ -5744,17 +5705,15 @@ maybe_add_partial_symtab_filename (const char *filename, const char *fullname,
>  	  && filename_ncmp (base_name, data->text, data->text_len) == 0)
>  	{
>  	  add_filename_to_list (data->completer_data, base_name, data->text,
> -				data->word, data->list);
> +				data->word);
>  	}
>      }
>  }
>  
> -/* Return a vector of all source files whose names begin with matching
> -   TEXT.  The file names are looked up in the symbol tables of this
> -   program.  If the answer is no matchess, then the return value is
> -   NULL.  */
> +/* Add all source files whose names begin with matching TEXT to CDATA.
> +   The file names are looked up in the symbol tables of this program.  */
>  
> -VEC (char_ptr) *
> +void
>  make_source_files_completion_list (struct completer_data *cdata,
>  				   const char *text, const char *word)
>  {
> @@ -5762,16 +5721,13 @@ make_source_files_completion_list (struct completer_data *cdata,
>    struct symtab *s;
>    struct objfile *objfile;
>    size_t text_len = strlen (text);
> -  VEC (char_ptr) *list = NULL;
>    const char *base_name;
>    struct add_partial_filename_data datum;
>    struct filename_seen_cache *filename_seen_cache;
> -  struct cleanup *back_to, *cache_cleanup;
> +  struct cleanup *cache_cleanup;
>  
>    if (!have_full_symbols () && !have_partial_symbols ())
> -    return list;
> -
> -  back_to = make_cleanup (do_free_completion_list, &list);
> +    return;
>  
>    filename_seen_cache = create_filename_seen_cache ();
>    cache_cleanup = make_cleanup (delete_filename_seen_cache,
> @@ -5786,7 +5742,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 (cdata, s->filename, text, word, &list);
> +	  add_filename_to_list (cdata, s->filename, text, word);
>  	}
>        else
>  	{
> @@ -5798,7 +5754,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 (cdata, base_name, text, word, &list);
> +	    add_filename_to_list (cdata, base_name, text, word);
>  	}
>      }
>  
> @@ -5806,15 +5762,11 @@ make_source_files_completion_list (struct completer_data *cdata,
>    datum.text = text;
>    datum.word = word;
>    datum.text_len = text_len;
> -  datum.list = &list;
>    datum.completer_data = cdata;
>    map_symbol_filenames (maybe_add_partial_symtab_filename, &datum,
>  			0 /*need_fullname*/);
>  
>    do_cleanups (cache_cleanup);
> -  discard_cleanups (back_to);
> -
> -  return list;
>  }
>  \f
>  /* Track MAIN */
> diff --git a/gdb/symtab.h b/gdb/symtab.h
> index 018852c..755e1d5 100644
> --- a/gdb/symtab.h
> +++ b/gdb/symtab.h
> @@ -1454,30 +1454,31 @@ extern void forget_cached_source_info (void);
>  
>  extern void select_source_symtab (struct symtab *);
>  
> -extern VEC (char_ptr) *default_make_symbol_completion_list_break_on
> +extern void default_make_symbol_completion_list_break_on
>   (struct completer_data *cdata, const char *text, const char *word,
>    const char *break_on, enum type_code code);
> -extern VEC (char_ptr) *
> +
> +extern void
>   default_make_symbol_completion_list (struct completer_data *,
>  				      const char *, const char *,
>  				      enum type_code);
> -extern VEC (char_ptr) *
> +extern void
>    make_symbol_completion_list (struct completer_data *, const char *,
>  			       const char *);
> -extern VEC (char_ptr) *
> +extern void
>    make_symbol_completion_type (struct completer_data *,
>  			       const char *, const char *,
>  			       enum type_code);
> -extern VEC (char_ptr) *
> +extern void
>    make_symbol_completion_list_fn (struct completer_data *,
>  				  struct cmd_list_element *,
>  				  const char *, const char *);
>  
> -extern VEC (char_ptr) *
> +extern void
>    make_file_symbol_completion_list (struct completer_data *,
>  				    const char *, const char *, const char *);
>  
> -extern VEC (char_ptr) *
> +extern void
>   make_source_files_completion_list (struct completer_data *, const char *,
>  				    const char *);
>  
> diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
> index 8d420894..c4c9cda 100644
> --- a/gdb/tui/tui-layout.c
> +++ b/gdb/tui/tui-layout.c
> @@ -353,7 +353,7 @@ tui_default_win_viewport_height (enum tui_win_type type,
>  /* Complete possible layout names.  TEXT is the complete text entered so
>     far, WORD is the word currently being completed.  */
>  
> -static VEC (char_ptr) *
> +static void
>  layout_completer (struct completer_data *cdata,
>  		  struct cmd_list_element *ignore,
>  		  const char *text, const char *word)
> @@ -361,7 +361,7 @@ layout_completer (struct completer_data *cdata,
>    static const char *layout_names [] =
>      { "src", "asm", "split", "regs", "next", "prev", NULL };
>  
> -  return complete_on_enum (cdata, layout_names, text, word);
> +  complete_on_enum (cdata, layout_names, text, word);
>  }
>  
>  /* Function to initialize gdb commands, for tui window layout
> diff --git a/gdb/tui/tui-regs.c b/gdb/tui/tui-regs.c
> index 17efd9f..bef01e5 100644
> --- a/gdb/tui/tui-regs.c
> +++ b/gdb/tui/tui-regs.c
> @@ -668,29 +668,26 @@ tui_reg_command (char *args, int from_tty)
>  /* Complete names of register groups, and add the special "prev" and "next"
>     names.  */
>  
> -static VEC (char_ptr) *
> +static void
>  tui_reggroup_completer (struct completer_data *cdata,
>  			struct cmd_list_element *ignore,
>  			const char *text, const char *word)
>  {
> -  VEC (char_ptr) *result = NULL;
>    static const char *extra[] = { "next", "prev", NULL };
>    size_t len = strlen (word);
>    const char **tmp;
>  
> -  result = reggroup_completer (cdata, ignore, text, word);
> +  reggroup_completer (cdata, ignore, text, word);
>  
>    for (tmp = extra; *tmp != NULL; ++tmp)
>      {
>        if (strncmp (word, *tmp, len) == 0)
>  	{
> -	  if (add_completion (cdata, &result, *tmp, NULL, NULL)
> +	  if (add_completion (cdata, *tmp, NULL, NULL)
>  	      == ADD_COMPLETION_MAX_REACHED)
>  	    break;
>  	}
>      }
> -
> -  return result;
>  }
>  
>  /* Provide a prototype to silence -Wmissing-prototypes.  */
> diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
> index 8e7fbd1..4690af1 100644
> --- a/gdb/tui/tui-win.c
> +++ b/gdb/tui/tui-win.c
> @@ -359,13 +359,12 @@ tui_set_var_cmd (char *null_args, int from_tty, struct cmd_list_element *c)
>     window names 'next' and 'prev' will also be considered as possible
>     completions of the window name.  */
>  
> -static VEC (char_ptr) *
> +static void
>  window_name_completer (int include_next_prev_p,
>  		       struct completer_data *cdata,
>  		       const char *text, const char *word)
>  {
>    VEC (const_char_ptr) *completion_name_vec = NULL;
> -  VEC (char_ptr) *matches_vec;
>    int win_type;
>  
>    for (win_type = SRC_WIN; win_type < MAX_MAJOR_WINDOWS; win_type++)
> @@ -399,32 +398,29 @@ window_name_completer (int include_next_prev_p,
>      }
>  
>    VEC_safe_push (const_char_ptr, completion_name_vec, NULL);
> -  matches_vec
> -    = complete_on_enum (cdata,
> -			VEC_address (const_char_ptr, completion_name_vec),
> -			text, word);
> +  complete_on_enum (cdata,
> +		    VEC_address (const_char_ptr, completion_name_vec),
> +		    text, word);
>  
>    VEC_free (const_char_ptr, completion_name_vec);
> -
> -  return matches_vec;
>  }
>  
>  /* Complete possible window names to focus on.  TEXT is the complete text
>     entered so far, WORD is the word currently being completed.  */
>  
> -static VEC (char_ptr) *
> +static void
>  focus_completer (struct completer_data *cdata,
>  		 struct cmd_list_element *ignore,
>  		  const char *text, const char *word)
>  {
> -  return window_name_completer (1, cdata, text, word);
> +  window_name_completer (1, cdata, text, word);
>  }
>  
>  /* Complete possible window names for winheight command.  TEXT is the
>     complete text entered so far, WORD is the word currently being
>     completed.  */
>  
> -static VEC (char_ptr) *
> +static void
>  winheight_completer (struct completer_data *cdata,
>  		     struct cmd_list_element *ignore,
>  		     const char *text, const char *word)
> @@ -432,9 +428,9 @@ winheight_completer (struct completer_data *cdata,
>    /* The first word is the window name.  That we can complete.  Subsequent
>       words can't be completed.  */
>    if (word != text)
> -    return NULL;
> +    return;
>  
> -  return window_name_completer (0, cdata, text, word);
> +  window_name_completer (0, cdata, text, word);
>  }
>  
>  /* Function to initialize gdb commands, for tui window
> diff --git a/gdb/value.c b/gdb/value.c
> index 22d392a..b3d4f04 100644
> --- a/gdb/value.c
> +++ b/gdb/value.c
> @@ -2062,10 +2062,9 @@ lookup_only_internalvar (const char *name)
>     Returns a vector of newly allocated strings, or NULL if no matches
>     were found.  */
>  
> -VEC (char_ptr) *
> +void
>  complete_internalvar (struct completer_data *cdata, const char *name)
>  {
> -  VEC (char_ptr) *result = NULL;
>    struct internalvar *var;
>    int len;
>  
> @@ -2074,12 +2073,10 @@ complete_internalvar (struct completer_data *cdata, const char *name)
>    for (var = internalvars; var; var = var->next)
>      if (strncmp (var->name, name, len) == 0)
>        {
> -	if (add_completion (cdata, &result, var->name, NULL, NULL)
> +	if (add_completion (cdata, var->name, NULL, NULL)
>  	    == ADD_COMPLETION_MAX_REACHED)
>  	  break;
>        }
> -
> -  return result;
>  }
>  
>  /* Create an internal variable with name NAME and with a void value.
> diff --git a/gdb/value.h b/gdb/value.h
> index 03df1b7..58c5c26 100644
> --- a/gdb/value.h
> +++ b/gdb/value.h
> @@ -876,8 +876,8 @@ extern struct internalvar *lookup_only_internalvar (const char *name);
>  
>  extern struct internalvar *create_internalvar (const char *name);
>  
> -extern VEC (char_ptr) *complete_internalvar (struct completer_data *cdata,
> -					     const char *name);
> +extern void complete_internalvar (struct completer_data *cdata,
> +				  const char *name);
>  
>  /* An internalvar can be dynamically computed by supplying a vector of
>     function pointers to perform various operations.  */

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v3 02/19] Remove completion_tracker_t from the public completion API.
  2015-08-23  1:02   ` Doug Evans
@ 2015-08-24 16:06     ` Doug Evans
  0 siblings, 0 replies; 45+ messages in thread
From: Doug Evans @ 2015-08-24 16:06 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches

Doug Evans <xdje42@gmail.com> writes:
> Keith Seitz <keiths@redhat.com> writes:
>>...
>> gdb/ChangeLog
>>
>> 	PR gdb/17960
>> 	* completer.c (struct completer_data) <tracker>: Change type to
>> 	htab_t.
>> 	(enum maybe_add_completion_enum): Make private; moved from
>> 	completer.h.
>> 	[DEFAULT_MAX_COMPLETIONS]: Define.
>> 	(new_completion_tracker): Remove function.
>> 	(new_completer_data): New function.
>> 	(free_completion_tracker): Remove function.
>> 	(free_completer_data): New function.
>> 	(make_cleanup_free_completion_tracker): Remove function.
>> 	(maybe_add_completion): Make static.  Update comments.
>> 	Use completer_data instead of completion_tracker_t.
>> 	(completer_strdup): New function.
>> 	(add_completion): New function.
>> 	(complete_line, gdb_completion_word_break_characters): Use
>> 	completer_data instead of completion_tracker.
>> 	* completer.h (completion_tracker_t, new_completion_tracker)
>> 	(make_cleanup_free_completion_tracker, maybe_add_completion)
>> 	(enum maybe_add_completion): Remove declarations.
>> 	(enum add_completion_status): Define.
>> 	(add_completion): Declare.
>> 	* symtab.c (completion_tracker): Remove variable.
>> 	(completion_list_add_name): Use add_completion instead of
>> 	maybe_add_completion and partial copy.
>> 	(default_make_symbol_completion_list_break_on_1): Do not use
>> 	completion_tracker.
>>
>> gdb/testsuite/ChangeLog
>>
>> 	PR gdb/17960
>> 	* gdb.base/completion.exp: Add some basic tests for the
>> 	location completer, including a regression test for
>> 	the gdb/17960 assertion failure.
>>...
>> @@ -803,48 +824,41 @@ complete_line_internal (struct completer_data *cdata,
>>  
>>  /* See completer.h.  */
>>  
>> -int max_completions = 200;
>> +#define DEFAULT_MAX_COMPLETIONS 200
>> +int max_completions = DEFAULT_MAX_COMPLETIONS;
>>  
>> -/* See completer.h.  */
>> +/* Allocate a new completer data structure.  */
>>  
>> -completion_tracker_t
>> -new_completion_tracker (void)
>> +static struct completer_data *
>> +new_completer_data (int size)
>>  {
>> -  if (max_completions <= 0)
>> -    return NULL;
>> +  struct completer_data *cdata = XCNEW (struct completer_data);
>>  
>> -  return htab_create_alloc (max_completions,
>> -			    htab_hash_string, (htab_eq) streq,
>> -			    NULL, xcalloc, xfree);
>> +  cdata->tracker
>> +    = htab_create_alloc ((size < 0 ? DEFAULT_MAX_COMPLETIONS : size),
>> +			 htab_hash_string, (htab_eq) streq, NULL,
>
> ====
>...
> I'm also slightly ambivalent on creating the hash table if
> max_completions is disabled (<= 0), and leaning towards not creating it
> to avoid potential confusion.
> Let's do the latter (pending reading the rest of the patchset - maybe
> there's a good reason to always create it).

Coming back to this now that I've gone through the entire series.
I now understand why the hashtable is always created. :-)
-> because it's now the only repository of completions.
So that's ok.

As I read the code the question "What does htab_create_alloc do if I
pass it a size of zero?" comes to mind.
It'll just start with a table size of the first prime it uses.
So that's ok.

I then checked the callers of new_completer_data:

complete_line does this:

  if (max_completions == 0)
    return NULL;

but gdb_completion_word_break_characters doesn't have this check
so new_completer_data has to handle any value for max_completions.

I don't think there's a problem here
(IIUC gdb_completion_word_break_characters correctly).
At the least it would be good to specify in the function comment of
new_completer_data that any value for size (-ve, zero, +ve) is ok.

^ permalink raw reply	[flat|nested] 45+ messages in thread

end of thread, other threads:[~2015-08-24 16:06 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-08-07  2:37 [PATCH v3 00/19] New completer API Keith Seitz
2015-08-06 19:18 ` [PATCH v3 09/19] Implement completion limiting for interpreter_completer Keith Seitz
2015-08-23  4:03   ` Doug Evans
2015-08-06 19:20 ` [PATCH v3 12/19] Implement completion limiting for sim_command_completer Keith Seitz
2015-08-23  4:11   ` Doug Evans
2015-08-06 19:58 ` [PATCH v3 02/19] Remove completion_tracker_t from the public completion API Keith Seitz
2015-08-23  1:02   ` Doug Evans
2015-08-24 16:06     ` Doug Evans
2015-08-06 19:58 ` [PATCH v3 06/19] Implement completion limiting for condition_completer Keith Seitz
2015-08-23  3:53   ` Doug Evans
2015-08-06 19:58 ` [PATCH v3 18/19] Use the hashtable to accumulate completion results Keith Seitz
2015-08-23 17:53   ` Doug Evans
2015-08-06 19:58 ` [PATCH v3 19/19] Remove the vector return result from the completion API Keith Seitz
2015-08-23 18:03   ` Doug Evans
2015-08-06 19:58 ` [PATCH v3 04/19] Implement completion limiting for add_filename_to_list Keith Seitz
2015-08-23  1:07   ` Doug Evans
2015-08-06 20:03 ` [PATCH v3 01/19] Add struct completer_data to the completion API Keith Seitz
2015-08-23  0:29   ` Doug Evans
2015-08-06 21:06 ` [PATCH v3 17/19] Make the completion API completely opaque Keith Seitz
2015-08-23 15:14   ` Doug Evans
2015-08-06 21:06 ` [PATCH v3 05/19] Implement completion limiting for ada_make_symbol_completion_list Keith Seitz
2015-08-23  3:47   ` Doug Evans
2015-08-06 22:03 ` [PATCH v3 16/19] Implement completion limiting for tui_reggroup_completer Keith Seitz
2015-08-23  4:25   ` Doug Evans
2015-08-06 22:03 ` [PATCH v3 07/19] Implement completion limiting for filename_completer Keith Seitz
2015-08-23  3:58   ` Doug Evans
2015-08-06 22:03 ` [PATCH v3 13/19] Implement completion limiting for complete_on_enum Keith Seitz
2015-08-23  4:19   ` Doug Evans
2015-08-06 22:03 ` [PATCH v3 11/19] Implement completion limiting for reg_or_group_completer Keith Seitz
2015-08-23  4:09   ` Doug Evans
2015-08-06 22:03 ` [PATCH v3 08/19] Implement completion limiting for signal_completer Keith Seitz
2015-08-23  3:59   ` Doug Evans
2015-08-06 22:12 ` [PATCH v3 14/19] Implement completion limiting in add_struct_fields Keith Seitz
2015-08-23  4:23   ` Doug Evans
2015-08-06 22:12 ` [PATCH v3 10/19] Implement completion limiting for cmdpy_completer Keith Seitz
2015-08-23  4:07   ` Doug Evans
2015-08-06 22:36 ` [PATCH v3 03/19] Implement completion-limiting for complete_on_cmdlist Keith Seitz
2015-08-23  1:05   ` Doug Evans
2015-08-07  2:37 ` [PATCH v3 15/19] Implement completion limiting for scmcmd_add_completion Keith Seitz
2015-08-23  4:24   ` Doug Evans
2015-08-07 22:57 ` [PATCH v3 00/19] New completer API Andrew Burgess
2015-08-08  0:04   ` Keith Seitz
2015-08-08  6:44     ` Andrew Burgess
2015-08-08 16:25       ` Keith Seitz
2015-08-22 22:25         ` Doug Evans

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).