From: Matt Rice <ratmice@gmail.com>
To: gdb-patches@sourceware.org
Subject: [patch] PR 12999 info macros command.
Date: Tue, 19 Jul 2011 09:57:00 -0000 [thread overview]
Message-ID: <CACTLOFot6DnZj173bQTLEqW=XzTDngjCLvpSZv4a-aCKfaLxog@mail.gmail.com> (raw)
[-- 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"
+
next reply other threads:[~2011-07-19 6:57 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-07-19 9:57 Matt Rice [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CACTLOFot6DnZj173bQTLEqW=XzTDngjCLvpSZv4a-aCKfaLxog@mail.gmail.com' \
--to=ratmice@gmail.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox