| Index: gdb/completer.c
 | 
| diff --git a/gdb/completer.c b/gdb/completer.c
 | 
| index 48a4e463a7f7c6cf325696382f06f76f0c307595..b9f069976340724f692c43ecb5a9fb9d06b80e83 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,20 +361,20 @@ 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;
 | 
|    int computed_type_name = 0;
 | 
| -  char *type_name = NULL;
 | 
| +  const char *type_name = NULL;
 | 
|  
 | 
|    CHECK_TYPEDEF (type);
 | 
|    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);
 | 
|  	    }
 | 
|  	}
 | 
| @@ -416,7 +396,7 @@ add_struct_fields (struct type *type, int *nextp, char **output,
 | 
|  
 | 
|    for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; --i)
 | 
|      {
 | 
| -      char *name = TYPE_FN_FIELDLIST_NAME (type, i);
 | 
| +      const char *name = TYPE_FN_FIELDLIST_NAME (type, i);
 | 
|  
 | 
|        if (name && ! strncmp (name, 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++;
 | 
|  	}
 | 
|      }
 | 
| 
 |