From d7d9f01ea18f14a9a1574042bd65dd73f9b6b2b8 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 18 Jul 2008 20:55:33 +0000 Subject: [PATCH] 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) : 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. --- gdb/ChangeLog | 44 ++++++++++++ gdb/Makefile.in | 2 +- gdb/NEWS | 6 ++ gdb/c-lang.c | 21 ++---- gdb/doc/ChangeLog | 4 ++ gdb/doc/gdb.texinfo | 40 +++++------ gdb/macrocmd.c | 146 +++++++++++++++++++++++++++++++++++--- gdb/macroexp.c | 26 +++---- gdb/macroexp.h | 6 ++ gdb/macroscope.c | 39 +++++++++- gdb/macroscope.h | 11 ++- gdb/macrotab.c | 57 ++++++++++++--- gdb/macrotab.h | 16 ++++- gdb/testsuite/ChangeLog | 4 ++ gdb/testsuite/gdb.base/macscp.exp | 44 ++++++++++++ 15 files changed, 389 insertions(+), 77 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a3a6931..73b3847 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,47 @@ +2008-07-18 Tom Tromey + + 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) : 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 * configure.ac: Put old value of $LIBS after -lbfd -liberty $intl diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 3e82b92..e2397df 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 e783259..9d9b30c 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 29aa765..9ce4bb9 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 8786b4a..3c6b66d 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2008-07-18 Tom Tromey + + * gdb.texinfo (Macros): Update. Use @code rather than @command. + 2008-07-10 Doug Evans * doc/gdb.texinfo: Document "set print symbol-loading on|off". diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 2920179..06d1db2 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 c5d3a8f..4a70d4f 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."), ¯olist); - - user_macros = new_macro_table (0, 0); } diff --git a/gdb/macroexp.c b/gdb/macroexp.c index f85cb4b..0cb9575 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 b10c13d..c563d1c 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 7383986..ef334b7 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, ""); + macro_allow_redefinitions (macro_user_macros); } diff --git a/gdb/macroscope.h b/gdb/macroscope.h index 4c288b5..d81a760 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 27e6fe6..7633c98 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 eb546bc..5ff36ea 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 adcadd7..1a07bc1 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2008-07-18 Tom Tromey + + * gdb.base/macscp.exp: Add macro tests. + 2008-07-17 Paul Pluzhnikov * 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 ccefc85..90c2d95 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." -- 2.7.4