| 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++;
|
| }
|
| }
|
|
|