* [patch] PR 12999 info macros command.
@ 2011-07-19 9:57 Matt Rice
2011-07-19 17:29 ` Tom Tromey
2011-07-20 17:24 ` Eli Zaretskii
0 siblings, 2 replies; 10+ messages in thread
From: Matt Rice @ 2011-07-19 9:57 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1341 bytes --]
this patch adds 2 commands,
info macros LINESPEC
info definitions MACRO
the PR only asks for the former, but the latter seemed possibly useful.
if you don't want it, i'll at least try and make it implementable with
python (when i finish that.)
not sure if 'info macros' is prudent with the kfail (at the end of the tests).
2011-07-18 Matt Rice <ratmice@gmail.com>
PR macros/12999
* gdb.texinfo (Macros): Add info definitions and info macros commands.
2011-07-18 Matt Rice <ratmice@gmail.com>
PR macros/12999
* gdb.base/info-macros.c: New test sources.
* gdb.base/info-macros.exp: New tests.
2011-07-18 Matt Rice <ratmice@gmail.com>
PR macros/12999
* macrotab.h (macro_callback_fn): Add new arguments to callback.
* macrotab.c (foreach_macro): Ditto.
(foreach_macro_in_scope): Ditto.
* macrocmd.c (print_macro_callback): New function.
(info_macro_command): Move some code to print_macro_definition.
(print_macro_definition): New function.
(print_one_macro): Add new arguments to callback.
(info_definitions_command): New function.
(info_macros_command): Ditto.
(_initialize_macrocmd): Add info macros and info definitions commands.
* symtab.c (add_macro_name): Add new arguments to callback.
[-- Attachment #2: foo.diff --]
[-- Type: application/octet-stream, Size: 14805 bytes --]
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 3a3a9fb..3a61b23 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -9590,9 +9590,25 @@ can be any string of tokens.
@cindex macro definition, showing
@cindex definition, showing a macro's
@item info macro @var{macro}
-Show the definition of the macro named @var{macro}, and describe the
+Show the current definition of the macro named @var{macro}, and describe the
source location or compiler command-line where that definition was established.
+@kindex info macros
+@cindex macro definition, showing
+@cindex definition, showing a macro's
+@item info macros @var{linespec}
+Show all macro definitions at the location of @var{linespec}, and describe the
+source location or compiler command-line where those definitions were
+established.
+
+@kindex info definitions
+@cindex macro definition, showing
+@cindex definition, showing a macro's
+@item info definitions @var{macro}
+Show all definitions of the macro named @var{macro}, in the current scope,
+and describe the source location or compiler command-line where those
+definitions were established.
+
@kindex macro define
@cindex user-defined macros
@cindex defining macros interactively
diff --git a/gdb/macrocmd.c b/gdb/macrocmd.c
index c77156a..5480305 100644
--- a/gdb/macrocmd.c
+++ b/gdb/macrocmd.c
@@ -134,36 +134,20 @@ show_pp_source_pos (struct ui_file *stream,
}
}
-
static void
-info_macro_command (char *name, int from_tty)
+print_macro_definition (const char *name,
+ const struct macro_definition *d,
+ struct macro_source_file *file,
+ int line)
{
- struct macro_scope *ms = NULL;
- struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms);
- struct macro_definition *d;
-
- if (! name || ! *name)
- error (_("You must follow the `info macro' command with the name"
- " of the macro\n"
- "whose definition you want to see."));
-
- ms = default_macro_scope ();
- if (! ms)
- error (_("GDB has no preprocessor macro information for that code."));
-
- d = macro_lookup_definition (ms->file, ms->line, name);
- if (d)
- {
- int line;
- struct macro_source_file *file
- = macro_definition_location (ms->file, ms->line, name, &line);
-
fprintf_filtered (gdb_stdout, "Defined at ");
show_pp_source_pos (gdb_stdout, file, line);
+
if (line != 0)
fprintf_filtered (gdb_stdout, "#define %s", name);
else
fprintf_filtered (gdb_stdout, "-D%s", name);
+
if (d->kind == macro_function_like)
{
int i;
@@ -177,10 +161,37 @@ info_macro_command (char *name, int from_tty)
}
fputs_filtered (")", gdb_stdout);
}
+
if (line != 0)
fprintf_filtered (gdb_stdout, " %s\n", d->replacement);
else
fprintf_filtered (gdb_stdout, "=%s\n", d->replacement);
+}
+
+static void
+info_macro_command (char *name, int from_tty)
+{
+ struct macro_scope *ms = NULL;
+ struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms);
+ struct macro_definition *d;
+
+ if (! name || ! *name)
+ error (_("You must follow the `info macro' command with the name"
+ " of the macro\n"
+ "whose definition you want to see."));
+
+ ms = default_macro_scope ();
+ if (! ms)
+ error (_("GDB has no preprocessor macro information for that code."));
+
+ d = macro_lookup_definition (ms->file, ms->line, name);
+ if (d)
+ {
+ int line;
+ struct macro_source_file *file
+ = macro_definition_location (ms->file, ms->line, name, &line);
+
+ print_macro_definition (name, d, file, line);
}
else
{
@@ -195,6 +206,58 @@ info_macro_command (char *name, int from_tty)
}
+static void
+print_macro_callback (const char *name, const struct macro_definition *macro,
+ struct macro_source_file *source, int line,
+ void *user_data)
+{
+ if (! user_data || strcmp (user_data, name) == 0)
+ print_macro_definition (name, macro, source, line);
+}
+
+static void
+info_definitions_command (char *name, int from_tty)
+{
+ struct macro_scope *ms = NULL;
+ struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms);
+
+ if (! name || ! *name)
+ error (_("You must follow the `info definitions' command with the name"
+ " of the macro\n"
+ "whose definition you want to see."));
+
+ ms = default_macro_scope ();
+
+ if (! ms || ! ms->file || ! ms->file->table)
+ error (_("GDB has no preprocessor macro information for that code."));
+
+ macro_for_each (ms->file->table, print_macro_callback, name);
+ do_cleanups (cleanup_chain);
+}
+
+static void
+info_macros_command (char *args, int from_tty)
+{
+ struct macro_scope *ms = NULL;
+ struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms);
+
+ if (args == NULL)
+ ms = default_macro_scope ();
+ else
+ {
+ struct symtabs_and_lines sals = decode_line_spec (args, 0);
+
+ if (sals.nelts)
+ ms = sal_macro_scope (sals.sals[0]);
+ }
+
+ if (! ms || ! ms->file || ! ms->file->table)
+ error (_("GDB has no preprocessor macro information for that code."));
+
+ macro_for_each_in_scope (ms->file, ms->line, print_macro_callback, NULL);
+ do_cleanups (cleanup_chain);
+}
+
\f
/* User-defined macros. */
@@ -359,6 +422,7 @@ macro_undef_command (char *exp, int from_tty)
static void
print_one_macro (const char *name, const struct macro_definition *macro,
+ struct macro_source_file *source, int line,
void *ignore)
{
fprintf_filtered (gdb_stdout, "macro define %s", name);
@@ -382,7 +446,6 @@ macro_list_command (char *exp, int from_tty)
macro_for_each (macro_user_macros, print_one_macro, NULL);
}
-
\f
/* Initializing the `macrocmd' module. */
@@ -420,6 +483,16 @@ expression work together to yield a pre-processed expression."),
_("Show the definition of MACRO, and its source location."),
&infolist);
+ add_cmd ("macros", no_class, info_macros_command,
+ _("Show the names of all macros at LINESPEC, or the current \
+scope."),
+ &infolist);
+
+ add_cmd ("definitions", no_class, info_definitions_command,
+ _("Show all definitions of the macro named MACRO in the\n\
+current scope."),
+ &infolist);
+
add_cmd ("define", no_class, macro_define_command, _("\
Define a new C/C++ preprocessor macro.\n\
The GDB command `macro define DEFINITION' is equivalent to placing a\n\
diff --git a/gdb/macrotab.c b/gdb/macrotab.c
index cba285d..efcf835 100644
--- a/gdb/macrotab.c
+++ b/gdb/macrotab.c
@@ -913,7 +913,8 @@ foreach_macro (splay_tree_node node, void *arg)
struct macro_key *key = (struct macro_key *) node->key;
struct macro_definition *def = (struct macro_definition *) node->value;
- (*datum->fn) (key->name, def, datum->user_data);
+ (*datum->fn) (key->name, def, key->start_file, key->start_line,
+ datum->user_data);
return 0;
}
@@ -945,7 +946,8 @@ foreach_macro_in_scope (splay_tree_node node, void *info)
&& (!key->end_file
|| compare_locations (key->end_file, key->end_line,
datum->file, datum->line) >= 0))
- (*datum->fn) (key->name, def, datum->user_data);
+ (*datum->fn) (key->name, def, key->start_file, key->start_line,
+ datum->user_data);
return 0;
}
diff --git a/gdb/macrotab.h b/gdb/macrotab.h
index d2b2b63..c81b13a 100644
--- a/gdb/macrotab.h
+++ b/gdb/macrotab.h
@@ -311,6 +311,8 @@ struct macro_source_file *(macro_definition_location
or macro_for_each_in_scope. */
typedef void (*macro_callback_fn) (const char *name,
const struct macro_definition *definition,
+ struct macro_source_file *source,
+ int line,
void *user_data);
/* Call the function FN for each macro in the macro table TABLE.
diff --git a/gdb/symtab.c b/gdb/symtab.c
index b792081..9447bd9 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -3771,6 +3771,7 @@ struct add_name_data
This adds a macro's name to the current completion list. */
static void
add_macro_name (const char *name, const struct macro_definition *ignore,
+ struct macro_source_file *ignore2, int ignore3,
void *user_data)
{
struct add_name_data *datum = (struct add_name_data *) user_data;
diff --git a/gdb/testsuite/gdb.base/info-macros.c b/gdb/testsuite/gdb.base/info-macros.c
new file mode 100644
index 0000000..de603e6
--- /dev/null
+++ b/gdb/testsuite/gdb.base/info-macros.c
@@ -0,0 +1,73 @@
+#ifdef DEF_MACROS
+
+ #ifdef ONE
+ #ifdef FOO
+ #undef FOO
+ #endif
+
+ #define FOO "hello"
+ #else
+ #undef FOO
+ #endif
+
+
+ #ifdef TWO
+ #ifdef FOO
+ #undef FOO
+ #endif
+ #define FOO " "
+ #endif
+
+ #ifdef THREE
+ #ifdef FOO
+ #undef FOO
+ #endif
+
+ #define FOO "world"
+ #endif
+
+ #ifdef FOUR
+ #ifdef FOO
+ #undef FOO
+ #endif
+ #define FOO(a) foo = a
+ #endif
+#else
+
+int main (int argc, const char **argv)
+{
+ char *foo;
+
+ #define DEF_MACROS
+ #define ONE
+ #include "info-macros.c"
+ foo = FOO;
+
+ #define TWO
+ #include "info-macros.c"
+ foo = FOO;
+
+ #define THREE
+ #include "info-macros.c"
+ foo = FOO;
+
+ #undef THREE
+ #include "info-macros.c"
+ foo = FOO;
+
+ #undef TWO
+ #include "info-macros.c"
+ foo = FOO;
+
+ #undef ONE
+ #include "info-macros.c"
+ foo = (char *)0;
+
+ #define FOUR
+ #include "info-macros.c"
+ FOO ("the end.");
+
+ return 0;
+}
+#endif
+
diff --git a/gdb/testsuite/gdb.base/info-macros.exp b/gdb/testsuite/gdb.base/info-macros.exp
new file mode 100644
index 0000000..1229895
--- /dev/null
+++ b/gdb/testsuite/gdb.base/info-macros.exp
@@ -0,0 +1,188 @@
+# Copyright 2011 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+set testfile "info-macros"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+get_compiler_info ${binfile}
+if [test_compiler_info gcc*] {
+ lappend options additional_flags=-g3
+} else {
+ return -1
+}
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} $options] } {
+ return -1
+}
+
+if ![runto_main] {
+ untested ${testfile}.exp
+ return -1
+}
+
+set test "info definitions FOO"
+gdb_test "$test" ".*#define FOO \"hello\".*" "info definitions FOO 1"
+gdb_test "$test" ".*#define FOO \" \".*" "info definitions FOO 2"
+gdb_test "$test" ".*#define FOO \"world\".*" "info definitions FOO 3"
+gdb_test "$test" ".*#define FOO\\(a\\) foo = a.*" "info definitions FOO 4"
+
+
+set test "info macros"
+gdb_test_multiple "$test" $test {
+ -re ".*#define FOO \"hello\".*\r\n$gdb_prompt" {
+ pass $test
+ }
+ -re ".*#define TWO.*\r\n$gdb_prompt" {
+ fail $test
+ }
+ -re ".*#define THREE.*\r\n$gdb_prompt" {
+ fail $test
+ }
+ -re ".*#define FOUR.*\r\n$gdb_prompt" {
+ fail $test
+ }
+}
+gdb_test "$test" ".*#define ONE.*" "info macros 1.1"
+gdb_test "next" ".*" ""
+
+gdb_test_multiple "$test" $test {
+ -re ".*#define FOO \" \".*\r\n$gdb_prompt" {
+ pass $test
+ }
+ -re ".*#define THREE.*\r\n$gdb_prompt" {
+ fail $test
+ }
+ -re ".*#define FOUR.*\r\n$gdb_prompt" {
+ fail $test
+ }
+}
+gdb_test "$test" ".*#define FOO \" \".*" "info macros 2"
+gdb_test "$test" ".*#define ONE.*" "info macros 2.1"
+gdb_test "$test" ".*#define TWO.*" "info macros 2.2"
+gdb_test "next" ".*" ""
+
+gdb_test_multiple "$test" $test {
+ -re ".*#define FOO \"world\".*\r\n$gdb_prompt" {
+ pass $test
+ }
+ -re ".*#define FOUR.*\r\n$gdb_prompt" {
+ fail $test
+ }
+}
+gdb_test "$test" ".*#define ONE.*" "info macros 3.1"
+gdb_test "$test" ".*#define TWO.*" "info macros 3.2"
+gdb_test "$test" ".*#define THREE.*" "info macros 3.3"
+
+set test "info macros *\$pc"
+gdb_test_multiple "$test" $test {
+ -re ".*#define FOO \"world\".*\r\n$gdb_prompt" {
+ pass $test
+ }
+ -re ".*#define FOUR.*\r\n$gdb_prompt" {
+ fail $test
+ }
+}
+gdb_test "$test" ".*#define ONE.*" "info macros 5.1"
+gdb_test "$test" ".*#define TWO.*" "info macros 5.2"
+gdb_test "$test" ".*#define THREE.*" "info macros 5.3"
+gdb_test "next" ".*" ""
+
+set test "info macros"
+gdb_test_multiple "$test" $test {
+ -re ".*#define FOO \" \".*\r\n$gdb_prompt" {
+ pass $test
+ }
+ -re ".*#define THREE.*\r\n$gdb_prompt" {
+ fail $test
+ }
+ -re ".*#define FOUR.*\r\n$gdb_prompt" {
+ fail $test
+ }
+}
+gdb_test "$test" ".*#define ONE.*" "info macros 6.1"
+gdb_test "$test" ".*#define TWO.*" "info macros 6.2"
+gdb_test "next" ".*" ""
+gdb_test "next" ".*" ""
+
+gdb_test_multiple "$test" $test.0 {
+ -re ".*#define FOO \" \".*\r\n$gdb_prompt" {
+ pass $test.0
+ }
+ -re ".*#define FOO \"hello\".*\r\n$gdb_prompt" {
+ fail $test.0
+ }
+ -re ".*#define FOO \"world\".*\r\n$gdb_prompt" {
+ fail $test.0
+ }
+ -re ".*#define FOO\\(a\\) foo = a.*" {
+ fail $test.0
+ }
+ -re ".*#define ONE.*\r\n$gdb_prompt" {
+ fail $test.0
+ }
+ -re ".*#define TWO.*\r\n$gdb_prompt" {
+ fail $test.0
+ }
+ -re ".*#define THREE.*\r\n$gdb_prompt" {
+ fail $test.0
+ }
+ -re ".*#define FOUR.*\r\n$gdb_prompt" {
+ fail $test.0
+ }
+ -re ".*#define DEF_MACROS.*\r\n$gdb_prompt" {
+ pass $test.0
+ }
+}
+
+gdb_test "next" ".*" ""
+gdb_test "$test" ".*#define FOO\\(a\\) foo = a.*" "info macros 7.1"
+gdb_test_multiple "$test" $test.0 {
+ -re ".*#define FOO\\(a\\) foo = a.*" {
+ pass $test.0
+ }
+ -re ".*#define FOO \" \".*\r\n$gdb_prompt" {
+ fail $test.0
+ }
+ -re ".*#define FOO \"hello\".*\r\n$gdb_prompt" {
+ fail $test.0
+ }
+ -re ".*#define FOO \"world\".*\r\n$gdb_prompt" {
+ fail $test.0
+ }
+ -re ".*#define ONE.*\r\n$gdb_prompt" {
+ fail $test.0
+ }
+ -re ".*#define TWO.*\r\n$gdb_prompt" {
+ fail $test.0
+ }
+ -re ".*#define THREE.*\r\n$gdb_prompt" {
+ fail $test.0
+ }
+ -re ".*#define FOUR.*\r\n$gdb_prompt" {
+ fail $test.0
+ }
+ -re ".*#define DEF_MACROS.*\r\n$gdb_prompt" {
+ pass $test.0
+ }
+}
+
+set test "info macros info-macros.c:42"
+
+gdb_test "$test" ".*define DEF_MACROS.*" "$test.1"
+# info macros on the line where the #define or #include is
+# fails to find the macro defined (though it works on the next line.)
+setup_kfail "gdb/NNNN" *-*-*
+gdb_test "$test" ".*define ONE.*" "$test.2"
+
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [patch] PR 12999 info macros command. 2011-07-19 9:57 [patch] PR 12999 info macros command Matt Rice @ 2011-07-19 17:29 ` Tom Tromey 2011-07-20 2:06 ` Matt Rice 2011-07-20 17:24 ` Eli Zaretskii 1 sibling, 1 reply; 10+ messages in thread From: Tom Tromey @ 2011-07-19 17:29 UTC (permalink / raw) To: Matt Rice; +Cc: gdb-patches >>>>> "Matt" == Matt Rice <ratmice@gmail.com> writes: Matt> this patch adds 2 commands, Matt> info macros LINESPEC Matt> info definitions MACRO Matt> the PR only asks for the former, but the latter seemed possibly useful. Thanks, this is very nice. Matt> +@kindex info definitions Matt> +@cindex macro definition, showing Matt> +@cindex definition, showing a macro's Matt> +@item info definitions @var{macro} Matt> +Show all definitions of the macro named @var{macro}, in the current scope, Matt> +and describe the source location or compiler command-line where those Matt> +definitions were established. I didn't understand what this did from this explanation. I got confused because "in the current scope" would seem to restrict us to a single definition. I would reword it to say something about "all definitions of MACRO at or before the indicated line in the indicated source file", or something to that effect. Matt> +print_macro_definition (const char *name, Matt> + const struct macro_definition *d, Matt> + struct macro_source_file *file, Matt> + int line) Add an introductory comment. Matt> +static void Matt> +print_macro_callback (const char *name, const struct macro_definition *macro, Matt> + struct macro_source_file *source, int line, Matt> + void *user_data) Likewise. Matt> + add_cmd ("macros", no_class, info_macros_command, Matt> + _("Show the names of all macros at LINESPEC, or the current \ Matt> +scope."), Matt> + &infolist); Matt> + Matt> + add_cmd ("definitions", no_class, info_definitions_command, Matt> + _("Show all definitions of the macro named MACRO in the\n\ Matt> +current scope."), Matt> + &infolist); I think the "definitions" one shouldn't have a \n in the help string. The first sentence of the help is special, it should be on one line. Also the text for "definitions" needs updating, following the docs. I'd like it if the help for all new commands included a usage line, e.g.: Usage: info macros [LINESPEC] Matt> --- a/gdb/macrotab.h Matt> +++ b/gdb/macrotab.h Matt> @@ -311,6 +311,8 @@ struct macro_source_file *(macro_definition_location Matt> or macro_for_each_in_scope. */ Matt> typedef void (*macro_callback_fn) (const char *name, Matt> const struct macro_definition *definition, Matt> + struct macro_source_file *source, Matt> + int line, Matt> void *user_data); The comment just above this typedef needs an update. Matt> +if [test_compiler_info gcc*] { Matt> + lappend options additional_flags=-g3 Matt> +} else { Matt> + return -1 Matt> +} I think this should probably call 'untested' first. Matt> +set test "info definitions FOO" Matt> +gdb_test "$test" ".*#define FOO \"hello\".*" "info definitions FOO 1" Matt> +gdb_test "$test" ".*#define FOO \" \".*" "info definitions FOO 2" Matt> +gdb_test "$test" ".*#define FOO \"world\".*" "info definitions FOO 3" Matt> +gdb_test "$test" ".*#define FOO\\(a\\) foo = a.*" "info definitions FOO 4" As you mentioned on irc, this is weird. How about just a single test with one big regexp that matches all the output? You can easily construct the regexp in pieces if that makes it simpler. Matt> +# info macros on the line where the #define or #include is Matt> +# fails to find the macro defined (though it works on the next line.) Matt> +setup_kfail "gdb/NNNN" *-*-* Matt> +gdb_test "$test" ".*define ONE.*" "$test.2" I suppose technically the macro is not actually defined until the next line. I don't think it matters much though, since the #define line will never be executable anyhow. Tom ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] PR 12999 info macros command. 2011-07-19 17:29 ` Tom Tromey @ 2011-07-20 2:06 ` Matt Rice 2011-07-20 14:14 ` Tom Tromey 0 siblings, 1 reply; 10+ messages in thread From: Matt Rice @ 2011-07-20 2:06 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 4546 bytes --] On Tue, Jul 19, 2011 at 10:16 AM, Tom Tromey <tromey@redhat.com> wrote: >>>>>> "Matt" == Matt Rice <ratmice@gmail.com> writes: > > Matt> this patch adds 2 commands, > Matt> info macros LINESPEC > Matt> info definitions MACRO > > Matt> the PR only asks for the former, but the latter seemed possibly useful. > > Thanks, this is very nice. Thanks for reviewing, updated. > Matt> +@kindex info definitions > Matt> +@cindex macro definition, showing > Matt> +@cindex definition, showing a macro's > Matt> +@item info definitions @var{macro} > Matt> +Show all definitions of the macro named @var{macro}, in the current scope, > Matt> +and describe the source location or compiler command-line where those > Matt> +definitions were established. > > I didn't understand what this did from this explanation. > I got confused because "in the current scope" would seem to restrict us > to a single definition. > > I would reword it to say something about "all definitions of MACRO at or > before the indicated line in the indicated source file", or something to > that effect. I used 'current' instead of 'indicated'. because the command does not have an argument use to indicate, but a 'current state'. > Matt> +print_macro_definition (const char *name, > Matt> + const struct macro_definition *d, > Matt> + struct macro_source_file *file, > Matt> + int line) > > Add an introductory comment. Ahh, yes these also needed a 'falling rocks'. warning. > Matt> +static void > Matt> +print_macro_callback (const char *name, const struct macro_definition *macro, > Matt> + struct macro_source_file *source, int line, > Matt> + void *user_data) > > Likewise. > > Matt> + add_cmd ("macros", no_class, info_macros_command, > Matt> + _("Show the names of all macros at LINESPEC, or the current \ > Matt> +scope."), > Matt> + &infolist); > Matt> + > Matt> + add_cmd ("definitions", no_class, info_definitions_command, > Matt> + _("Show all definitions of the macro named MACRO in the\n\ > Matt> +current scope."), > Matt> + &infolist); > > I think the "definitions" one shouldn't have a \n in the help string. > The first sentence of the help is special, it should be on one line. > Also the text for "definitions" needs updating, following the docs. > > I'd like it if the help for all new commands included a usage line, > e.g.: > > Usage: info macros [LINESPEC] > > Matt> --- a/gdb/macrotab.h > Matt> +++ b/gdb/macrotab.h > Matt> @@ -311,6 +311,8 @@ struct macro_source_file *(macro_definition_location > Matt> or macro_for_each_in_scope. */ > Matt> typedef void (*macro_callback_fn) (const char *name, > Matt> const struct macro_definition *definition, > Matt> + struct macro_source_file *source, > Matt> + int line, > Matt> void *user_data); > > The comment just above this typedef needs an update. > > Matt> +if [test_compiler_info gcc*] { > Matt> + lappend options additional_flags=-g3 > Matt> +} else { > Matt> + return -1 > Matt> +} > > I think this should probably call 'untested' first. > > Matt> +set test "info definitions FOO" > Matt> +gdb_test "$test" ".*#define FOO \"hello\".*" "info definitions FOO 1" > Matt> +gdb_test "$test" ".*#define FOO \" \".*" "info definitions FOO 2" > Matt> +gdb_test "$test" ".*#define FOO \"world\".*" "info definitions FOO 3" > Matt> +gdb_test "$test" ".*#define FOO\\(a\\) foo = a.*" "info definitions FOO 4" > > As you mentioned on irc, this is weird. > > How about just a single test with one big regexp that matches all the > output? You can easily construct the regexp in pieces if that makes it > simpler. K, I updated the whole test like that, and also fixed some issues with it. > Matt> +# info macros on the line where the #define or #include is > Matt> +# fails to find the macro defined (though it works on the next line.) > Matt> +setup_kfail "gdb/NNNN" *-*-* > Matt> +gdb_test "$test" ".*define ONE.*" "$test.2" > > I suppose technically the macro is not actually defined until the next > line. I don't think it matters much though, since the #define line will > never be executable anyhow. Yeah, and if you are going to explicitly give it as a linespec, you are probably staring right at the macro definition to get its line number. So its kind of an awkward corner case. [-- Attachment #2: foo.diff --] [-- Type: application/octet-stream, Size: 16540 bytes --] diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 3a3a9fb..2d1821b 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -9590,9 +9590,25 @@ can be any string of tokens. @cindex macro definition, showing @cindex definition, showing a macro's @item info macro @var{macro} -Show the definition of the macro named @var{macro}, and describe the +Show the current definition of the macro named @var{macro}, and describe the source location or compiler command-line where that definition was established. +@kindex info macros +@cindex macro definition, showing +@cindex definition, showing a macro's +@item info macros @var{linespec} +Show all macro definitions at the location of @var{linespec}, and describe the +source location or compiler command-line where those definitions were +established. + +@kindex info definitions +@cindex macro definition, showing +@cindex definition, showing a macro's +@item info definitions @var{macro} +Show all definitions of the macro named @var{macro} at or before the current +line in the current source file, and describe the source location or +compiler command-line where those definitions were established. + @kindex macro define @cindex user-defined macros @cindex defining macros interactively diff --git a/gdb/macrocmd.c b/gdb/macrocmd.c index c77156a..7f605ba 100644 --- a/gdb/macrocmd.c +++ b/gdb/macrocmd.c @@ -117,7 +117,10 @@ macro_expand_once_command (char *exp, int from_tty) return; } +/* Outputs the include path of a macro starting at FILE and LINE to STREAM. + Care should be taken that this function does not cause any lookups into + the splay tree so that it can be safely used while iterating. */ static void show_pp_source_pos (struct ui_file *stream, struct macro_source_file *file, @@ -134,36 +137,27 @@ show_pp_source_pos (struct ui_file *stream, } } +/* Outputs a macro for human consumption, detailing the include path + and macro definition. NAME is the name of the macro. + D the definition. FILE the start of the include path, and LINE the + line number in FILE. + Care should be taken that this function does not cause any lookups into + the splay tree so that it can be safely used while iterating. */ static void -info_macro_command (char *name, int from_tty) +print_macro_definition (const char *name, + const struct macro_definition *d, + struct macro_source_file *file, + int line) { - struct macro_scope *ms = NULL; - struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms); - struct macro_definition *d; - - if (! name || ! *name) - error (_("You must follow the `info macro' command with the name" - " of the macro\n" - "whose definition you want to see.")); - - ms = default_macro_scope (); - if (! ms) - error (_("GDB has no preprocessor macro information for that code.")); - - d = macro_lookup_definition (ms->file, ms->line, name); - if (d) - { - int line; - struct macro_source_file *file - = macro_definition_location (ms->file, ms->line, name, &line); - fprintf_filtered (gdb_stdout, "Defined at "); show_pp_source_pos (gdb_stdout, file, line); + if (line != 0) fprintf_filtered (gdb_stdout, "#define %s", name); else fprintf_filtered (gdb_stdout, "-D%s", name); + if (d->kind == macro_function_like) { int i; @@ -177,10 +171,37 @@ info_macro_command (char *name, int from_tty) } fputs_filtered (")", gdb_stdout); } + if (line != 0) fprintf_filtered (gdb_stdout, " %s\n", d->replacement); else fprintf_filtered (gdb_stdout, "=%s\n", d->replacement); +} + +static void +info_macro_command (char *name, int from_tty) +{ + struct macro_scope *ms = NULL; + struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms); + struct macro_definition *d; + + if (! name || ! *name) + error (_("You must follow the `info macro' command with the name" + " of the macro\n" + "whose definition you want to see.")); + + ms = default_macro_scope (); + if (! ms) + error (_("GDB has no preprocessor macro information for that code.")); + + d = macro_lookup_definition (ms->file, ms->line, name); + if (d) + { + int line; + struct macro_source_file *file + = macro_definition_location (ms->file, ms->line, name, &line); + + print_macro_definition (name, d, file, line); } else { @@ -194,6 +215,64 @@ info_macro_command (char *name, int from_tty) do_cleanups (cleanup_chain); } +/* A callback function for usage with macro_for_each and friends. + If USER_DATA is null all macros will be printed. + Otherwise USER_DATA is considered to be a string, printing + only macros who's NAME matches USER_DATA. Other arguments are + routed to print_macro_definition. */ +static void +print_macro_callback (const char *name, const struct macro_definition *macro, + struct macro_source_file *source, int line, + void *user_data) +{ + if (! user_data || strcmp (user_data, name) == 0) + print_macro_definition (name, macro, source, line); +} + +/* Implementation of the "info definitions" command. */ +static void +info_definitions_command (char *name, int from_tty) +{ + struct macro_scope *ms = NULL; + struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms); + + if (! name || ! *name) + error (_("The `info definitions' command requires a macro name as an \ +argument.\n" + "Usage: info definitions MACRO\n")); + + ms = default_macro_scope (); + + if (! ms || ! ms->file || ! ms->file->table) + error (_("GDB has no preprocessor macro information for that code.")); + + macro_for_each (ms->file->table, print_macro_callback, name); + do_cleanups (cleanup_chain); +} + +/* Implementation of the "info macros" command. */ +static void +info_macros_command (char *args, int from_tty) +{ + struct macro_scope *ms = NULL; + struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms); + + if (args == NULL) + ms = default_macro_scope (); + else + { + struct symtabs_and_lines sals = decode_line_spec (args, 0); + + if (sals.nelts) + ms = sal_macro_scope (sals.sals[0]); + } + + if (! ms || ! ms->file || ! ms->file->table) + error (_("GDB has no preprocessor macro information for that code.")); + + macro_for_each_in_scope (ms->file, ms->line, print_macro_callback, NULL); + do_cleanups (cleanup_chain); +} \f /* User-defined macros. */ @@ -359,6 +438,7 @@ macro_undef_command (char *exp, int from_tty) static void print_one_macro (const char *name, const struct macro_definition *macro, + struct macro_source_file *source, int line, void *ignore) { fprintf_filtered (gdb_stdout, "macro define %s", name); @@ -382,7 +462,6 @@ macro_list_command (char *exp, int from_tty) macro_for_each (macro_user_macros, print_one_macro, NULL); } - \f /* Initializing the `macrocmd' module. */ @@ -420,6 +499,18 @@ expression work together to yield a pre-processed expression."), _("Show the definition of MACRO, and its source location."), &infolist); + add_cmd ("macros", no_class, info_macros_command, + _("Show the definitions of all macros at LINESPEC, or the current \ +source location.\n\ +Usage: info source [LINESPEC]"), + &infolist); + + add_cmd ("definitions", no_class, info_definitions_command, + _("Show all definitions of MACRO defined before the current\ + source location.\n\ +Usage: info definitions MACRO"), + &infolist); + add_cmd ("define", no_class, macro_define_command, _("\ Define a new C/C++ preprocessor macro.\n\ The GDB command `macro define DEFINITION' is equivalent to placing a\n\ diff --git a/gdb/macrotab.c b/gdb/macrotab.c index cba285d..efcf835 100644 --- a/gdb/macrotab.c +++ b/gdb/macrotab.c @@ -913,7 +913,8 @@ foreach_macro (splay_tree_node node, void *arg) struct macro_key *key = (struct macro_key *) node->key; struct macro_definition *def = (struct macro_definition *) node->value; - (*datum->fn) (key->name, def, datum->user_data); + (*datum->fn) (key->name, def, key->start_file, key->start_line, + datum->user_data); return 0; } @@ -945,7 +946,8 @@ foreach_macro_in_scope (splay_tree_node node, void *info) && (!key->end_file || compare_locations (key->end_file, key->end_line, datum->file, datum->line) >= 0)) - (*datum->fn) (key->name, def, datum->user_data); + (*datum->fn) (key->name, def, key->start_file, key->start_line, + datum->user_data); return 0; } diff --git a/gdb/macrotab.h b/gdb/macrotab.h index d2b2b63..a10351a 100644 --- a/gdb/macrotab.h +++ b/gdb/macrotab.h @@ -306,11 +306,14 @@ struct macro_source_file *(macro_definition_location int *definition_line)); /* Callback function when walking a macro table. NAME is the name of - the macro, and DEFINITION is the definition. USER_DATA is an - arbitrary pointer which is passed by the caller to macro_for_each - or macro_for_each_in_scope. */ + the macro, and DEFINITION is the definition. SOURCE is the file at the + start of the include path, and LINE is the line number of the SOURCE file + where the macro was defined. USER_DATA is an arbitrary pointer which is + passed by the caller to macro_for_each or macro_for_each_in_scope. */ typedef void (*macro_callback_fn) (const char *name, const struct macro_definition *definition, + struct macro_source_file *source, + int line, void *user_data); /* Call the function FN for each macro in the macro table TABLE. diff --git a/gdb/symtab.c b/gdb/symtab.c index b792081..9447bd9 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -3771,6 +3771,7 @@ struct add_name_data This adds a macro's name to the current completion list. */ static void add_macro_name (const char *name, const struct macro_definition *ignore, + struct macro_source_file *ignore2, int ignore3, void *user_data) { struct add_name_data *datum = (struct add_name_data *) user_data; diff --git a/gdb/testsuite/gdb.base/info-macros.c b/gdb/testsuite/gdb.base/info-macros.c new file mode 100644 index 0000000..f874156 --- /dev/null +++ b/gdb/testsuite/gdb.base/info-macros.c @@ -0,0 +1,73 @@ +#ifdef DEF_MACROS + + #ifdef ONE + #ifdef FOO + #undef FOO + #endif + + #define FOO "hello" + #else + #undef FOO + #endif + + + #ifdef TWO + #ifdef FOO + #undef FOO + #endif + #define FOO " " + #endif + + #ifdef THREE + #ifdef FOO + #undef FOO + #endif + + #define FOO "world" + #endif + + #ifdef FOUR + #ifdef FOO + #undef FOO + #endif + #define FOO(a) foo = a + #endif +#else + +int main (int argc, const char **argv) +{ + char *foo; + + #define DEF_MACROS + #define ONE + #include "info-macros.c" + foo = FOO; + + #define TWO + #include "info-macros.c" + foo = FOO; + + #define THREE + #include "info-macros.c" + foo = FOO; + + #undef THREE + #include "info-macros.c" + foo = FOO; + + #undef TWO + #include "info-macros.c" + foo = FOO; + + #undef ONE + #include "info-macros.c" + foo = (char *)0; + + #define FOUR + #include "info-macros.c" + FOO ("the end."); + + return 0; +} +#endif + diff --git a/gdb/testsuite/gdb.base/info-macros.exp b/gdb/testsuite/gdb.base/info-macros.exp new file mode 100644 index 0000000..bd5a870 --- /dev/null +++ b/gdb/testsuite/gdb.base/info-macros.exp @@ -0,0 +1,202 @@ +# Copyright 2011 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +set testfile "info-macros" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +get_compiler_info ${binfile} +if [test_compiler_info gcc*] { + lappend options additional_flags=-g3 +} else { + untested ${testfile}.exp + return -1 +} + +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} $options] } { + untested ${testfile}.exp + return -1 +} + +if ![runto_main] { + untested ${testfile}.exp + return -1 +} + +set test "info definitions FOO" +set r1 ".*#define FOO \"hello\"" +set r2 ".*#define FOO \" \"" +set r3 ".*#define FOO \"world\"" +set r4 ".*#define FOO\\(a\\) foo = a" +set testname "$test 1" +gdb_test "$test" "$r1$r2$r3$r4" "$testname" + + +set test "info macros" +set r1 ".*#define FOO \"hello\"" +set r2 ".*#define ONE" +set r3 ".*\r\n$gdb_prompt" +set testname "$test 2" +gdb_test_multiple "$test" $testname { + -re "$r1$r2$r3" { + pass $testname + } + -re ".*#define TWO.*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define THREE.*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define FOUR.*\r\n$gdb_prompt" { + fail $testname + } +} +gdb_test "next" ".*" "" + +set r1 ".*#define FOO \" \"" +set r2 ".*#define ONE" +set r3 ".*#define TWO" +set r4 ".*\r\n$gdb_prompt" +set testname "$test 4" +gdb_test_multiple "$test" $testname { + -re ".*#define THREE.*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define FOUR.*\r\n$gdb_prompt" { + fail $testname + } + -re "$r1$r2$r3$r4" { + pass $testname + } +} +gdb_test "next" ".*" "" + +# in alpabetical order... +set r1 ".*#define FOO \"world\"" +set r2 ".*#define ONE" +set r3 ".*#define THREE" +set r4 ".*#define TWO" +set r5 ".*\r\n$gdb_prompt" +set testname "$test 4" +gdb_test_multiple "$test" $testname { + -re ".*#define FOUR.*\r\n$gdb_prompt" { + fail $testname + } + -re "$r1$r2$r3$r4$r5" { + pass $testname + } +} +# same as above with a linespec. +set test "info macros *\$pc" +gdb_test_multiple "$test" $test { + -re ".*#define FOUR.*\r\n$gdb_prompt" { + fail $test + } + -re "$r1$r2$r3$r4$r5" { + pass $test + } +} +gdb_test "next" ".*" "" + +set r1 ".*#define FOO \" \"" +set r2 ".*#define ONE" +set r3 ".*#define TWO." +set r4 ".*\r\n$gdb_prompt" +set testname "$test 5" +set test "info macros" +gdb_test_multiple "$test" $test { + -re ".*#define THREE.*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define FOUR.*\r\n$gdb_prompt" { + fail $testname + } + -re "$r1$r2$r3$r4" { + pass $testname + } +} +gdb_test "next" ".*" "" +gdb_test "next" ".*" "" + +set r1 ".*#define DEF_MACROS" +set r2 ".*\r\n$gdb_prompt" +set testname "$test 6" +gdb_test_multiple "$test" $testname { + -re ".*#define FOO \" \".*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define FOO \"hello\".*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define FOO \"world\".*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define FOO\\(a\\) foo = a.*" { + fail $testname + } + -re ".*#define ONE.*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define TWO.*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define THREE.*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define FOUR.*\r\n$gdb_prompt" { + fail $testname + } + -re "$r1$r2" { + pass $testname + } +} + +gdb_test "next" ".*" "" +set r1 ".*#define DEF_MACROS" +set r2 ".*#define FOO\\(a\\) foo = a" +set r3 ".*#define FOUR" +set r4 ".*\r\n$gdb_prompt" +set testname "$test 7" +gdb_test_multiple "$test" $testname { + -re ".*#define FOO \" \".*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define FOO \"hello\".*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define FOO \"world\".*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define ONE.*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define TWO.*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define THREE.*\r\n$gdb_prompt" { + fail $testname + } + -re "$r1$r2$r3$r4" { + pass $testname + } +} + +set test "info macros info-macros.c:42" + +set r1 ".*define DEF_MACROS" +set r2 ".*define ONE" +# info macros on the line where the #define or #include is +# fails to find the macro defined (though it works on the next line.) +setup_kfail "gdb/NNNN" *-*-* +gdb_test "$test" "$r1$r2" "$test" ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] PR 12999 info macros command. 2011-07-20 2:06 ` Matt Rice @ 2011-07-20 14:14 ` Tom Tromey 0 siblings, 0 replies; 10+ messages in thread From: Tom Tromey @ 2011-07-20 14:14 UTC (permalink / raw) To: Matt Rice; +Cc: gdb-patches >>>>> "Matt" == Matt Rice <ratmice@gmail.com> writes: Matt> Thanks for reviewing, updated. The code bits are ok. Thanks! Tom ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] PR 12999 info macros command. 2011-07-19 9:57 [patch] PR 12999 info macros command Matt Rice 2011-07-19 17:29 ` Tom Tromey @ 2011-07-20 17:24 ` Eli Zaretskii 2011-07-21 6:47 ` Matt Rice 1 sibling, 1 reply; 10+ messages in thread From: Eli Zaretskii @ 2011-07-20 17:24 UTC (permalink / raw) To: Matt Rice; +Cc: gdb-patches > Date: Mon, 18 Jul 2011 23:57:25 -0700 > From: Matt Rice <ratmice@gmail.com> > > this patch adds 2 commands, > info macros LINESPEC > info definitions MACRO Thanks. A few minor comments and a question. > +@cindex definition, showing a macro's That sounds awkward. Suggest "@cindex definition of a macro, showing" instead. > +@item info macros @var{linespec} > +Show all macro definitions at the location of @var{linespec}, and describe the Suggest a slight rewording: Show all macro definitions that are in effect at the location specified by @var{linespec}, and describe ... > +@cindex definition, showing a macro's It's not useful to have identical index entries so close to one another. I suggest to remove the second one. > +Show all definitions of the macro named @var{macro}, in the current scope, It might be better to say "... definitions of the named @var{macro} ...". Also, what is the "scope" of a macro? ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] PR 12999 info macros command. 2011-07-20 17:24 ` Eli Zaretskii @ 2011-07-21 6:47 ` Matt Rice 2011-07-21 10:22 ` Eli Zaretskii 2011-07-21 14:07 ` Tom Tromey 0 siblings, 2 replies; 10+ messages in thread From: Matt Rice @ 2011-07-21 6:47 UTC (permalink / raw) To: Eli Zaretskii; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 1671 bytes --] On Wed, Jul 20, 2011 at 10:04 AM, Eli Zaretskii <eliz@gnu.org> wrote: >> Date: Mon, 18 Jul 2011 23:57:25 -0700 >> From: Matt Rice <ratmice@gmail.com> >> >> this patch adds 2 commands, >> info macros LINESPEC >> info definitions MACRO > > Thanks. A few minor comments and a question. > >> +@cindex definition, showing a macro's > > That sounds awkward. Suggest "@cindex definition of a macro, showing" > instead. This actually came from the existing 'info macro'. command, I updated that. >> +@item info macros @var{linespec} >> +Show all macro definitions at the location of @var{linespec}, and describe the > > Suggest a slight rewording: > > Show all macro definitions that are in effect at the location > specified by @var{linespec}, and describe ... k. >> +@cindex definition, showing a macro's > > It's not useful to have identical index entries so close to one > another. I suggest to remove the second one. ahh, I see. >> +Show all definitions of the macro named @var{macro}, in the current scope, > > It might be better to say "... definitions of the named @var{macro} ...". k. > Also, what is the "scope" of a macro? to answer your question scope of a macro is all lines between #define and #undef, not extending beyond the boundry of a compilation unit. Its the wrong word though, and not what 'info definitions' does, neither was my second patch correct. because 'info definitions' looks throughout a compilation unit. Updated the docs, and the 'help' command text for 'info definitions'. I added @cindex macros, from debug info so it would be near the existing @cindex macros, user-defined [-- Attachment #2: foo.diff --] [-- Type: application/octet-stream, Size: 10093 bytes --] diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 3a3a9fb..49b467d 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -9588,11 +9588,24 @@ can be any string of tokens. @kindex info macro @cindex macro definition, showing -@cindex definition, showing a macro's +@cindex definition of a macro, showing +@cindex macros, from debug info @item info macro @var{macro} -Show the definition of the macro named @var{macro}, and describe the +Show the current definition of the named @var{macro}, and describe the source location or compiler command-line where that definition was established. +@kindex info macros +@item info macros @var{linespec} +Show all macro definitions that are in effect at the location specified +by @var{linespec}, and describe the source location or compiler +command-line where those definitions were established. + +@kindex info definitions +@item info definitions @var{macro} +Show all definitions of the named @var{macro} that are defined in the current +compilation unit, and describe the source location or compiler command-line +where those definitions were established. + @kindex macro define @cindex user-defined macros @cindex defining macros interactively diff --git a/gdb/macrocmd.c b/gdb/macrocmd.c index c77156a..b8f2746 100644 --- a/gdb/macrocmd.c +++ b/gdb/macrocmd.c @@ -117,7 +117,10 @@ macro_expand_once_command (char *exp, int from_tty) return; } +/* Outputs the include path of a macro starting at FILE and LINE to STREAM. + Care should be taken that this function does not cause any lookups into + the splay tree so that it can be safely used while iterating. */ static void show_pp_source_pos (struct ui_file *stream, struct macro_source_file *file, @@ -134,36 +137,27 @@ show_pp_source_pos (struct ui_file *stream, } } +/* Outputs a macro for human consumption, detailing the include path + and macro definition. NAME is the name of the macro. + D the definition. FILE the start of the include path, and LINE the + line number in FILE. + Care should be taken that this function does not cause any lookups into + the splay tree so that it can be safely used while iterating. */ static void -info_macro_command (char *name, int from_tty) +print_macro_definition (const char *name, + const struct macro_definition *d, + struct macro_source_file *file, + int line) { - struct macro_scope *ms = NULL; - struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms); - struct macro_definition *d; - - if (! name || ! *name) - error (_("You must follow the `info macro' command with the name" - " of the macro\n" - "whose definition you want to see.")); - - ms = default_macro_scope (); - if (! ms) - error (_("GDB has no preprocessor macro information for that code.")); - - d = macro_lookup_definition (ms->file, ms->line, name); - if (d) - { - int line; - struct macro_source_file *file - = macro_definition_location (ms->file, ms->line, name, &line); - fprintf_filtered (gdb_stdout, "Defined at "); show_pp_source_pos (gdb_stdout, file, line); + if (line != 0) fprintf_filtered (gdb_stdout, "#define %s", name); else fprintf_filtered (gdb_stdout, "-D%s", name); + if (d->kind == macro_function_like) { int i; @@ -177,10 +171,37 @@ info_macro_command (char *name, int from_tty) } fputs_filtered (")", gdb_stdout); } + if (line != 0) fprintf_filtered (gdb_stdout, " %s\n", d->replacement); else fprintf_filtered (gdb_stdout, "=%s\n", d->replacement); +} + +static void +info_macro_command (char *name, int from_tty) +{ + struct macro_scope *ms = NULL; + struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms); + struct macro_definition *d; + + if (! name || ! *name) + error (_("You must follow the `info macro' command with the name" + " of the macro\n" + "whose definition you want to see.")); + + ms = default_macro_scope (); + if (! ms) + error (_("GDB has no preprocessor macro information for that code.")); + + d = macro_lookup_definition (ms->file, ms->line, name); + if (d) + { + int line; + struct macro_source_file *file + = macro_definition_location (ms->file, ms->line, name, &line); + + print_macro_definition (name, d, file, line); } else { @@ -194,6 +215,64 @@ info_macro_command (char *name, int from_tty) do_cleanups (cleanup_chain); } +/* A callback function for usage with macro_for_each and friends. + If USER_DATA is null all macros will be printed. + Otherwise USER_DATA is considered to be a string, printing + only macros who's NAME matches USER_DATA. Other arguments are + routed to print_macro_definition. */ +static void +print_macro_callback (const char *name, const struct macro_definition *macro, + struct macro_source_file *source, int line, + void *user_data) +{ + if (! user_data || strcmp (user_data, name) == 0) + print_macro_definition (name, macro, source, line); +} + +/* Implementation of the "info definitions" command. */ +static void +info_definitions_command (char *name, int from_tty) +{ + struct macro_scope *ms = NULL; + struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms); + + if (! name || ! *name) + error (_("The `info definitions' command requires a macro name as an \ +argument.\n" + "Usage: info definitions MACRO\n")); + + ms = default_macro_scope (); + + if (! ms || ! ms->file || ! ms->file->table) + error (_("GDB has no preprocessor macro information for that code.")); + + macro_for_each (ms->file->table, print_macro_callback, name); + do_cleanups (cleanup_chain); +} + +/* Implementation of the "info macros" command. */ +static void +info_macros_command (char *args, int from_tty) +{ + struct macro_scope *ms = NULL; + struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms); + + if (args == NULL) + ms = default_macro_scope (); + else + { + struct symtabs_and_lines sals = decode_line_spec (args, 0); + + if (sals.nelts) + ms = sal_macro_scope (sals.sals[0]); + } + + if (! ms || ! ms->file || ! ms->file->table) + error (_("GDB has no preprocessor macro information for that code.")); + + macro_for_each_in_scope (ms->file, ms->line, print_macro_callback, NULL); + do_cleanups (cleanup_chain); +} \f /* User-defined macros. */ @@ -359,6 +438,7 @@ macro_undef_command (char *exp, int from_tty) static void print_one_macro (const char *name, const struct macro_definition *macro, + struct macro_source_file *source, int line, void *ignore) { fprintf_filtered (gdb_stdout, "macro define %s", name); @@ -382,7 +462,6 @@ macro_list_command (char *exp, int from_tty) macro_for_each (macro_user_macros, print_one_macro, NULL); } - \f /* Initializing the `macrocmd' module. */ @@ -420,6 +499,18 @@ expression work together to yield a pre-processed expression."), _("Show the definition of MACRO, and its source location."), &infolist); + add_cmd ("macros", no_class, info_macros_command, + _("Show the definitions of all macros at LINESPEC, or the current \ +source location.\n\ +Usage: info source [LINESPEC]"), + &infolist); + + add_cmd ("definitions", no_class, info_definitions_command, + _("Show all definitions of MACRO defined int the current \ + compilation unit.\n\ +Usage: info definitions MACRO"), + &infolist); + add_cmd ("define", no_class, macro_define_command, _("\ Define a new C/C++ preprocessor macro.\n\ The GDB command `macro define DEFINITION' is equivalent to placing a\n\ diff --git a/gdb/macrotab.c b/gdb/macrotab.c index cba285d..efcf835 100644 --- a/gdb/macrotab.c +++ b/gdb/macrotab.c @@ -913,7 +913,8 @@ foreach_macro (splay_tree_node node, void *arg) struct macro_key *key = (struct macro_key *) node->key; struct macro_definition *def = (struct macro_definition *) node->value; - (*datum->fn) (key->name, def, datum->user_data); + (*datum->fn) (key->name, def, key->start_file, key->start_line, + datum->user_data); return 0; } @@ -945,7 +946,8 @@ foreach_macro_in_scope (splay_tree_node node, void *info) && (!key->end_file || compare_locations (key->end_file, key->end_line, datum->file, datum->line) >= 0)) - (*datum->fn) (key->name, def, datum->user_data); + (*datum->fn) (key->name, def, key->start_file, key->start_line, + datum->user_data); return 0; } diff --git a/gdb/macrotab.h b/gdb/macrotab.h index d2b2b63..a10351a 100644 --- a/gdb/macrotab.h +++ b/gdb/macrotab.h @@ -306,11 +306,14 @@ struct macro_source_file *(macro_definition_location int *definition_line)); /* Callback function when walking a macro table. NAME is the name of - the macro, and DEFINITION is the definition. USER_DATA is an - arbitrary pointer which is passed by the caller to macro_for_each - or macro_for_each_in_scope. */ + the macro, and DEFINITION is the definition. SOURCE is the file at the + start of the include path, and LINE is the line number of the SOURCE file + where the macro was defined. USER_DATA is an arbitrary pointer which is + passed by the caller to macro_for_each or macro_for_each_in_scope. */ typedef void (*macro_callback_fn) (const char *name, const struct macro_definition *definition, + struct macro_source_file *source, + int line, void *user_data); /* Call the function FN for each macro in the macro table TABLE. diff --git a/gdb/symtab.c b/gdb/symtab.c index b792081..9447bd9 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -3771,6 +3771,7 @@ struct add_name_data This adds a macro's name to the current completion list. */ static void add_macro_name (const char *name, const struct macro_definition *ignore, + struct macro_source_file *ignore2, int ignore3, void *user_data) { struct add_name_data *datum = (struct add_name_data *) user_data; ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] PR 12999 info macros command. 2011-07-21 6:47 ` Matt Rice @ 2011-07-21 10:22 ` Eli Zaretskii 2011-07-21 14:07 ` Tom Tromey 1 sibling, 0 replies; 10+ messages in thread From: Eli Zaretskii @ 2011-07-21 10:22 UTC (permalink / raw) To: Matt Rice; +Cc: gdb-patches > Date: Wed, 20 Jul 2011 15:01:10 -0700 > From: Matt Rice <ratmice@gmail.com> > Cc: gdb-patches@sourceware.org > > Updated the docs, and the 'help' command text for 'info definitions'. > I added @cindex macros, from debug info > so it would be near the existing @cindex macros, user-defined The documentation part of this patch is approved. Thanks. > + add_cmd ("definitions", no_class, info_definitions_command, > + _("Show all definitions of MACRO defined int the current \ > + compilation unit.\n\ "all definitions ... defined" uses the word redundantly. Suggest to remove the "defined" part. Also, there's a typo ("int" should be "in"). ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] PR 12999 info macros command. 2011-07-21 6:47 ` Matt Rice 2011-07-21 10:22 ` Eli Zaretskii @ 2011-07-21 14:07 ` Tom Tromey 2011-07-21 15:56 ` Matt Rice 1 sibling, 1 reply; 10+ messages in thread From: Tom Tromey @ 2011-07-21 14:07 UTC (permalink / raw) To: Matt Rice; +Cc: Eli Zaretskii, gdb-patches >>>>> "Matt" == Matt Rice <ratmice@gmail.com> writes: Matt> Updated the docs, and the 'help' command text for 'info definitions'. Matt> I added @cindex macros, from debug info Matt> so it would be near the existing @cindex macros, user-defined Two more nits... Matt> + if (! name || ! *name) Matt> + error (_("The `info definitions' command requires a macro name as an \ Matt> +argument.\n" Matt> + "Usage: info definitions MACRO\n")); I think "usage" lines should be in the help text, but not in errors. So, please remove it here. Also, errors should not end with \n. Matt> + add_cmd ("macros", no_class, info_macros_command, Matt> + _("Show the definitions of all macros at LINESPEC, or the current \ Matt> +source location.\n\ Matt> +Usage: info source [LINESPEC]"), Typo: s/source/macros/ This is ok with those changes. Tom ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] PR 12999 info macros command. 2011-07-21 14:07 ` Tom Tromey @ 2011-07-21 15:56 ` Matt Rice 2011-07-21 16:13 ` Pedro Alves 0 siblings, 1 reply; 10+ messages in thread From: Matt Rice @ 2011-07-21 15:56 UTC (permalink / raw) To: Tom Tromey; +Cc: Eli Zaretskii, gdb-patches [-- Attachment #1: Type: text/plain, Size: 127 bytes --] On Thu, Jul 21, 2011 at 7:03 AM, Tom Tromey <tromey@redhat.com> wrote: > This is ok with those changes. commited as attached. [-- Attachment #2: foo.diff --] [-- Type: application/octet-stream, Size: 16436 bytes --] diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 3a3a9fb..49b467d 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -9588,11 +9588,24 @@ can be any string of tokens. @kindex info macro @cindex macro definition, showing -@cindex definition, showing a macro's +@cindex definition of a macro, showing +@cindex macros, from debug info @item info macro @var{macro} -Show the definition of the macro named @var{macro}, and describe the +Show the current definition of the named @var{macro}, and describe the source location or compiler command-line where that definition was established. +@kindex info macros +@item info macros @var{linespec} +Show all macro definitions that are in effect at the location specified +by @var{linespec}, and describe the source location or compiler +command-line where those definitions were established. + +@kindex info definitions +@item info definitions @var{macro} +Show all definitions of the named @var{macro} that are defined in the current +compilation unit, and describe the source location or compiler command-line +where those definitions were established. + @kindex macro define @cindex user-defined macros @cindex defining macros interactively diff --git a/gdb/macrocmd.c b/gdb/macrocmd.c index c77156a..d1ac7fa 100644 --- a/gdb/macrocmd.c +++ b/gdb/macrocmd.c @@ -117,7 +117,10 @@ macro_expand_once_command (char *exp, int from_tty) return; } +/* Outputs the include path of a macro starting at FILE and LINE to STREAM. + Care should be taken that this function does not cause any lookups into + the splay tree so that it can be safely used while iterating. */ static void show_pp_source_pos (struct ui_file *stream, struct macro_source_file *file, @@ -134,36 +137,27 @@ show_pp_source_pos (struct ui_file *stream, } } +/* Outputs a macro for human consumption, detailing the include path + and macro definition. NAME is the name of the macro. + D the definition. FILE the start of the include path, and LINE the + line number in FILE. + Care should be taken that this function does not cause any lookups into + the splay tree so that it can be safely used while iterating. */ static void -info_macro_command (char *name, int from_tty) +print_macro_definition (const char *name, + const struct macro_definition *d, + struct macro_source_file *file, + int line) { - struct macro_scope *ms = NULL; - struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms); - struct macro_definition *d; - - if (! name || ! *name) - error (_("You must follow the `info macro' command with the name" - " of the macro\n" - "whose definition you want to see.")); - - ms = default_macro_scope (); - if (! ms) - error (_("GDB has no preprocessor macro information for that code.")); - - d = macro_lookup_definition (ms->file, ms->line, name); - if (d) - { - int line; - struct macro_source_file *file - = macro_definition_location (ms->file, ms->line, name, &line); - fprintf_filtered (gdb_stdout, "Defined at "); show_pp_source_pos (gdb_stdout, file, line); + if (line != 0) fprintf_filtered (gdb_stdout, "#define %s", name); else fprintf_filtered (gdb_stdout, "-D%s", name); + if (d->kind == macro_function_like) { int i; @@ -177,10 +171,37 @@ info_macro_command (char *name, int from_tty) } fputs_filtered (")", gdb_stdout); } + if (line != 0) fprintf_filtered (gdb_stdout, " %s\n", d->replacement); else fprintf_filtered (gdb_stdout, "=%s\n", d->replacement); +} + +static void +info_macro_command (char *name, int from_tty) +{ + struct macro_scope *ms = NULL; + struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms); + struct macro_definition *d; + + if (! name || ! *name) + error (_("You must follow the `info macro' command with the name" + " of the macro\n" + "whose definition you want to see.")); + + ms = default_macro_scope (); + if (! ms) + error (_("GDB has no preprocessor macro information for that code.")); + + d = macro_lookup_definition (ms->file, ms->line, name); + if (d) + { + int line; + struct macro_source_file *file + = macro_definition_location (ms->file, ms->line, name, &line); + + print_macro_definition (name, d, file, line); } else { @@ -194,6 +215,63 @@ info_macro_command (char *name, int from_tty) do_cleanups (cleanup_chain); } +/* A callback function for usage with macro_for_each and friends. + If USER_DATA is null all macros will be printed. + Otherwise USER_DATA is considered to be a string, printing + only macros who's NAME matches USER_DATA. Other arguments are + routed to print_macro_definition. */ +static void +print_macro_callback (const char *name, const struct macro_definition *macro, + struct macro_source_file *source, int line, + void *user_data) +{ + if (! user_data || strcmp (user_data, name) == 0) + print_macro_definition (name, macro, source, line); +} + +/* Implementation of the "info definitions" command. */ +static void +info_definitions_command (char *name, int from_tty) +{ + struct macro_scope *ms = NULL; + struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms); + + if (! name || ! *name) + error (_("The `info definitions' command requires a macro name as an \ +argument.")); + + ms = default_macro_scope (); + + if (! ms || ! ms->file || ! ms->file->table) + error (_("GDB has no preprocessor macro information for that code.")); + + macro_for_each (ms->file->table, print_macro_callback, name); + do_cleanups (cleanup_chain); +} + +/* Implementation of the "info macros" command. */ +static void +info_macros_command (char *args, int from_tty) +{ + struct macro_scope *ms = NULL; + struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms); + + if (args == NULL) + ms = default_macro_scope (); + else + { + struct symtabs_and_lines sals = decode_line_spec (args, 0); + + if (sals.nelts) + ms = sal_macro_scope (sals.sals[0]); + } + + if (! ms || ! ms->file || ! ms->file->table) + error (_("GDB has no preprocessor macro information for that code.")); + + macro_for_each_in_scope (ms->file, ms->line, print_macro_callback, NULL); + do_cleanups (cleanup_chain); +} \f /* User-defined macros. */ @@ -359,6 +437,7 @@ macro_undef_command (char *exp, int from_tty) static void print_one_macro (const char *name, const struct macro_definition *macro, + struct macro_source_file *source, int line, void *ignore) { fprintf_filtered (gdb_stdout, "macro define %s", name); @@ -382,7 +461,6 @@ macro_list_command (char *exp, int from_tty) macro_for_each (macro_user_macros, print_one_macro, NULL); } - \f /* Initializing the `macrocmd' module. */ @@ -420,6 +498,17 @@ expression work together to yield a pre-processed expression."), _("Show the definition of MACRO, and its source location."), &infolist); + add_cmd ("macros", no_class, info_macros_command, + _("Show the definitions of all macros at LINESPEC, or the current \ +source location.\n\ +Usage: info macros [LINESPEC]"), + &infolist); + + add_cmd ("definitions", no_class, info_definitions_command, + _("Show all definitions of MACRO in the current compilation unit.\n\ +Usage: info definitions MACRO"), + &infolist); + add_cmd ("define", no_class, macro_define_command, _("\ Define a new C/C++ preprocessor macro.\n\ The GDB command `macro define DEFINITION' is equivalent to placing a\n\ diff --git a/gdb/macrotab.c b/gdb/macrotab.c index cba285d..efcf835 100644 --- a/gdb/macrotab.c +++ b/gdb/macrotab.c @@ -913,7 +913,8 @@ foreach_macro (splay_tree_node node, void *arg) struct macro_key *key = (struct macro_key *) node->key; struct macro_definition *def = (struct macro_definition *) node->value; - (*datum->fn) (key->name, def, datum->user_data); + (*datum->fn) (key->name, def, key->start_file, key->start_line, + datum->user_data); return 0; } @@ -945,7 +946,8 @@ foreach_macro_in_scope (splay_tree_node node, void *info) && (!key->end_file || compare_locations (key->end_file, key->end_line, datum->file, datum->line) >= 0)) - (*datum->fn) (key->name, def, datum->user_data); + (*datum->fn) (key->name, def, key->start_file, key->start_line, + datum->user_data); return 0; } diff --git a/gdb/macrotab.h b/gdb/macrotab.h index d2b2b63..a10351a 100644 --- a/gdb/macrotab.h +++ b/gdb/macrotab.h @@ -306,11 +306,14 @@ struct macro_source_file *(macro_definition_location int *definition_line)); /* Callback function when walking a macro table. NAME is the name of - the macro, and DEFINITION is the definition. USER_DATA is an - arbitrary pointer which is passed by the caller to macro_for_each - or macro_for_each_in_scope. */ + the macro, and DEFINITION is the definition. SOURCE is the file at the + start of the include path, and LINE is the line number of the SOURCE file + where the macro was defined. USER_DATA is an arbitrary pointer which is + passed by the caller to macro_for_each or macro_for_each_in_scope. */ typedef void (*macro_callback_fn) (const char *name, const struct macro_definition *definition, + struct macro_source_file *source, + int line, void *user_data); /* Call the function FN for each macro in the macro table TABLE. diff --git a/gdb/symtab.c b/gdb/symtab.c index b792081..9447bd9 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -3771,6 +3771,7 @@ struct add_name_data This adds a macro's name to the current completion list. */ static void add_macro_name (const char *name, const struct macro_definition *ignore, + struct macro_source_file *ignore2, int ignore3, void *user_data) { struct add_name_data *datum = (struct add_name_data *) user_data; diff --git a/gdb/testsuite/gdb.base/info-macros.c b/gdb/testsuite/gdb.base/info-macros.c new file mode 100644 index 0000000..f874156 --- /dev/null +++ b/gdb/testsuite/gdb.base/info-macros.c @@ -0,0 +1,73 @@ +#ifdef DEF_MACROS + + #ifdef ONE + #ifdef FOO + #undef FOO + #endif + + #define FOO "hello" + #else + #undef FOO + #endif + + + #ifdef TWO + #ifdef FOO + #undef FOO + #endif + #define FOO " " + #endif + + #ifdef THREE + #ifdef FOO + #undef FOO + #endif + + #define FOO "world" + #endif + + #ifdef FOUR + #ifdef FOO + #undef FOO + #endif + #define FOO(a) foo = a + #endif +#else + +int main (int argc, const char **argv) +{ + char *foo; + + #define DEF_MACROS + #define ONE + #include "info-macros.c" + foo = FOO; + + #define TWO + #include "info-macros.c" + foo = FOO; + + #define THREE + #include "info-macros.c" + foo = FOO; + + #undef THREE + #include "info-macros.c" + foo = FOO; + + #undef TWO + #include "info-macros.c" + foo = FOO; + + #undef ONE + #include "info-macros.c" + foo = (char *)0; + + #define FOUR + #include "info-macros.c" + FOO ("the end."); + + return 0; +} +#endif + diff --git a/gdb/testsuite/gdb.base/info-macros.exp b/gdb/testsuite/gdb.base/info-macros.exp new file mode 100644 index 0000000..bd5a870 --- /dev/null +++ b/gdb/testsuite/gdb.base/info-macros.exp @@ -0,0 +1,202 @@ +# Copyright 2011 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +set testfile "info-macros" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +get_compiler_info ${binfile} +if [test_compiler_info gcc*] { + lappend options additional_flags=-g3 +} else { + untested ${testfile}.exp + return -1 +} + +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} $options] } { + untested ${testfile}.exp + return -1 +} + +if ![runto_main] { + untested ${testfile}.exp + return -1 +} + +set test "info definitions FOO" +set r1 ".*#define FOO \"hello\"" +set r2 ".*#define FOO \" \"" +set r3 ".*#define FOO \"world\"" +set r4 ".*#define FOO\\(a\\) foo = a" +set testname "$test 1" +gdb_test "$test" "$r1$r2$r3$r4" "$testname" + + +set test "info macros" +set r1 ".*#define FOO \"hello\"" +set r2 ".*#define ONE" +set r3 ".*\r\n$gdb_prompt" +set testname "$test 2" +gdb_test_multiple "$test" $testname { + -re "$r1$r2$r3" { + pass $testname + } + -re ".*#define TWO.*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define THREE.*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define FOUR.*\r\n$gdb_prompt" { + fail $testname + } +} +gdb_test "next" ".*" "" + +set r1 ".*#define FOO \" \"" +set r2 ".*#define ONE" +set r3 ".*#define TWO" +set r4 ".*\r\n$gdb_prompt" +set testname "$test 4" +gdb_test_multiple "$test" $testname { + -re ".*#define THREE.*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define FOUR.*\r\n$gdb_prompt" { + fail $testname + } + -re "$r1$r2$r3$r4" { + pass $testname + } +} +gdb_test "next" ".*" "" + +# in alpabetical order... +set r1 ".*#define FOO \"world\"" +set r2 ".*#define ONE" +set r3 ".*#define THREE" +set r4 ".*#define TWO" +set r5 ".*\r\n$gdb_prompt" +set testname "$test 4" +gdb_test_multiple "$test" $testname { + -re ".*#define FOUR.*\r\n$gdb_prompt" { + fail $testname + } + -re "$r1$r2$r3$r4$r5" { + pass $testname + } +} +# same as above with a linespec. +set test "info macros *\$pc" +gdb_test_multiple "$test" $test { + -re ".*#define FOUR.*\r\n$gdb_prompt" { + fail $test + } + -re "$r1$r2$r3$r4$r5" { + pass $test + } +} +gdb_test "next" ".*" "" + +set r1 ".*#define FOO \" \"" +set r2 ".*#define ONE" +set r3 ".*#define TWO." +set r4 ".*\r\n$gdb_prompt" +set testname "$test 5" +set test "info macros" +gdb_test_multiple "$test" $test { + -re ".*#define THREE.*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define FOUR.*\r\n$gdb_prompt" { + fail $testname + } + -re "$r1$r2$r3$r4" { + pass $testname + } +} +gdb_test "next" ".*" "" +gdb_test "next" ".*" "" + +set r1 ".*#define DEF_MACROS" +set r2 ".*\r\n$gdb_prompt" +set testname "$test 6" +gdb_test_multiple "$test" $testname { + -re ".*#define FOO \" \".*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define FOO \"hello\".*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define FOO \"world\".*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define FOO\\(a\\) foo = a.*" { + fail $testname + } + -re ".*#define ONE.*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define TWO.*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define THREE.*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define FOUR.*\r\n$gdb_prompt" { + fail $testname + } + -re "$r1$r2" { + pass $testname + } +} + +gdb_test "next" ".*" "" +set r1 ".*#define DEF_MACROS" +set r2 ".*#define FOO\\(a\\) foo = a" +set r3 ".*#define FOUR" +set r4 ".*\r\n$gdb_prompt" +set testname "$test 7" +gdb_test_multiple "$test" $testname { + -re ".*#define FOO \" \".*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define FOO \"hello\".*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define FOO \"world\".*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define ONE.*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define TWO.*\r\n$gdb_prompt" { + fail $testname + } + -re ".*#define THREE.*\r\n$gdb_prompt" { + fail $testname + } + -re "$r1$r2$r3$r4" { + pass $testname + } +} + +set test "info macros info-macros.c:42" + +set r1 ".*define DEF_MACROS" +set r2 ".*define ONE" +# info macros on the line where the #define or #include is +# fails to find the macro defined (though it works on the next line.) +setup_kfail "gdb/NNNN" *-*-* +gdb_test "$test" "$r1$r2" "$test" ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] PR 12999 info macros command. 2011-07-21 15:56 ` Matt Rice @ 2011-07-21 16:13 ` Pedro Alves 0 siblings, 0 replies; 10+ messages in thread From: Pedro Alves @ 2011-07-21 16:13 UTC (permalink / raw) To: gdb-patches; +Cc: Matt Rice, Tom Tromey, Eli Zaretskii On Thursday 21 July 2011 16:19:15, Matt Rice wrote: > On Thu, Jul 21, 2011 at 7:03 AM, Tom Tromey <tromey@redhat.com> wrote: > > This is ok with those changes. > > commited as attached. This definitely deserves a NEWS entry. -- Pedro Alves ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2011-07-21 15:54 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2011-07-19 9:57 [patch] PR 12999 info macros command Matt Rice 2011-07-19 17:29 ` Tom Tromey 2011-07-20 2:06 ` Matt Rice 2011-07-20 14:14 ` Tom Tromey 2011-07-20 17:24 ` Eli Zaretskii 2011-07-21 6:47 ` Matt Rice 2011-07-21 10:22 ` Eli Zaretskii 2011-07-21 14:07 ` Tom Tromey 2011-07-21 15:56 ` Matt Rice 2011-07-21 16:13 ` Pedro Alves
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox