[PATCH 15/18] Implement completion limiting for scmcmd_add_completion.

Keith Seitz
2015-04-13T19:23:43Z

This patch converts scmcmd_add_completion to use maybe_add_completion and
adds some tests for this new behavior.

gdb/ChangeLog

* guile/scm-cmd.c (cmdscm_add_completion): Add completer_data
argument. All callers updated.
Use maybe_add_completion.

gdb/testsuite/ChangeLog

* gdb.guile/scm-cmd.exp: Add completion limiting tests.
---
gdb/guile/scm-cmd.c | 21 +++++++++++++++++----
gdb/testsuite/gdb.guile/scm-cmd.exp | 24 ++++++++++++++++++++++++
2 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/gdb/guile/scm-cmd.c b/gdb/guile/scm-cmd.c
index 2c57d17..1680c27 100644
--- a/gdb/guile/scm-cmd.c
+++ b/gdb/guile/scm-cmd.c
@@ -348,10 +348,12 @@ cmdscm_bad_completion_result (const char *msg, SCM completion)
The result is a boolean indicating success. */

static int
-cmdscm_add_completion (SCM completion, VEC (char_ptr) **result)
+cmdscm_add_completion (SCM completion, struct completer_data *cdata,
+ VEC (char_ptr) **result)
{
char *item;
SCM except_scm;
+ enum maybe_add_completion_enum add_status;

if (!scm_is_string (completion))
{
@@ -370,7 +372,18 @@ cmdscm_add_completion (SCM completion, VEC (char_ptr) **result)
return 0;
}

- VEC_safe_push (char_ptr, *result, item);
+ add_status = maybe_add_completion (cdata, item);
+ switch (add_status)
+ {
+ case MAYBE_ADD_COMPLETION_OK:
+ case MAYBE_ADD_COMPLETION_OK_MAX_REACHED:
+ VEC_safe_push (char_ptr, *result, item);
+ break;
+ case MAYBE_ADD_COMPLETION_MAX_REACHED:
+ case MAYBE_ADD_COMPLETION_DUPLICATE:
+ xfree (item);
+ break;
+ }

return 1;
}
@@ -418,7 +431,7 @@ cmdscm_completer (struct completer_data *cdata,
{
SCM next = scm_car (list);

- if (!cmdscm_add_completion (next, &result))
+ if (!cmdscm_add_completion (next, cdata, &result))
{
VEC_free (char_ptr, result);
goto done;
@@ -442,7 +455,7 @@ cmdscm_completer (struct completer_data *cdata,
goto done;
}

- if (!cmdscm_add_completion (next, &result))
+ if (!cmdscm_add_completion (next, cdata, &result))
{
VEC_free (char_ptr, result);
goto done;
diff --git a/gdb/testsuite/gdb.guile/scm-cmd.exp b/gdb/testsuite/gdb.guile/scm-cmd.exp
index 53c0fdf..ac721c3 100644
--- a/gdb/testsuite/gdb.guile/scm-cmd.exp
+++ b/gdb/testsuite/gdb.guile/scm-cmd.exp
@@ -196,6 +196,30 @@ gdb_test "test-scheme-error-cmd ugh" \
"Error occurred in Scheme-implemented GDB command." \
"call scheme-error command"

+# Test completion limiting.
+set max_completions 2
+gdb_test_no_output "set max-completions $max_completions"
+set end "\\\*\\\*\\\* List may be truncated, "
+append end "max-completions reached\\\. \\\*\\\*\\\*"
+set test "limit complete completer-as-function 42\."
+gdb_test_multiple "complete completer-as-function 42\." $test {
+ "complete completer-as-function 42\\\." { exp_continue }
+ -re "completer-as-function 42\\\.\[1-3\]\r\n" {
+ incr seen
+ exp_continue
+ }
+ -re ".*$end\r\n$gdb_prompt $" {
+ if {$seen == $max_completions} {
+ pass $test
+ } else {
+ fail "$test ($seen/$max_completions)"
+ }
+ }
+ -re ".*$gdb_prompt $" {
+ fail "$test (unlimited)"
+ }
+}
+
# If there is a problem with object management, this can often trigger it.
# It is useful to do this last, after we've created a bunch of command objects.