/* Parser for linespec for the GNU debugger, GDB.
- Copyright (C) 1986-2016 Free Software Foundation, Inc.
+ Copyright (C) 1986-2017 Free Software Foundation, Inc.
This file is part of GDB.
#include "ada-lang.h"
#include "stack.h"
#include "location.h"
+#include "common/function-view.h"
typedef struct symbol *symbolp;
DEF_VEC_P (symbolp);
VEC (symbolp) *symbols;
VEC (bound_minimal_symbol_d) *minimal_symbols;
} result;
+
+ /* Possibly add a symbol to the results. */
+ bool add_symbol (symbol *sym);
};
+bool
+collect_info::add_symbol (symbol *sym)
+{
+ /* In list mode, add all matching symbols, regardless of class.
+ This allows the user to type "list a_global_variable". */
+ if (SYMBOL_CLASS (sym) == LOC_BLOCK || this->state->list_mode)
+ VEC_safe_push (symbolp, this->result.symbols, sym);
+
+ /* Continue iterating. */
+ return true;
+}
+
/* Token types */
enum ls_token_type
};
typedef enum ls_token_type linespec_token_type;
-/* List of keywords */
-
-static const char * const linespec_keywords[] = { "if", "thread", "task" };
+/* List of keywords. This is NULL-terminated so that it can be used
+ as enum completer. */
+const char * const linespec_keywords[] = { "if", "thread", "task", NULL };
#define IF_KEYWORD_INDEX 0
/* A token of the linespec lexer */
/* Prototypes for local functions. */
-static void iterate_over_file_blocks (struct symtab *symtab,
- const char *name, domain_enum domain,
- symbol_found_callback_ftype *callback,
- void *data);
+static void iterate_over_file_blocks
+ (struct symtab *symtab, const char *name, domain_enum domain,
+ gdb::function_view<symbol_found_callback_ftype> callback);
static void initialize_defaults (struct symtab **default_symtab,
int *default_line);
if (p != NULL)
{
- for (i = 0; i < ARRAY_SIZE (linespec_keywords); ++i)
+ for (i = 0; linespec_keywords[i] != NULL; ++i)
{
int len = strlen (linespec_keywords[i]);
{
p += len;
p = skip_spaces_const (p);
- for (j = 0; j < ARRAY_SIZE (linespec_keywords); ++j)
+ for (j = 0; linespec_keywords[j] != NULL; ++j)
{
int nextlen = strlen (linespec_keywords[j]);
{
if ((PARSER_STATE (parser)->language->la_language
== language_cplus)
- && (PARSER_STREAM (parser) - start) > 8
- /* strlen ("operator") */)
+ && (PARSER_STREAM (parser) - start) > CP_OPERATOR_LEN)
{
- const char *p = strstr (start, "operator");
+ const char *p = strstr (start, CP_OPERATOR_STR);
if (p != NULL && is_operator_name (p))
{
return 1;
}
-/* A callback function and the additional data to call it with. */
-
-struct symbol_and_data_callback
-{
- /* The callback to use. */
- symbol_found_callback_ftype *callback;
-
- /* Data to be passed to the callback. */
- void *data;
-};
-
-/* A helper for iterate_over_all_matching_symtabs that is used to
- restrict calls to another callback to symbols representing inline
- symbols only. */
-
-static int
-iterate_inline_only (struct symbol *sym, void *d)
-{
- if (SYMBOL_INLINED (sym))
- {
- struct symbol_and_data_callback *cad
- = (struct symbol_and_data_callback *) d;
-
- return cad->callback (sym, cad->data);
- }
- return 1; /* Continue iterating. */
-}
-
-/* Some data for the expand_symtabs_matching callback. */
-
-struct symbol_matcher_data
-{
- /* The lookup name against which symbol name should be compared. */
- const char *lookup_name;
-
- /* The routine to be used for comparison. */
- symbol_name_cmp_ftype symbol_name_cmp;
-};
-
-/* A helper for iterate_over_all_matching_symtabs that is passed as a
- callback to the expand_symtabs_matching method. */
-
-static int
-iterate_name_matcher (const char *name, void *d)
-{
- const struct symbol_matcher_data *data
- = (const struct symbol_matcher_data *) d;
-
- if (data->symbol_name_cmp (name, data->lookup_name) == 0)
- return 1; /* Expand this symbol's symbol table. */
- return 0; /* Skip this symbol. */
-}
-
/* A helper that walks over all matching symtabs in all objfiles and
calls CALLBACK for each symbol matching NAME. If SEARCH_PSPACE is
not NULL, then the search is restricted to just that program
- space. If INCLUDE_INLINE is nonzero then symbols representing
+ space. If INCLUDE_INLINE is true then symbols representing
inlined instances of functions will be included in the result. */
static void
-iterate_over_all_matching_symtabs (struct linespec_state *state,
- const char *name,
- const domain_enum domain,
- symbol_found_callback_ftype *callback,
- void *data,
- struct program_space *search_pspace,
- int include_inline)
+iterate_over_all_matching_symtabs
+ (struct linespec_state *state, const char *name, const domain_enum domain,
+ struct program_space *search_pspace, bool include_inline,
+ gdb::function_view<symbol_found_callback_ftype> callback)
{
struct objfile *objfile;
struct program_space *pspace;
- struct symbol_matcher_data matcher_data;
- matcher_data.lookup_name = name;
- matcher_data.symbol_name_cmp =
- state->language->la_get_symbol_name_cmp != NULL
- ? state->language->la_get_symbol_name_cmp (name)
- : strcmp_iw;
+ /* The routine to be used for comparison. */
+ symbol_name_cmp_ftype symbol_name_cmp
+ = (state->language->la_get_symbol_name_cmp != NULL
+ ? state->language->la_get_symbol_name_cmp (name)
+ : strcmp_iw);
ALL_PSPACES (pspace)
{
struct compunit_symtab *cu;
if (objfile->sf)
- objfile->sf->qf->expand_symtabs_matching (objfile, NULL,
- iterate_name_matcher,
- NULL, ALL_DOMAIN,
- &matcher_data);
+ objfile->sf->qf->expand_symtabs_matching
+ (objfile,
+ NULL,
+ [&] (const char *symbol_name)
+ {
+ return symbol_name_cmp (symbol_name, name) == 0;
+ },
+ NULL,
+ ALL_DOMAIN);
ALL_OBJFILE_COMPUNITS (objfile, cu)
{
struct symtab *symtab = COMPUNIT_FILETABS (cu);
- iterate_over_file_blocks (symtab, name, domain, callback, data);
+ iterate_over_file_blocks (symtab, name, domain, callback);
if (include_inline)
{
- struct symbol_and_data_callback cad = { callback, data };
struct block *block;
int i;
{
block = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symtab), i);
state->language->la_iterate_over_symbols
- (block, name, domain, iterate_inline_only, &cad);
+ (block, name, domain, [&] (symbol *sym)
+ {
+ /* Restrict calls to CALLBACK to symbols
+ representing inline symbols only. */
+ if (SYMBOL_INLINED (sym))
+ return callback (sym);
+ return true;
+ });
}
}
}
/* Iterate over static and global blocks. */
static void
-iterate_over_file_blocks (struct symtab *symtab,
- const char *name, domain_enum domain,
- symbol_found_callback_ftype *callback, void *data)
+iterate_over_file_blocks
+ (struct symtab *symtab, const char *name, domain_enum domain,
+ gdb::function_view<symbol_found_callback_ftype> callback)
{
struct block *block;
for (block = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symtab), STATIC_BLOCK);
block != NULL;
block = BLOCK_SUPERBLOCK (block))
- LA_ITERATE_OVER_SYMBOLS (block, name, domain, callback, data);
+ LA_ITERATE_OVER_SYMBOLS (block, name, domain, callback);
}
/* A helper for find_method. This finds all methods in type T which
struct symtabs_and_lines *result,
const char *select_mode)
{
- char *args, *prompt;
+ char *args;
+ const char *prompt;
int i;
struct cleanup *old_chain;
VEC (const_char_ptr) *filters = NULL;
if (token.type != LSTOKEN_NUMBER)
unexpected_linespec_error (parser);
- /* Record the lione offset and get the next token. */
+ /* Record the line offset and get the next token. */
name = copy_token_string (token);
cleanup = make_cleanup (xfree, name);
return;
/* Save everything as an explicit location. */
- canon = state->canonical->location
+ state->canonical->location
= new_explicit_location (&ls->explicit_loc);
+ canon = state->canonical->location.get ();
explicit_loc = get_explicit_location (canon);
if (explicit_loc->label_name != NULL)
do_cleanups (cleanup);
}
+/* See linespec.h. */
+
+void
+linespec_complete_function (completion_tracker &tracker,
+ const char *function,
+ const char *source_filename)
+{
+ complete_symbol_mode mode = complete_symbol_mode::LINESPEC;
+
+ if (source_filename != NULL)
+ {
+ collect_file_symbol_completion_matches (tracker, mode,
+ function, function,
+ source_filename);
+ }
+ else
+ collect_symbol_completion_matches (tracker, mode, function, function);
+}
+
/* A helper function for decode_line_full and decode_line_1 to
turn LOCATION into symtabs_and_lines. */
search_pspace, default_symtab,
default_line, canonical);
cleanups = make_cleanup (linespec_parser_delete, &parser);
- save_current_program_space ();
+
+ scoped_restore_current_program_space restore_pspace;
result = event_location_to_sals (&parser, location);
state = PARSER_STATE (&parser);
if (select_mode == NULL)
{
- if (ui_out_is_mi_like_p (interp_ui_out (top_level_interpreter ())))
+ if (interp_ui_out (top_level_interpreter ())->is_mi_like_p ())
select_mode = multiple_symbols_all;
else
select_mode = multiple_symbols_select_mode ();
search_pspace, default_symtab,
default_line, NULL);
cleanups = make_cleanup (linespec_parser_delete, &parser);
- save_current_program_space ();
+
+ scoped_restore_current_program_space restore_pspace;
result = event_location_to_sals (&parser, location);
{
struct symtabs_and_lines sals;
struct symtab_and_line cursal;
- struct event_location *location;
- struct cleanup *cleanup;
if (string == 0)
error (_("Empty line specification."));
and get a default source symtab+line or it will recursively call us! */
cursal = get_current_source_symtab_and_line ();
- location = string_to_event_location (&string, current_language);
- cleanup = make_cleanup_delete_event_location (location);
- sals = decode_line_1 (location, flags, NULL,
+ event_location_up location = string_to_event_location (&string,
+ current_language);
+ sals = decode_line_1 (location.get (), flags, NULL,
cursal.symtab, cursal.line);
if (*string)
error (_("Junk at end of line specification: %s"), string);
- do_cleanups (cleanup);
return sals;
}
decode_line_with_last_displayed (char *string, int flags)
{
struct symtabs_and_lines sals;
- struct event_location *location;
- struct cleanup *cleanup;
if (string == 0)
error (_("Empty line specification."));
- location = string_to_event_location (&string, current_language);
- cleanup = make_cleanup_delete_event_location (location);
+ event_location_up location = string_to_event_location (&string,
+ current_language);
if (last_displayed_sal_is_valid ())
- sals = decode_line_1 (location, flags, NULL,
+ sals = decode_line_1 (location.get (), flags, NULL,
get_last_displayed_symtab (),
get_last_displayed_line ());
else
- sals = decode_line_1 (location, flags, NULL, (struct symtab *) NULL, 0);
+ sals = decode_line_1 (location.get (), flags, NULL,
+ (struct symtab *) NULL, 0);
if (*string)
error (_("Junk at end of line specification: %s"), string);
- do_cleanups (cleanup);
return sals;
}
return values;
}
-/* An instance of this type is used when collecting prefix symbols for
- decode_compound. */
+namespace {
-struct decode_compound_collector
+/* A function object that serves as symbol_found_callback_ftype
+ callback for iterate_over_symbols. This is used by
+ lookup_prefix_sym to collect type symbols. */
+class decode_compound_collector
{
- /* The result vector. */
- VEC (symbolp) *symbols;
+public:
+ decode_compound_collector ()
+ : m_symbols (NULL)
+ {
+ m_unique_syms = htab_create_alloc (1, htab_hash_pointer,
+ htab_eq_pointer, NULL,
+ xcalloc, xfree);
+ }
+ ~decode_compound_collector ()
+ {
+ if (m_unique_syms != NULL)
+ htab_delete (m_unique_syms);
+ }
+
+ /* Releases ownership of the collected symbols and returns them. */
+ VEC (symbolp) *release_symbols ()
+ {
+ VEC (symbolp) *res = m_symbols;
+ m_symbols = NULL;
+ return res;
+ }
+
+ /* Callable as a symbol_found_callback_ftype callback. */
+ bool operator () (symbol *sym);
+
+private:
/* A hash table of all symbols we found. We use this to avoid
adding any symbol more than once. */
- htab_t unique_syms;
-};
+ htab_t m_unique_syms;
-/* A callback for iterate_over_symbols that is used by
- lookup_prefix_sym to collect type symbols. */
+ /* The result vector. */
+ VEC (symbolp) *m_symbols;
+};
-static int
-collect_one_symbol (struct symbol *sym, void *d)
+bool
+decode_compound_collector::operator () (symbol *sym)
{
- struct decode_compound_collector *collector
- = (struct decode_compound_collector *) d;
void **slot;
struct type *t;
if (SYMBOL_CLASS (sym) != LOC_TYPEDEF)
- return 1; /* Continue iterating. */
+ return true; /* Continue iterating. */
t = SYMBOL_TYPE (sym);
t = check_typedef (t);
if (TYPE_CODE (t) != TYPE_CODE_STRUCT
&& TYPE_CODE (t) != TYPE_CODE_UNION
&& TYPE_CODE (t) != TYPE_CODE_NAMESPACE)
- return 1; /* Continue iterating. */
+ return true; /* Continue iterating. */
- slot = htab_find_slot (collector->unique_syms, sym, INSERT);
+ slot = htab_find_slot (m_unique_syms, sym, INSERT);
if (!*slot)
{
*slot = sym;
- VEC_safe_push (symbolp, collector->symbols, sym);
+ VEC_safe_push (symbolp, m_symbols, sym);
}
- return 1; /* Continue iterating. */
+ return true; /* Continue iterating. */
}
+} // namespace
+
/* Return any symbols corresponding to CLASS_NAME in FILE_SYMTABS. */
static VEC (symbolp) *
{
int ix;
struct symtab *elt;
- struct decode_compound_collector collector;
- struct cleanup *outer;
- struct cleanup *cleanup;
-
- collector.symbols = NULL;
- outer = make_cleanup (VEC_cleanup (symbolp), &collector.symbols);
-
- collector.unique_syms = htab_create_alloc (1, htab_hash_pointer,
- htab_eq_pointer, NULL,
- xcalloc, xfree);
- cleanup = make_cleanup_htab_delete (collector.unique_syms);
+ decode_compound_collector collector;
for (ix = 0; VEC_iterate (symtab_ptr, file_symtabs, ix, elt); ++ix)
{
if (elt == NULL)
{
iterate_over_all_matching_symtabs (state, class_name, STRUCT_DOMAIN,
- collect_one_symbol, &collector,
- NULL, 0);
+ NULL, false, collector);
iterate_over_all_matching_symtabs (state, class_name, VAR_DOMAIN,
- collect_one_symbol, &collector,
- NULL, 0);
+ NULL, false, collector);
}
else
{
been filtered out earlier. */
gdb_assert (!SYMTAB_PSPACE (elt)->executing_startup);
set_current_program_space (SYMTAB_PSPACE (elt));
- iterate_over_file_blocks (elt, class_name, STRUCT_DOMAIN,
- collect_one_symbol, &collector);
- iterate_over_file_blocks (elt, class_name, VAR_DOMAIN,
- collect_one_symbol, &collector);
+ iterate_over_file_blocks (elt, class_name, STRUCT_DOMAIN, collector);
+ iterate_over_file_blocks (elt, class_name, VAR_DOMAIN, collector);
}
}
- do_cleanups (cleanup);
- discard_cleanups (outer);
- return collector.symbols;
+ return collector.release_symbols ();
}
/* A qsort comparison function for symbols. The resulting order does
\f
-/* This object is used when collecting all matching symtabs. */
+namespace {
-struct symtab_collector
+/* This function object is a callback for iterate_over_symtabs, used
+ when collecting all matching symtabs. */
+
+class symtab_collector
{
+public:
+ symtab_collector ()
+ {
+ m_symtabs = NULL;
+ m_symtab_table = htab_create (1, htab_hash_pointer, htab_eq_pointer,
+ NULL);
+ }
+
+ ~symtab_collector ()
+ {
+ if (m_symtab_table != NULL)
+ htab_delete (m_symtab_table);
+ }
+
+ /* Callable as a symbol_found_callback_ftype callback. */
+ bool operator () (symtab *sym);
+
+ /* Releases ownership of the collected symtabs and returns them. */
+ VEC (symtab_ptr) *release_symtabs ()
+ {
+ VEC (symtab_ptr) *res = m_symtabs;
+ m_symtabs = NULL;
+ return res;
+ }
+
+private:
/* The result vector of symtabs. */
- VEC (symtab_ptr) *symtabs;
+ VEC (symtab_ptr) *m_symtabs;
/* This is used to ensure the symtabs are unique. */
- htab_t symtab_table;
+ htab_t m_symtab_table;
};
-/* Callback for iterate_over_symtabs. */
-
-static int
-add_symtabs_to_list (struct symtab *symtab, void *d)
+bool
+symtab_collector::operator () (struct symtab *symtab)
{
- struct symtab_collector *data = (struct symtab_collector *) d;
void **slot;
- slot = htab_find_slot (data->symtab_table, symtab, INSERT);
+ slot = htab_find_slot (m_symtab_table, symtab, INSERT);
if (!*slot)
{
*slot = symtab;
- VEC_safe_push (symtab_ptr, data->symtabs, symtab);
+ VEC_safe_push (symtab_ptr, m_symtabs, symtab);
}
- return 0;
+ return false;
}
+} // namespace
+
/* Given a file name, return a VEC of all matching symtabs. If
SEARCH_PSPACE is not NULL, the search is restricted to just that
program space. */
collect_symtabs_from_filename (const char *file,
struct program_space *search_pspace)
{
- struct symtab_collector collector;
- struct cleanup *cleanups;
- struct program_space *pspace;
-
- collector.symtabs = NULL;
- collector.symtab_table = htab_create (1, htab_hash_pointer, htab_eq_pointer,
- NULL);
- cleanups = make_cleanup_htab_delete (collector.symtab_table);
+ symtab_collector collector;
/* Find that file's data. */
if (search_pspace == NULL)
{
+ struct program_space *pspace;
+
ALL_PSPACES (pspace)
{
if (pspace->executing_startup)
continue;
set_current_program_space (pspace);
- iterate_over_symtabs (file, add_symtabs_to_list, &collector);
+ iterate_over_symtabs (file, collector);
}
}
else
{
set_current_program_space (search_pspace);
- iterate_over_symtabs (file, add_symtabs_to_list, &collector);
+ iterate_over_symtabs (file, collector);
}
- do_cleanups (cleanups);
- return collector.symtabs;
+ return collector.release_symtabs ();
}
/* Return all the symtabs associated to the FILENAME. If SEARCH_PSPACE is
for (ix = 0; VEC_iterate (symtab_ptr, ls->file_symtabs, ix, elt); ++ix)
{
- int i;
- VEC (CORE_ADDR) *pcs;
- CORE_ADDR pc;
+ std::vector<CORE_ADDR> pcs;
/* The logic above should ensure this. */
gdb_assert (elt != NULL);
set_current_program_space (SYMTAB_PSPACE (elt));
pcs = find_pcs_for_symtab_line (elt, line, best_entry);
- for (i = 0; VEC_iterate (CORE_ADDR, pcs, i, pc); ++i)
+ for (CORE_ADDR pc : pcs)
{
struct symtab_and_line sal;
sal.pc = pc;
add_sal_to_sals_basic (sals, &sal);
}
-
- VEC_free (CORE_ADDR, pcs);
}
}
}
\f
-/* A callback used to possibly add a symbol to the results. */
-
-static int
-collect_symbols (struct symbol *sym, void *data)
-{
- struct collect_info *info = (struct collect_info *) data;
-
- /* In list mode, add all matching symbols, regardless of class.
- This allows the user to type "list a_global_variable". */
- if (SYMBOL_CLASS (sym) == LOC_BLOCK || info->state->list_mode)
- VEC_safe_push (symbolp, info->result.symbols, sym);
- return 1; /* Continue iterating. */
-}
-
/* We've found a minimal symbol MSYMBOL in OBJFILE to associate with our
linespec; return the SAL in RESULT. This function should return SALs
matching those from find_function_start_sal, otherwise false
if (elt == NULL)
{
iterate_over_all_matching_symtabs (info->state, name, VAR_DOMAIN,
- collect_symbols, info,
- pspace, 1);
+ pspace, true, [&] (symbol *sym)
+ { return info->add_symbol (sym); });
search_minsyms_for_name (info, name, pspace, NULL);
}
else if (pspace == NULL || pspace == SYMTAB_PSPACE (elt))
been filtered out earlier. */
gdb_assert (!SYMTAB_PSPACE (elt)->executing_startup);
set_current_program_space (SYMTAB_PSPACE (elt));
- iterate_over_file_blocks (elt, name, VAR_DOMAIN,
- collect_symbols, info);
+ iterate_over_file_blocks (elt, name, VAR_DOMAIN, [&] (symbol *sym)
+ { return info->add_symbol (sym); });
/* If no new symbols were found in this iteration and this symtab
is in assembler, we might actually be looking for a label for
return 0;
}
-/* See the comment in linespec.h. */
-
-void
-init_linespec_result (struct linespec_result *lr)
-{
- memset (lr, 0, sizeof (*lr));
-}
-
-/* See the comment in linespec.h. */
-
-void
-destroy_linespec_result (struct linespec_result *ls)
+linespec_result::~linespec_result ()
{
int i;
struct linespec_sals *lsal;
- delete_event_location (ls->location);
- for (i = 0; VEC_iterate (linespec_sals, ls->sals, i, lsal); ++i)
+ for (i = 0; VEC_iterate (linespec_sals, sals, i, lsal); ++i)
{
xfree (lsal->canonical);
xfree (lsal->sals.sals);
}
- VEC_free (linespec_sals, ls->sals);
-}
-
-/* Cleanup function for a linespec_result. */
-
-static void
-cleanup_linespec_result (void *a)
-{
- destroy_linespec_result ((struct linespec_result *) a);
-}
-
-/* See the comment in linespec.h. */
-
-struct cleanup *
-make_cleanup_destroy_linespec_result (struct linespec_result *ls)
-{
- return make_cleanup (cleanup_linespec_result, ls);
+ VEC_free (linespec_sals, sals);
}
/* Return the quote characters permitted by the linespec parser. */