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>
* 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) \
$(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) \

View File

@ -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

View File

@ -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;
}
gdb_assert (! macro_original_text);
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>
* doc/gdb.texinfo: Document "set print symbol-loading on|off".

View File

@ -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}.
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.
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}.

View File

@ -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);
}

View File

@ -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;

View File

@ -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 */

View File

@ -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)
@ -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 *
default_macro_scope (void)
{
@ -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;
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"
/* 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. */

View File

@ -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,9 +743,10 @@ 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;
if (! t->redef_ok)
k = check_for_redefinition (source, line,
name, macro_object_like,
0, 0,
@ -764,9 +777,10 @@ 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;
if (! t->redef_ok)
k = check_for_redefinition (source, line,
name, macro_function_like,
argc, argv,
@ -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),

View File

@ -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 */

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>
* gdb.base/foll-fork.exp: Fix for Linux/VDSO failure.

View File

@ -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."