mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-01 20:12:01 +08:00
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.
This commit is contained in:
@ -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
|
||||
|
@ -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) \
|
||||
|
6
gdb/NEWS
6
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
|
||||
|
17
gdb/c-lang.c
17
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;
|
||||
}
|
||||
|
||||
gdb_assert (! macro_original_text);
|
||||
make_cleanup (scan_macro_cleanup, 0);
|
||||
|
@ -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".
|
||||
|
@ -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}.
|
||||
|
146
gdb/macrocmd.c
146
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."),
|
||||
¯olist);
|
||||
|
||||
user_macros = new_macro_table (0, 0);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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. */
|
||||
|
@ -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),
|
||||
|
@ -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 */
|
||||
|
@ -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.
|
||||
|
@ -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."
|
||||
|
Reference in New Issue
Block a user