summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2008-07-18 20:55:33 +0000
committerTom Tromey <tromey@redhat.com>2008-07-18 20:55:33 +0000
commit841edd2e8e5b0ace46bac925dfa97be9e8e63f1d (patch)
tree477ba6fc0e08f0d6b4438e983369c7600d815eb1
parent77e32f560ca48ecd355665642c4163bb1e415a8e (diff)
downloadgdb-841edd2e8e5b0ace46bac925dfa97be9e8e63f1d.tar.gz
gdb
PR gdb/855: * NEWS: Add entry for macro commands. * Makefile.in (macrocmd.o): Add gdb_string.h. * macroscope.h (user_macro_scope): Declare. (default_macro_scope): Update documentation. (macro_user_macros): Declare. * c-lang.c (c_preprocess_and_parse): Always attempt macro lookup. Use user_macro_scope. (null_macro_lookup): Remove. * macrotab.h (macro_callback_fn): Declare. (macro_for_each): Likewise. (macro_allow_redefinitions): Likewise. * macrotab.c (foreach_macro): New function (macro_for_each): Likewise. (struct macro_table) <redef_ok>: New field. (macro_allow_redefinitions): New function. (new_macro_table): Update. (macro_define_function): Likewise. (macro_define_object): Likewise. * macroscope.c (user_macro_scope): New function. (default_macro_scope): Use it. (macro_user_macros): New global. (standard_macro_lookup): Look in macro_user_macros. (_initialize_macroscope): New function. * macroexp.h (macro_is_whitespace, macro_is_digit, macro_is_identifier_nondigit): Declare. * macroexp.c (macro_is_whitespace): Rename. No longer static. (macro_is_digit): Likewise. (macro_is_identifier_nondigit): Likewise. (get_identifier): Update. (get_pp_number): Likewise. (get_token): Likewise. * macrocmd.c (skip_ws): New function. (extract_identifier): Likewise. (free_macro_definition_ptr): Likewise. (user_macros): Remove. (macro_define_command): Implement. (_initialize_macrocmd): Update. (macro_undef_command): Implement. (print_one_macro): New function. (macro_list_command): Implement. gdb/doc * gdb.texinfo (Macros): Update. Use @code rather than @command. gdb/testsuite * gdb.base/macscp.exp: Add macro tests.
-rw-r--r--gdb/ChangeLog44
-rw-r--r--gdb/Makefile.in2
-rw-r--r--gdb/NEWS6
-rw-r--r--gdb/c-lang.c21
-rw-r--r--gdb/doc/ChangeLog4
-rw-r--r--gdb/doc/gdb.texinfo40
-rw-r--r--gdb/macrocmd.c146
-rw-r--r--gdb/macroexp.c26
-rw-r--r--gdb/macroexp.h6
-rw-r--r--gdb/macroscope.c39
-rw-r--r--gdb/macroscope.h11
-rw-r--r--gdb/macrotab.c57
-rw-r--r--gdb/macrotab.h16
-rw-r--r--gdb/testsuite/ChangeLog4
-rw-r--r--gdb/testsuite/gdb.base/macscp.exp44
15 files changed, 389 insertions, 77 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a3a6931f677..73b38479ced 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,47 @@
+2008-07-18 Tom Tromey <tromey@redhat.com>
+
+ PR gdb/855:
+ * NEWS: Add entry for macro commands.
+ * Makefile.in (macrocmd.o): Add gdb_string.h.
+ * macroscope.h (user_macro_scope): Declare.
+ (default_macro_scope): Update documentation.
+ (macro_user_macros): Declare.
+ * c-lang.c (c_preprocess_and_parse): Always attempt macro lookup.
+ Use user_macro_scope.
+ (null_macro_lookup): Remove.
+ * macrotab.h (macro_callback_fn): Declare.
+ (macro_for_each): Likewise.
+ (macro_allow_redefinitions): Likewise.
+ * macrotab.c (foreach_macro): New function
+ (macro_for_each): Likewise.
+ (struct macro_table) <redef_ok>: New field.
+ (macro_allow_redefinitions): New function.
+ (new_macro_table): Update.
+ (macro_define_function): Likewise.
+ (macro_define_object): Likewise.
+ * macroscope.c (user_macro_scope): New function.
+ (default_macro_scope): Use it.
+ (macro_user_macros): New global.
+ (standard_macro_lookup): Look in macro_user_macros.
+ (_initialize_macroscope): New function.
+ * macroexp.h (macro_is_whitespace, macro_is_digit,
+ macro_is_identifier_nondigit): Declare.
+ * macroexp.c (macro_is_whitespace): Rename. No longer static.
+ (macro_is_digit): Likewise.
+ (macro_is_identifier_nondigit): Likewise.
+ (get_identifier): Update.
+ (get_pp_number): Likewise.
+ (get_token): Likewise.
+ * macrocmd.c (skip_ws): New function.
+ (extract_identifier): Likewise.
+ (free_macro_definition_ptr): Likewise.
+ (user_macros): Remove.
+ (macro_define_command): Implement.
+ (_initialize_macrocmd): Update.
+ (macro_undef_command): Implement.
+ (print_one_macro): New function.
+ (macro_list_command): Implement.
+
2008-07-18 Joseph Myers <joseph@codesourcery.com>
* configure.ac: Put old value of $LIBS after -lbfd -liberty $intl
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 3e82b928dd0..e2397dff405 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -2456,7 +2456,7 @@ m88k-tdep.o: m88k-tdep.c $(defs_h) $(arch_utils_h) $(dis_asm_h) $(frame_h) \
$(regcache_h) $(regset_h) $(symtab_h) $(trad_frame_h) $(value_h) \
$(gdb_assert_h) $(gdb_string_h) $(m88k_tdep_h)
macrocmd.o: macrocmd.c $(defs_h) $(macrotab_h) $(macroexp_h) $(macroscope_h) \
- $(command_h) $(gdbcmd_h)
+ $(command_h) $(gdbcmd_h) $(gdb_string_h)
macroexp.o: macroexp.c $(defs_h) $(gdb_obstack_h) $(bcache_h) $(macrotab_h) \
$(macroexp_h) $(gdb_assert_h)
macroscope.o: macroscope.c $(defs_h) $(macroscope_h) $(symtab_h) $(source_h) \
diff --git a/gdb/NEWS b/gdb/NEWS
index e7832594d4d..9d9b30c7a04 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -112,6 +112,12 @@ show disable-randomization
x86 DICOS i[34567]86-*-dicos*
+macro define
+macro list
+macro undef
+ These allow macros to be defined, undefined, and listed
+ interactively.
+
*** Changes in GDB 6.8
* New native configurations
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 29aa765e02f..9ce4bb9f4e1 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -261,13 +261,6 @@ macro_lookup_ftype *expression_macro_lookup_func;
void *expression_macro_lookup_baton;
-static struct macro_definition *
-null_macro_lookup (const char *name, void *baton)
-{
- return 0;
-}
-
-
static int
c_preprocess_and_parse (void)
{
@@ -279,17 +272,11 @@ c_preprocess_and_parse (void)
scope = sal_macro_scope (find_pc_line (expression_context_pc, 0));
else
scope = default_macro_scope ();
+ if (! scope)
+ scope = user_macro_scope ();
- if (scope)
- {
- expression_macro_lookup_func = standard_macro_lookup;
- expression_macro_lookup_baton = (void *) scope;
- }
- else
- {
- expression_macro_lookup_func = null_macro_lookup;
- expression_macro_lookup_baton = 0;
- }
+ expression_macro_lookup_func = standard_macro_lookup;
+ expression_macro_lookup_baton = (void *) scope;
gdb_assert (! macro_original_text);
make_cleanup (scan_macro_cleanup, 0);
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 8786b4aeac7..3c6b66d3e14 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,7 @@
+2008-07-18 Tom Tromey <tromey@redhat.com>
+
+ * gdb.texinfo (Macros): Update. Use @code rather than @command.
+
2008-07-10 Doug Evans <dje@google.com>
* doc/gdb.texinfo: Document "set print symbol-loading on|off".
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 2920179533c..06d1db29839 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -1,6 +1,6 @@
\input texinfo @c -*-texinfo-*-
@c Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998,
-@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008
+@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
@c Free Software Foundation, Inc.
@c
@c %**start of header
@@ -7923,31 +7923,29 @@ source location where that definition was established.
@cindex macros, user-defined
@item macro define @var{macro} @var{replacement-list}
@itemx macro define @var{macro}(@var{arglist}) @var{replacement-list}
-@i{(This command is not yet implemented.)} Introduce a definition for a
-preprocessor macro named @var{macro}, invocations of which are replaced
-by the tokens given in @var{replacement-list}. The first form of this
-command defines an ``object-like'' macro, which takes no arguments; the
-second form defines a ``function-like'' macro, which takes the arguments
-given in @var{arglist}.
-
-A definition introduced by this command is in scope in every expression
-evaluated in @value{GDBN}, until it is removed with the @command{macro
-undef} command, described below. The definition overrides all
-definitions for @var{macro} present in the program being debugged, as
-well as any previous user-supplied definition.
+Introduce a definition for a preprocessor macro named @var{macro},
+invocations of which are replaced by the tokens given in
+@var{replacement-list}. The first form of this command defines an
+``object-like'' macro, which takes no arguments; the second form
+defines a ``function-like'' macro, which takes the arguments given in
+@var{arglist}.
+
+A definition introduced by this command is in scope in every
+expression evaluated in @value{GDBN}, until it is removed with the
+@code{macro undef} command, described below. The definition overrides
+all definitions for @var{macro} present in the program being debugged,
+as well as any previous user-supplied definition.
@kindex macro undef
@item macro undef @var{macro}
-@i{(This command is not yet implemented.)} Remove any user-supplied
-definition for the macro named @var{macro}. This command only affects
-definitions provided with the @command{macro define} command, described
-above; it cannot remove definitions present in the program being
-debugged.
+Remove any user-supplied definition for the macro named @var{macro}.
+This command only affects definitions provided with the @code{macro
+define} command, described above; it cannot remove definitions present
+in the program being debugged.
@kindex macro list
@item macro list
-@i{(This command is not yet implemented.)} List all the macros
-defined using the @code{macro define} command.
+List all the macros defined using the @code{macro define} command.
@end table
@cindex macros, example of debugging with
@@ -8026,7 +8024,7 @@ expands to: once (M + 1)
(@value{GDBP})
@end smallexample
-In the example above, note that @command{macro expand-once} expands only
+In the example above, note that @code{macro expand-once} expands only
the macro invocation explicit in the original text --- the invocation of
@code{ADD} --- but does not expand the invocation of the macro @code{M},
which was introduced by @code{ADD}.
diff --git a/gdb/macrocmd.c b/gdb/macrocmd.c
index c5d3a8fb806..4a70d4fb3d3 100644
--- a/gdb/macrocmd.c
+++ b/gdb/macrocmd.c
@@ -24,6 +24,7 @@
#include "macroscope.h"
#include "command.h"
#include "gdbcmd.h"
+#include "gdb_string.h"
/* The `macro' prefix command. */
@@ -189,31 +190,156 @@ info_macro_command (char *name, int from_tty)
/* User-defined macros. */
-/* A table of user-defined macros. Unlike the macro tables used for
- symtabs, this one uses xmalloc for all its allocation, not an
- obstack, and it doesn't bcache anything; it just xmallocs things. So
- it's perfectly possible to remove things from this, or redefine
- things. */
-static struct macro_table *user_macros;
+static void
+skip_ws (char **expp)
+{
+ while (macro_is_whitespace (**expp))
+ ++*expp;
+}
+
+static char *
+extract_identifier (char **expp)
+{
+ char *result;
+ char *p = *expp;
+ unsigned int len;
+ if (! *p || ! macro_is_identifier_nondigit (*p))
+ return NULL;
+ for (++p;
+ *p && (macro_is_identifier_nondigit (*p) || macro_is_digit (*p));
+ ++p)
+ ;
+ len = p - *expp;
+ result = (char *) xmalloc (len + 1);
+ memcpy (result, *expp, len);
+ result[len] = '\0';
+ *expp += len;
+ return result;
+}
+
+/* Helper function to clean up a temporarily-constructed macro object.
+ This assumes that the contents were all allocated with xmalloc. */
+static void
+free_macro_definition_ptr (void *ptr)
+{
+ int i;
+ struct macro_definition *loc = (struct macro_definition *) ptr;
+ for (i = 0; i < loc->argc; ++i)
+ xfree ((char *) loc->argv[i]);
+ xfree ((char *) loc->argv);
+ /* Note that the 'replacement' field is not allocated. */
+}
static void
macro_define_command (char *exp, int from_tty)
{
- error (_("Command not implemented yet."));
+ struct macro_definition new_macro;
+ char *name = NULL;
+ struct cleanup *cleanup_chain = make_cleanup (free_macro_definition_ptr,
+ &new_macro);
+ make_cleanup (free_current_contents, &name);
+
+ memset (&new_macro, 0, sizeof (struct macro_definition));
+
+ skip_ws (&exp);
+ name = extract_identifier (&exp);
+ if (! name)
+ error (_("Invalid macro name."));
+ if (*exp == '(')
+ {
+ /* Function-like macro. */
+ int alloced = 5;
+ char **argv = (char **) xmalloc (alloced * sizeof (char *));
+
+ new_macro.kind = macro_function_like;
+ new_macro.argc = 0;
+ new_macro.argv = (const char * const *) argv;
+
+ /* Skip the '(' and whitespace. */
+ ++exp;
+ skip_ws (&exp);
+
+ while (*exp != ')')
+ {
+ int i;
+
+ if (new_macro.argc == alloced)
+ {
+ alloced *= 2;
+ argv = (char **) xrealloc (argv, alloced * sizeof (char *));
+ /* Must update new_macro as well... */
+ new_macro.argv = (const char * const *) argv;
+ }
+ argv[new_macro.argc] = extract_identifier (&exp);
+ if (! argv[new_macro.argc])
+ error (_("Macro is missing an argument."));
+ ++new_macro.argc;
+
+ for (i = new_macro.argc - 2; i >= 0; --i)
+ {
+ if (! strcmp (argv[i], argv[new_macro.argc - 1]))
+ error (_("Two macro arguments with identical names."));
+ }
+
+ skip_ws (&exp);
+ if (*exp == ',')
+ {
+ ++exp;
+ skip_ws (&exp);
+ }
+ else if (*exp != ')')
+ error (_("',' or ')' expected at end of macro arguments."));
+ }
+ /* Skip the closing paren. */
+ ++exp;
+
+ macro_define_function (macro_main (macro_user_macros), -1, name,
+ new_macro.argc, (const char **) new_macro.argv,
+ exp);
+ }
+ else
+ macro_define_object (macro_main (macro_user_macros), -1, name, exp);
+
+ do_cleanups (cleanup_chain);
}
static void
macro_undef_command (char *exp, int from_tty)
{
- error (_("Command not implemented yet."));
+ char *name;
+ skip_ws (&exp);
+ name = extract_identifier (&exp);
+ if (! name)
+ error (_("Invalid macro name."));
+ macro_undef (macro_main (macro_user_macros), -1, name);
+ xfree (name);
+}
+
+
+static void
+print_one_macro (const char *name, const struct macro_definition *macro)
+{
+ fprintf_filtered (gdb_stdout, "macro define %s", name);
+ if (macro->kind == macro_function_like)
+ {
+ int i;
+ fprintf_filtered (gdb_stdout, "(");
+ for (i = 0; i < macro->argc; ++i)
+ fprintf_filtered (gdb_stdout, "%s%s", (i > 0) ? ", " : "",
+ macro->argv[i]);
+ fprintf_filtered (gdb_stdout, ")");
+ }
+ /* Note that we don't need a leading space here -- "macro define"
+ provided it. */
+ fprintf_filtered (gdb_stdout, "%s\n", macro->replacement);
}
static void
macro_list_command (char *exp, int from_tty)
{
- error (_("Command not implemented yet."));
+ macro_for_each (macro_user_macros, print_one_macro);
}
@@ -273,6 +399,4 @@ Remove the definition of the C/C++ preprocessor macro with the given name."),
add_cmd ("list", no_class, macro_list_command,
_("List all the macros defined using the `macro define' command."),
&macrolist);
-
- user_macros = new_macro_table (0, 0);
}
diff --git a/gdb/macroexp.c b/gdb/macroexp.c
index f85cb4b1358..0cb9575678e 100644
--- a/gdb/macroexp.c
+++ b/gdb/macroexp.c
@@ -171,8 +171,8 @@ appendmem (struct macro_buffer *b, char *addr, int len)
/* Recognizing preprocessor tokens. */
-static int
-is_whitespace (int c)
+int
+macro_is_whitespace (int c)
{
return (c == ' '
|| c == '\t'
@@ -182,15 +182,15 @@ is_whitespace (int c)
}
-static int
-is_digit (int c)
+int
+macro_is_digit (int c)
{
return ('0' <= c && c <= '9');
}
-static int
-is_identifier_nondigit (int c)
+int
+macro_is_identifier_nondigit (int c)
{
return (c == '_'
|| ('a' <= c && c <= 'z')
@@ -255,13 +255,13 @@ static int
get_identifier (struct macro_buffer *tok, char *p, char *end)
{
if (p < end
- && is_identifier_nondigit (*p))
+ && macro_is_identifier_nondigit (*p))
{
char *tok_start = p;
while (p < end
- && (is_identifier_nondigit (*p)
- || is_digit (*p)))
+ && (macro_is_identifier_nondigit (*p)
+ || macro_is_digit (*p)))
p++;
set_token (tok, tok_start, p);
@@ -277,15 +277,15 @@ static int
get_pp_number (struct macro_buffer *tok, char *p, char *end)
{
if (p < end
- && (is_digit (*p)
+ && (macro_is_digit (*p)
|| *p == '.'))
{
char *tok_start = p;
while (p < end)
{
- if (is_digit (*p)
- || is_identifier_nondigit (*p)
+ if (macro_is_digit (*p)
+ || macro_is_identifier_nondigit (*p)
|| *p == '.')
p++;
else if (p + 2 <= end
@@ -485,7 +485,7 @@ get_token (struct macro_buffer *tok,
only occur after a #include, which we will never see. */
while (p < end)
- if (is_whitespace (*p))
+ if (macro_is_whitespace (*p))
p++;
else if (get_comment (tok, p, end))
p += tok->len;
diff --git a/gdb/macroexp.h b/gdb/macroexp.h
index b10c13d87cf..c563d1cce55 100644
--- a/gdb/macroexp.h
+++ b/gdb/macroexp.h
@@ -84,5 +84,11 @@ char *macro_expand_next (char **lexptr,
macro_lookup_ftype *lookup_func,
void *lookup_baton);
+/* Functions to classify characters according to cpp rules. */
+
+int macro_is_whitespace (int c);
+int macro_is_identifier_nondigit (int c);
+int macro_is_digit (int c);
+
#endif /* MACROEXP_H */
diff --git a/gdb/macroscope.c b/gdb/macroscope.c
index 73839860e06..ef334b7efe1 100644
--- a/gdb/macroscope.c
+++ b/gdb/macroscope.c
@@ -27,6 +27,13 @@
#include "inferior.h"
#include "complaints.h"
+/* A table of user-defined macros. Unlike the macro tables used for
+ symtabs, this one uses xmalloc for all its allocation, not an
+ obstack, and it doesn't bcache anything; it just xmallocs things. So
+ it's perfectly possible to remove things from this, or redefine
+ things. */
+struct macro_table *macro_user_macros;
+
struct macro_scope *
sal_macro_scope (struct symtab_and_line sal)
@@ -78,6 +85,16 @@ sal_macro_scope (struct symtab_and_line sal)
struct macro_scope *
+user_macro_scope (void)
+{
+ struct macro_scope *ms;
+ ms = XNEW (struct macro_scope);
+ ms->file = macro_main (macro_user_macros);
+ ms->line = -1;
+ return ms;
+}
+
+struct macro_scope *
default_macro_scope (void)
{
struct symtab_and_line sal;
@@ -110,7 +127,11 @@ default_macro_scope (void)
sal.line = cursal.line;
}
- return sal_macro_scope (sal);
+ ms = sal_macro_scope (sal);
+ if (! ms)
+ ms = user_macro_scope ();
+
+ return ms;
}
@@ -121,6 +142,20 @@ struct macro_definition *
standard_macro_lookup (const char *name, void *baton)
{
struct macro_scope *ms = (struct macro_scope *) baton;
+ struct macro_definition *result;
+
+ /* Give user-defined macros priority over all others. */
+ result = macro_lookup_definition (macro_main (macro_user_macros), -1, name);
+ if (! result)
+ result = macro_lookup_definition (ms->file, ms->line, name);
+ return result;
+}
+
- return macro_lookup_definition (ms->file, ms->line, name);
+void
+_initialize_macroscope (void)
+{
+ macro_user_macros = new_macro_table (0, 0);
+ macro_set_main (macro_user_macros, "<user-defined>");
+ macro_allow_redefinitions (macro_user_macros);
}
diff --git a/gdb/macroscope.h b/gdb/macroscope.h
index 4c288b50ebb..d81a760aad9 100644
--- a/gdb/macroscope.h
+++ b/gdb/macroscope.h
@@ -24,6 +24,9 @@
#include "symtab.h"
+/* The table of macros defined by the user. */
+extern struct macro_table *macro_user_macros;
+
/* All the information we need to decide which macro definitions are
in scope: a source file (either a main source file or an
#inclusion), and a line number in that file. */
@@ -39,12 +42,18 @@ struct macro_scope {
struct macro_scope *sal_macro_scope (struct symtab_and_line sal);
+/* Return a `struct macro_scope' object representing just the
+ user-defined macros. The result is allocated using xmalloc; the
+ caller is responsible for freeing it. */
+struct macro_scope *user_macro_scope (void);
+
/* Return a `struct macro_scope' object describing the scope the `macro
expand' and `macro expand-once' commands should use for looking up
macros. If we have a selected frame, this is the source location of
its PC; otherwise, this is the last listing position.
- If we have no macro information for the current location, return zero.
+ If we have no macro information for the current location, return
+ the user macro scope.
The object returned is allocated using xmalloc; the caller is
responsible for freeing it. */
diff --git a/gdb/macrotab.c b/gdb/macrotab.c
index 27e6fe6d0cd..7633c98d4f5 100644
--- a/gdb/macrotab.c
+++ b/gdb/macrotab.c
@@ -46,6 +46,10 @@ struct macro_table
#inclusion tree; everything else is #included from here. */
struct macro_source_file *main_source;
+ /* True if macros in this table can be redefined without issuing an
+ error. */
+ int redef_ok;
+
/* The table of macro definitions. This is a splay tree (an ordered
binary tree that stays balanced, effectively), sorted by macro
name. Where a macro gets defined more than once (presumably with
@@ -427,6 +431,14 @@ macro_main (struct macro_table *t)
}
+void
+macro_allow_redefinitions (struct macro_table *t)
+{
+ gdb_assert (! t->obstack);
+ t->redef_ok = 1;
+}
+
+
struct macro_source_file *
macro_include (struct macro_source_file *source,
int line,
@@ -731,13 +743,14 @@ macro_define_object (struct macro_source_file *source, int line,
const char *name, const char *replacement)
{
struct macro_table *t = source->table;
- struct macro_key *k;
+ struct macro_key *k = NULL;
struct macro_definition *d;
- k = check_for_redefinition (source, line,
- name, macro_object_like,
- 0, 0,
- replacement);
+ if (! t->redef_ok)
+ k = check_for_redefinition (source, line,
+ name, macro_object_like,
+ 0, 0,
+ replacement);
/* If we're redefining a symbol, and the existing key would be
identical to our new key, then the splay_tree_insert function
@@ -764,13 +777,14 @@ macro_define_function (struct macro_source_file *source, int line,
const char *replacement)
{
struct macro_table *t = source->table;
- struct macro_key *k;
+ struct macro_key *k = NULL;
struct macro_definition *d;
- k = check_for_redefinition (source, line,
- name, macro_function_like,
- argc, argv,
- replacement);
+ if (! t->redef_ok)
+ k = check_for_redefinition (source, line,
+ name, macro_function_like,
+ argc, argv,
+ replacement);
/* See comments about duplicate keys in macro_define_object. */
if (k && ! key_compare (k, name, source, line))
@@ -873,6 +887,28 @@ macro_definition_location (struct macro_source_file *source,
}
+/* Helper function for macro_for_each. */
+static int
+foreach_macro (splay_tree_node node, void *fnp)
+{
+ macro_callback_fn *fn = (macro_callback_fn *) fnp;
+ struct macro_key *key = (struct macro_key *) node->key;
+ struct macro_definition *def = (struct macro_definition *) node->value;
+ (**fn) (key->name, def);
+ return 0;
+}
+
+/* Call FN for every macro in TABLE. */
+void
+macro_for_each (struct macro_table *table, macro_callback_fn fn)
+{
+ /* Note that we pass in the address of 'fn' because, pedantically
+ speaking, we can't necessarily cast a pointer-to-function to a
+ void*. */
+ splay_tree_foreach (table->definitions, foreach_macro, &fn);
+}
+
+
/* Creating and freeing macro tables. */
@@ -893,6 +929,7 @@ new_macro_table (struct obstack *obstack,
t->obstack = obstack;
t->bcache = b;
t->main_source = NULL;
+ t->redef_ok = 0;
t->definitions = (splay_tree_new_with_allocator
(macro_tree_compare,
((splay_tree_delete_key_fn) macro_tree_delete_key),
diff --git a/gdb/macrotab.h b/gdb/macrotab.h
index eb546bccf7f..5ff36ea2cd6 100644
--- a/gdb/macrotab.h
+++ b/gdb/macrotab.h
@@ -72,6 +72,8 @@ struct bcache;
/* A table of all the macro definitions for a given compilation unit. */
struct macro_table;
+/* The definition of a single macro. */
+struct macro_definition;
/* A source file that participated in a compilation unit --- either a
main file, or an #included file. If a file is #included more than
@@ -189,6 +191,11 @@ struct macro_source_file *macro_set_main (struct macro_table *table,
/* Return the main source file of the macro table TABLE. */
struct macro_source_file *macro_main (struct macro_table *table);
+/* Mark the macro table TABLE so that macros defined in this table can
+ be redefined without error. Note that it invalid to call this if
+ TABLE is allocated on an obstack. */
+void macro_allow_redefinitions (struct macro_table *table);
+
/* Record a #inclusion.
Record in SOURCE's macro table that, at line number LINE in SOURCE,
@@ -247,7 +254,6 @@ void macro_define_function (struct macro_source_file *source, int line,
void macro_undef (struct macro_source_file *source, int line,
const char *name);
-
/* Different kinds of macro definitions. */
enum macro_kind
{
@@ -298,5 +304,13 @@ struct macro_source_file *(macro_definition_location
const char *name,
int *definition_line));
+/* Callback function when walking a macro table. NAME is the name of
+ the macro, and DEFINITION is the definition. */
+typedef void (*macro_callback_fn) (const char *name,
+ const struct macro_definition *definition);
+
+/* Call the function FN for each macro in the macro table TABLE. */
+void macro_for_each (struct macro_table *table, macro_callback_fn fn);
+
#endif /* MACROTAB_H */
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index adcadd71431..1a07bc1defe 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2008-07-18 Tom Tromey <tromey@redhat.com>
+
+ * gdb.base/macscp.exp: Add macro tests.
+
2008-07-17 Paul Pluzhnikov <ppluzhnikov@google.com>
* gdb.base/foll-fork.exp: Fix for Linux/VDSO failure.
diff --git a/gdb/testsuite/gdb.base/macscp.exp b/gdb/testsuite/gdb.base/macscp.exp
index ccefc85835b..90c2d9531f3 100644
--- a/gdb/testsuite/gdb.base/macscp.exp
+++ b/gdb/testsuite/gdb.base/macscp.exp
@@ -423,8 +423,52 @@ gdb_test "print M" \
" = 0" \
"print expression with macro in scope."
+gdb_test "macro define M 72" \
+ "" \
+ "user macro override"
+
+gdb_test "print M" \
+ " = 72" \
+ "choose user macro"
+
+gdb_test "macro undef M" \
+ "" \
+ "remove user override"
+
+gdb_test "print M" \
+ " = 0" \
+ "print expression with macro after removing override"
+
gdb_test "next" "foo = 2;" "next to definition"
gdb_test "print M" \
"No symbol \"M\" in current context\." \
"print expression with macro after undef."
+
+gdb_test "macro define M 5" \
+ "" \
+ "basic macro define"
+
+gdb_test "print M" \
+ " = 5" \
+ "expansion of defined macro"
+
+gdb_test "macro list" \
+ "macro define M 5" \
+ "basic macro list"
+
+gdb_test "macro define M(x) x" \
+ "" \
+ "basic redefine, macro with args"
+
+gdb_test "print M (7)" \
+ " = 7" \
+ "expansion of macro with arguments"
+
+gdb_test "macro undef M" \
+ "" \
+ "basic macro undef"
+
+gdb_test "print M" \
+ "No symbol \"M\" in current context\." \
+ "print expression with macro after user undef."