* RFA: Patch: implement missing macro functions
@ 2008-05-21 4:50 Tom Tromey
2008-05-24 15:42 ` Pedro Alves
[not found] ` <8f2776cb0805301626v4ff4d933ua6b833aaa7056aaa@mail.gmail.com>
0 siblings, 2 replies; 12+ messages in thread
From: Tom Tromey @ 2008-05-21 4:50 UTC (permalink / raw)
To: gdb-patches
This morning I figured out that I could solve a longstanding gcc
debugging problem I've had using 'macro define'. Then to my dismay I
discovered that this function was not implemented.
I suppose the point of having a stub function here is to get someone
like me to show up and implement it :-). And, my annoyance at running
into the stub was at least partially counteracted by reading the code
and the docs... the macro expansion stuff all seems quite nice.
This patch implements macro define, macro undef, and macro list.
It adds some nominal test cases -- nothing major.
Now you can do things like:
macro define offsetof(T, F) ((int) &(((T *) 0)->F))
... which is quite handy.
In case you're curious, my use in gcc is to allow macro expansion of
the many gcc tree accessor macros, while avoiding the statement
expressions in the check macros that (of course) gdb does not
understand. To do this I just redefine all the accessors with
gdb-safe ones, e.g.:
macro define TREE_TYPE(NODE) ((T)->common.type)
I haven't tested these yet, that's my next job. Too bad that gdb
try/catch patch never went in... adding a lot of "macro define"s to
gcc's .gdbinit is problematic since they will all cause errors on
older gdbs :-(
So... ok to commit?
Tom
ChangeLog:
2008-05-20 Tom Tromey <tromey@redhat.com>
* macroscope.h (user_macro_scope): Declare.
(default_macro_scope): Update documentation.
* c-lang.c (c_preprocess_and_parse): Always attempt macro lookup.
Use user_macro_scope.
(null_macro_lookup): Remove.
* macrotab.h (macro_define_user, macro_definition_delete,
macro_user_macros): Declare.
(macro_callback_fn): Declare.
(macro_for_each): Likewise.
* macrotab.c (macro_definition_delete): New function.
(macro_tree_delete_value): Use it.
(macro_define_user): New function.
(macro_lookup_definition): Look in user-defined macro table.
(foreach_macro): New function
(macro_for_each): Likewise.
* macroscope.c (user_macro_scope): New function.
(default_macro_scope): Use it.
* 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.
(macro_user_macros): Rename from user_macros. No longer static.
(macro_define_command): Implement.
(_initialize_macrocmd): Update. Set main file on
macro_user_macros.
(macro_undef_command): Implement.
(print_one_macro): New function.
(macro_list_command): Implement.
testsuite/ChangeLog:
2008-05-20 Tom Tromey <tromey@redhat.com>
* gdb.base/macscp.exp: Add macro tests.
doc/ChangeLog:
2008-05-20 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Macros): Update.
Index: c-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/c-lang.c,v
retrieving revision 1.53
diff -u -r1.53 c-lang.c
--- c-lang.c 6 Apr 2008 08:56:36 -0000 1.53
+++ c-lang.c 21 May 2008 00:25:07 -0000
@@ -261,13 +261,6 @@
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 @@
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);
Index: macrocmd.c
===================================================================
RCS file: /cvs/src/src/gdb/macrocmd.c,v
retrieving revision 1.13
diff -u -r1.13 macrocmd.c
--- macrocmd.c 1 Jan 2008 22:53:12 -0000 1.13
+++ macrocmd.c 21 May 2008 00:25:07 -0000
@@ -24,6 +24,7 @@
#include "macroscope.h"
#include "command.h"
#include "gdbcmd.h"
+#include "gdb_string.h"
\f
/* The `macro' prefix command. */
@@ -189,31 +190,161 @@
\f
/* User-defined 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;
+}
+
+static void
+free_macro_definition_ptr (void *ptr)
+{
+ struct macro_definition **loc = (struct macro_definition **) ptr;
+ if (*loc)
+ macro_definition_delete (*loc);
+}
+
/* 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;
+struct macro_table *macro_user_macros;
static void
macro_define_command (char *exp, int from_tty)
{
- error (_("Command not implemented yet."));
+ struct macro_definition *new_macro = NULL;
+ char *name = NULL;
+ struct cleanup *cleanup_chain = make_cleanup (free_macro_definition_ptr,
+ &new_macro);
+ cleanup_chain = make_my_cleanup (&cleanup_chain, free_current_contents,
+ &name);
+
+ new_macro = XZALLOC (struct macro_definition);
+ new_macro->table = macro_user_macros;
+
+ 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;
+ }
+ else
+ new_macro->kind = macro_object_like;
+
+ new_macro->replacement = xstrdup (exp);
+
+ macro_define_user (name, new_macro);
+ xfree (name);
+ discard_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);
+ gdb_flush (gdb_stdout);
}
static void
macro_list_command (char *exp, int from_tty)
{
- error (_("Command not implemented yet."));
+ macro_for_each (macro_user_macros, print_one_macro);
}
@@ -274,5 +405,6 @@
_("List all the macros defined using the `macro define' command."),
¯olist);
- user_macros = new_macro_table (0, 0);
+ macro_user_macros = new_macro_table (0, 0);
+ macro_set_main (macro_user_macros, "<user-defined>");
}
Index: macroexp.c
===================================================================
RCS file: /cvs/src/src/gdb/macroexp.c,v
retrieving revision 1.13
diff -u -r1.13 macroexp.c
--- macroexp.c 1 Jan 2008 22:53:12 -0000 1.13
+++ macroexp.c 21 May 2008 00:25:07 -0000
@@ -171,8 +171,8 @@
/* Recognizing preprocessor tokens. */
-static int
-is_whitespace (int c)
+int
+macro_is_whitespace (int c)
{
return (c == ' '
|| c == '\t'
@@ -182,15 +182,15 @@
}
-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 @@
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 @@
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 @@
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;
Index: macroexp.h
===================================================================
RCS file: /cvs/src/src/gdb/macroexp.h,v
retrieving revision 1.6
diff -u -r1.6 macroexp.h
--- macroexp.h 1 Jan 2008 22:53:12 -0000 1.6
+++ macroexp.h 21 May 2008 00:25:07 -0000
@@ -84,5 +84,11 @@
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 */
Index: macroscope.c
===================================================================
RCS file: /cvs/src/src/gdb/macroscope.c,v
retrieving revision 1.14
diff -u -r1.14 macroscope.c
--- macroscope.c 1 Jan 2008 22:53:12 -0000 1.14
+++ macroscope.c 21 May 2008 00:25:07 -0000
@@ -78,6 +78,16 @@
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 +120,11 @@
sal.line = cursal.line;
}
- return sal_macro_scope (sal);
+ ms = sal_macro_scope (sal);
+ if (! ms)
+ ms = user_macro_scope ();
+
+ return ms;
}
Index: macroscope.h
===================================================================
RCS file: /cvs/src/src/gdb/macroscope.h,v
retrieving revision 1.6
diff -u -r1.6 macroscope.h
--- macroscope.h 1 Jan 2008 22:53:12 -0000 1.6
+++ macroscope.h 21 May 2008 00:25:07 -0000
@@ -39,12 +39,18 @@
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. */
Index: macrotab.c
===================================================================
RCS file: /cvs/src/src/gdb/macrotab.c,v
retrieving revision 1.15
diff -u -r1.15 macrotab.c
--- macrotab.c 1 Jan 2008 22:53:12 -0000 1.15
+++ macrotab.c 21 May 2008 00:25:08 -0000
@@ -587,11 +587,9 @@
}
-/* Free a macro definition. */
-static void
-macro_tree_delete_value (void *untyped_definition)
+void
+macro_definition_delete (struct macro_definition *d)
{
- struct macro_definition *d = (struct macro_definition *) untyped_definition;
struct macro_table *t = d->table;
if (d->kind == macro_function_like)
@@ -608,6 +606,15 @@
}
+/* Free a macro definition. For use by splay trees. */
+static void
+macro_tree_delete_value (void *untyped_definition)
+{
+ struct macro_definition *d = (struct macro_definition *) untyped_definition;
+ macro_definition_delete (d);
+}
+
+
/* Find the splay tree node for the definition of NAME at LINE in
SOURCE, or zero if there is none. */
static splay_tree_node
@@ -786,6 +793,25 @@
void
+macro_define_user (const char *name, struct macro_definition *new_macro)
+{
+ struct macro_key *key;
+ splay_tree_node n = find_definition (name, new_macro->table->main_source, -1);
+
+ if (n)
+ {
+ key = (struct macro_key *) n->key;
+ splay_tree_remove (new_macro->table->definitions, n->key);
+ }
+
+ key = new_macro_key (new_macro->table, name, new_macro->table->main_source,
+ -1);
+ splay_tree_insert (new_macro->table->definitions, (splay_tree_key) key,
+ (splay_tree_value) new_macro);
+}
+
+
+void
macro_undef (struct macro_source_file *source, int line,
const char *name)
{
@@ -845,7 +871,12 @@
macro_lookup_definition (struct macro_source_file *source,
int line, const char *name)
{
- splay_tree_node n = find_definition (name, source, line);
+ splay_tree_node n;
+
+ /* Give user-defined macros priority over all others. */
+ n = find_definition (name, macro_user_macros->main_source, -1);
+ if (! n)
+ n = find_definition (name, source, line);
if (n)
return (struct macro_definition *) n->value;
@@ -873,6 +904,24 @@
}
+/* 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;
+}
+
+void
+macro_for_each (struct macro_table *table, macro_callback_fn fn)
+{
+ splay_tree_foreach (table->definitions, foreach_macro, fn);
+}
+
+
\f
/* Creating and freeing macro tables. */
Index: macrotab.h
===================================================================
RCS file: /cvs/src/src/gdb/macrotab.h,v
retrieving revision 1.9
diff -u -r1.9 macrotab.h
--- macrotab.h 1 Jan 2008 22:53:12 -0000 1.9
+++ macrotab.h 21 May 2008 00:25:08 -0000
@@ -72,6 +72,8 @@
/* 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
@@ -241,12 +243,23 @@
const char *replacement);
+/* Record a macro definition given a fully-filled macro_definition
+ object. The object and its contents must be allocated
+ appropriately for the table into which the new macro will be
+ inserted; it is the caller's responsibility to ensure this. A
+ previous macro definition of the same name will be silently
+ removed. NAME is the name of the new macro; it is copied by this
+ function as needed. */
+void macro_define_user (const char *name, struct macro_definition *new_macro);
+
/* Record an #undefinition.
Record in SOURCE's macro table that, at line number LINE in SOURCE,
we removed the definition for the preprocessor symbol named NAME. */
void macro_undef (struct macro_source_file *source, int line,
const char *name);
+/* Delete a macro_definition object. */
+void macro_definition_delete (struct macro_definition *obj);
/* Different kinds of macro definitions. */
enum macro_kind
@@ -298,5 +311,16 @@
const char *name,
int *definition_line));
+/* The table of macros defined by the user. */
+extern struct macro_table *macro_user_macros;
+
+
+/* Callback function when walking a macro table. */
+typedef void (*macro_callback_fn) (const char *,
+ const struct macro_definition *);
+
+/* Call a function for each macro in the table. */
+void macro_for_each (struct macro_table *, macro_callback_fn);
+
#endif /* MACROTAB_H */
Index: testsuite/gdb.base/macscp.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/macscp.exp,v
retrieving revision 1.7
diff -u -r1.7 macscp.exp
--- testsuite/gdb.base/macscp.exp 3 May 2008 22:30:51 -0000 1.7
+++ testsuite/gdb.base/macscp.exp 21 May 2008 00:25:09 -0000
@@ -428,3 +428,23 @@
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 undef M" \
+ "" \
+ "basic macro undef"
+
+gdb_test "print M" \
+ "No symbol \"M\" in current context\." \
+ "print expression with macro after user undef."
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.495
diff -u -r1.495 gdb.texinfo
--- doc/gdb.texinfo 9 May 2008 17:02:01 -0000 1.495
+++ doc/gdb.texinfo 21 May 2008 00:25:12 -0000
@@ -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
+@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008
@c Free Software Foundation, Inc.
@c
@c %**start of header
@@ -7822,12 +7822,12 @@
@cindex macros, user-defined
@item macro define @var{macro} @var{replacement-list}
@itemx macro define @var{macro}(@var{arglist}) @var{replacement-list}
-@i{(This command is not yet implemented.)} Introduce a definition for a
-preprocessor macro named @var{macro}, invocations of which are replaced
-by the tokens given in @var{replacement-list}. The first form of this
-command defines an ``object-like'' macro, which takes no arguments; the
-second form defines a ``function-like'' macro, which takes the arguments
-given in @var{arglist}.
+Introduce a definition for a preprocessor macro named @var{macro},
+invocations of which are replaced by the tokens given in
+@var{replacement-list}. The first form of this command defines an
+``object-like'' macro, which takes no arguments; the second form
+defines a ``function-like'' macro, which takes the arguments given in
+@var{arglist}.
A definition introduced by this command is in scope in every expression
evaluated in @value{GDBN}, until it is removed with the @command{macro
@@ -7837,16 +7837,14 @@
@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 @command{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
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: RFA: Patch: implement missing macro functions 2008-05-21 4:50 RFA: Patch: implement missing macro functions Tom Tromey @ 2008-05-24 15:42 ` Pedro Alves 2008-05-24 16:34 ` Tom Tromey 2008-05-25 12:37 ` Tom Tromey [not found] ` <8f2776cb0805301626v4ff4d933ua6b833aaa7056aaa@mail.gmail.com> 1 sibling, 2 replies; 12+ messages in thread From: Pedro Alves @ 2008-05-24 15:42 UTC (permalink / raw) To: gdb-patches, Tom Tromey Hi Tom, You'll need someone else to comment on the big picture -- I'll comment on a few strokes, below, > static void > macro_define_command (char *exp, int from_tty) > { > - error (_("Command not implemented yet.")); > + struct macro_definition *new_macro = NULL; > + char *name = NULL; > + struct cleanup *cleanup_chain = make_cleanup (free_macro_definition_ptr, > + &new_macro); > + cleanup_chain = make_my_cleanup (&cleanup_chain, free_current_contents, > + &name); That is a big nop to write + with 2 leaks attached. The new cleanup is being discarded and leaked, so NAME isn't being free'd at all. Don't call make_my_cleanup directly. Instead, call make_cleanup and discard its result: You want to hold the cleanup chain pointer representing the old cleanups on function entry, and that is returned on the first make_cleanup call. struct cleanup *cleanup_chain = make_cleanup (free_macro_definition_ptr, &new_macro); make_cleanup (free_current_contents, &name); (pedantically, if you don't need the NAME variable after cleaning up or an exception is thrown (local vars usually apply), an xfree cleanup is also fine, like in `make_cleanup (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); > + gdb_flush (gdb_stdout); > } Did you really need a gdb_flush here? > > +/* Helper function for macro_for_each. */ > +static int > +foreach_macro (splay_tree_node node, void *fnp) > +{ > + macro_callback_fn fn = (macro_callback_fn) fnp; (Hmmm, can we assume casting void* <-> func pointers is safe on all supported hosts/compilers? Posix and Windows do require it to be safe. I actually have no idea how much GDB common code relies on it today.) > + struct macro_key *key = (struct macro_key *) node->key; > + struct macro_definition *def = (struct macro_definition *) node->value; > + (*fn) (key->name, def); > + return 0; > +} > + > +void > +macro_for_each (struct macro_table *table, macro_callback_fn fn) > +{ > + splay_tree_foreach (table->definitions, foreach_macro, fn); > +} > > #endif /* MACROTAB_H */ > Index: testsuite/gdb.base/macscp.exp > =================================================================== > RCS file: /cvs/src/src/gdb/testsuite/gdb.base/macscp.exp,v > retrieving revision 1.7 > diff -u -r1.7 macscp.exp > --- testsuite/gdb.base/macscp.exp 3 May 2008 22:30:51 -0000 1.7 > +++ testsuite/gdb.base/macscp.exp 21 May 2008 00:25:09 -0000 > @@ -428,3 +428,23 @@ > 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 undef M" \ > + "" \ > + "basic macro undef" > + > +gdb_test "print M" \ > + "No symbol \"M\" in current context\." \ > + "print expression with macro after user undef." Would it make sense to have a test with macro arguments, and a test where a user macro overrides a source macro? -- Pedro Alves ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFA: Patch: implement missing macro functions 2008-05-24 15:42 ` Pedro Alves @ 2008-05-24 16:34 ` Tom Tromey 2008-05-25 12:37 ` Tom Tromey 1 sibling, 0 replies; 12+ messages in thread From: Tom Tromey @ 2008-05-24 16:34 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches >>>>> "Pedro" == Pedro Alves <pedro@codesourcery.com> writes: Pedro> You'll need someone else to comment on the big picture -- I'll Pedro> comment on a few strokes, below, Thanks for taking the time to do this. >> + cleanup_chain = make_my_cleanup (&cleanup_chain, free_current_contents, >> + &name); Pedro> That is a big nop to write + with 2 leaks attached. The new cleanup is Pedro> being discarded and leaked, so NAME isn't being free'd at all. Pedro> Don't call make_my_cleanup directly. Instead, call Pedro> make_cleanup and discard its result: Ok, thanks. I forgot to mention in my note that I wanted someone to look at this. I don't actually understand the cleanup mechanism... I looked a bit but didn't see any documentation on how to use it. >> + gdb_flush (gdb_stdout); Pedro> Did you really need a gdb_flush here? Probably not. I'll remove it and see. >> >> +/* Helper function for macro_for_each. */ >> +static int >> +foreach_macro (splay_tree_node node, void *fnp) >> +{ >> + macro_callback_fn fn = (macro_callback_fn) fnp; Pedro> (Hmmm, can we assume casting void* <-> func pointers is safe on all Pedro> supported hosts/compilers? Posix and Windows do require it to Pedro> be safe. I actually have no idea how much GDB common code relies Pedro> on it today.) I'll just fix it. Pedro> Would it make sense to have a test with macro arguments, and Pedro> a test where a user macro overrides a source macro? Yeah. Lazy me! I will add those. Tom ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFA: Patch: implement missing macro functions 2008-05-24 15:42 ` Pedro Alves 2008-05-24 16:34 ` Tom Tromey @ 2008-05-25 12:37 ` Tom Tromey 2008-05-25 18:03 ` Eli Zaretskii 2008-05-25 20:39 ` Pedro Alves 1 sibling, 2 replies; 12+ messages in thread From: Tom Tromey @ 2008-05-25 12:37 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches >>>>> "Pedro" == Pedro Alves <pedro@codesourcery.com> writes: Pedro> You'll need someone else to comment on the big picture -- I'll Pedro> comment on a few strokes, below, Here's an updated patch. I think it addresses all your comments. Let me know what you think. Tom ChangeLog: 2008-05-23 Tom Tromey <tromey@redhat.com> * macroscope.h (user_macro_scope): Declare. (default_macro_scope): Update documentation. * c-lang.c (c_preprocess_and_parse): Always attempt macro lookup. Use user_macro_scope. (null_macro_lookup): Remove. * macrotab.h (macro_define_user, macro_definition_delete, macro_user_macros): Declare. (macro_callback_fn): Declare. (macro_for_each): Likewise. * macrotab.c (macro_definition_delete): New function. (macro_tree_delete_value): Use it. (macro_define_user): New function. (macro_lookup_definition): Look in user-defined macro table. (foreach_macro): New function (macro_for_each): Likewise. * macroscope.c (user_macro_scope): New function. (default_macro_scope): Use it. * 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. (macro_user_macros): Rename from user_macros. No longer static. (macro_define_command): Implement. (_initialize_macrocmd): Update. Set main file on macro_user_macros. (macro_undef_command): Implement. (print_one_macro): New function. (macro_list_command): Implement. testsuite/ChangeLog: 2008-05-23 Tom Tromey <tromey@redhat.com> * gdb.base/macscp.exp: Add macro tests. doc/ChangeLog: 2008-05-23 Tom Tromey <tromey@redhat.com> * gdb.texinfo (Macros): Update. Index: c-lang.c =================================================================== RCS file: /cvs/src/src/gdb/c-lang.c,v retrieving revision 1.53 diff -u -r1.53 c-lang.c --- c-lang.c 6 Apr 2008 08:56:36 -0000 1.53 +++ c-lang.c 23 May 2008 20:26:58 -0000 @@ -261,13 +261,6 @@ 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 @@ 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); Index: macrocmd.c =================================================================== RCS file: /cvs/src/src/gdb/macrocmd.c,v retrieving revision 1.13 diff -u -r1.13 macrocmd.c --- macrocmd.c 1 Jan 2008 22:53:12 -0000 1.13 +++ macrocmd.c 23 May 2008 20:26:58 -0000 @@ -24,6 +24,7 @@ #include "macroscope.h" #include "command.h" #include "gdbcmd.h" +#include "gdb_string.h" \f /* The `macro' prefix command. */ @@ -189,31 +190,159 @@ \f /* User-defined 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; +} + +static void +free_macro_definition_ptr (void *ptr) +{ + struct macro_definition **loc = (struct macro_definition **) ptr; + if (*loc) + macro_definition_delete (*loc); +} + /* 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; +struct macro_table *macro_user_macros; static void macro_define_command (char *exp, int from_tty) { - error (_("Command not implemented yet.")); + struct macro_definition *new_macro = NULL; + char *name = NULL; + struct cleanup *cleanup_chain = make_cleanup (free_macro_definition_ptr, + &new_macro); + make_cleanup (free_current_contents, &name); + + new_macro = XZALLOC (struct macro_definition); + new_macro->table = macro_user_macros; + + 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; + } + else + new_macro->kind = macro_object_like; + + new_macro->replacement = xstrdup (exp); + + macro_define_user (name, new_macro); + xfree (name); + discard_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); } @@ -274,5 +403,6 @@ _("List all the macros defined using the `macro define' command."), ¯olist); - user_macros = new_macro_table (0, 0); + macro_user_macros = new_macro_table (0, 0); + macro_set_main (macro_user_macros, "<user-defined>"); } Index: macroexp.c =================================================================== RCS file: /cvs/src/src/gdb/macroexp.c,v retrieving revision 1.13 diff -u -r1.13 macroexp.c --- macroexp.c 1 Jan 2008 22:53:12 -0000 1.13 +++ macroexp.c 23 May 2008 20:26:58 -0000 @@ -171,8 +171,8 @@ /* Recognizing preprocessor tokens. */ -static int -is_whitespace (int c) +int +macro_is_whitespace (int c) { return (c == ' ' || c == '\t' @@ -182,15 +182,15 @@ } -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 @@ 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 @@ 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 @@ 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; Index: macroexp.h =================================================================== RCS file: /cvs/src/src/gdb/macroexp.h,v retrieving revision 1.6 diff -u -r1.6 macroexp.h --- macroexp.h 1 Jan 2008 22:53:12 -0000 1.6 +++ macroexp.h 23 May 2008 20:26:58 -0000 @@ -84,5 +84,11 @@ 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 */ Index: macroscope.c =================================================================== RCS file: /cvs/src/src/gdb/macroscope.c,v retrieving revision 1.14 diff -u -r1.14 macroscope.c --- macroscope.c 1 Jan 2008 22:53:12 -0000 1.14 +++ macroscope.c 23 May 2008 20:26:58 -0000 @@ -78,6 +78,16 @@ 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 +120,11 @@ sal.line = cursal.line; } - return sal_macro_scope (sal); + ms = sal_macro_scope (sal); + if (! ms) + ms = user_macro_scope (); + + return ms; } Index: macroscope.h =================================================================== RCS file: /cvs/src/src/gdb/macroscope.h,v retrieving revision 1.6 diff -u -r1.6 macroscope.h --- macroscope.h 1 Jan 2008 22:53:12 -0000 1.6 +++ macroscope.h 23 May 2008 20:26:58 -0000 @@ -39,12 +39,18 @@ 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. */ Index: macrotab.c =================================================================== RCS file: /cvs/src/src/gdb/macrotab.c,v retrieving revision 1.15 diff -u -r1.15 macrotab.c --- macrotab.c 1 Jan 2008 22:53:12 -0000 1.15 +++ macrotab.c 23 May 2008 20:26:58 -0000 @@ -587,11 +587,9 @@ } -/* Free a macro definition. */ -static void -macro_tree_delete_value (void *untyped_definition) +void +macro_definition_delete (struct macro_definition *d) { - struct macro_definition *d = (struct macro_definition *) untyped_definition; struct macro_table *t = d->table; if (d->kind == macro_function_like) @@ -608,6 +606,15 @@ } +/* Free a macro definition. For use by splay trees. */ +static void +macro_tree_delete_value (void *untyped_definition) +{ + struct macro_definition *d = (struct macro_definition *) untyped_definition; + macro_definition_delete (d); +} + + /* Find the splay tree node for the definition of NAME at LINE in SOURCE, or zero if there is none. */ static splay_tree_node @@ -786,6 +793,25 @@ void +macro_define_user (const char *name, struct macro_definition *new_macro) +{ + struct macro_key *key; + splay_tree_node n = find_definition (name, new_macro->table->main_source, -1); + + if (n) + { + key = (struct macro_key *) n->key; + splay_tree_remove (new_macro->table->definitions, n->key); + } + + key = new_macro_key (new_macro->table, name, new_macro->table->main_source, + -1); + splay_tree_insert (new_macro->table->definitions, (splay_tree_key) key, + (splay_tree_value) new_macro); +} + + +void macro_undef (struct macro_source_file *source, int line, const char *name) { @@ -845,7 +871,12 @@ macro_lookup_definition (struct macro_source_file *source, int line, const char *name) { - splay_tree_node n = find_definition (name, source, line); + splay_tree_node n; + + /* Give user-defined macros priority over all others. */ + n = find_definition (name, macro_user_macros->main_source, -1); + if (! n) + n = find_definition (name, source, line); if (n) return (struct macro_definition *) n->value; @@ -873,6 +904,27 @@ } +/* 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; +} + +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); +} + + \f /* Creating and freeing macro tables. */ Index: macrotab.h =================================================================== RCS file: /cvs/src/src/gdb/macrotab.h,v retrieving revision 1.9 diff -u -r1.9 macrotab.h --- macrotab.h 1 Jan 2008 22:53:12 -0000 1.9 +++ macrotab.h 23 May 2008 20:26:58 -0000 @@ -72,6 +72,8 @@ /* 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 @@ -241,12 +243,23 @@ const char *replacement); +/* Record a macro definition given a fully-filled macro_definition + object. The object and its contents must be allocated + appropriately for the table into which the new macro will be + inserted; it is the caller's responsibility to ensure this. A + previous macro definition of the same name will be silently + removed. NAME is the name of the new macro; it is copied by this + function as needed. */ +void macro_define_user (const char *name, struct macro_definition *new_macro); + /* Record an #undefinition. Record in SOURCE's macro table that, at line number LINE in SOURCE, we removed the definition for the preprocessor symbol named NAME. */ void macro_undef (struct macro_source_file *source, int line, const char *name); +/* Delete a macro_definition object. */ +void macro_definition_delete (struct macro_definition *obj); /* Different kinds of macro definitions. */ enum macro_kind @@ -298,5 +311,16 @@ const char *name, int *definition_line)); +/* The table of macros defined by the user. */ +extern struct macro_table *macro_user_macros; + + +/* Callback function when walking a macro table. */ +typedef void (*macro_callback_fn) (const char *, + const struct macro_definition *); + +/* Call a function for each macro in the table. */ +void macro_for_each (struct macro_table *, macro_callback_fn); + #endif /* MACROTAB_H */ Index: testsuite/gdb.base/macscp.exp =================================================================== RCS file: /cvs/src/src/gdb/testsuite/gdb.base/macscp.exp,v retrieving revision 1.7 diff -u -r1.7 macscp.exp --- testsuite/gdb.base/macscp.exp 3 May 2008 22:30:51 -0000 1.7 +++ testsuite/gdb.base/macscp.exp 23 May 2008 20:26:59 -0000 @@ -423,8 +423,52 @@ " = 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." Index: doc/gdb.texinfo =================================================================== RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v retrieving revision 1.495 diff -u -r1.495 gdb.texinfo --- doc/gdb.texinfo 9 May 2008 17:02:01 -0000 1.495 +++ doc/gdb.texinfo 23 May 2008 20:27:02 -0000 @@ -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 +@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008 @c Free Software Foundation, Inc. @c @c %**start of header @@ -7822,12 +7822,12 @@ @cindex macros, user-defined @item macro define @var{macro} @var{replacement-list} @itemx macro define @var{macro}(@var{arglist}) @var{replacement-list} -@i{(This command is not yet implemented.)} Introduce a definition for a -preprocessor macro named @var{macro}, invocations of which are replaced -by the tokens given in @var{replacement-list}. The first form of this -command defines an ``object-like'' macro, which takes no arguments; the -second form defines a ``function-like'' macro, which takes the arguments -given in @var{arglist}. +Introduce a definition for a preprocessor macro named @var{macro}, +invocations of which are replaced by the tokens given in +@var{replacement-list}. The first form of this command defines an +``object-like'' macro, which takes no arguments; the second form +defines a ``function-like'' macro, which takes the arguments given in +@var{arglist}. A definition introduced by this command is in scope in every expression evaluated in @value{GDBN}, until it is removed with the @command{macro @@ -7837,16 +7837,14 @@ @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 @command{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 ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFA: Patch: implement missing macro functions 2008-05-25 12:37 ` Tom Tromey @ 2008-05-25 18:03 ` Eli Zaretskii 2008-05-25 21:51 ` Tom Tromey 2008-05-25 20:39 ` Pedro Alves 1 sibling, 1 reply; 12+ messages in thread From: Eli Zaretskii @ 2008-05-25 18:03 UTC (permalink / raw) To: Tom Tromey; +Cc: pedro, gdb-patches > Cc: gdb-patches@sourceware.org > From: Tom Tromey <tromey@redhat.com> > Date: Fri, 23 May 2008 14:28:32 -0600 > > +This command only affects definitions provided with the @command{macro > +define} command, described above; it cannot remove definitions present > +in the program being debugged. We use @code for GDB commands, not @command. (Yes, I know it was like that in the original text.) Other than that, the patch for the manual is fine with me. Btw, I think these new commands deserve a NEWS entry. Thanks. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFA: Patch: implement missing macro functions 2008-05-25 18:03 ` Eli Zaretskii @ 2008-05-25 21:51 ` Tom Tromey 2008-05-26 16:18 ` Eli Zaretskii 0 siblings, 1 reply; 12+ messages in thread From: Tom Tromey @ 2008-05-25 21:51 UTC (permalink / raw) To: Eli Zaretskii; +Cc: pedro, gdb-patches >>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes: Eli> We use @code for GDB commands, not @command. (Yes, I know it was like Eli> that in the original text.) Other than that, the patch for the manual Eli> is fine with me. I fixed all the macro-related uses of @command. Eli> Btw, I think these new commands deserve a NEWS entry. Done. Here's a new patch. Let me know what you think. Tom ChangeLog: 2008-05-23 Tom Tromey <tromey@redhat.com> * NEWS: Add entry for macro commands. * macroscope.h (user_macro_scope): Declare. (default_macro_scope): Update documentation. * c-lang.c (c_preprocess_and_parse): Always attempt macro lookup. Use user_macro_scope. (null_macro_lookup): Remove. * macrotab.h (macro_define_user, macro_definition_delete, macro_user_macros): Declare. (macro_callback_fn): Declare. (macro_for_each): Likewise. * macrotab.c (macro_definition_delete): New function. (macro_tree_delete_value): Use it. (macro_define_user): New function. (macro_lookup_definition): Look in user-defined macro table. (foreach_macro): New function (macro_for_each): Likewise. * macroscope.c (user_macro_scope): New function. (default_macro_scope): Use it. * 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. (macro_user_macros): Rename from user_macros. No longer static. (macro_define_command): Implement. (_initialize_macrocmd): Update. Set main file on macro_user_macros. (macro_undef_command): Implement. (print_one_macro): New function. (macro_list_command): Implement. testsuite/ChangeLog: 2008-05-23 Tom Tromey <tromey@redhat.com> * gdb.base/macscp.exp: Add macro tests. doc/ChangeLog: 2008-05-23 Tom Tromey <tromey@redhat.com> * gdb.texinfo (Macros): Update. Use @code rather than @command. Index: NEWS =================================================================== RCS file: /cvs/src/src/gdb/NEWS,v retrieving revision 1.273 diff -u -r1.273 NEWS --- NEWS 9 May 2008 19:17:46 -0000 1.273 +++ NEWS 23 May 2008 21:07:18 -0000 @@ -78,6 +78,12 @@ the current CPSR value for instructions without symbols; previous versions of GDB behaved as if "set arm fallback-mode arm". +macro define +macro list +macro undef + These commands are now implemented. These allow macros to be + defined, undefined, and listed interactively. + *** Changes in GDB 6.8 * New native configurations Index: c-lang.c =================================================================== RCS file: /cvs/src/src/gdb/c-lang.c,v retrieving revision 1.53 diff -u -r1.53 c-lang.c --- c-lang.c 6 Apr 2008 08:56:36 -0000 1.53 +++ c-lang.c 23 May 2008 21:07:18 -0000 @@ -261,13 +261,6 @@ 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 @@ 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); Index: macrocmd.c =================================================================== RCS file: /cvs/src/src/gdb/macrocmd.c,v retrieving revision 1.13 diff -u -r1.13 macrocmd.c --- macrocmd.c 1 Jan 2008 22:53:12 -0000 1.13 +++ macrocmd.c 23 May 2008 21:07:18 -0000 @@ -24,6 +24,7 @@ #include "macroscope.h" #include "command.h" #include "gdbcmd.h" +#include "gdb_string.h" \f /* The `macro' prefix command. */ @@ -189,31 +190,159 @@ \f /* User-defined 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; +} + +static void +free_macro_definition_ptr (void *ptr) +{ + struct macro_definition **loc = (struct macro_definition **) ptr; + if (*loc) + macro_definition_delete (*loc); +} + /* 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; +struct macro_table *macro_user_macros; static void macro_define_command (char *exp, int from_tty) { - error (_("Command not implemented yet.")); + struct macro_definition *new_macro = NULL; + char *name = NULL; + struct cleanup *cleanup_chain = make_cleanup (free_macro_definition_ptr, + &new_macro); + make_cleanup (free_current_contents, &name); + + new_macro = XZALLOC (struct macro_definition); + new_macro->table = macro_user_macros; + + 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; + } + else + new_macro->kind = macro_object_like; + + new_macro->replacement = xstrdup (exp); + + macro_define_user (name, new_macro); + xfree (name); + discard_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); } @@ -274,5 +403,6 @@ _("List all the macros defined using the `macro define' command."), ¯olist); - user_macros = new_macro_table (0, 0); + macro_user_macros = new_macro_table (0, 0); + macro_set_main (macro_user_macros, "<user-defined>"); } Index: macroexp.c =================================================================== RCS file: /cvs/src/src/gdb/macroexp.c,v retrieving revision 1.13 diff -u -r1.13 macroexp.c --- macroexp.c 1 Jan 2008 22:53:12 -0000 1.13 +++ macroexp.c 23 May 2008 21:07:18 -0000 @@ -171,8 +171,8 @@ /* Recognizing preprocessor tokens. */ -static int -is_whitespace (int c) +int +macro_is_whitespace (int c) { return (c == ' ' || c == '\t' @@ -182,15 +182,15 @@ } -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 @@ 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 @@ 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 @@ 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; Index: macroexp.h =================================================================== RCS file: /cvs/src/src/gdb/macroexp.h,v retrieving revision 1.6 diff -u -r1.6 macroexp.h --- macroexp.h 1 Jan 2008 22:53:12 -0000 1.6 +++ macroexp.h 23 May 2008 21:07:18 -0000 @@ -84,5 +84,11 @@ 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 */ Index: macroscope.c =================================================================== RCS file: /cvs/src/src/gdb/macroscope.c,v retrieving revision 1.14 diff -u -r1.14 macroscope.c --- macroscope.c 1 Jan 2008 22:53:12 -0000 1.14 +++ macroscope.c 23 May 2008 21:07:18 -0000 @@ -78,6 +78,16 @@ 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 +120,11 @@ sal.line = cursal.line; } - return sal_macro_scope (sal); + ms = sal_macro_scope (sal); + if (! ms) + ms = user_macro_scope (); + + return ms; } Index: macroscope.h =================================================================== RCS file: /cvs/src/src/gdb/macroscope.h,v retrieving revision 1.6 diff -u -r1.6 macroscope.h --- macroscope.h 1 Jan 2008 22:53:12 -0000 1.6 +++ macroscope.h 23 May 2008 21:07:18 -0000 @@ -39,12 +39,18 @@ 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. */ Index: macrotab.c =================================================================== RCS file: /cvs/src/src/gdb/macrotab.c,v retrieving revision 1.15 diff -u -r1.15 macrotab.c --- macrotab.c 1 Jan 2008 22:53:12 -0000 1.15 +++ macrotab.c 23 May 2008 21:07:18 -0000 @@ -587,11 +587,9 @@ } -/* Free a macro definition. */ -static void -macro_tree_delete_value (void *untyped_definition) +void +macro_definition_delete (struct macro_definition *d) { - struct macro_definition *d = (struct macro_definition *) untyped_definition; struct macro_table *t = d->table; if (d->kind == macro_function_like) @@ -608,6 +606,15 @@ } +/* Free a macro definition. For use by splay trees. */ +static void +macro_tree_delete_value (void *untyped_definition) +{ + struct macro_definition *d = (struct macro_definition *) untyped_definition; + macro_definition_delete (d); +} + + /* Find the splay tree node for the definition of NAME at LINE in SOURCE, or zero if there is none. */ static splay_tree_node @@ -786,6 +793,25 @@ void +macro_define_user (const char *name, struct macro_definition *new_macro) +{ + struct macro_key *key; + splay_tree_node n = find_definition (name, new_macro->table->main_source, -1); + + if (n) + { + key = (struct macro_key *) n->key; + splay_tree_remove (new_macro->table->definitions, n->key); + } + + key = new_macro_key (new_macro->table, name, new_macro->table->main_source, + -1); + splay_tree_insert (new_macro->table->definitions, (splay_tree_key) key, + (splay_tree_value) new_macro); +} + + +void macro_undef (struct macro_source_file *source, int line, const char *name) { @@ -845,7 +871,12 @@ macro_lookup_definition (struct macro_source_file *source, int line, const char *name) { - splay_tree_node n = find_definition (name, source, line); + splay_tree_node n; + + /* Give user-defined macros priority over all others. */ + n = find_definition (name, macro_user_macros->main_source, -1); + if (! n) + n = find_definition (name, source, line); if (n) return (struct macro_definition *) n->value; @@ -873,6 +904,27 @@ } +/* 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; +} + +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); +} + + \f /* Creating and freeing macro tables. */ Index: macrotab.h =================================================================== RCS file: /cvs/src/src/gdb/macrotab.h,v retrieving revision 1.9 diff -u -r1.9 macrotab.h --- macrotab.h 1 Jan 2008 22:53:12 -0000 1.9 +++ macrotab.h 23 May 2008 21:07:18 -0000 @@ -72,6 +72,8 @@ /* 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 @@ -241,12 +243,23 @@ const char *replacement); +/* Record a macro definition given a fully-filled macro_definition + object. The object and its contents must be allocated + appropriately for the table into which the new macro will be + inserted; it is the caller's responsibility to ensure this. A + previous macro definition of the same name will be silently + removed. NAME is the name of the new macro; it is copied by this + function as needed. */ +void macro_define_user (const char *name, struct macro_definition *new_macro); + /* Record an #undefinition. Record in SOURCE's macro table that, at line number LINE in SOURCE, we removed the definition for the preprocessor symbol named NAME. */ void macro_undef (struct macro_source_file *source, int line, const char *name); +/* Delete a macro_definition object. */ +void macro_definition_delete (struct macro_definition *obj); /* Different kinds of macro definitions. */ enum macro_kind @@ -298,5 +311,16 @@ const char *name, int *definition_line)); +/* The table of macros defined by the user. */ +extern struct macro_table *macro_user_macros; + + +/* Callback function when walking a macro table. */ +typedef void (*macro_callback_fn) (const char *, + const struct macro_definition *); + +/* Call a function for each macro in the table. */ +void macro_for_each (struct macro_table *, macro_callback_fn); + #endif /* MACROTAB_H */ Index: testsuite/gdb.base/macscp.exp =================================================================== RCS file: /cvs/src/src/gdb/testsuite/gdb.base/macscp.exp,v retrieving revision 1.7 diff -u -r1.7 macscp.exp --- testsuite/gdb.base/macscp.exp 3 May 2008 22:30:51 -0000 1.7 +++ testsuite/gdb.base/macscp.exp 23 May 2008 21:07:20 -0000 @@ -423,8 +423,52 @@ " = 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." Index: doc/gdb.texinfo =================================================================== RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v retrieving revision 1.495 diff -u -r1.495 gdb.texinfo --- doc/gdb.texinfo 9 May 2008 17:02:01 -0000 1.495 +++ doc/gdb.texinfo 23 May 2008 21:07:23 -0000 @@ -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 +@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008 @c Free Software Foundation, Inc. @c @c %**start of header @@ -7822,31 +7822,29 @@ @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 @@ -7925,7 +7923,7 @@ (@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}. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFA: Patch: implement missing macro functions 2008-05-25 21:51 ` Tom Tromey @ 2008-05-26 16:18 ` Eli Zaretskii 2008-05-26 16:25 ` Tom Tromey 0 siblings, 1 reply; 12+ messages in thread From: Eli Zaretskii @ 2008-05-26 16:18 UTC (permalink / raw) To: Tom Tromey; +Cc: pedro, gdb-patches > Cc: pedro@codesourcery.com, gdb-patches@sourceware.org > From: Tom Tromey <tromey@redhat.com> > Date: Fri, 23 May 2008 15:07:56 -0600 > > I fixed all the macro-related uses of @command. Thanks. > Here's a new patch. Let me know what you think. It's okay, but for a single minor nit: > +macro define > +macro list > +macro undef > + These commands are now implemented. These allow macros to be > + defined, undefined, and listed interactively. I think we should delete the first sentence. Users who read NEWS do not know that these commands were documented, but not implemented. Just saying "These commands allow macros to be defined, undefined, and listed interactively from within GDB." is enough Thanks. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFA: Patch: implement missing macro functions 2008-05-26 16:18 ` Eli Zaretskii @ 2008-05-26 16:25 ` Tom Tromey 0 siblings, 0 replies; 12+ messages in thread From: Tom Tromey @ 2008-05-26 16:25 UTC (permalink / raw) To: Eli Zaretskii; +Cc: pedro, gdb-patches >>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes: >> + These commands are now implemented. These allow macros to be >> + defined, undefined, and listed interactively. Eli> I think we should delete the first sentence. Users who read NEWS do Eli> not know that these commands were documented, but not implemented. Eli> Just saying "These commands allow macros to be defined, undefined, and Eli> listed interactively from within GDB." is enough I made this change. I think I will hold off sending a new patch until after the next code review. Tom ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFA: Patch: implement missing macro functions 2008-05-25 12:37 ` Tom Tromey 2008-05-25 18:03 ` Eli Zaretskii @ 2008-05-25 20:39 ` Pedro Alves 1 sibling, 0 replies; 12+ messages in thread From: Pedro Alves @ 2008-05-25 20:39 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches A Friday 23 May 2008 21:28:32, Tom Tromey wrote: > >>>>> "Pedro" == Pedro Alves <pedro@codesourcery.com> writes: > > Pedro> You'll need someone else to comment on the big picture -- I'll > Pedro> comment on a few strokes, below, > > Here's an updated patch. I think it addresses all your comments. > Let me know what you think. Fine with me, thanks! -- Pedro Alves ^ permalink raw reply [flat|nested] 12+ messages in thread
[parent not found: <8f2776cb0805301626v4ff4d933ua6b833aaa7056aaa@mail.gmail.com>]
* Re: RFA: Patch: implement missing macro functions [not found] ` <8f2776cb0805301626v4ff4d933ua6b833aaa7056aaa@mail.gmail.com> @ 2008-06-06 0:22 ` Tom Tromey 2008-07-18 20:01 ` Daniel Jacobowitz 0 siblings, 1 reply; 12+ messages in thread From: Tom Tromey @ 2008-06-06 0:22 UTC (permalink / raw) To: Jim Blandy; +Cc: gdb-patches Jim sent me a private critique of this patch. (Thanks Jim.) Here is a new version, which I believe addresses all his comments: * Don't introduce macro_define_user * More comments for macro_for_each * macrotab.[ch] should continue to be just opaque macro table type implementation -- put special lookup in macroscope.c and not here * Don't export macro_definition_delete This required a couple other changes to make it so interactive redefinitions did not cause an error -- I decided the cleanest approach was to add a new table attribute, then use that. Also, I realized a Makefile.in fix was needed. Ok? Tom ChangeLog: 2008-06-05 Tom Tromey <tromey@redhat.com> * NEWS: Add entry for macro commands. * Makefile.in (macrocmd.o): Add gdb_string.h. * macroscope.h (user_macro_scope): Declare. (default_macro_scope): Update documentation. (macro_user_macros): Declare. * c-lang.c (c_preprocess_and_parse): Always attempt macro lookup. Use user_macro_scope. (null_macro_lookup): Remove. * macrotab.h (macro_callback_fn): Declare. (macro_for_each): Likewise. (macro_allow_redefinitions): Likewise. * macrotab.c (foreach_macro): New function (macro_for_each): Likewise. (struct macro_table) <redef_ok>: New field. (macro_allow_redefinitions): New function. (new_macro_table): Update. (macro_define_function): Likewise. (macro_define_object): Likewise. * macroscope.c (user_macro_scope): New function. (default_macro_scope): Use it. (macro_user_macros): New global. (standard_macro_lookup): Look in macro_user_macros. (_initialize_macroscope): New function. * macroexp.h (macro_is_whitespace, macro_is_digit, macro_is_identifier_nondigit): Declare. * macroexp.c (macro_is_whitespace): Rename. No longer static. (macro_is_digit): Likewise. (macro_is_identifier_nondigit): Likewise. (get_identifier): Update. (get_pp_number): Likewise. (get_token): Likewise. * macrocmd.c (skip_ws): New function. (extract_identifier): Likewise. (free_macro_definition_ptr): Likewise. (user_macros): Remove. (macro_define_command): Implement. (_initialize_macrocmd): Update. (macro_undef_command): Implement. (print_one_macro): New function. (macro_list_command): Implement. doc/ChangeLog: 2008-06-05 Tom Tromey <tromey@redhat.com> * gdb.texinfo (Macros): Update. Use @code rather than @command. testsuite/ChangeLog: 2008-06-05 Tom Tromey <tromey@redhat.com> * gdb.base/macscp.exp: Add macro tests. Index: Makefile.in =================================================================== RCS file: /cvs/src/src/gdb/Makefile.in,v retrieving revision 1.1018 diff -u -r1.1018 Makefile.in --- Makefile.in 9 May 2008 17:02:01 -0000 1.1018 +++ Makefile.in 6 Jun 2008 00:14:43 -0000 @@ -2468,7 +2468,7 @@ $(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) \ Index: NEWS =================================================================== RCS file: /cvs/src/src/gdb/NEWS,v retrieving revision 1.273 diff -u -r1.273 NEWS --- NEWS 9 May 2008 19:17:46 -0000 1.273 +++ NEWS 6 Jun 2008 00:14:44 -0000 @@ -78,6 +89,12 @@ the current CPSR value for instructions without symbols; previous versions of GDB behaved as if "set arm fallback-mode arm". +macro define +macro list +macro undef + These allow macros to be defined, undefined, and listed + interactively. + *** Changes in GDB 6.8 * New native configurations Index: macrocmd.c =================================================================== RCS file: /cvs/src/src/gdb/macrocmd.c,v retrieving revision 1.13 diff -u -r1.13 macrocmd.c --- macrocmd.c 1 Jan 2008 22:53:12 -0000 1.13 +++ macrocmd.c 6 Jun 2008 00:14:44 -0000 @@ -24,6 +24,7 @@ #include "macroscope.h" #include "command.h" #include "gdbcmd.h" +#include "gdb_string.h" \f /* The `macro' prefix command. */ @@ -189,31 +190,156 @@ \f /* 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 @@ 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); } Index: macroexp.c =================================================================== RCS file: /cvs/src/src/gdb/macroexp.c,v retrieving revision 1.13 diff -u -r1.13 macroexp.c --- macroexp.c 1 Jan 2008 22:53:12 -0000 1.13 +++ macroexp.c 6 Jun 2008 00:14:44 -0000 @@ -171,8 +171,8 @@ /* Recognizing preprocessor tokens. */ -static int -is_whitespace (int c) +int +macro_is_whitespace (int c) { return (c == ' ' || c == '\t' @@ -182,15 +182,15 @@ } -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 @@ 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 @@ 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 @@ 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; Index: macroexp.h =================================================================== RCS file: /cvs/src/src/gdb/macroexp.h,v retrieving revision 1.6 diff -u -r1.6 macroexp.h --- macroexp.h 1 Jan 2008 22:53:12 -0000 1.6 +++ macroexp.h 6 Jun 2008 00:14:44 -0000 @@ -84,5 +84,11 @@ 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 */ Index: macroscope.c =================================================================== RCS file: /cvs/src/src/gdb/macroscope.c,v retrieving revision 1.14 diff -u -r1.14 macroscope.c --- macroscope.c 1 Jan 2008 22:53:12 -0000 1.14 +++ macroscope.c 6 Jun 2008 00:14:44 -0000 @@ -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 @@ 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 @@ 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 @@ 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, "<user-defined>"); + macro_allow_redefinitions (macro_user_macros); } Index: macroscope.h =================================================================== RCS file: /cvs/src/src/gdb/macroscope.h,v retrieving revision 1.6 diff -u -r1.6 macroscope.h --- macroscope.h 1 Jan 2008 22:53:12 -0000 1.6 +++ macroscope.h 6 Jun 2008 00:14:44 -0000 @@ -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 *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. */ Index: macrotab.c =================================================================== RCS file: /cvs/src/src/gdb/macrotab.c,v retrieving revision 1.15 diff -u -r1.15 macrotab.c --- macrotab.c 1 Jan 2008 22:53:12 -0000 1.15 +++ macrotab.c 6 Jun 2008 00:14:44 -0000 @@ -46,6 +46,10 @@ #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 @@ } +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 @@ 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 @@ 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 @@ } +/* 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); +} + + \f /* Creating and freeing macro tables. */ @@ -893,6 +929,7 @@ 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), Index: macrotab.h =================================================================== RCS file: /cvs/src/src/gdb/macrotab.h,v retrieving revision 1.9 diff -u -r1.9 macrotab.h --- macrotab.h 1 Jan 2008 22:53:12 -0000 1.9 +++ macrotab.h 6 Jun 2008 00:14:44 -0000 @@ -72,6 +72,8 @@ /* 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 @@ /* 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_undef (struct macro_source_file *source, int line, const char *name); - /* Different kinds of macro definitions. */ enum macro_kind { @@ -298,5 +304,13 @@ 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 */ Index: doc/gdb.texinfo =================================================================== RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v retrieving revision 1.495 diff -u -r1.495 gdb.texinfo --- doc/gdb.texinfo 9 May 2008 17:02:01 -0000 1.495 +++ doc/gdb.texinfo 6 Jun 2008 00:14:48 -0000 @@ -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 +@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008 @c Free Software Foundation, Inc. @c @c %**start of header @@ -7822,31 +7834,29 @@ @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 @@ -7925,7 +7935,7 @@ (@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}. Index: testsuite/gdb.base/macscp.exp =================================================================== RCS file: /cvs/src/src/gdb/testsuite/gdb.base/macscp.exp,v retrieving revision 1.7 diff -u -r1.7 macscp.exp --- testsuite/gdb.base/macscp.exp 3 May 2008 22:30:51 -0000 1.7 +++ testsuite/gdb.base/macscp.exp 6 Jun 2008 00:14:50 -0000 @@ -423,8 +423,52 @@ " = 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." ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFA: Patch: implement missing macro functions 2008-06-06 0:22 ` Tom Tromey @ 2008-07-18 20:01 ` Daniel Jacobowitz 2008-07-18 20:56 ` Tom Tromey 0 siblings, 1 reply; 12+ messages in thread From: Daniel Jacobowitz @ 2008-07-18 20:01 UTC (permalink / raw) To: Tom Tromey; +Cc: Jim Blandy, gdb-patches On Thu, Jun 05, 2008 at 06:21:52PM -0600, Tom Tromey wrote: > Jim sent me a private critique of this patch. (Thanks Jim.) > > Here is a new version, which I believe addresses all his comments: > > * Don't introduce macro_define_user > * More comments for macro_for_each > * macrotab.[ch] should continue to be just opaque macro table type > implementation -- put special lookup in macroscope.c and not here > * Don't export macro_definition_delete > > This required a couple other changes to make it so interactive > redefinitions did not cause an error -- I decided the cleanest > approach was to add a new table attribute, then use that. > > Also, I realized a Makefile.in fix was needed. > > Ok? Since Jim doesn't seem to have further comments, this patch is OK - I went through it and didn't see anything wrong. > @@ -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 > +@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008 > @c Free Software Foundation, Inc. > @c > @c %**start of header Whoops, 2007 also please. -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFA: Patch: implement missing macro functions 2008-07-18 20:01 ` Daniel Jacobowitz @ 2008-07-18 20:56 ` Tom Tromey 0 siblings, 0 replies; 12+ messages in thread From: Tom Tromey @ 2008-07-18 20:56 UTC (permalink / raw) To: Jim Blandy; +Cc: gdb-patches >>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes: Daniel> Since Jim doesn't seem to have further comments, this patch is OK - I Daniel> went through it and didn't see anything wrong. Thanks, I checked it in. I noticed that this was PR 855, so I added a note to the ChangeLog entry before committing. >> -@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 >> +@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008 Daniel> Whoops, 2007 also please. Done. Tom ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2008-07-18 20:56 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-05-21 4:50 RFA: Patch: implement missing macro functions Tom Tromey
2008-05-24 15:42 ` Pedro Alves
2008-05-24 16:34 ` Tom Tromey
2008-05-25 12:37 ` Tom Tromey
2008-05-25 18:03 ` Eli Zaretskii
2008-05-25 21:51 ` Tom Tromey
2008-05-26 16:18 ` Eli Zaretskii
2008-05-26 16:25 ` Tom Tromey
2008-05-25 20:39 ` Pedro Alves
[not found] ` <8f2776cb0805301626v4ff4d933ua6b833aaa7056aaa@mail.gmail.com>
2008-06-06 0:22 ` Tom Tromey
2008-07-18 20:01 ` Daniel Jacobowitz
2008-07-18 20:56 ` Tom Tromey
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox