This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[2/3] FYI: change completers to return a VEC


I'm checking this in on the trunk.

This changes the completers in gdb to return a VEC rather than a
NULL-terminated array of strings.

I've wanted to do this for a long time, and yesterday while writing a
new completion function, finally got around to it.

This is an improvement primarily because it removes code, but also
because VECs are just simpler to use than writing the equivalent code
inline everywhere.

Built and regtested on x86-64 Fedora 16.
mcheck did catch one buglet in an earlier revision, thanks Jan.

Tom

>From 7c8e87e276b60dbd297a38256a275e8e9e01c088 Mon Sep 17 00:00:00 2001
From: Tom Tromey <tromey@redhat.com>
Date: Wed, 13 Jun 2012 07:50:15 -0600
Subject: [PATCH 2/3] change completion functions to use a VEC

	* ada-lang.c (ada_make_symbol_completion_list): Return a VEC.
	* breakpoint.c (catch_syscall_completer): Return a VEC.
	* cli/cli-cmds.c (complete_command): Update.
	* cli/cli-decode.c (complete_on_cmdlist): Return a VEC.
	(complete_on_enum): Likewise.
	* command.h: Include gdb_vecs.h.
	(completer_ftype): Change return type.
	(complete_on_cmdlist, complete_on_enum): Likewise.
	* completer.c (noop_completer, filename_completer)
	(location_completer): Return a VEC.
	(add_struct_fields): Remove 'nextp' argument.  Change 'output'
	to a VEC.
	(expression_completer, complete_line_internal, complete_line)
	(command_completer): Return a VEC.
	(gdb_completion_word_break_characters, line_completion_function):
	Update.
	* completer.h: Include gdb_vecs.h.
	(complete_line, noop_completer, filename_completer)
	(expression_completer, location_completer, command_completer):
	Update.
	* f-lang.c (f_word_break_characters): Return a VEC.
	* interps.c (interpreter_completer): Return a VEC.
	* language.h (struct language_defn)
	<la_make_symbol_completion_list>: Return a VEC.
	* python/py-cmd.c (cmdpy_completer): Return a VEC.
	* symtab.c (free_completion_list): Take a VEC.
	(return_val_size, return_val_index): Remove.
	(return_val): Now a VEC.
	(completion_list_add_name): Update.
	(default_make_symbol_completion_list_break_on)
	(default_make_symbol_completion_list, make_symbol_completion_list)
	(make_symbol_completion_list_fn, make_file_symbol_completion_list):
	Return a VEC.
	(add_filename_to_list): Update.
	(struct add_partial_filename_data) <list_used, list_alloced>: Remove.
	<list>: Now a VEC.
	(maybe_add_partial_symtab_filename): Update.
	(make_source_files_completion_list): Return a VEC.
	* symtab.h (default_make_symbol_completion_list_break_on)
	(default_make_symbol_completion_list, make_symbol_completion_list)
	(make_symbol_completion_list_fn, make_file_symbol_completion_list)
	(make_source_files_completion_list): Update.
---
 gdb/ada-lang.c       |   26 ++--------
 gdb/breakpoint.c     |    4 +-
 gdb/cli/cli-cmds.c   |   32 ++++++------
 gdb/cli/cli-decode.c |   94 ++++++++--------------------------
 gdb/command.h        |   13 +++--
 gdb/completer.c      |  137 ++++++++++++++++++++------------------------------
 gdb/completer.h      |   28 ++++++-----
 gdb/f-lang.c         |    2 +-
 gdb/interps.c        |   39 ++++----------
 gdb/language.h       |    8 ++--
 gdb/python/py-cmd.c  |   13 ++---
 gdb/symtab.c         |  107 ++++++++++++---------------------------
 gdb/symtab.h         |   16 +++---
 13 files changed, 185 insertions(+), 334 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index af0fdb5..6f65472 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -5797,11 +5797,10 @@ ada_expand_partial_symbol_name (const char *name, void *user_data)
                                   data->wild_match, data->encoded) != NULL;
 }
 
-/* Return a list of possible symbol names completing TEXT0.  The list
-   is NULL terminated.  WORD is the entire command on which completion
-   is made.  */
+/* Return a list of possible symbol names completing TEXT0.  WORD is
+   the entire command on which completion is made.  */
 
-static char **
+static VEC (char_ptr) *
 ada_make_symbol_completion_list (char *text0, char *word)
 {
   char *text;
@@ -5914,24 +5913,7 @@ ada_make_symbol_completion_list (char *text0, char *word)
     }
   }
 
-  /* Append the closing NULL entry.  */
-  VEC_safe_push (char_ptr, completions, NULL);
-
-  /* Make a copy of the COMPLETIONS VEC before we free it, and then
-     return the copy.  It's unfortunate that we have to make a copy
-     of an array that we're about to destroy, but there is nothing much
-     we can do about it.  Fortunately, it's typically not a very large
-     array.  */
-  {
-    const size_t completions_size = 
-      VEC_length (char_ptr, completions) * sizeof (char *);
-    char **result = xmalloc (completions_size);
-    
-    memcpy (result, VEC_address (char_ptr, completions), completions_size);
-
-    VEC_free (char_ptr, completions);
-    return result;
-  }
+  return completions;
 }
 
                                 /* Field Access */
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 8e90298..d76065d 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -14578,12 +14578,12 @@ catching_syscall_number (int syscall_number)
 }
 
 /* Complete syscall names.  Used by "catch syscall".  */
-static char **
+static VEC (char_ptr) *
 catch_syscall_completer (struct cmd_list_element *cmd,
                          char *text, char *word)
 {
   const char **list = get_syscall_names ();
-  char **retlist
+  VEC (char_ptr) *retlist
     = (list == NULL) ? NULL : complete_on_enum (list, text, word);
 
   xfree (list);
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index e5fa206..24d55c3 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -254,7 +254,8 @@ static void
 complete_command (char *arg, int from_tty)
 {
   int argpoint;
-  char **completions, *point, *arg_prefix;
+  char *point, *arg_prefix;
+  VEC (char_ptr) *completions;
 
   dont_repeat ();
 
@@ -282,33 +283,30 @@ complete_command (char *arg, int from_tty)
 
   if (completions)
     {
-      int item, size;
+      int ix, size = VEC_length (char_ptr, completions);
+      char *item, *prev = NULL;
 
-      for (size = 0; completions[size]; ++size)
-	;
-      qsort (completions, size, sizeof (char *), compare_strings);
+      qsort (VEC_address (char_ptr, completions), size,
+	     sizeof (char *), compare_strings);
 
       /* We do extra processing here since we only want to print each
 	 unique item once.  */
-      item = 0;
-      while (item < size)
+      for (ix = 0; VEC_iterate (char_ptr, completions, ix, item); ++ix)
 	{
 	  int next_item;
 
-	  printf_unfiltered ("%s%s\n", arg_prefix, completions[item]);
-	  next_item = item + 1;
-	  while (next_item < size
-		 && ! strcmp (completions[item], completions[next_item]))
+	  if (prev == NULL || strcmp (item, prev) != 0)
 	    {
-	      xfree (completions[next_item]);
-	      ++next_item;
+	      printf_unfiltered ("%s%s\n", arg_prefix, item);
+	      xfree (prev);
+	      prev = item;
 	    }
-
-	  xfree (completions[item]);
-	  item = next_item;
+	  else
+	    xfree (item);
 	}
 
-      xfree (completions);
+      xfree (prev);
+      VEC_free (char_ptr, completions);
     }
 }
 
diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index 2974d11..c337b43 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -1637,26 +1637,20 @@ lookup_cmd_composition (char *text,
    "foo" and we want to complete to "foobar".  If WORD is "oo", return
    "oobar"; if WORD is "baz/foo", return "baz/foobar".  */
 
-char **
+VEC (char_ptr) *
 complete_on_cmdlist (struct cmd_list_element *list, char *text, char *word)
 {
   struct cmd_list_element *ptr;
-  char **matchlist;
-  int sizeof_matchlist;
-  int matches;
+  VEC (char_ptr) *matchlist = NULL;
   int textlen = strlen (text);
   int pass;
   int saw_deprecated_match = 0;
 
-  sizeof_matchlist = 10;
-  matchlist = (char **) xmalloc (sizeof_matchlist * sizeof (char *));
-  matches = 0;
-
   /* We do one or two passes.  In the first pass, we skip deprecated
      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; matches == 0 && pass < 2; ++pass)
+  for (pass = 0; matchlist == 0 && pass < 2; ++pass)
     {
       for (ptr = list; ptr; ptr = ptr->next)
 	if (!strncmp (ptr->name, text, textlen)
@@ -1664,6 +1658,8 @@ complete_on_cmdlist (struct cmd_list_element *list, char *text, char *word)
 	    && (ptr->func
 		|| ptr->prefixlist))
 	  {
+	    char *match;
+
 	    if (pass == 0)
 	      {
 		if ((ptr->flags & CMD_DEPRECATED) != 0)
@@ -1673,31 +1669,22 @@ complete_on_cmdlist (struct cmd_list_element *list, char *text, char *word)
 		  }
 	      }
 
-	    if (matches == sizeof_matchlist)
-	      {
-		sizeof_matchlist *= 2;
-		matchlist = (char **) xrealloc ((char *) matchlist,
-						(sizeof_matchlist
-						 * sizeof (char *)));
-	      }
-
-	    matchlist[matches] = (char *)
-	      xmalloc (strlen (word) + strlen (ptr->name) + 1);
+	    match = (char *) xmalloc (strlen (word) + strlen (ptr->name) + 1);
 	    if (word == text)
-	      strcpy (matchlist[matches], ptr->name);
+	      strcpy (match, ptr->name);
 	    else if (word > text)
 	      {
 		/* Return some portion of ptr->name.  */
-		strcpy (matchlist[matches], ptr->name + (word - text));
+		strcpy (match, ptr->name + (word - text));
 	      }
 	    else
 	      {
 		/* Return some of text plus ptr->name.  */
-		strncpy (matchlist[matches], word, text - word);
-		matchlist[matches][text - word] = '\0';
-		strcat (matchlist[matches], ptr->name);
+		strncpy (match, word, text - word);
+		match[text - word] = '\0';
+		strcat (match, ptr->name);
 	      }
-	    ++matches;
+	    VEC_safe_push (char_ptr, matchlist, match);
 	  }
       /* If we saw no matching deprecated commands in the first pass,
 	 just bail out.  */
@@ -1705,18 +1692,6 @@ complete_on_cmdlist (struct cmd_list_element *list, char *text, char *word)
 	break;
     }
 
-  if (matches == 0)
-    {
-      xfree (matchlist);
-      matchlist = 0;
-    }
-  else
-    {
-      matchlist = (char **) xrealloc ((char *) matchlist, ((matches + 1)
-							* sizeof (char *)));
-      matchlist[matches] = (char *) 0;
-    }
-
   return matchlist;
 }
 
@@ -1730,64 +1705,39 @@ complete_on_cmdlist (struct cmd_list_element *list, char *text, char *word)
    and we want to complete to "foobar".  If WORD is "oo", return
    "oobar"; if WORD is "baz/foo", return "baz/foobar".  */
 
-char **
+VEC (char_ptr) *
 complete_on_enum (const char *const *enumlist,
 		  char *text,
 		  char *word)
 {
-  char **matchlist;
-  int sizeof_matchlist;
-  int matches;
+  VEC (char_ptr) *matchlist = NULL;
   int textlen = strlen (text);
   int i;
   const char *name;
 
-  sizeof_matchlist = 10;
-  matchlist = (char **) xmalloc (sizeof_matchlist * sizeof (char *));
-  matches = 0;
-
   for (i = 0; (name = enumlist[i]) != NULL; i++)
     if (strncmp (name, text, textlen) == 0)
       {
-	if (matches == sizeof_matchlist)
-	  {
-	    sizeof_matchlist *= 2;
-	    matchlist = (char **) xrealloc ((char *) matchlist,
-					    (sizeof_matchlist
-					     * sizeof (char *)));
-	  }
+	char *match;
 
-	matchlist[matches] = (char *)
-	  xmalloc (strlen (word) + strlen (name) + 1);
+	match = (char *) xmalloc (strlen (word) + strlen (name) + 1);
 	if (word == text)
-	  strcpy (matchlist[matches], name);
+	  strcpy (match, name);
 	else if (word > text)
 	  {
 	    /* Return some portion of name.  */
-	    strcpy (matchlist[matches], name + (word - text));
+	    strcpy (match, name + (word - text));
 	  }
 	else
 	  {
 	    /* Return some of text plus name.  */
-	    strncpy (matchlist[matches], word, text - word);
-	    matchlist[matches][text - word] = '\0';
-	    strcat (matchlist[matches], name);
+	    strncpy (match, word, text - word);
+	    match[text - word] = '\0';
+	    strcat (match, name);
 	  }
-	++matches;
+	VEC_safe_push (char_ptr, matchlist, match);
       }
 
-  if (matches == 0)
-    {
-      xfree (matchlist);
-      matchlist = 0;
-    }
-  else
-    {
-      matchlist = (char **) xrealloc ((char *) matchlist, ((matches + 1)
-							   * sizeof (char *)));
-      matchlist[matches] = (char *) 0;
-    }
-
   return matchlist;
 }
 
diff --git a/gdb/command.h b/gdb/command.h
index eba3a5b..3064ce2 100644
--- a/gdb/command.h
+++ b/gdb/command.h
@@ -19,6 +19,8 @@
 #if !defined (COMMAND_H)
 #define COMMAND_H 1
 
+#include "gdb_vecs.h"
+
 /* This file defines the public interface for any code wanting to
    create commands.  */
 
@@ -149,7 +151,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 char **completer_ftype (struct cmd_list_element *, char *, char *);
+typedef VEC (char_ptr) *completer_ftype (struct cmd_list_element *,
+					 char *, char *);
 
 extern void set_cmd_completer (struct cmd_list_element *, completer_ftype *);
 
@@ -208,11 +211,11 @@ extern struct cmd_list_element *add_info (char *,
 
 extern struct cmd_list_element *add_info_alias (char *, char *, int);
 
-extern char **complete_on_cmdlist (struct cmd_list_element *,
-				   char *, char *);
+extern VEC (char_ptr) *complete_on_cmdlist (struct cmd_list_element *,
+					    char *, char *);
 
-extern char **complete_on_enum (const char *const *enumlist,
-				char *, char *);
+extern VEC (char_ptr) *complete_on_enum (const char *const *enumlist,
+					 char *, char *);
 
 /* Functions that implement commands about CLI commands.  */
 
diff --git a/gdb/completer.c b/gdb/completer.c
index 5939d08..b9f0699 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -104,7 +104,7 @@ 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.  */
-char **
+VEC (char_ptr) *
 noop_completer (struct cmd_list_element *ignore, 
 		char *text, char *prefix)
 {
@@ -112,19 +112,12 @@ noop_completer (struct cmd_list_element *ignore,
 }
 
 /* Complete on filenames.  */
-char **
+VEC (char_ptr) *
 filename_completer (struct cmd_list_element *ignore, 
 		    char *text, char *word)
 {
   int subsequent_name;
-  char **return_val;
-  int return_val_used;
-  int return_val_alloced;
-
-  return_val_used = 0;
-  /* Small for testing.  */
-  return_val_alloced = 1;
-  return_val = (char **) xmalloc (return_val_alloced * sizeof (char *));
+  VEC (char_ptr) *return_val = NULL;
 
   subsequent_name = 0;
   while (1)
@@ -132,18 +125,8 @@ filename_completer (struct cmd_list_element *ignore,
       char *p, *q;
 
       p = rl_filename_completion_function (text, subsequent_name);
-      if (return_val_used >= return_val_alloced)
-	{
-	  return_val_alloced *= 2;
-	  return_val =
-	    (char **) xrealloc (return_val,
-				return_val_alloced * sizeof (char *));
-	}
       if (p == NULL)
-	{
-	  return_val[return_val_used++] = p;
-	  break;
-	}
+	break;
       /* We need to set subsequent_name to a non-zero value before the
 	 continue line below, because otherwise, if the first file
 	 seen by GDB is a backup file whose name ends in a `~', we
@@ -159,13 +142,12 @@ filename_completer (struct cmd_list_element *ignore,
 
       if (word == text)
 	/* Return exactly p.  */
-	return_val[return_val_used++] = p;
+	q = p;
       else if (word > text)
 	{
 	  /* Return some portion of p.  */
 	  q = xmalloc (strlen (p) + 5);
 	  strcpy (q, p + (word - text));
-	  return_val[return_val_used++] = q;
 	  xfree (p);
 	}
       else
@@ -175,9 +157,9 @@ filename_completer (struct cmd_list_element *ignore,
 	  strncpy (q, word, text - word);
 	  q[text - word] = '\0';
 	  strcat (q, p);
-	  return_val[return_val_used++] = q;
 	  xfree (p);
 	}
+      VEC_safe_push (char_ptr, return_val, q);
     }
 #if 0
   /* There is no way to do this just long enough to affect quote
@@ -199,13 +181,13 @@ filename_completer (struct cmd_list_element *ignore,
    This is intended to be used in commands that set breakpoints
    etc.  */
 
-char **
+VEC (char_ptr) *
 location_completer (struct cmd_list_element *ignore, 
 		    char *text, char *word)
 {
-  int n_syms = 0, n_files = 0;
-  char ** fn_list = NULL;
-  char ** list = NULL;
+  int n_syms, n_files, ix;
+  VEC (char_ptr) *fn_list = NULL;
+  VEC (char_ptr) *list = NULL;
   char *p;
   int quote_found = 0;
   int quoted = *text == '\'' || *text == '"';
@@ -290,21 +272,26 @@ location_completer (struct cmd_list_element *ignore,
 	fn_list = make_source_files_completion_list (text, text);
     }
 
-  /* How many completions do we have in both lists?  */
-  if (fn_list)
-    for ( ; fn_list[n_files]; n_files++)
-      ;
-  if (list)
-    for ( ; list[n_syms]; 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)
+    {
+      VEC_free (char_ptr, list); /* Paranoia.  */
+      list = fn_list;
+      fn_list = NULL;
+    }
+  else
+    {
+      for (ix = 0; VEC_iterate (char_ptr, fn_list, ix, p); ++ix)
+	VEC_safe_push (char_ptr, list, p);
+      VEC_free (char_ptr, fn_list);
+    }
 
-  /* Make list[] large enough to hold both lists, then catenate
-     fn_list[] onto the end of list[].  */
   if (n_syms && n_files)
     {
-      list = xrealloc (list, (n_syms + n_files + 1) * sizeof (char *));
-      memcpy (list + n_syms, fn_list, (n_files + 1) * sizeof (char *));
-      xfree (fn_list);
+      /* Nothing.  */
     }
   else if (n_files)
     {
@@ -323,23 +310,18 @@ location_completer (struct cmd_list_element *ignore,
 	 completion, because rl_complete will prepend "/foo/" to each
 	 candidate completion.  The loop below removes that leading
 	 part.  */
-      for (n_files = 0; fn_list[n_files]; n_files++)
+      for (ix = 0; VEC_iterate (char_ptr, list, ix, p); ++ix)
 	{
-	  memmove (fn_list[n_files], fn_list[n_files] + (word - text),
-		   strlen (fn_list[n_files]) + 1 - (word - text));
+	  memmove (p, p + (word - text),
+		   strlen (p) + 1 - (word - text));
 	}
-      /* Return just the file-name list as the result.  */
-      list = fn_list;
     }
   else if (!n_syms)
     {
       /* 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);
-      xfree (fn_list);
     }
-  else
-    xfree (fn_list);
 
   return list;
 }
@@ -379,9 +361,9 @@ count_struct_fields (struct type *type)
 
 /* Helper for expression_completer which recursively adds field and
    method names from TYPE, a struct or union type, to the array
-   OUTPUT.  This function assumes that OUTPUT is correctly-sized.  */
+   OUTPUT.  */
 static void
-add_struct_fields (struct type *type, int *nextp, char **output,
+add_struct_fields (struct type *type, VEC (char_ptr) **output,
 		   char *fieldname, int namelen)
 {
   int i;
@@ -392,7 +374,7 @@ add_struct_fields (struct type *type, int *nextp, char **output,
   for (i = 0; i < TYPE_NFIELDS (type); ++i)
     {
       if (i < TYPE_N_BASECLASSES (type))
-	add_struct_fields (TYPE_BASECLASS (type, i), nextp,
+	add_struct_fields (TYPE_BASECLASS (type, i),
 			   output, fieldname, namelen);
       else if (TYPE_FIELD_NAME (type, i))
 	{
@@ -400,15 +382,13 @@ add_struct_fields (struct type *type, int *nextp, char **output,
 	    {
 	      if (! strncmp (TYPE_FIELD_NAME (type, i), 
 			     fieldname, namelen))
-		{
-		  output[*nextp] = xstrdup (TYPE_FIELD_NAME (type, i));
-		  ++*nextp;
-		}
+		VEC_safe_push (char_ptr, *output,
+			       xstrdup (TYPE_FIELD_NAME (type, i)));
 	    }
 	  else if (TYPE_CODE (TYPE_FIELD_TYPE (type, i)) == TYPE_CODE_UNION)
 	    {
 	      /* Recurse into anonymous unions.  */
-	      add_struct_fields (TYPE_FIELD_TYPE (type, i), nextp, 
+	      add_struct_fields (TYPE_FIELD_TYPE (type, i),
 				 output, fieldname, namelen);
 	    }
 	}
@@ -427,10 +407,7 @@ add_struct_fields (struct type *type, int *nextp, char **output,
 	    }
 	  /* Omit constructors from the completion list.  */
 	  if (!type_name || strcmp (type_name, name))
-	    {
-	      output[*nextp] = xstrdup (name);
-	      ++*nextp;
-	    }
+	    VEC_safe_push (char_ptr, *output, xstrdup (name));
 	}
     }
 }
@@ -438,7 +415,7 @@ add_struct_fields (struct type *type, int *nextp, char **output,
 /* Complete on expressions.  Often this means completing on symbol
    names, but some language parsers also have support for completing
    field names.  */
-char **
+VEC (char_ptr) *
 expression_completer (struct cmd_list_element *ignore, 
 		      char *text, char *word)
 {
@@ -471,11 +448,9 @@ expression_completer (struct cmd_list_element *ignore,
 	{
 	  int alloc = count_struct_fields (type);
 	  int flen = strlen (fieldname);
-	  int out = 0;
-	  char **result = (char **) xmalloc ((alloc + 1) * sizeof (char *));
+	  VEC (char_ptr) *result = NULL;
 
-	  add_struct_fields (type, &out, result, fieldname, flen);
-	  result[out] = NULL;
+	  add_struct_fields (type, &result, fieldname, flen);
 	  xfree (fieldname);
 	  return result;
 	}
@@ -552,12 +527,12 @@ complete_line_internal_reason;
    once sub-command completions are exhausted, we simply return NULL.
  */
 
-static char **
+static VEC (char_ptr) *
 complete_line_internal (const char *text, 
 			char *line_buffer, int point,
 			complete_line_internal_reason reason)
 {
-  char **list = NULL;
+  VEC (char_ptr) *list = NULL;
   char *tmp_command, *p;
   /* Pointer within tmp_command which corresponds to text.  */
   char *word;
@@ -794,9 +769,9 @@ complete_line_internal (const char *text,
 
   return list;
 }
-/* Generate completions all at once.  Returns a NULL-terminated array
-   of strings.  Both the array and each element are allocated with
-   xmalloc.  It can also return NULL if there are no completions.
+/* Generate completions all at once.  Returns a vector of strings.
+   Each element is allocated with xmalloc.  It can also return NULL if
+   there are no completions.
 
    TEXT is the caller's idea of the "word" we are looking at.
 
@@ -806,7 +781,7 @@ complete_line_internal (const char *text,
    POINT is the offset in that line of the cursor.  You
    should pretend that the line ends at POINT.  */
 
-char **
+VEC (char_ptr) *
 complete_line (const char *text, char *line_buffer, int point)
 {
   return complete_line_internal (text, line_buffer, 
@@ -814,7 +789,7 @@ complete_line (const char *text, char *line_buffer, int point)
 }
 
 /* Complete on command names.  Used by "help".  */
-char **
+VEC (char_ptr) *
 command_completer (struct cmd_list_element *ignore, 
 		   char *text, char *word)
 {
@@ -828,7 +803,7 @@ command_completer (struct cmd_list_element *ignore,
 char *
 gdb_completion_word_break_characters (void)
 {
-  char **list;
+  VEC (char_ptr) *list;
 
   list = complete_line_internal (rl_line_buffer, rl_line_buffer, rl_point,
 				 handle_brkchars);
@@ -861,7 +836,7 @@ static char *
 line_completion_function (const char *text, int matches, 
 			  char *line_buffer, int point)
 {
-  static char **list = (char **) NULL;	/* Cache of completions.  */
+  static VEC (char_ptr) *list = NULL;	/* Cache of completions.  */
   static int index;			/* Next cached completion.  */
   char *output = NULL;
 
@@ -877,24 +852,22 @@ line_completion_function (const char *text, int matches,
 	     inside.  This is because rl_complete_internal () frees
 	     the strings.  As complete_line may abort by calling
 	     `error' clear LIST now.  */
-	  xfree (list);
-	  list = NULL;
+	  VEC_free (char_ptr, list);
 	}
       index = 0;
       list = complete_line (text, line_buffer, point);
     }
 
   /* If we found a list of potential completions during initialization
-     then dole them out one at a time.  The vector of completions is
-     NULL terminated, so after returning the last one, return NULL
-     (and continue to do so) each time we are called after that, until
-     a new list is available.  */
+     then dole them out one at a time.  After returning the last one,
+     return NULL (and continue to do so) each time we are called after
+     that, until a new list is available.  */
 
   if (list)
     {
-      output = list[index];
-      if (output)
+      if (index < VEC_length (char_ptr, list))
 	{
+	  output = VEC_index (char_ptr, list, index);
 	  index++;
 	}
     }
diff --git a/gdb/completer.h b/gdb/completer.h
index 0f52245..680bc2d 100644
--- a/gdb/completer.h
+++ b/gdb/completer.h
@@ -17,27 +17,29 @@
 #if !defined (COMPLETER_H)
 #define COMPLETER_H 1
 
-extern char **complete_line (const char *text,
-			     char *line_buffer,
-			     int point);
+#include "gdb_vecs.h"
+
+extern VEC (char_ptr) *complete_line (const char *text,
+				      char *line_buffer,
+				      int point);
 
 extern char *readline_line_completion_function (const char *text,
 						int matches);
 
-extern char **noop_completer (struct cmd_list_element *,
-			      char *, char *);
+extern VEC (char_ptr) *noop_completer (struct cmd_list_element *,
+				       char *, char *);
 
-extern char **filename_completer (struct cmd_list_element *,
-				  char *, char *);
+extern VEC (char_ptr) *filename_completer (struct cmd_list_element *,
+					   char *, char *);
 
-extern char **expression_completer (struct cmd_list_element *,
-				    char *, char *);
+extern VEC (char_ptr) *expression_completer (struct cmd_list_element *,
+					     char *, char *);
 
-extern char **location_completer (struct cmd_list_element *,
-				  char *, char *);
+extern VEC (char_ptr) *location_completer (struct cmd_list_element *,
+					   char *, char *);
 
-extern char **command_completer (struct cmd_list_element *,
-				 char *, char *);
+extern VEC (char_ptr) *command_completer (struct cmd_list_element *,
+					  char *, char *);
 
 extern char *get_gdb_completer_quote_characters (void);
 
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index 3368d01..7492149 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -263,7 +263,7 @@ f_word_break_characters (void)
 /* Consider the modules separator :: as a valid symbol name character
    class.  */
 
-static char **
+static VEC (char_ptr) *
 f_make_symbol_completion_list (char *text, char *word)
 {
   return default_make_symbol_completion_list_break_on (text, word, ":");
diff --git a/gdb/interps.c b/gdb/interps.c
index 23e5a10..9b24c59 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -73,8 +73,6 @@ struct interp
 
 /* Functions local to this file.  */
 static void initialize_interps (void);
-static char **interpreter_completer (struct cmd_list_element *cmd,
-				     char *text, char *word);
 
 /* The magic initialization routine for this module.  */
 
@@ -445,54 +443,39 @@ interpreter_exec_cmd (char *args, int from_tty)
 }
 
 /* List the possible interpreters which could complete the given text.  */
-static char **
+static VEC (char_ptr) *
 interpreter_completer (struct cmd_list_element *ignore, char *text, char *word)
 {
-  int alloced = 0;
   int textlen;
-  int num_matches;
-  char **matches;
+  VEC (char_ptr) *matches = NULL;
   struct interp *interp;
 
-  /* We expect only a very limited number of interpreters, so just
-     allocate room for all of them plus one for the last that must be NULL
-     to correctly end the list.  */
-  for (interp = interp_list; interp != NULL; interp = interp->next)
-    ++alloced;
-  matches = (char **) xcalloc (alloced + 1, sizeof (char *));
-
-  num_matches = 0;
   textlen = strlen (text);
   for (interp = interp_list; interp != NULL; interp = interp->next)
     {
       if (strncmp (interp->name, text, textlen) == 0)
 	{
-	  matches[num_matches] =
-	    (char *) xmalloc (strlen (word) + strlen (interp->name) + 1);
+	  char *match;
+
+	  match = (char *) xmalloc (strlen (word) + strlen (interp->name) + 1);
 	  if (word == text)
-	    strcpy (matches[num_matches], interp->name);
+	    strcpy (match, interp->name);
 	  else if (word > text)
 	    {
 	      /* Return some portion of interp->name.  */
-	      strcpy (matches[num_matches], interp->name + (word - text));
+	      strcpy (match, interp->name + (word - text));
 	    }
 	  else
 	    {
 	      /* Return some of text plus interp->name.  */
-	      strncpy (matches[num_matches], word, text - word);
-	      matches[num_matches][text - word] = '\0';
-	      strcat (matches[num_matches], interp->name);
+	      strncpy (match, word, text - word);
+	      match[text - word] = '\0';
+	      strcat (match, interp->name);
 	    }
-	  ++num_matches;
+	  VEC_safe_push (char_ptr, matches, match);
 	}
     }
 
-  if (num_matches == 0)
-    {
-      xfree (matches);
-      matches = NULL;
-    }
-
   return matches;
 }
 
diff --git a/gdb/language.h b/gdb/language.h
index d612c70..38c4830 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -306,10 +306,10 @@ struct language_defn
     /* The list of characters forming word boundaries.  */
     char *(*la_word_break_characters) (void);
 
-    /* Should return a NULL terminated array of all symbols which
-       are possible completions for TEXT.  WORD is the entire command
-       on which the completion is being made.  */
-    char **(*la_make_symbol_completion_list) (char *text, char *word);
+    /* Should return a vector of all symbols which are possible
+       completions for TEXT.  WORD is the entire command on which the
+       completion is being made.  */
+    VEC (char_ptr) *(*la_make_symbol_completion_list) (char *text, char *word);
 
     /* 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 605c8c0..d8e375c 100644
--- a/gdb/python/py-cmd.c
+++ b/gdb/python/py-cmd.c
@@ -206,12 +206,12 @@ cmdpy_function (struct cmd_list_element *command, char *args, int from_tty)
 
 /* Called by gdb for command completion.  */
 
-static char **
+static VEC (char_ptr) *
 cmdpy_completer (struct cmd_list_element *command, char *text, char *word)
 {
   cmdpy_object *obj = (cmdpy_object *) get_cmd_context (command);
   PyObject *textobj, *wordobj, *resultobj = NULL;
-  char **result = NULL;
+  VEC (char_ptr) *result = NULL;
   struct cleanup *cleanup;
 
   cleanup = ensure_python_env (get_current_arch (), current_language);
@@ -253,10 +253,10 @@ cmdpy_completer (struct cmd_list_element *command, char *text, char *word)
       if (len < 0)
 	goto done;
 
-      result = (char **) xmalloc ((len + 1) * sizeof (char *));
       for (i = out = 0; i < len; ++i)
 	{
 	  PyObject *elt = PySequence_GetItem (resultobj, i);
+	  char *item;
 
 	  if (elt == NULL || ! gdbpy_is_string (elt))
 	    {
@@ -264,16 +264,15 @@ cmdpy_completer (struct cmd_list_element *command, char *text, char *word)
 	      PyErr_Clear ();
 	      continue;
 	    }
-	  result[out] = python_string_to_host_string (elt);
-	  if (result[out] == NULL)
+	  item = python_string_to_host_string (elt);
+	  if (item == NULL)
 	    {
 	      /* Skip problem elements.  */
 	      PyErr_Clear ();
 	      continue;
 	    }
-	  ++out;
+	  VEC_safe_push (char_ptr, result, item);
 	}
-      result[out] = NULL;
     }
   else if (PyInt_Check (resultobj))
     {
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 6133b5c..3efcb1b 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -3881,17 +3881,14 @@ compare_symbol_name (const char *name, const char *sym_text, int sym_text_len)
 /* Free any memory associated with a completion list.  */
 
 static void
-free_completion_list (char ***list_ptr)
+free_completion_list (VEC (char_ptr) **list_ptr)
 {
-  int i = 0;
-  char **list = *list_ptr;
+  int i;
+  char *p;
 
-  while (list[i] != NULL)
-    {
-      xfree (list[i]);
-      i++;
-    }
-  xfree (list);
+  for (i = 0; VEC_iterate (char_ptr, *list_ptr, i, p); ++i)
+    xfree (p);
+  VEC_free (char_ptr, *list_ptr);
 }
 
 /* Callback for make_cleanup.  */
@@ -3904,9 +3901,7 @@ do_free_completion_list (void *list)
 
 /* Helper routine for make_symbol_completion_list.  */
 
-static int return_val_size;
-static int return_val_index;
-static char **return_val;
+static VEC (char_ptr) *return_val;
 
 #define COMPLETION_LIST_ADD_SYMBOL(symbol, sym_text, len, text, word) \
       completion_list_add_name \
@@ -3953,13 +3948,7 @@ completion_list_add_name (const char *symname,
 	strcat (new, symname);
       }
 
-    if (return_val_index + 3 > return_val_size)
-      {
-	newsize = (return_val_size *= 2) * sizeof (char *);
-	return_val = (char **) xrealloc ((char *) return_val, newsize);
-      }
-    return_val[return_val_index++] = new;
-    return_val[return_val_index] = NULL;
+    VEC_safe_push (char_ptr, return_val, new);
   }
 }
 
@@ -4123,7 +4112,7 @@ expand_partial_symbol_name (const char *name, void *user_data)
   return compare_symbol_name (name, datum->sym_text, datum->sym_text_len);
 }
 
-char **
+VEC (char_ptr) *
 default_make_symbol_completion_list_break_on (char *text, char *word,
 					      const char *break_on)
 {
@@ -4178,9 +4167,7 @@ default_make_symbol_completion_list_break_on (char *text, char *word,
       /* A double-quoted string is never a symbol, nor does it make sense
          to complete it any other way.  */
       {
-	return_val = (char **) xmalloc (sizeof (char *));
-	return_val[0] = NULL;
-	return return_val;
+	return NULL;
       }
     else
       {
@@ -4216,10 +4203,7 @@ default_make_symbol_completion_list_break_on (char *text, char *word,
     }
   gdb_assert (sym_text[sym_text_len] == '\0' || sym_text[sym_text_len] == '(');
 
-  return_val_size = 100;
-  return_val_index = 0;
-  return_val = (char **) xmalloc ((return_val_size + 1) * sizeof (char *));
-  return_val[0] = NULL;
+  return_val = NULL;
   back_to = make_cleanup (do_free_completion_list, &return_val);
 
   datum.sym_text = sym_text;
@@ -4334,17 +4318,17 @@ default_make_symbol_completion_list_break_on (char *text, char *word,
   return (return_val);
 }
 
-char **
+VEC (char_ptr) *
 default_make_symbol_completion_list (char *text, char *word)
 {
   return default_make_symbol_completion_list_break_on (text, word, "");
 }
 
-/* Return a NULL terminated array of all symbols (regardless of class)
-   which begin by matching TEXT.  If the answer is no symbols, then
-   the return value is an array which contains only a NULL pointer.  */
+/* 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.  */
 
-char **
+VEC (char_ptr) *
 make_symbol_completion_list (char *text, char *word)
 {
   return current_language->la_make_symbol_completion_list (text, word);
@@ -4353,7 +4337,7 @@ make_symbol_completion_list (char *text, char *word)
 /* Like make_symbol_completion_list, but suitable for use as a
    completion function.  */
 
-char **
+VEC (char_ptr) *
 make_symbol_completion_list_fn (struct cmd_list_element *ignore,
 				char *text, char *word)
 {
@@ -4363,7 +4347,7 @@ make_symbol_completion_list_fn (struct cmd_list_element *ignore,
 /* Like make_symbol_completion_list, but returns a list of symbols
    defined in a source file FILE.  */
 
-char **
+VEC (char_ptr) *
 make_file_symbol_completion_list (char *text, char *word, char *srcfile)
 {
   struct symbol *sym;
@@ -4409,9 +4393,7 @@ make_file_symbol_completion_list (char *text, char *word, char *srcfile)
       /* A double-quoted string is never a symbol, nor does it make sense
          to complete it any other way.  */
       {
-	return_val = (char **) xmalloc (sizeof (char *));
-	return_val[0] = NULL;
-	return return_val;
+	return NULL;
       }
     else
       {
@@ -4422,10 +4404,7 @@ make_file_symbol_completion_list (char *text, char *word, char *srcfile)
 
   sym_text_len = strlen (sym_text);
 
-  return_val_size = 10;
-  return_val_index = 0;
-  return_val = (char **) xmalloc ((return_val_size + 1) * sizeof (char *));
-  return_val[0] = NULL;
+  return_val = NULL;
 
   /* Find the symtab for SRCFILE (this loads it if it was not yet read
      in).  */
@@ -4468,18 +4447,11 @@ make_file_symbol_completion_list (char *text, char *word, char *srcfile)
 
 static void
 add_filename_to_list (const char *fname, char *text, char *word,
-		      char ***list, int *list_used, int *list_alloced)
+		      VEC (char_ptr) **list)
 {
   char *new;
   size_t fnlen = strlen (fname);
 
-  if (*list_used + 1 >= *list_alloced)
-    {
-      *list_alloced *= 2;
-      *list = (char **) xrealloc ((char *) *list,
-				  *list_alloced * sizeof (char *));
-    }
-
   if (word == text)
     {
       /* Return exactly fname.  */
@@ -4500,8 +4472,7 @@ add_filename_to_list (const char *fname, char *text, char *word,
       new[text - word] = '\0';
       strcat (new, fname);
     }
-  (*list)[*list_used] = new;
-  (*list)[++*list_used] = NULL;
+  VEC_safe_push (char_ptr, *list, new);
 }
 
 static int
@@ -4529,9 +4500,7 @@ struct add_partial_filename_data
   char *text;
   char *word;
   int text_len;
-  char ***list;
-  int *list_used;
-  int *list_alloced;
+  VEC (char_ptr) **list;
 };
 
 /* A callback for map_partial_symbol_filenames.  */
@@ -4549,8 +4518,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 (filename, data->text, data->word,
-			    data->list, data->list_used, data->list_alloced);
+      add_filename_to_list (filename, data->text, data->word, data->list);
     }
   else
     {
@@ -4559,32 +4527,27 @@ maybe_add_partial_symtab_filename (const char *filename, const char *fullname,
       if (base_name != filename
 	  && !filename_seen (base_name, 1, data->first)
 	  && filename_ncmp (base_name, data->text, data->text_len) == 0)
-	add_filename_to_list (base_name, data->text, data->word,
-			      data->list, data->list_used, data->list_alloced);
+	add_filename_to_list (base_name, data->text, data->word, data->list);
     }
 }
 
-/* Return a NULL terminated array 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 an array which contains only a NULL pointer.  */
+/* 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.  */
 
-char **
+VEC (char_ptr) *
 make_source_files_completion_list (char *text, char *word)
 {
   struct symtab *s;
   struct objfile *objfile;
   int first = 1;
-  int list_alloced = 1;
-  int list_used = 0;
   size_t text_len = strlen (text);
-  char **list = (char **) xmalloc (list_alloced * sizeof (char *));
+  VEC (char_ptr) *list = NULL;
   const char *base_name;
   struct add_partial_filename_data datum;
   struct cleanup *back_to;
 
-  list[0] = NULL;
-
   if (!have_full_symbols () && !have_partial_symbols ())
     return list;
 
@@ -4599,8 +4562,7 @@ make_source_files_completion_list (char *text, char *word)
 	{
 	  /* This file matches for a completion; add it to the current
 	     list of matches.  */
-	  add_filename_to_list (s->filename, text, word,
-				&list, &list_used, &list_alloced);
+	  add_filename_to_list (s->filename, text, word, &list);
 	}
       else
 	{
@@ -4612,8 +4574,7 @@ make_source_files_completion_list (char *text, char *word)
 	  if (base_name != s->filename
 	      && !filename_seen (base_name, 1, &first)
 	      && filename_ncmp (base_name, text, text_len) == 0)
-	    add_filename_to_list (base_name, text, word,
-				  &list, &list_used, &list_alloced);
+	    add_filename_to_list (base_name, text, word, &list);
 	}
     }
 
@@ -4622,8 +4583,6 @@ make_source_files_completion_list (char *text, char *word)
   datum.word = word;
   datum.text_len = text_len;
   datum.list = &list;
-  datum.list_used = &list_used;
-  datum.list_alloced = &list_alloced;
   map_partial_symbol_filenames (maybe_add_partial_symtab_filename, &datum,
 				0 /*need_fullname*/);
   discard_cleanups (back_to);
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 526fe5a..38472e0 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -22,6 +22,7 @@
 #define SYMTAB_H 1
 
 #include "vec.h"
+#include "gdb_vecs.h"
 
 /* Opaque declarations.  */
 struct ui_file;
@@ -1150,16 +1151,17 @@ extern void forget_cached_source_info (void);
 
 extern void select_source_symtab (struct symtab *);
 
-extern char **default_make_symbol_completion_list_break_on
+extern VEC (char_ptr) *default_make_symbol_completion_list_break_on
   (char *text, char *word, const char *break_on);
-extern char **default_make_symbol_completion_list (char *, char *);
-extern char **make_symbol_completion_list (char *, char *);
-extern char **make_symbol_completion_list_fn (struct cmd_list_element *,
-					      char *, char *);
+extern VEC (char_ptr) *default_make_symbol_completion_list (char *, char *);
+extern VEC (char_ptr) *make_symbol_completion_list (char *, char *);
+extern VEC (char_ptr) *make_symbol_completion_list_fn (struct cmd_list_element *,
+						       char *, char *);
 
-extern char **make_file_symbol_completion_list (char *, char *, char *);
+extern VEC (char_ptr) *make_file_symbol_completion_list (char *,
+							 char *, char *);
 
-extern char **make_source_files_completion_list (char *, char *);
+extern VEC (char_ptr) *make_source_files_completion_list (char *, char *);
 
 /* symtab.c */
 
-- 
1.7.7.6


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]