[PATCH 1/7] [python] API for macros: abort or continuing macro iterators.

matt rice
2011-08-24T15:11:35Z

2011-08-23 Matt Rice <ratmice@gmail.com>

* macrocmd.c (print_macro_callback): Return a walk status
and continue indefinitely.
(print_one_macro): Ditto.
* macrotab.c (foreach_macro): Return based on callback
status.
(foreach_macro_in_scope): Ditto.
(macro_for_each): Return a macro walk completion result.
(macro_for_each_in_scope): Ditto.
* macrotab.h (macro_walk_status): New enum.
(macro_walk_result): Ditto.
(macro_callback_fn): Return a macro_walk_status.
(macro_for_each, macro_for_each_in_scope): Return a macro_walk_result.
* symtab.c (add_macro_name): Return a walk status and
continue indefinitely.
---
gdb/macrocmd.c | 7 +++++--
gdb/macrotab.c | 33 ++++++++++++++++++++++-----------
gdb/macrotab.h | 48 +++++++++++++++++++++++++++++++++++-------------
gdb/symtab.c | 3 ++-
4 files changed, 64 insertions(+), 27 deletions(-)

diff --git a/gdb/macrocmd.c b/gdb/macrocmd.c
index d1ac7fa..e929fe0 100644
--- a/gdb/macrocmd.c
+++ b/gdb/macrocmd.c
@@ -220,13 +220,15 @@ info_macro_command (char *name, int from_tty)
Otherwise USER_DATA is considered to be a string, printing
only macros who's NAME matches USER_DATA. Other arguments are
routed to print_macro_definition. */
-static void
+static enum macro_walk_status
print_macro_callback (const char *name, const struct macro_definition *macro,
struct macro_source_file *source, int line,
void *user_data)
{
if (! user_data || strcmp (user_data, name) == 0)
print_macro_definition (name, macro, source, line);
+
+ return macro_walk_continue;
}

/* Implementation of the "info definitions" command. */
@@ -435,7 +437,7 @@ macro_undef_command (char *exp, int from_tty)
}

-static void
+static enum macro_walk_status
print_one_macro (const char *name, const struct macro_definition *macro,
struct macro_source_file *source, int line,
void *ignore)
@@ -452,6 +454,7 @@ print_one_macro (const char *name, const struct macro_definition *macro,
fprintf_filtered (gdb_stdout, ")");
}
fprintf_filtered (gdb_stdout, " %s\n", macro->replacement);
+ return macro_walk_continue;
}

diff --git a/gdb/macrotab.c b/gdb/macrotab.c
index efcf835..e4007a5 100644
--- a/gdb/macrotab.c
+++ b/gdb/macrotab.c
@@ -912,14 +912,15 @@ foreach_macro (splay_tree_node node, void *arg)
struct macro_for_each_data *datum = (struct macro_for_each_data *) arg;
struct macro_key *key = (struct macro_key *) node->key;
struct macro_definition *def = (struct macro_definition *) node->value;
+ enum macro_walk_status status;

- (*datum->fn) (key->name, def, key->start_file, key->start_line,
- datum->user_data);
- return 0;
+ status = (*datum->fn) (key->name, def, key->start_file, key->start_line,
+ datum->user_data);
+ return status == macro_walk_abort;
}

/* Call FN for every macro in TABLE. */
-void
+enum macro_walk_result
macro_for_each (struct macro_table *table, macro_callback_fn fn,
void *user_data)
{
@@ -929,15 +930,21 @@ macro_for_each (struct macro_table *table, macro_callback_fn fn,
datum.user_data = user_data;
datum.file = NULL;
datum.line = 0;
- splay_tree_foreach (table->definitions, foreach_macro, &datum);
+
+ if (splay_tree_foreach (table->definitions, foreach_macro, &datum) != 0)
+ return macro_walk_aborted;
+ else
+ return macro_walk_completed;
}

+/* Helper function for macro_for_each_in_scope. */
static int
foreach_macro_in_scope (splay_tree_node node, void *info)
{
struct macro_for_each_data *datum = (struct macro_for_each_data *) info;
struct macro_key *key = (struct macro_key *) node->key;
struct macro_definition *def = (struct macro_definition *) node->value;
+ enum macro_walk_status status = macro_walk_continue;

/* See if this macro is defined before the passed-in line, and
extends past that line. */
@@ -946,13 +953,14 @@ foreach_macro_in_scope (splay_tree_node node, void *info)
&& (!key->end_file
|| compare_locations (key->end_file, key->end_line,
datum->file, datum->line) >= 0))
- (*datum->fn) (key->name, def, key->start_file, key->start_line,
- datum->user_data);
- return 0;
+ status = (*datum->fn) (key->name, def, key->start_file, key->start_line,
+ datum->user_data);
+
+ return status == macro_walk_abort;
}

/* Call FN for every macro is visible in SCOPE. */
-void
+enum macro_walk_result
macro_for_each_in_scope (struct macro_source_file *file, int line,
macro_callback_fn fn, void *user_data)
{
@@ -962,8 +970,11 @@ macro_for_each_in_scope (struct macro_source_file *file, int line,
datum.user_data = user_data;
datum.file = file;
datum.line = line;
- splay_tree_foreach (file->table->definitions,
- foreach_macro_in_scope, &datum);
+ if (splay_tree_foreach (file->table->definitions,
+ foreach_macro_in_scope, &datum) == 0)
+ return macro_walk_completed;
+ else
+ return macro_walk_aborted;
}

diff --git a/gdb/macrotab.h b/gdb/macrotab.h
index a10351a..4b1c686 100644
--- a/gdb/macrotab.h
+++ b/gdb/macrotab.h
@@ -305,28 +305,50 @@ struct macro_source_file *(macro_definition_location
const char *name,
int *definition_line));

+/* Allows you to abort or continue a walk of the macro table. */
+enum macro_walk_status {
+ macro_walk_abort,
+ macro_walk_continue
+};
+
/* Callback function when walking a macro table. NAME is the name of
the macro, and DEFINITION is the definition. SOURCE is the file at the
start of the include path, and LINE is the line number of the SOURCE file
where the macro was defined. USER_DATA is an arbitrary pointer which is
- passed by the caller to macro_for_each or macro_for_each_in_scope. */
-typedef void (*macro_callback_fn) (const char *name,
- const struct macro_definition *definition,
- struct macro_source_file *source,
- int line,
- void *user_data);
+ passed by the caller to macro_for_each or macro_for_each_in_scope.
+ The callback must return a macro_walk_status. A return value of
+ macro_walk_abort will stop walking the macro table, a return value of
+ macro_walk_continue will proceed to the next iteration. */
+typedef enum macro_walk_status (*macro_callback_fn)
+ (const char *name,
+ const struct macro_definition *definition,
+ struct macro_source_file *source,
+ int line,
+ void *user_data);
+
+/* Describes the results of a walk of the macro table */
+enum macro_walk_result {
+ macro_walk_aborted,
+ macro_walk_completed
+};

/* Call the function FN for each macro in the macro table TABLE.
- USER_DATA is passed, untranslated, to FN. */
-void macro_for_each (struct macro_table *table, macro_callback_fn fn,
- void *user_data);
+ USER_DATA is passed, untranslated, to FN. Returns macro_walk_aborted,
+ or macro_walk_complete depending on the value returned by the callback
+ function passed in. */
+enum macro_walk_result macro_for_each (struct macro_table *table,
+ macro_callback_fn fn,
+ void *user_data);

/* Call the function FN for each macro that is visible in a given
scope. The scope is represented by FILE and LINE. USER_DATA is
- passed, untranslated, to FN. */
-void macro_for_each_in_scope (struct macro_source_file *file, int line,
- macro_callback_fn fn,
- void *user_data);
+ passed, untranslated, to FN. Returns macro_walk_aborted, or
+ macro_walk_complete depending on value returned by the callback
+ function passed in. */
+enum macro_walk_result macro_for_each_in_scope (struct macro_source_file *file,
+ int line,
+ macro_callback_fn fn,
+ void *user_data);

#endif /* MACROTAB_H */
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 9447bd9..6f22bce 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -3769,7 +3769,7 @@ struct add_name_data

/* A callback used with macro_for_each and macro_for_each_in_scope.
This adds a macro's name to the current completion list. */
-static void
+static enum macro_walk_status
add_macro_name (const char *name, const struct macro_definition *ignore,
struct macro_source_file *ignore2, int ignore3,
void *user_data)
@@ -3779,6 +3779,7 @@ add_macro_name (const char *name, const struct macro_definition *ignore,
completion_list_add_name ((char *) name,
datum->sym_text, datum->sym_text_len,
datum->text, datum->word);
+ return macro_walk_continue;
}

/* A callback for expand_partial_symbol_names. */
--
1.7.4.4