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