This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH v3 02/19] Remove completion_tracker_t from the public completion API.


Keith Seitz <keiths@redhat.com> writes:
> Differences from last version:
>
> 1. Removed comments about recording an additional completion from
>    add_completion.
> 2. Removed requirement to xstrdup arg to add_completion; add_completeion
>     uses new function completer_strdup.
> 3. Consolidated (oft-repeated) partial copy code into completer_strdup.
>    Removed this code from all completion functions.
>
> ---
>
> This patch removes the recently introduced "completion tracker" concept
> from the public completion API.  In the previous patch, the completion
> tracker was added to the (new) completer_data structure that is now
> used by all completion functions.
>
> Since completion_tracker_t is now used entirely inside completer.c, there
> is no need to make its type opaque, so the typedef has been removed.
>
> This patch also fixes gdb/17960, which is easily demonstrated:
>
> $ gdb -nx -q gdb
> (gdb) b gdb.c:ma<TAB>
> ./../src/gdb/completer.c:837: internal-error: maybe_add_completion:
> Assertion `tracker != NULL' failed.
> A problem internal to GDB has been detected,
> further debugging may prove unreliable.
> Quit this debugging session? (y or n)
>
> This occurs because the code path in this case is:
> complete_line
> - complete_line_internal
> -- location_completer
>
> gdb/ChangeLog
>
> 	PR gdb/17960
> 	* completer.c (struct completer_data) <tracker>: Change type to
> 	htab_t.
> 	(enum maybe_add_completion_enum): Make private; moved from
> 	completer.h.
> 	[DEFAULT_MAX_COMPLETIONS]: Define.
> 	(new_completion_tracker): Remove function.
> 	(new_completer_data): New function.
> 	(free_completion_tracker): Remove function.
> 	(free_completer_data): New function.
> 	(make_cleanup_free_completion_tracker): Remove function.
> 	(maybe_add_completion): Make static.  Update comments.
> 	Use completer_data instead of completion_tracker_t.
> 	(completer_strdup): New function.
> 	(add_completion): New function.
> 	(complete_line, gdb_completion_word_break_characters): Use
> 	completer_data instead of completion_tracker.
> 	* completer.h (completion_tracker_t, new_completion_tracker)
> 	(make_cleanup_free_completion_tracker, maybe_add_completion)
> 	(enum maybe_add_completion): Remove declarations.
> 	(enum add_completion_status): Define.
> 	(add_completion): Declare.
> 	* symtab.c (completion_tracker): Remove variable.
> 	(completion_list_add_name): Use add_completion instead of
> 	maybe_add_completion and partial copy.
> 	(default_make_symbol_completion_list_break_on_1): Do not use
> 	completion_tracker.
>
> gdb/testsuite/ChangeLog
>
> 	PR gdb/17960
> 	* gdb.base/completion.exp: Add some basic tests for the
> 	location completer, including a regression test for
> 	the gdb/17960 assertion failure.

Hi.
A few nits, grep for ^====.

> ---
>  gdb/completer.c                       |  231 +++++++++++++++++++++++----------
>  gdb/completer.h                       |   66 +++------
>  gdb/symtab.c                          |   62 +--------
>  gdb/testsuite/gdb.base/completion.exp |   78 +++++++++++
>  4 files changed, 260 insertions(+), 177 deletions(-)
>
> diff --git a/gdb/completer.c b/gdb/completer.c
> index 476f9f2..bf4137e 100644
> --- a/gdb/completer.c
> +++ b/gdb/completer.c
> @@ -92,10 +92,31 @@ static char *gdb_completer_quote_characters = "'";
>  
>  struct completer_data
>  {
> -  /* The completion tracker being used by the completer.  */
> -  completion_tracker_t tracker;
> +  /* A hashtable used to track completions.  */
> +  htab_t tracker;
>  };
>  
> +/* Return values for maybe_add_completion.  */
> +
> +enum maybe_add_completion_enum
> +{
> +  /* NAME has been recorded and max_completions has not been reached,
> +     or completion tracking is disabled (max_completions < 0).  */
> +  MAYBE_ADD_COMPLETION_OK,
> +
> +  /* NAME has been recorded and max_completions has been reached
> +     (thus the caller can stop searching).  */
> +  MAYBE_ADD_COMPLETION_OK_MAX_REACHED,
> +
> +  /* max-completions entries has been reached.
> +     Whether NAME is a duplicate or not is not determined.  */
> +  MAYBE_ADD_COMPLETION_MAX_REACHED,
> +
> +  /* NAME has already been recorded.
> +     Note that this is never returned if completion tracking is disabled
> +     (max_completions < 0).  */
> +  MAYBE_ADD_COMPLETION_DUPLICATE
> +};
>  
>  /* Accessor for some completer data that may interest other files.  */
>  
> @@ -803,48 +824,41 @@ complete_line_internal (struct completer_data *cdata,
>  
>  /* See completer.h.  */
>  
> -int max_completions = 200;
> +#define DEFAULT_MAX_COMPLETIONS 200
> +int max_completions = DEFAULT_MAX_COMPLETIONS;
>  
> -/* See completer.h.  */
> +/* Allocate a new completer data structure.  */
>  
> -completion_tracker_t
> -new_completion_tracker (void)
> +static struct completer_data *
> +new_completer_data (int size)
>  {
> -  if (max_completions <= 0)
> -    return NULL;
> +  struct completer_data *cdata = XCNEW (struct completer_data);
>  
> -  return htab_create_alloc (max_completions,
> -			    htab_hash_string, (htab_eq) streq,
> -			    NULL, xcalloc, xfree);
> +  cdata->tracker
> +    = htab_create_alloc ((size < 0 ? DEFAULT_MAX_COMPLETIONS : size),
> +			 htab_hash_string, (htab_eq) streq, NULL,

====
One can argue the cast makes things fragile (however slightly).
I'm slightly ambivalent on the point, but I do lean towards removing
the cast and having a wrapper function for streq so the cast isn't
needed.  Let's do the latter.
[IWBN if hashtab itself provided one, but that's another patch for
another day.]
 
I'm also slightly ambivalent on creating the hash table if
max_completions is disabled (<= 0), and leaning towards not creating it
to avoid potential confusion.
Let's do the latter (pending reading the rest of the patchset - maybe
there's a good reason to always create it).

> +			 xcalloc, xfree);
> +  return cdata;
>  }
>  
> -/* Cleanup routine to free a completion tracker and reset the pointer
> -   to NULL.  */
> +/* Free the completion data represented by P.  */
>  
>  static void
> -free_completion_tracker (void *p)
> +free_completer_data (void *p)
>  {
> -  completion_tracker_t *tracker_ptr = p;
> +  struct completer_data *cdata = p;
>  
> -  htab_delete (*tracker_ptr);
> -  *tracker_ptr = NULL;
> +  htab_delete (cdata->tracker);
> +  xfree (cdata);
>  }
>  
> -/* See completer.h.  */
> -
> -struct cleanup *
> -make_cleanup_free_completion_tracker (completion_tracker_t *tracker_ptr)
> -{
> -  if (*tracker_ptr == NULL)
> -    return make_cleanup (null_cleanup, NULL);
> -
> -  return make_cleanup (free_completion_tracker, tracker_ptr);
> -}
> -
> -/* See completer.h.  */
> +/* Add the completion NAME to the list of generated completions if
> +   it is not there already.
> +   If max_completions is negative, nothing is done, not even watching
> +   for duplicates, and MAYBE_ADD_COMPLETION_OK is always returned.  */
>  
> -enum maybe_add_completion_enum
> -maybe_add_completion (completion_tracker_t tracker, char *name)
> +static enum maybe_add_completion_enum
> +maybe_add_completion (struct completer_data *cdata, char *name)
>  {
>    void **slot;
>  
> @@ -853,23 +867,82 @@ maybe_add_completion (completion_tracker_t tracker, char *name)
>    if (max_completions == 0)
>      return MAYBE_ADD_COMPLETION_MAX_REACHED;
>  
> -  gdb_assert (tracker != NULL);

====
Let's keep this assert (assuming we're going with not creating the
hashtab if we don't have to, i.e., if max_completions <= 0).

> -
> -  if (htab_elements (tracker) >= max_completions)
> +  if (htab_elements (cdata->tracker) >= max_completions)
>      return MAYBE_ADD_COMPLETION_MAX_REACHED;
>  
> -  slot = htab_find_slot (tracker, name, INSERT);
> +  slot = htab_find_slot (cdata->tracker, name, INSERT);
>  
>    if (*slot != HTAB_EMPTY_ENTRY)
>      return MAYBE_ADD_COMPLETION_DUPLICATE;
>  
>    *slot = name;
>  
> -  return (htab_elements (tracker) < max_completions
> +  return (htab_elements (cdata->tracker) < max_completions
>  	  ? MAYBE_ADD_COMPLETION_OK
>  	  : MAYBE_ADD_COMPLETION_OK_MAX_REACHED);
>  }
>  
> +/* A strdup-like function used by the completer to copy bits of completion
> +   strings.  */
> +
> +static char *
> +completer_strdup (const char *match, const char *text, const char *word)
> +{
> +  char *alloc;
> +
> +  if (text == NULL || word == NULL || text == word)
> +    return xstrdup (match);
> +
> +  if (word > text)
> +    {
> +      gdb_assert (strlen (match) > (word - text));
> +
> +      /* Return some portion of match.  */
> +      match += (word - text);
> +      alloc = xmalloc (strlen (match) + 1);
> +      strcpy (alloc, match);

====
This can still use xstrdup (right?).

> +    }
> +  else
> +    {
> +      /* Return some of text plus match.  */
> +      alloc = xmalloc (strlen (match) + (text - word) + 1);
> +      strncpy (alloc, word, text - word);
> +      alloc[text - word] = '\0';
> +      strcat (alloc, match);
> +    }
> +
> +  return alloc;
> +}

====
I didn't review this function too closely to confirm it's correct.
I'm going to assume it is for the moment.
IWBN to have a description of each parameter in the function comment.
I realize the terms match,text,word have very specific meanings
in this file. Just a WBN.

> +
> +/* See completer.h.  */
> +
> +enum add_completion_status
> +add_completion (struct completer_data *cdata, VEC (char_ptr) **result,
> +		const char *match, const char *text, const char *word)
> +{
> +  enum maybe_add_completion_enum add_status;
> +  char *alloc = completer_strdup (match, text, word);
> +
> +  add_status = maybe_add_completion (cdata, alloc);
> +  switch (add_status)
> +    {
> +    case MAYBE_ADD_COMPLETION_OK:
> +      VEC_safe_push (char_ptr, *result, alloc);
> +      break;
> +    case MAYBE_ADD_COMPLETION_OK_MAX_REACHED:
> +      VEC_safe_push (char_ptr, *result, alloc);
> +      return ADD_COMPLETION_MAX_REACHED;
> +    case MAYBE_ADD_COMPLETION_MAX_REACHED:
> +      xfree (alloc);
> +      return ADD_COMPLETION_MAX_REACHED;
> +    case MAYBE_ADD_COMPLETION_DUPLICATE:
> +      xfree (alloc);
> +      break;
> +    }
> +
> +  return ADD_COMPLETION_OK;
> +}
> +
>  void
>  throw_max_completions_reached_error (void)
>  {
> @@ -894,54 +967,63 @@ complete_line (const char *text, const char *line_buffer, int point)
>  {
>    VEC (char_ptr) *list;
>    VEC (char_ptr) *result = NULL;
> -  struct cleanup *cleanups;
> -  completion_tracker_t tracker;
> +  struct cleanup *cdata_cleanup, *list_cleanup;
>    char *candidate;
> -  int ix, max_reached;
> +  int ix;
> +  struct completer_data *cdata;
>  
>    if (max_completions == 0)
>      return NULL;
> -  list = complete_line_internal (NULL, text, line_buffer, point,
> +
> +  cdata = new_completer_data (max_completions);
> +  cdata_cleanup = make_cleanup (free_completer_data, cdata);
> +  list = complete_line_internal (cdata, text, line_buffer, point,
>  				 handle_completions);
>    if (max_completions < 0)
> -    return list;
> -
> -  tracker = new_completion_tracker ();
> -  cleanups = make_cleanup_free_completion_tracker (&tracker);
> -  make_cleanup_free_char_ptr_vec (list);
> -
> -  /* Do a final test for too many completions.  Individual completers may
> -     do some of this, but are not required to.  Duplicates are also removed
> -     here.  Otherwise the user is left scratching his/her head: readline and
> -     complete_command will remove duplicates, and if removal of duplicates
> -     there brings the total under max_completions the user may think gdb quit
> -     searching too early.  */
> -
> -  for (ix = 0, max_reached = 0;
> -       !max_reached && VEC_iterate (char_ptr, list, ix, candidate);
> -       ++ix)
>      {
> -      enum maybe_add_completion_enum add_status;
> +      do_cleanups (cdata_cleanup);
> +      return list;
> +    }
> +
> +  list_cleanup = make_cleanup_free_char_ptr_vec (list);
>  
> -      add_status = maybe_add_completion (tracker, candidate);
> +  /* If complete_line_internal returned more completions than were
> +     recorded by the completion tracker, then the completer function that
> +     was run does not support completion tracking.  In this case,
> +     do a final test for too many completions.
>  
> -      switch (add_status)
> +     Duplicates are also removed here.  Otherwise the user is left
> +     scratching his/her head: readline and complete_command will remove
> +     duplicates, and if removal of duplicates there brings the total under
> +     max_completions the user may think gdb quit searching too early.  */
> +
> +  if (VEC_length (char_ptr, list) > htab_elements (cdata->tracker))
> +    {
> +      enum add_completion_status max_reached = ADD_COMPLETION_OK;
> +
> +      /* Clear the tracker so that we can re-use it to count the number
> +	 of returned completions.  */
> +      htab_empty (cdata->tracker);
> +
> +      for (ix = 0; (max_reached == ADD_COMPLETION_OK
> +		    && VEC_iterate (char_ptr, list, ix, candidate)); ++ix)
>  	{
> -	  case MAYBE_ADD_COMPLETION_OK:
> -	    VEC_safe_push (char_ptr, result, xstrdup (candidate));
> -	    break;
> -	  case MAYBE_ADD_COMPLETION_OK_MAX_REACHED:
> -	    VEC_safe_push (char_ptr, result, xstrdup (candidate));
> -	    max_reached = 1;
> -	    break;
> -      	  case MAYBE_ADD_COMPLETION_MAX_REACHED:
> -	    gdb_assert_not_reached ("more than max completions reached");
> -	  case MAYBE_ADD_COMPLETION_DUPLICATE:
> -	    break;
> +	  max_reached = add_completion (cdata, &result, candidate, NULL, NULL);
>  	}
> +
> +      /* The return result has been assembled and the original list from
> +	 complete_line_internal is no longer needed.  Free it.  */
> +      do_cleanups (list_cleanup);
> +    }
> +  else
> +    {
> +      /* There is a valid tracker for the completion -- simply return
> +	 the completed list.  */
> +      discard_cleanups (list_cleanup);
> +      result = list;
>      }
>  
> -  do_cleanups (cleanups);
> +  do_cleanups (cdata_cleanup);
>  
>    return result;
>  }
> @@ -1074,9 +1156,14 @@ char *
>  gdb_completion_word_break_characters (void)
>  {
>    VEC (char_ptr) *list;
> +  struct completer_data *cdata;
> +  struct cleanup *cleanup;
>  
> -  list = complete_line_internal (NULL, rl_line_buffer, rl_line_buffer,
> +  cdata = new_completer_data (max_completions);
> +  cleanup = make_cleanup (free_completer_data, cdata);
> +  list = complete_line_internal (cdata, rl_line_buffer, rl_line_buffer,
>  				 rl_point, handle_brkchars);
> +  do_cleanups (cleanup);
>    gdb_assert (list == NULL);
>    return rl_completer_word_break_characters;
>  }
> diff --git a/gdb/completer.h b/gdb/completer.h
> index 7139c0a..43d1321 100644
> --- a/gdb/completer.h
> +++ b/gdb/completer.h
> @@ -132,59 +132,31 @@ extern const char *skip_quoted (const char *);
>  
>  extern int max_completions;
>  
> -/* Object to track how many unique completions have been generated.
> -   Used to limit the size of generated completion lists.  */
> +/* Return values for add_completion.  */
>  
> -typedef htab_t completion_tracker_t;
> -
> -/* Create a new completion tracker.
> -   The result is a hash table to track added completions, or NULL
> -   if max_completions <= 0.  If max_completions < 0, tracking is disabled.
> -   If max_completions == 0, the max is indeed zero.  */
> -
> -extern completion_tracker_t new_completion_tracker (void);
> -
> -/* Make a cleanup to free a completion tracker, and reset its pointer
> -   to NULL.  */
> -
> -extern struct cleanup *make_cleanup_free_completion_tracker
> -		      (completion_tracker_t *tracker_ptr);
> -
> -/* Return values for maybe_add_completion.  */
> -
> -enum maybe_add_completion_enum
> +enum add_completion_status
>  {
> -  /* NAME has been recorded and max_completions has not been reached,
> -     or completion tracking is disabled (max_completions < 0).  */
> -  MAYBE_ADD_COMPLETION_OK,
> -
> -  /* NAME has been recorded and max_completions has been reached
> -     (thus the caller can stop searching).  */
> -  MAYBE_ADD_COMPLETION_OK_MAX_REACHED,
> -
> -  /* max-completions entries has been reached.
> -     Whether NAME is a duplicate or not is not determined.  */
> -  MAYBE_ADD_COMPLETION_MAX_REACHED,
> -
> -  /* NAME has already been recorded.
> -     Note that this is never returned if completion tracking is disabled
> -     (max_completions < 0).  */
> -  MAYBE_ADD_COMPLETION_DUPLICATE
> +  /* Completion was added -- keep looking for more.  */
> +  ADD_COMPLETION_OK,
> +
> +  /* Maximum number of completions has been reached or the maximum
> +     has already been reached by a previous call to add_completion.
> +     Callers can make no assumptions about whether the completion was
> +     added or not.  */
> +  ADD_COMPLETION_MAX_REACHED
>  };
>  
> -/* Add the completion NAME to the list of generated completions if
> -   it is not there already.
> -   If max_completions is negative, nothing is done, not even watching
> -   for duplicates, and MAYBE_ADD_COMPLETION_OK is always returned.
> +/* Add the given MATCH to the completer result in CDATA.
> +   Returns one of the above enum add_completion_status codes to indicate
> +   whether the caller should continue to look for/compute more completions.
>  
> -   If MAYBE_ADD_COMPLETION_MAX_REACHED is returned, callers are required to
> -   record at least one more completion.  The final list will be pruned to
> -   max_completions, but recording at least one more than max_completions is
> -   the signal to the completion machinery that too many completions were
> -   found.  */
> +   If TEXT and WORD are non-NULL, then portions of the strings will be
> +   saved into the completion list.  See completer_strdup for more.  */
>  
> -extern enum maybe_add_completion_enum
> -  maybe_add_completion (completion_tracker_t tracker, char *name);
> +extern enum add_completion_status
> +  add_completion (struct completer_data *cdata,
> +		  VEC (char_ptr) **result, const char *match,
> +		  const char *text, const char *word);
>  
>  /* Wrapper to throw MAX_COMPLETIONS_REACHED_ERROR.  */ 
>  
> diff --git a/gdb/symtab.c b/gdb/symtab.c
> index f4407a0..34eb6d7 100644
> --- a/gdb/symtab.c
> +++ b/gdb/symtab.c
> @@ -5046,15 +5046,6 @@ static VEC (char_ptr) *return_val;
>    completion_list_add_name						\
>    (cdata, MSYMBOL_NATURAL_NAME (symbol), (sym_text), (len), (text), (word))
>  
> -/* Tracker for how many unique completions have been generated.  Used
> -   to terminate completion list generation early if the list has grown
> -   to a size so large as to be useless.  This helps avoid GDB seeming
> -   to lock up in the event the user requests to complete on something
> -   vague that necessitates the time consuming expansion of many symbol
> -   tables.  */
> -
> -static completion_tracker_t completion_tracker;
> -
>  /*  Test to see if the symbol specified by SYMNAME (which is already
>     demangled for C++ symbols) matches SYM_TEXT in the first SYM_TEXT_LEN
>     characters.  If so, add it to the current completion list.  */
> @@ -5070,50 +5061,11 @@ completion_list_add_name (struct completer_data *cdata,
>      return;
>  
>    /* We have a match for a completion, so add SYMNAME to the current list
> -     of matches.  Note that the name is moved to freshly malloc'd space.  */
> -
> -  {
> -    char *newobj;
> -    enum maybe_add_completion_enum add_status;
> -
> -    if (word == sym_text)
> -      {
> -	newobj = xmalloc (strlen (symname) + 5);
> -	strcpy (newobj, symname);
> -      }
> -    else if (word > sym_text)
> -      {
> -	/* Return some portion of symname.  */
> -	newobj = xmalloc (strlen (symname) + 5);
> -	strcpy (newobj, symname + (word - sym_text));
> -      }
> -    else
> -      {
> -	/* Return some of SYM_TEXT plus symname.  */
> -	newobj = xmalloc (strlen (symname) + (sym_text - word) + 5);
> -	strncpy (newobj, word, sym_text - word);
> -	newobj[sym_text - word] = '\0';
> -	strcat (newobj, symname);
> -      }
> -
> -    add_status = maybe_add_completion (completion_tracker, newobj);
> +     of matches.  */
>  
> -    switch (add_status)
> -      {
> -      case MAYBE_ADD_COMPLETION_OK:
> -	VEC_safe_push (char_ptr, return_val, newobj);
> -	break;
> -      case MAYBE_ADD_COMPLETION_OK_MAX_REACHED:
> -	VEC_safe_push (char_ptr, return_val, newobj);
> -	throw_max_completions_reached_error ();
> -      case MAYBE_ADD_COMPLETION_MAX_REACHED:
> -	xfree (newobj);
> -	throw_max_completions_reached_error ();
> -      case MAYBE_ADD_COMPLETION_DUPLICATE:
> -	xfree (newobj);
> -	break;
> -      }
> -  }
> +    if (add_completion (cdata, &return_val, symname, sym_text, word)
> +	== ADD_COMPLETION_MAX_REACHED)
> +      throw_max_completions_reached_error ();
>  }
>  
>  /* ObjC: In case we are completing on a selector, look as the msymbol
> @@ -5358,7 +5310,6 @@ default_make_symbol_completion_list_break_on_1 (struct completer_data *cdata,
>    /* Length of sym_text.  */
>    int sym_text_len;
>    struct add_name_data datum;
> -  struct cleanup *cleanups;
>  
>    /* Now look for the symbol we are supposed to complete on.  */
>    {
> @@ -5429,9 +5380,6 @@ default_make_symbol_completion_list_break_on_1 (struct completer_data *cdata,
>      }
>    gdb_assert (sym_text[sym_text_len] == '\0' || sym_text[sym_text_len] == '(');
>  
> -  completion_tracker = new_completion_tracker ();
> -  cleanups = make_cleanup_free_completion_tracker (&completion_tracker);
> -
>    datum.sym_text = sym_text;
>    datum.sym_text_len = sym_text_len;
>    datum.text = text;
> @@ -5549,8 +5497,6 @@ default_make_symbol_completion_list_break_on_1 (struct completer_data *cdata,
>        /* User-defined macros are always visible.  */
>        macro_for_each (macro_user_macros, add_macro_name, &datum);
>      }
> -
> -  do_cleanups (cleanups);
>  }
>  
>  VEC (char_ptr) *
> diff --git a/gdb/testsuite/gdb.base/completion.exp b/gdb/testsuite/gdb.base/completion.exp
> index 1eb0fd8..710aac0 100644
> --- a/gdb/testsuite/gdb.base/completion.exp
> +++ b/gdb/testsuite/gdb.base/completion.exp
> @@ -777,6 +777,84 @@ gdb_test_multiple "" "$test" {
>  }
>  
>  #
> +# Tests for the location completer
> +#
> +
> +# Turn off pending breakpoint support so that we don't get queried
> +# all the time.
> +gdb_test_no_output "set breakpoint pending off"
> +
> +set subsrc [string range $srcfile 0 [expr {[string length $srcfile] - 3}]]
> +set test "tab complete break $subsrc"
> +send_gdb "break $subsrc\t\t"
> +gdb_test_multiple "" $test {
> +    -re "break\.c.*break1\.c.*$gdb_prompt " {
> +	send_gdb "1\t\n"
> +	gdb_test_multiple "" $test {
> +	    -re ".*Function \"$srcfile2\" not defined\..*$gdb_prompt " {
> +		pass $test
> +	    }
> +	    -re "$gdb_prompt p$" {
> +		fail $test
> +	    }
> +	}
> +    }
> +
> +    -re "$gdb_prompt p$" {
> +	fail $test
> +    }
> +}
> +
> +gdb_test "complete break $subsrc" "break\.c.*break1\.c"
> +
> +# gdb/17960
> +set test "tab complete break $srcfile:ma"
> +send_gdb "break $srcfile:ma\t"
> +gdb_test_multiple "" $test {
> +    -re "break $srcfile:main " {
> +	send_gdb "\n"
> +	gdb_test_multiple "" $test {
> +	    -re ".*Breakpoint.*at .*/$srcfile, line .*$gdb_prompt " {
> +		pass $test
> +		gdb_test_no_output "delete breakpoint \$bpnum" \
> +		    "delete breakpoint for $test"
> +	    }
> +	    -re "$gdb_prompt p$" {
> +		fail $test
> +	    }
> +	}
> +    }
> +    -re "$gdb_prompt p$" {
> +	fail $test
> +    }
> +}
> +
> +gdb_test "complete break $srcfile:ma" "break\.c:main"
> +
> +set test "tab complete break need"
> +send_gdb "break need\t"
> +gdb_test_multiple "" $test {
> +    -re "break need_malloc " {
> +	send_gdb "\n"
> +	gdb_test_multiple "" $test {
> +	    -re ".*Breakpoint.*at .*/$srcfile, line .*$gdb_prompt " {
> +		pass $test
> +		gdb_test_no_output "delete breakpoint \$bpnum" \
> +		    "delete breakpoint for $test"
> +	    }
> +	    -re "$gdb_prompt p$" {
> +		fail $test
> +	    }
> +	}
> +    }
> +    -re "$gdb_prompt p$" {
> +	fail $test
> +    }
> +}
> +
> +gdb_test "complete break need" "need_malloc"
> +
> +#
>  # Completion limiting.
>  #
>  


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]