This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[RFA 1/5] Explicit linespecs - refactor linespec parsing
- From: Keith Seitz <keiths at redhat dot com>
- To: "gdb-patches at sourceware dot org ml" <gdb-patches at sourceware dot org>
- Date: Thu, 26 Jul 2012 20:46:29 -0700
- Subject: [RFA 1/5] Explicit linespecs - refactor linespec parsing
Hi,
This first patch refactors a bunch of code in linespec.c to allow for a
different parsing function. This is mainly to facilitate sharing code
with decode_line_full. In the end, regardless of what the actual
parsing function is, the results must be the same.
Questions/comments/concerns?
Keith
ChangeLog
2012-07-26 Keith Seitz <keiths@redhat.com>
* linespec.c (linespec_parse_func): New typedef.
(struct ls_parser): Add PARSE_IT.
(undefined_label_error): New function.
(source_file_not_found_error): New function.
(linespec_parse_basic): Use undefined_label_error.
(parse_linespec): Add/use DATA parameter instead of previous
ARGPTR parameter.
(linespec_parser_new): Add FUNC parameter.
(do_decode_line): Move most of decode_line_full here to here.
Use the parser's PARSE_IT function to do the actual parsing.
(decode_line_full): Use do_decode_line.
(decode_line_1): Pass parsing function name to
linespec_parser_new and call it to do the parsing.
(symtabs_from_filename): Use source_file_not_found_error.
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 3d7f62f..2b84515 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -265,6 +265,12 @@ typedef struct ls_token linespec_token;
#define LS_TOKEN_STOKEN(TOK) (TOK).data.string
#define LS_TOKEN_KEYWORD(TOK) (TOK).data.keyword
+/* A parser function definition used by do_decode_line. */
+
+struct ls_parser;
+typedef struct symtabs_and_lines (*linespec_parse_func) (struct ls_parser *,
+ void *client_data);
+
/* An instance of the linespec parser. */
struct ls_parser
@@ -293,6 +299,9 @@ struct ls_parser
/* The result of the parse. */
struct linespec result;
#define PARSER_RESULT(PPTR) (&(PPTR)->result)
+
+ /* The function to actually do the parsing. */
+ linespec_parse_func parse_it;
};
typedef struct ls_parser linespec_parser;
@@ -1433,6 +1442,29 @@ unexpected_linespec_error (linespec_parser *parser)
token_type_strings[token.type]);
}
+/* Throw an undefined label error. */
+
+static void ATTRIBUTE_NORETURN
+undefined_label_error (const char *function, const char *label)
+{
+ if (function != NULL)
+ throw_error (NOT_FOUND_ERROR,
+ _("No label \"%s\" defined in function \"%s\"."),
+ label, function);
+ else
+ throw_error (NOT_FOUND_ERROR,
+ _("No label \"%s\" defined in current function."), label);
+}
+
+/* Throw a source file not found error. */
+
+static void ATTRIBUTE_NORETURN
+source_file_not_found_error (const char *name)
+{
+ throw_error (NOT_FOUND_ERROR,
+ _("No source file named %s."), name);
+}
+
/* Parse and return a line offset in STRING. */
static struct line_offset
@@ -1587,9 +1619,8 @@ linespec_parse_basic (linespec_parser *parser)
else
{
/* We don't know what it was, but it isn't a label. */
- throw_error (NOT_FOUND_ERROR,
- _("No label \"%s\" defined in function \"%s\"."),
- name, PARSER_RESULT (parser)->function_name);
+ undefined_label_error (PARSER_RESULT (parser)->function_name,
+ name);
}
/* Check for a line offset. */
@@ -1995,15 +2026,16 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
if no file is validly specified. Callers must check that.
Also, the line number returned may be invalid. */
-/* Parse the linespec in ARGPTR. */
+/* Parse the linespec in DATA. */
static struct symtabs_and_lines
-parse_linespec (linespec_parser *parser, char **argptr)
+parse_linespec (linespec_parser *parser, void *data)
{
linespec_token token;
struct symtabs_and_lines values;
volatile struct gdb_exception file_exception;
struct cleanup *cleanup;
+ char **argptr = (char **) data;
/* A special case to start. It has become quite popular for
IDEs to work around bugs in the previous parser by quoting
@@ -2210,7 +2242,7 @@ linespec_state_constructor (struct linespec_state *self,
/* Initialize a new linespec parser. */
static void
-linespec_parser_new (linespec_parser *parser,
+linespec_parser_new (linespec_parser *parser, linespec_parse_func func,
int flags, const struct language_defn *language,
struct symtab *default_symtab,
int default_line,
@@ -2219,6 +2251,7 @@ linespec_parser_new (linespec_parser *parser,
parser->lexer.current.type = LSTOKEN_CONSUMED;
memset (PARSER_RESULT (parser), 0, sizeof (struct linespec));
PARSER_RESULT (parser)->line_offset.sign = LINE_OFFSET_UNKNOWN;
+ parser->parse_it = func;
linespec_state_constructor (PARSER_STATE (parser), flags, language,
default_symtab, default_line, canonical);
}
@@ -2261,42 +2294,35 @@ linespec_parser_delete (void *arg)
linespec_state_destructor (PARSER_STATE (parser));
}
-/* See linespec.h. */
+/* Decode the linespec given in DATA with the PARSER.
+ SELECT_MODE and FILTER are from decode_line_full. */
-void
-decode_line_full (char **argptr, int flags,
- struct symtab *default_symtab,
- int default_line, struct linespec_result *canonical,
- const char *select_mode,
- const char *filter)
+static void
+do_decode_line (linespec_parser *parser, void *data,
+ const char *select_mode, const char *filter)
{
struct symtabs_and_lines result;
struct cleanup *cleanups;
- char *arg_start = *argptr;
VEC (const_char_ptr) *filters = NULL;
- linespec_parser parser;
struct linespec_state *state;
- gdb_assert (canonical != NULL);
/* The filter only makes sense for 'all'. */
gdb_assert (filter == NULL || select_mode == multiple_symbols_all);
gdb_assert (select_mode == NULL
|| select_mode == multiple_symbols_all
|| select_mode == multiple_symbols_ask
|| select_mode == multiple_symbols_cancel);
- gdb_assert ((flags & DECODE_LINE_LIST_MODE) == 0);
- linespec_parser_new (&parser, flags, current_language, default_symtab,
- default_line, canonical);
- cleanups = make_cleanup (linespec_parser_delete, &parser);
+ cleanups = make_cleanup (null_cleanup, NULL);
save_current_program_space ();
- result = parse_linespec (&parser, argptr);
- state = PARSER_STATE (&parser);
+ result = (*parser->parse_it) (parser, data);
+ state = PARSER_STATE (parser);
- gdb_assert (result.nelts == 1 || canonical->pre_expanded);
- gdb_assert (canonical->addr_string != NULL);
- canonical->pre_expanded = 1;
+ gdb_assert (result.nelts == 1 || state->canonical->pre_expanded);
+ gdb_assert (state->canonical->addr_string != NULL);
+ gdb_assert (result.nelts == 0 || state->canonical_names != NULL);
+ state->canonical->pre_expanded = 1;
/* Arrange for allocated canonical names to be freed. */
if (result.nelts > 0)
@@ -2336,6 +2362,29 @@ decode_line_full (char **argptr, int flags,
do_cleanups (cleanups);
}
+/* See linespec.h.
+ All of the real work is done in do_decode_line. */
+
+void
+decode_line_full (char **argptr, int flags,
+ struct symtab *default_symtab,
+ int default_line, struct linespec_result *canonical,
+ const char *select_mode,
+ const char *filter)
+{
+ linespec_parser parser;
+ struct cleanup *cleanups;
+
+ gdb_assert (canonical != NULL);
+ gdb_assert ((flags & DECODE_LINE_LIST_MODE) == 0);
+
+ linespec_parser_new (&parser, parse_linespec, flags, current_language,
+ default_symtab, default_line, canonical);
+ cleanups = make_cleanup (linespec_parser_delete, &parser);
+ do_decode_line (&parser, argptr, select_mode, filter);
+ do_cleanups (cleanups);
+}
+
/* See linespec.h. */
struct symtabs_and_lines
@@ -2347,12 +2396,12 @@ decode_line_1 (char **argptr, int flags,
linespec_parser parser;
struct cleanup *cleanups;
- linespec_parser_new (&parser, flags, current_language, default_symtab,
- default_line, NULL);
+ linespec_parser_new (&parser, parse_linespec, flags, current_language,
+ default_symtab, default_line, NULL);
cleanups = make_cleanup (linespec_parser_delete, &parser);
save_current_program_space ();
- result = parse_linespec (&parser, argptr);
+ result = (*parser.parse_it) (&parser, argptr);
do_cleanups (cleanups);
return result;
@@ -2879,7 +2928,7 @@ symtabs_from_filename (const char *filename)
throw_error (NOT_FOUND_ERROR,
_("No symbol table is loaded. "
"Use the \"file\" command."));
- throw_error (NOT_FOUND_ERROR, _("No source file named %s."), filename);
+ source_file_not_found_error (filename);
}
return result;