diff options
author | Jan Kratochvil <jan.kratochvil@redhat.com> | 2013-03-04 19:30:28 +0000 |
---|---|---|
committer | Jan Kratochvil <jan.kratochvil@redhat.com> | 2013-03-04 19:30:28 +0000 |
commit | 33f448b11ed775f3d4dcf2c21100ba3b239b6b4a (patch) | |
tree | 44b4f4ff304b1518c07b5add2c1018b992864308 /gdb/linespec.c | |
parent | feb1472522ea3ff9c0456462f36ce2e29be29f28 (diff) | |
download | gdb-33f448b11ed775f3d4dcf2c21100ba3b239b6b4a.zip gdb-33f448b11ed775f3d4dcf2c21100ba3b239b6b4a.tar.gz gdb-33f448b11ed775f3d4dcf2c21100ba3b239b6b4a.tar.bz2 |
gdb/
* linespec.c (struct linespec_canonical_name): New.
(struct linespec_state): Change canonical_names type to it.
(add_sal_to_sals): Change variable canonical_name to canonical. Change
xrealloc element size. Initialize the different CANONICAL fields.
(canonical_to_fullform): New.
(filter_results): Use it. Add variables canonical, fullform and
cleanup.
(struct decode_line_2_item, decode_line_2_compare_items): New.
(decode_line_2): Remove variables iter and item_names, add variables
items and items_count. Modify the code for these new variables.
gdb/testsuite/
* gdb.linespec/base/one/thefile.cc (twodup): New.
(m): Call it.
* gdb.linespec/base/two/thefile.cc (dupname): New.
(n): Call it.
* gdb.linespec/break-ask.exp: New file.
* gdb.linespec/lspec.cc (body_elsewhere): New comment marker.
Diffstat (limited to 'gdb/linespec.c')
-rw-r--r-- | gdb/linespec.c | 196 |
1 files changed, 150 insertions, 46 deletions
diff --git a/gdb/linespec.c b/gdb/linespec.c index 2e98db7..01f5e0a 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -157,6 +157,21 @@ struct linespec }; typedef struct linespec *linespec_p; +/* A canonical linespec represented as a symtab-related string. + + Each entry represents the "SYMTAB:SUFFIX" linespec string. + SYMTAB can be converted for example by symtab_to_fullname or + symtab_to_filename_for_display as needed. */ + +struct linespec_canonical_name +{ + /* Remaining text part of the linespec string. */ + char *suffix; + + /* If NULL then SUFFIX is the whole linespec string. */ + struct symtab *symtab; +}; + /* An instance of this is used to keep all state while linespec operates. This instance is passed around as a 'this' pointer to the various implementation methods. */ @@ -186,7 +201,7 @@ struct linespec_state struct linespec_result *canonical; /* Canonical strings that mirror the symtabs_and_lines result. */ - char **canonical_names; + struct linespec_canonical_name *canonical_names; /* This is a set of address_entry objects which is used to prevent duplicate symbols from being entered into the result. */ @@ -848,10 +863,12 @@ add_sal_to_sals (struct linespec_state *self, if (self->canonical) { - char *canonical_name = NULL; + struct linespec_canonical_name *canonical; self->canonical_names = xrealloc (self->canonical_names, - sals->nelts * sizeof (char *)); + (sals->nelts + * sizeof (*self->canonical_names))); + canonical = &self->canonical_names[sals->nelts - 1]; if (!literal_canonical && sal->symtab) { const char *fullname = symtab_to_fullname (sal->symtab); @@ -861,17 +878,21 @@ add_sal_to_sals (struct linespec_state *self, the time being. */ if (symname != NULL && sal->line != 0 && self->language->la_language == language_ada) - canonical_name = xstrprintf ("%s:%s:%d", fullname, symname, - sal->line); + canonical->suffix = xstrprintf ("%s:%d", symname, sal->line); else if (symname != NULL) - canonical_name = xstrprintf ("%s:%s", fullname, symname); + canonical->suffix = xstrdup (symname); else - canonical_name = xstrprintf ("%s:%d", fullname, sal->line); + canonical->suffix = xstrprintf ("%d", sal->line); + canonical->symtab = sal->symtab; + } + else + { + if (symname != NULL) + canonical->suffix = xstrdup (symname); + else + canonical->suffix = NULL; + canonical->symtab = NULL; } - else if (symname != NULL) - canonical_name = xstrdup (symname); - - self->canonical_names[sals->nelts - 1] = canonical_name; } } @@ -1200,6 +1221,19 @@ find_toplevel_string (const char *haystack, const char *needle) return NULL; } +/* Convert CANONICAL to its string representation using + symtab_to_fullname for SYMTAB. The caller must xfree the result. */ + +static char * +canonical_to_fullform (const struct linespec_canonical_name *canonical) +{ + if (canonical->symtab == NULL) + return xstrdup (canonical->suffix); + else + return xstrprintf ("%s:%s", symtab_to_fullname (canonical->symtab), + canonical->suffix); +} + /* Given FILTERS, a list of canonical names, filter the sals in RESULT and store the result in SELF->CANONICAL. */ @@ -1220,8 +1254,18 @@ filter_results (struct linespec_state *self, for (j = 0; j < result->nelts; ++j) { - if (strcmp (name, self->canonical_names[j]) == 0) + const struct linespec_canonical_name *canonical; + char *fullform; + struct cleanup *cleanup; + + canonical = &self->canonical_names[j]; + fullform = canonical_to_fullform (canonical); + cleanup = make_cleanup (xfree, fullform); + + if (strcmp (name, fullform) == 0) add_sal_to_sals_basic (&lsal.sals, &result->sals[j]); + + do_cleanups (cleanup); } if (lsal.sals.nelts > 0) @@ -1247,6 +1291,44 @@ convert_results_to_lsals (struct linespec_state *self, VEC_safe_push (linespec_sals, self->canonical->sals, &lsal); } +/* A structure that contains two string representations of a struct + linespec_canonical_name: + - one where the the symtab's fullname is used; + - one where the filename followed the "set filename-display" + setting. */ + +struct decode_line_2_item +{ + /* The form using symtab_to_fullname. + It must be xfree'ed after use. */ + char *fullform; + + /* The form using symtab_to_filename_for_display. + It must be xfree'ed after use. */ + char *displayform; + + /* Field is initialized to zero and it is set to one if the user + requested breakpoint for this entry. */ + unsigned int selected : 1; +}; + +/* Helper for qsort to sort decode_line_2_item entries by DISPLAYFORM and + secondarily by FULLFORM. */ + +static int +decode_line_2_compare_items (const void *ap, const void *bp) +{ + const struct decode_line_2_item *a = ap; + const struct decode_line_2_item *b = bp; + int retval; + + retval = strcmp (a->displayform, b->displayform); + if (retval != 0) + return retval; + + return strcmp (a->fullform, b->fullform); +} + /* Handle multiple results in RESULT depending on SELECT_MODE. This will either return normally, throw an exception on multiple results, or present a menu to the user. On return, the SALS vector @@ -1257,58 +1339,80 @@ decode_line_2 (struct linespec_state *self, struct symtabs_and_lines *result, const char *select_mode) { - const char *iter; char *args, *prompt; int i; struct cleanup *old_chain; - VEC (const_char_ptr) *item_names = NULL, *filters = NULL; + VEC (const_char_ptr) *filters = NULL; struct get_number_or_range_state state; + struct decode_line_2_item *items; + int items_count; gdb_assert (select_mode != multiple_symbols_all); gdb_assert (self->canonical != NULL); + gdb_assert (result->nelts >= 1); + + old_chain = make_cleanup (VEC_cleanup (const_char_ptr), &filters); - old_chain = make_cleanup (VEC_cleanup (const_char_ptr), &item_names); - make_cleanup (VEC_cleanup (const_char_ptr), &filters); - for (i = 0; i < result->nelts; ++i) + /* Prepare ITEMS array. */ + items_count = result->nelts; + items = xmalloc (sizeof (*items) * items_count); + make_cleanup (xfree, items); + for (i = 0; i < items_count; ++i) { - int j, found = 0; - const char *iter; + const struct linespec_canonical_name *canonical; + struct decode_line_2_item *item; + + canonical = &self->canonical_names[i]; + gdb_assert (canonical->suffix != NULL); + item = &items[i]; - gdb_assert (self->canonical_names[i] != NULL); - for (j = 0; VEC_iterate (const_char_ptr, item_names, j, iter); ++j) + item->fullform = canonical_to_fullform (canonical); + make_cleanup (xfree, item->fullform); + + if (canonical->symtab == NULL) + item->displayform = canonical->suffix; + else { - if (strcmp (iter, self->canonical_names[i]) == 0) - { - found = 1; - break; - } + const char *fn_for_display; + + fn_for_display = symtab_to_filename_for_display (canonical->symtab); + item->displayform = xstrprintf ("%s:%s", fn_for_display, + canonical->suffix); + make_cleanup (xfree, item->displayform); } - if (!found) - VEC_safe_push (const_char_ptr, item_names, self->canonical_names[i]); + item->selected = 0; } - if (select_mode == multiple_symbols_cancel - && VEC_length (const_char_ptr, item_names) > 1) + /* Sort the list of method names. */ + qsort (items, items_count, sizeof (*items), decode_line_2_compare_items); + + /* Remove entries with the same FULLFORM. */ + if (items_count >= 2) + { + struct decode_line_2_item *dst, *src; + + dst = items; + for (src = &items[1]; src < &items[items_count]; src++) + if (strcmp (src->fullform, dst->fullform) != 0) + *++dst = *src; + items_count = dst + 1 - items; + } + + if (select_mode == multiple_symbols_cancel && items_count > 1) error (_("canceled because the command is ambiguous\n" "See set/show multiple-symbol.")); - if (select_mode == multiple_symbols_all - || VEC_length (const_char_ptr, item_names) == 1) + if (select_mode == multiple_symbols_all || items_count == 1) { do_cleanups (old_chain); convert_results_to_lsals (self, result); return; } - /* Sort the list of method names alphabetically. */ - qsort (VEC_address (const_char_ptr, item_names), - VEC_length (const_char_ptr, item_names), - sizeof (const_char_ptr), compare_strings); - printf_unfiltered (_("[0] cancel\n[1] all\n")); - for (i = 0; VEC_iterate (const_char_ptr, item_names, i, iter); ++i) - printf_unfiltered ("[%d] %s\n", i + 2, iter); + for (i = 0; i < items_count; i++) + printf_unfiltered ("[%d] %s\n", i + 2, items[i].displayform); prompt = getenv ("PS2"); if (prompt == NULL) @@ -1343,16 +1447,16 @@ decode_line_2 (struct linespec_state *self, } num -= 2; - if (num >= VEC_length (const_char_ptr, item_names)) + if (num >= items_count) printf_unfiltered (_("No choice number %d.\n"), num); else { - const char *elt = VEC_index (const_char_ptr, item_names, num); + struct decode_line_2_item *item = &items[num]; - if (elt != NULL) + if (!item->selected) { - VEC_safe_push (const_char_ptr, filters, elt); - VEC_replace (const_char_ptr, item_names, num, NULL); + VEC_safe_push (const_char_ptr, filters, item->fullform); + item->selected = 1; } else { @@ -2326,8 +2430,8 @@ decode_line_full (char **argptr, int flags, make_cleanup (xfree, state->canonical_names); for (i = 0; i < result.nelts; ++i) { - gdb_assert (state->canonical_names[i] != NULL); - make_cleanup (xfree, state->canonical_names[i]); + gdb_assert (state->canonical_names[i].suffix != NULL); + make_cleanup (xfree, state->canonical_names[i].suffix); } } |