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.
This commit is contained in:
Tom Tromey
2008-07-18 20:55:33 +00:00
parent a9dc948127
commit d7d9f01ea1
15 changed files with 388 additions and 76 deletions

View File

@ -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> 2008-07-18 Joseph Myers <joseph@codesourcery.com>
* configure.ac: Put old value of $LIBS after -lbfd -liberty $intl * configure.ac: Put old value of $LIBS after -lbfd -liberty $intl

View File

@ -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) \ $(regcache_h) $(regset_h) $(symtab_h) $(trad_frame_h) $(value_h) \
$(gdb_assert_h) $(gdb_string_h) $(m88k_tdep_h) $(gdb_assert_h) $(gdb_string_h) $(m88k_tdep_h)
macrocmd.o: macrocmd.c $(defs_h) $(macrotab_h) $(macroexp_h) $(macroscope_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.o: macroexp.c $(defs_h) $(gdb_obstack_h) $(bcache_h) $(macrotab_h) \
$(macroexp_h) $(gdb_assert_h) $(macroexp_h) $(gdb_assert_h)
macroscope.o: macroscope.c $(defs_h) $(macroscope_h) $(symtab_h) $(source_h) \ macroscope.o: macroscope.c $(defs_h) $(macroscope_h) $(symtab_h) $(source_h) \

View File

@ -112,6 +112,12 @@ show disable-randomization
x86 DICOS i[34567]86-*-dicos* 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 *** Changes in GDB 6.8
* New native configurations * New native configurations

View File

@ -261,13 +261,6 @@ macro_lookup_ftype *expression_macro_lookup_func;
void *expression_macro_lookup_baton; void *expression_macro_lookup_baton;
static struct macro_definition *
null_macro_lookup (const char *name, void *baton)
{
return 0;
}
static int static int
c_preprocess_and_parse (void) 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)); scope = sal_macro_scope (find_pc_line (expression_context_pc, 0));
else else
scope = default_macro_scope (); 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;
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;
}
gdb_assert (! macro_original_text); gdb_assert (! macro_original_text);
make_cleanup (scan_macro_cleanup, 0); make_cleanup (scan_macro_cleanup, 0);

View File

@ -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> 2008-07-10 Doug Evans <dje@google.com>
* doc/gdb.texinfo: Document "set print symbol-loading on|off". * doc/gdb.texinfo: Document "set print symbol-loading on|off".

View File

@ -1,6 +1,6 @@
\input texinfo @c -*-texinfo-*- \input texinfo @c -*-texinfo-*-
@c Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, @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 Free Software Foundation, Inc.
@c @c
@c %**start of header @c %**start of header
@ -7923,31 +7923,29 @@ source location where that definition was established.
@cindex macros, user-defined @cindex macros, user-defined
@item macro define @var{macro} @var{replacement-list} @item macro define @var{macro} @var{replacement-list}
@itemx macro define @var{macro}(@var{arglist}) @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 Introduce a definition for a preprocessor macro named @var{macro},
preprocessor macro named @var{macro}, invocations of which are replaced invocations of which are replaced by the tokens given in
by the tokens given in @var{replacement-list}. The first form of this @var{replacement-list}. The first form of this command defines an
command defines an ``object-like'' macro, which takes no arguments; the ``object-like'' macro, which takes no arguments; the second form
second form defines a ``function-like'' macro, which takes the arguments defines a ``function-like'' macro, which takes the arguments given in
given in @var{arglist}. @var{arglist}.
A definition introduced by this command is in scope in every expression A definition introduced by this command is in scope in every
evaluated in @value{GDBN}, until it is removed with the @command{macro expression evaluated in @value{GDBN}, until it is removed with the
undef} command, described below. The definition overrides all @code{macro undef} command, described below. The definition overrides
definitions for @var{macro} present in the program being debugged, as all definitions for @var{macro} present in the program being debugged,
well as any previous user-supplied definition. as well as any previous user-supplied definition.
@kindex macro undef @kindex macro undef
@item macro undef @var{macro} @item macro undef @var{macro}
@i{(This command is not yet implemented.)} Remove any user-supplied Remove any user-supplied definition for the macro named @var{macro}.
definition for the macro named @var{macro}. This command only affects This command only affects definitions provided with the @code{macro
definitions provided with the @command{macro define} command, described define} command, described above; it cannot remove definitions present
above; it cannot remove definitions present in the program being in the program being debugged.
debugged.
@kindex macro list @kindex macro list
@item macro list @item macro list
@i{(This command is not yet implemented.)} List all the macros List all the macros defined using the @code{macro define} command.
defined using the @code{macro define} command.
@end table @end table
@cindex macros, example of debugging with @cindex macros, example of debugging with
@ -8026,7 +8024,7 @@ expands to: once (M + 1)
(@value{GDBP}) (@value{GDBP})
@end smallexample @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 the macro invocation explicit in the original text --- the invocation of
@code{ADD} --- but does not expand the invocation of the macro @code{M}, @code{ADD} --- but does not expand the invocation of the macro @code{M},
which was introduced by @code{ADD}. which was introduced by @code{ADD}.

View File

@ -24,6 +24,7 @@
#include "macroscope.h" #include "macroscope.h"
#include "command.h" #include "command.h"
#include "gdbcmd.h" #include "gdbcmd.h"
#include "gdb_string.h"
/* The `macro' prefix command. */ /* The `macro' prefix command. */
@ -189,31 +190,156 @@ info_macro_command (char *name, int from_tty)
/* User-defined macros. */ /* User-defined macros. */
/* A table of user-defined macros. Unlike the macro tables used for static void
symtabs, this one uses xmalloc for all its allocation, not an skip_ws (char **expp)
obstack, and it doesn't bcache anything; it just xmallocs things. So {
it's perfectly possible to remove things from this, or redefine while (macro_is_whitespace (**expp))
things. */ ++*expp;
static struct macro_table *user_macros; }
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 static void
macro_define_command (char *exp, int from_tty) 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 static void
macro_undef_command (char *exp, int from_tty) 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 static void
macro_list_command (char *exp, int from_tty) 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, add_cmd ("list", no_class, macro_list_command,
_("List all the macros defined using the `macro define' command."), _("List all the macros defined using the `macro define' command."),
&macrolist); &macrolist);
user_macros = new_macro_table (0, 0);
} }

View File

@ -171,8 +171,8 @@ appendmem (struct macro_buffer *b, char *addr, int len)
/* Recognizing preprocessor tokens. */ /* Recognizing preprocessor tokens. */
static int int
is_whitespace (int c) macro_is_whitespace (int c)
{ {
return (c == ' ' return (c == ' '
|| c == '\t' || c == '\t'
@ -182,15 +182,15 @@ is_whitespace (int c)
} }
static int int
is_digit (int c) macro_is_digit (int c)
{ {
return ('0' <= c && c <= '9'); return ('0' <= c && c <= '9');
} }
static int int
is_identifier_nondigit (int c) macro_is_identifier_nondigit (int c)
{ {
return (c == '_' return (c == '_'
|| ('a' <= c && c <= 'z') || ('a' <= c && c <= 'z')
@ -255,13 +255,13 @@ static int
get_identifier (struct macro_buffer *tok, char *p, char *end) get_identifier (struct macro_buffer *tok, char *p, char *end)
{ {
if (p < end if (p < end
&& is_identifier_nondigit (*p)) && macro_is_identifier_nondigit (*p))
{ {
char *tok_start = p; char *tok_start = p;
while (p < end while (p < end
&& (is_identifier_nondigit (*p) && (macro_is_identifier_nondigit (*p)
|| is_digit (*p))) || macro_is_digit (*p)))
p++; p++;
set_token (tok, tok_start, p); set_token (tok, tok_start, p);
@ -277,15 +277,15 @@ static int
get_pp_number (struct macro_buffer *tok, char *p, char *end) get_pp_number (struct macro_buffer *tok, char *p, char *end)
{ {
if (p < end if (p < end
&& (is_digit (*p) && (macro_is_digit (*p)
|| *p == '.')) || *p == '.'))
{ {
char *tok_start = p; char *tok_start = p;
while (p < end) while (p < end)
{ {
if (is_digit (*p) if (macro_is_digit (*p)
|| is_identifier_nondigit (*p) || macro_is_identifier_nondigit (*p)
|| *p == '.') || *p == '.')
p++; p++;
else if (p + 2 <= end 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. */ only occur after a #include, which we will never see. */
while (p < end) while (p < end)
if (is_whitespace (*p)) if (macro_is_whitespace (*p))
p++; p++;
else if (get_comment (tok, p, end)) else if (get_comment (tok, p, end))
p += tok->len; p += tok->len;

View File

@ -84,5 +84,11 @@ char *macro_expand_next (char **lexptr,
macro_lookup_ftype *lookup_func, macro_lookup_ftype *lookup_func,
void *lookup_baton); 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 */ #endif /* MACROEXP_H */

View File

@ -27,6 +27,13 @@
#include "inferior.h" #include "inferior.h"
#include "complaints.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 * struct macro_scope *
sal_macro_scope (struct symtab_and_line sal) sal_macro_scope (struct symtab_and_line sal)
@ -77,6 +84,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 * struct macro_scope *
default_macro_scope (void) default_macro_scope (void)
{ {
@ -110,7 +127,11 @@ default_macro_scope (void)
sal.line = cursal.line; 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) standard_macro_lookup (const char *name, void *baton)
{ {
struct macro_scope *ms = (struct macro_scope *) baton; struct macro_scope *ms = (struct macro_scope *) baton;
struct macro_definition *result;
return macro_lookup_definition (ms->file, ms->line, name); /* 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;
}
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);
} }

View File

@ -24,6 +24,9 @@
#include "symtab.h" #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 /* All the information we need to decide which macro definitions are
in scope: a source file (either a main source file or an in scope: a source file (either a main source file or an
#inclusion), and a line number in that file. */ #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); 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 /* Return a `struct macro_scope' object describing the scope the `macro
expand' and `macro expand-once' commands should use for looking up expand' and `macro expand-once' commands should use for looking up
macros. If we have a selected frame, this is the source location of macros. If we have a selected frame, this is the source location of
its PC; otherwise, this is the last listing position. 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 The object returned is allocated using xmalloc; the caller is
responsible for freeing it. */ responsible for freeing it. */

View File

@ -46,6 +46,10 @@ struct macro_table
#inclusion tree; everything else is #included from here. */ #inclusion tree; everything else is #included from here. */
struct macro_source_file *main_source; 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 /* The table of macro definitions. This is a splay tree (an ordered
binary tree that stays balanced, effectively), sorted by macro binary tree that stays balanced, effectively), sorted by macro
name. Where a macro gets defined more than once (presumably with 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 * struct macro_source_file *
macro_include (struct macro_source_file *source, macro_include (struct macro_source_file *source,
int line, int line,
@ -731,13 +743,14 @@ macro_define_object (struct macro_source_file *source, int line,
const char *name, const char *replacement) const char *name, const char *replacement)
{ {
struct macro_table *t = source->table; struct macro_table *t = source->table;
struct macro_key *k; struct macro_key *k = NULL;
struct macro_definition *d; struct macro_definition *d;
k = check_for_redefinition (source, line, if (! t->redef_ok)
name, macro_object_like, k = check_for_redefinition (source, line,
0, 0, name, macro_object_like,
replacement); 0, 0,
replacement);
/* If we're redefining a symbol, and the existing key would be /* If we're redefining a symbol, and the existing key would be
identical to our new key, then the splay_tree_insert function 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) const char *replacement)
{ {
struct macro_table *t = source->table; struct macro_table *t = source->table;
struct macro_key *k; struct macro_key *k = NULL;
struct macro_definition *d; struct macro_definition *d;
k = check_for_redefinition (source, line, if (! t->redef_ok)
name, macro_function_like, k = check_for_redefinition (source, line,
argc, argv, name, macro_function_like,
replacement); argc, argv,
replacement);
/* See comments about duplicate keys in macro_define_object. */ /* See comments about duplicate keys in macro_define_object. */
if (k && ! key_compare (k, name, source, line)) 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. */ /* Creating and freeing macro tables. */
@ -893,6 +929,7 @@ new_macro_table (struct obstack *obstack,
t->obstack = obstack; t->obstack = obstack;
t->bcache = b; t->bcache = b;
t->main_source = NULL; t->main_source = NULL;
t->redef_ok = 0;
t->definitions = (splay_tree_new_with_allocator t->definitions = (splay_tree_new_with_allocator
(macro_tree_compare, (macro_tree_compare,
((splay_tree_delete_key_fn) macro_tree_delete_key), ((splay_tree_delete_key_fn) macro_tree_delete_key),

View File

@ -72,6 +72,8 @@ struct bcache;
/* A table of all the macro definitions for a given compilation unit. */ /* A table of all the macro definitions for a given compilation unit. */
struct macro_table; struct macro_table;
/* The definition of a single macro. */
struct macro_definition;
/* A source file that participated in a compilation unit --- either a /* A source file that participated in a compilation unit --- either a
main file, or an #included file. If a file is #included more than 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. */ /* Return the main source file of the macro table TABLE. */
struct macro_source_file *macro_main (struct 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 a #inclusion.
Record in SOURCE's macro table that, at line number LINE in SOURCE, 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, void macro_undef (struct macro_source_file *source, int line,
const char *name); const char *name);
/* Different kinds of macro definitions. */ /* Different kinds of macro definitions. */
enum macro_kind enum macro_kind
{ {
@ -298,5 +304,13 @@ struct macro_source_file *(macro_definition_location
const char *name, const char *name,
int *definition_line)); 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 */ #endif /* MACROTAB_H */

View File

@ -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> 2008-07-17 Paul Pluzhnikov <ppluzhnikov@google.com>
* gdb.base/foll-fork.exp: Fix for Linux/VDSO failure. * gdb.base/foll-fork.exp: Fix for Linux/VDSO failure.

View File

@ -423,8 +423,52 @@ gdb_test "print M" \
" = 0" \ " = 0" \
"print expression with macro in scope." "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 "next" "foo = 2;" "next to definition"
gdb_test "print M" \ gdb_test "print M" \
"No symbol \"M\" in current context\." \ "No symbol \"M\" in current context\." \
"print expression with macro after undef." "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."