diff options
author | Pedro Alves <palves@redhat.com> | 2017-12-13 16:38:49 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2017-12-13 16:38:49 +0000 |
commit | 60a20c190789fd75d1955576160cbbfe94c792fb (patch) | |
tree | 3ca6c6a997ea7ca80c2051857d7cf478eefca4ac /gdb/completer.c | |
parent | 0b982d685e840948eed4619843a0cc5ce8991d6c (diff) | |
download | gdb-60a20c190789fd75d1955576160cbbfe94c792fb.zip gdb-60a20c190789fd75d1955576160cbbfe94c792fb.tar.gz gdb-60a20c190789fd75d1955576160cbbfe94c792fb.tar.bz2 |
Factor out final completion match string building
We have several places doing essentially the same thing; factor them
out to a central place. Some of the places overallocate for no good
reason, or use strcat unnecessarily. The centralized version is more
precise and to the point.
(I considered making the gdb::unique_xmalloc_ptr overload version of
make_completer_match_str try to realloc (not xrealloc) probably
avoiding an allocation in most cases, but that'd be probably overdoing
it, and also, now that I'm writing this I thought I'd try to see how
could we ever get to filename_completer with "text != word", but I
couldn't figure it out. Running the testsuite with 'gdb_assert (text
== word);' never tripped on the assertion either. So post gdb 8.1,
I'll probably propose a patch to simplify filename_completer a bit,
and the gdb::unique_xmalloc_str overload can be removed then.)
gdb/ChangeLog:
2017-12-13 Pedro Alves <palves@redhat.com>
* cli/cli-decode.c (complete_on_cmdlist, complete_on_enum): Use
make_completion_match_str.
* completer.c: Use gdb::unique_xmalloc_ptr and
make_completion_match_str.
(make_completion_match_str_1): New.
(make_completion_match_str(const char *, const char *,
const char *)): New.
(make_completion_match_str(gdb::unique_xmalloc_ptr<char> &&,
const char *, const char *)): New.
* completer.h (make_completion_match_str(const char *,
const char *, const char *)): New.
(make_completion_match_str(gdb::unique_xmalloc_ptr<char> &&,
const char *, const char *)): New.
* interps.c (interpreter_completer): Use make_completion_match_str.
* symtab.c (completion_list_add_name, add_filename_to_list): Use
make_completion_match_str.
Diffstat (limited to 'gdb/completer.c')
-rw-r--r-- | gdb/completer.c | 92 |
1 files changed, 64 insertions, 28 deletions
diff --git a/gdb/completer.c b/gdb/completer.c index 1cfabcd..0195114 100644 --- a/gdb/completer.c +++ b/gdb/completer.c @@ -158,10 +158,9 @@ filename_completer (struct cmd_list_element *ignore, subsequent_name = 0; while (1) { - char *p, *q; - - p = rl_filename_completion_function (text, subsequent_name); - if (p == NULL) + gdb::unique_xmalloc_ptr<char> p_rl + (rl_filename_completion_function (text, subsequent_name)); + if (p_rl == NULL) break; /* We need to set subsequent_name to a non-zero value before the continue line below, because otherwise, if the first file @@ -170,32 +169,12 @@ filename_completer (struct cmd_list_element *ignore, subsequent_name = 1; /* Like emacs, don't complete on old versions. Especially useful in the "source" command. */ + const char *p = p_rl.get (); if (p[strlen (p) - 1] == '~') - { - xfree (p); - continue; - } + continue; - if (word == text) - /* Return exactly p. */ - q = p; - else if (word > text) - { - /* Return some portion of p. */ - q = (char *) xmalloc (strlen (p) + 5); - strcpy (q, p + (word - text)); - xfree (p); - } - else - { - /* Return some of TEXT plus p. */ - q = (char *) xmalloc (strlen (p) + (text - word) + 5); - strncpy (q, word, text - word); - q[text - word] = '\0'; - strcat (q, p); - xfree (p); - } - tracker.add_completion (gdb::unique_xmalloc_ptr<char> (q)); + tracker.add_completion + (make_completion_match_str (std::move (p_rl), text, word)); } #if 0 /* There is no way to do this just long enough to affect quote @@ -1580,6 +1559,63 @@ completion_tracker::add_completions (completion_list &&list) add_completion (std::move (candidate)); } +/* Helper for the make_completion_match_str overloads. Returns NULL + as an indication that we want MATCH_NAME exactly. It is up to the + caller to xstrdup that string if desired. */ + +static char * +make_completion_match_str_1 (const char *match_name, + const char *text, const char *word) +{ + char *newobj; + + if (word == text) + { + /* Return NULL as an indication that we want MATCH_NAME + exactly. */ + return NULL; + } + else if (word > text) + { + /* Return some portion of MATCH_NAME. */ + newobj = xstrdup (match_name + (word - text)); + } + else + { + /* Return some of WORD plus MATCH_NAME. */ + size_t len = strlen (match_name); + newobj = (char *) xmalloc (text - word + len + 1); + memcpy (newobj, word, text - word); + memcpy (newobj + (text - word), match_name, len + 1); + } + + return newobj; +} + +/* See completer.h. */ + +gdb::unique_xmalloc_ptr<char> +make_completion_match_str (const char *match_name, + const char *text, const char *word) +{ + char *newobj = make_completion_match_str_1 (match_name, text, word); + if (newobj == NULL) + newobj = xstrdup (match_name); + return gdb::unique_xmalloc_ptr<char> (newobj); +} + +/* See completer.h. */ + +gdb::unique_xmalloc_ptr<char> +make_completion_match_str (gdb::unique_xmalloc_ptr<char> &&match_name, + const char *text, const char *word) +{ + char *newobj = make_completion_match_str_1 (match_name.get (), text, word); + if (newobj == NULL) + return std::move (match_name); + return gdb::unique_xmalloc_ptr<char> (newobj); +} + /* Generate completions all at once. Does nothing if max_completions is 0. If max_completions is non-negative, this will collect at most max_completions strings. |