gdb
authorTom Tromey <tromey@redhat.com>
Fri, 18 Jul 2008 20:55:33 +0000 (20:55 +0000)
committerTom Tromey <tromey@redhat.com>
Fri, 18 Jul 2008 20:55:33 +0000 (20:55 +0000)
PR gdb/855:
* NEWS: Add entry for macro commands.
* Makefile.in (macrocmd.o): Add gdb_string.h.
* macroscope.h (user_macro_scope): Declare.
(default_macro_scope): Update documentation.
(macro_user_macros): Declare.
* c-lang.c (c_preprocess_and_parse): Always attempt macro lookup.
Use user_macro_scope.
(null_macro_lookup): Remove.
* macrotab.h (macro_callback_fn): Declare.
(macro_for_each): Likewise.
(macro_allow_redefinitions): Likewise.
* macrotab.c (foreach_macro): New function
(macro_for_each): Likewise.
(struct macro_table) <redef_ok>: New field.
(macro_allow_redefinitions): New function.
(new_macro_table): Update.
(macro_define_function): Likewise.
(macro_define_object): Likewise.
* macroscope.c (user_macro_scope): New function.
(default_macro_scope): Use it.
(macro_user_macros): New global.
(standard_macro_lookup): Look in macro_user_macros.
(_initialize_macroscope): New function.
* macroexp.h (macro_is_whitespace, macro_is_digit,
macro_is_identifier_nondigit): Declare.
* macroexp.c (macro_is_whitespace): Rename.  No longer static.
(macro_is_digit): Likewise.
(macro_is_identifier_nondigit): Likewise.
(get_identifier): Update.
(get_pp_number): Likewise.
(get_token): Likewise.
* macrocmd.c (skip_ws): New function.
(extract_identifier): Likewise.
(free_macro_definition_ptr): Likewise.
(user_macros): Remove.
(macro_define_command): Implement.
(_initialize_macrocmd): Update.
(macro_undef_command): Implement.
(print_one_macro): New function.
(macro_list_command): Implement.
gdb/doc
* gdb.texinfo (Macros): Update.  Use @code rather than @command.
gdb/testsuite
* gdb.base/macscp.exp: Add macro tests.

15 files changed:
gdb/ChangeLog
gdb/Makefile.in
gdb/NEWS
gdb/c-lang.c
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/macrocmd.c
gdb/macroexp.c
gdb/macroexp.h
gdb/macroscope.c
gdb/macroscope.h
gdb/macrotab.c
gdb/macrotab.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/macscp.exp

index a3a6931..73b3847 100644 (file)
@@ -1,3 +1,47 @@
+2008-07-18  Tom Tromey  <tromey@redhat.com>
+
+       PR gdb/855:
+       * NEWS: Add entry for macro commands.
+       * Makefile.in (macrocmd.o): Add gdb_string.h.
+       * macroscope.h (user_macro_scope): Declare.
+       (default_macro_scope): Update documentation.
+       (macro_user_macros): Declare.
+       * c-lang.c (c_preprocess_and_parse): Always attempt macro lookup.
+       Use user_macro_scope.
+       (null_macro_lookup): Remove.
+       * macrotab.h (macro_callback_fn): Declare.
+       (macro_for_each): Likewise.
+       (macro_allow_redefinitions): Likewise.
+       * macrotab.c (foreach_macro): New function
+       (macro_for_each): Likewise.
+       (struct macro_table) <redef_ok>: New field.
+       (macro_allow_redefinitions): New function.
+       (new_macro_table): Update.
+       (macro_define_function): Likewise.
+       (macro_define_object): Likewise.
+       * macroscope.c (user_macro_scope): New function.
+       (default_macro_scope): Use it.
+       (macro_user_macros): New global.
+       (standard_macro_lookup): Look in macro_user_macros.
+       (_initialize_macroscope): New function.
+       * macroexp.h (macro_is_whitespace, macro_is_digit,
+       macro_is_identifier_nondigit): Declare.
+       * macroexp.c (macro_is_whitespace): Rename.  No longer static.
+       (macro_is_digit): Likewise.
+       (macro_is_identifier_nondigit): Likewise.
+       (get_identifier): Update.
+       (get_pp_number): Likewise.
+       (get_token): Likewise.
+       * macrocmd.c (skip_ws): New function.
+       (extract_identifier): Likewise.
+       (free_macro_definition_ptr): Likewise.
+       (user_macros): Remove.
+       (macro_define_command): Implement.
+       (_initialize_macrocmd): Update.
+       (macro_undef_command): Implement.
+       (print_one_macro): New function.
+       (macro_list_command): Implement.
+
 2008-07-18  Joseph Myers  <joseph@codesourcery.com>
 
        * configure.ac: Put old value of $LIBS after -lbfd -liberty $intl
index 3e82b92..e2397df 100644 (file)
@@ -2456,7 +2456,7 @@ m88k-tdep.o: m88k-tdep.c $(defs_h) $(arch_utils_h) $(dis_asm_h) $(frame_h) \
        $(regcache_h) $(regset_h) $(symtab_h) $(trad_frame_h) $(value_h) \
        $(gdb_assert_h) $(gdb_string_h) $(m88k_tdep_h)
 macrocmd.o: macrocmd.c $(defs_h) $(macrotab_h) $(macroexp_h) $(macroscope_h) \
-       $(command_h) $(gdbcmd_h)
+       $(command_h) $(gdbcmd_h) $(gdb_string_h)
 macroexp.o: macroexp.c $(defs_h) $(gdb_obstack_h) $(bcache_h) $(macrotab_h) \
        $(macroexp_h) $(gdb_assert_h)
 macroscope.o: macroscope.c $(defs_h) $(macroscope_h) $(symtab_h) $(source_h) \
index e783259..9d9b30c 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -112,6 +112,12 @@ show disable-randomization
 
 x86 DICOS                      i[34567]86-*-dicos*
 
+macro define
+macro list
+macro undef
+  These allow macros to be defined, undefined, and listed
+  interactively.
+
 *** Changes in GDB 6.8
 
 * New native configurations
index 29aa765..9ce4bb9 100644 (file)
@@ -261,13 +261,6 @@ macro_lookup_ftype *expression_macro_lookup_func;
 void *expression_macro_lookup_baton;
 
 
-static struct macro_definition *
-null_macro_lookup (const char *name, void *baton)
-{
-  return 0;
-}
-
-
 static int
 c_preprocess_and_parse (void)
 {
@@ -279,17 +272,11 @@ c_preprocess_and_parse (void)
     scope = sal_macro_scope (find_pc_line (expression_context_pc, 0));
   else
     scope = default_macro_scope ();
+  if (! scope)
+    scope = user_macro_scope ();
 
-  if (scope)
-    {
-      expression_macro_lookup_func = standard_macro_lookup;
-      expression_macro_lookup_baton = (void *) scope;
-    }
-  else
-    {
-      expression_macro_lookup_func = null_macro_lookup;
-      expression_macro_lookup_baton = 0;      
-    }
+  expression_macro_lookup_func = standard_macro_lookup;
+  expression_macro_lookup_baton = (void *) scope;
 
   gdb_assert (! macro_original_text);
   make_cleanup (scan_macro_cleanup, 0);
index 8786b4a..3c6b66d 100644 (file)
@@ -1,3 +1,7 @@
+2008-07-18  Tom Tromey  <tromey@redhat.com>
+
+       * gdb.texinfo (Macros): Update.  Use @code rather than @command.
+
 2008-07-10  Doug Evans  <dje@google.com>
 
        * doc/gdb.texinfo: Document "set print symbol-loading on|off".
index 2920179..06d1db2 100644 (file)
@@ -1,6 +1,6 @@
 \input texinfo      @c -*-texinfo-*-
 @c Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998,
-@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008
+@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
 @c Free Software Foundation, Inc.
 @c
 @c %**start of header
@@ -7923,31 +7923,29 @@ source location where that definition was established.
 @cindex macros, user-defined
 @item macro define @var{macro} @var{replacement-list}
 @itemx macro define @var{macro}(@var{arglist}) @var{replacement-list}
-@i{(This command is not yet implemented.)}  Introduce a definition for a
-preprocessor macro named @var{macro}, invocations of which are replaced
-by the tokens given in @var{replacement-list}.  The first form of this
-command defines an ``object-like'' macro, which takes no arguments; the
-second form defines a ``function-like'' macro, which takes the arguments
-given in @var{arglist}.
-
-A definition introduced by this command is in scope in every expression
-evaluated in @value{GDBN}, until it is removed with the @command{macro
-undef} command, described below.  The definition overrides all
-definitions for @var{macro} present in the program being debugged, as
-well as any previous user-supplied definition.
+Introduce a definition for a preprocessor macro named @var{macro},
+invocations of which are replaced by the tokens given in
+@var{replacement-list}.  The first form of this command defines an
+``object-like'' macro, which takes no arguments; the second form
+defines a ``function-like'' macro, which takes the arguments given in
+@var{arglist}.
+
+A definition introduced by this command is in scope in every
+expression evaluated in @value{GDBN}, until it is removed with the
+@code{macro undef} command, described below.  The definition overrides
+all definitions for @var{macro} present in the program being debugged,
+as well as any previous user-supplied definition.
 
 @kindex macro undef
 @item macro undef @var{macro}
-@i{(This command is not yet implemented.)}  Remove any user-supplied
-definition for the macro named @var{macro}.  This command only affects
-definitions provided with the @command{macro define} command, described
-above; it cannot remove definitions present in the program being
-debugged.
+Remove any user-supplied definition for the macro named @var{macro}.
+This command only affects definitions provided with the @code{macro
+define} command, described above; it cannot remove definitions present
+in the program being debugged.
 
 @kindex macro list
 @item macro list
-@i{(This command is not yet implemented.)}  List all the macros
-defined using the @code{macro define} command.
+List all the macros defined using the @code{macro define} command.
 @end table
 
 @cindex macros, example of debugging with
@@ -8026,7 +8024,7 @@ expands to: once (M + 1)
 (@value{GDBP})
 @end smallexample
 
-In the example above, note that @command{macro expand-once} expands only
+In the example above, note that @code{macro expand-once} expands only
 the macro invocation explicit in the original text --- the invocation of
 @code{ADD} --- but does not expand the invocation of the macro @code{M},
 which was introduced by @code{ADD}.
index c5d3a8f..4a70d4f 100644 (file)
@@ -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 @@ info_macro_command (char *name, int from_tty)
 \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 @@ Remove the definition of the C/C++ preprocessor macro with the given name."),
   add_cmd ("list", no_class, macro_list_command,
           _("List all the macros defined using the `macro define' command."),
           &macrolist);
-
-  user_macros = new_macro_table (0, 0);
 }
index f85cb4b..0cb9575 100644 (file)
@@ -171,8 +171,8 @@ appendmem (struct macro_buffer *b, char *addr, int len)
 /* Recognizing preprocessor tokens.  */
 
 
-static int
-is_whitespace (int c)
+int
+macro_is_whitespace (int c)
 {
   return (c == ' '
           || c == '\t'
@@ -182,15 +182,15 @@ is_whitespace (int c)
 }
 
 
-static int
-is_digit (int c)
+int
+macro_is_digit (int c)
 {
   return ('0' <= c && c <= '9');
 }
 
 
-static int
-is_identifier_nondigit (int c)
+int
+macro_is_identifier_nondigit (int c)
 {
   return (c == '_'
           || ('a' <= c && c <= 'z')
@@ -255,13 +255,13 @@ static int
 get_identifier (struct macro_buffer *tok, char *p, char *end)
 {
   if (p < end
-      && is_identifier_nondigit (*p))
+      && macro_is_identifier_nondigit (*p))
     {
       char *tok_start = p;
 
       while (p < end
-             && (is_identifier_nondigit (*p)
-                 || is_digit (*p)))
+             && (macro_is_identifier_nondigit (*p)
+                 || macro_is_digit (*p)))
         p++;
 
       set_token (tok, tok_start, p);
@@ -277,15 +277,15 @@ static int
 get_pp_number (struct macro_buffer *tok, char *p, char *end)
 {
   if (p < end
-      && (is_digit (*p)
+      && (macro_is_digit (*p)
           || *p == '.'))
     {
       char *tok_start = p;
 
       while (p < end)
         {
-          if (is_digit (*p)
-              || is_identifier_nondigit (*p)
+          if (macro_is_digit (*p)
+              || macro_is_identifier_nondigit (*p)
               || *p == '.')
             p++;
           else if (p + 2 <= end
@@ -485,7 +485,7 @@ get_token (struct macro_buffer *tok,
      only occur after a #include, which we will never see.  */
 
   while (p < end)
-    if (is_whitespace (*p))
+    if (macro_is_whitespace (*p))
       p++;
     else if (get_comment (tok, p, end))
       p += tok->len;
index b10c13d..c563d1c 100644 (file)
@@ -84,5 +84,11 @@ char *macro_expand_next (char **lexptr,
                          macro_lookup_ftype *lookup_func,
                          void *lookup_baton);
 
+/* Functions to classify characters according to cpp rules.  */
+
+int macro_is_whitespace (int c);
+int macro_is_identifier_nondigit (int c);
+int macro_is_digit (int c);
+
 
 #endif /* MACROEXP_H */
index 7383986..ef334b7 100644 (file)
 #include "inferior.h"
 #include "complaints.h"
 
+/* A table of user-defined macros.  Unlike the macro tables used for
+   symtabs, this one uses xmalloc for all its allocation, not an
+   obstack, and it doesn't bcache anything; it just xmallocs things.  So
+   it's perfectly possible to remove things from this, or redefine
+   things.  */
+struct macro_table *macro_user_macros;
+
 
 struct macro_scope *
 sal_macro_scope (struct symtab_and_line sal)
@@ -78,6 +85,16 @@ sal_macro_scope (struct symtab_and_line sal)
 
 
 struct macro_scope *
+user_macro_scope (void)
+{
+  struct macro_scope *ms;
+  ms = XNEW (struct macro_scope);
+  ms->file = macro_main (macro_user_macros);
+  ms->line = -1;
+  return ms;
+}
+
+struct macro_scope *
 default_macro_scope (void)
 {
   struct symtab_and_line sal;
@@ -110,7 +127,11 @@ default_macro_scope (void)
       sal.line = cursal.line;
     }
 
-  return sal_macro_scope (sal);
+  ms = sal_macro_scope (sal);
+  if (! ms)
+    ms = user_macro_scope ();
+
+  return ms;
 }
 
 
@@ -121,6 +142,20 @@ struct macro_definition *
 standard_macro_lookup (const char *name, void *baton)
 {
   struct macro_scope *ms = (struct macro_scope *) baton;
+  struct macro_definition *result;
+
+  /* Give user-defined macros priority over all others.  */
+  result = macro_lookup_definition (macro_main (macro_user_macros), -1, name);
+  if (! result)
+    result = macro_lookup_definition (ms->file, ms->line, name);
+  return result;
+}
+
 
-  return macro_lookup_definition (ms->file, ms->line, name);
+void
+_initialize_macroscope (void)
+{
+  macro_user_macros = new_macro_table (0, 0);
+  macro_set_main (macro_user_macros, "<user-defined>");
+  macro_allow_redefinitions (macro_user_macros);
 }
index 4c288b5..d81a760 100644 (file)
@@ -24,6 +24,9 @@
 #include "symtab.h"
 
 
+/* The table of macros defined by the user.  */
+extern struct macro_table *macro_user_macros;
+
 /* All the information we need to decide which macro definitions are
    in scope: a source file (either a main source file or an
    #inclusion), and a line number in that file.  */
@@ -39,12 +42,18 @@ struct macro_scope {
 struct macro_scope *sal_macro_scope (struct symtab_and_line sal);
 
 
+/* Return a `struct macro_scope' object representing just the
+   user-defined macros.  The result is allocated using xmalloc; the
+   caller is responsible for freeing it.  */
+struct macro_scope *user_macro_scope (void);
+
 /* Return a `struct macro_scope' object describing the scope the `macro
    expand' and `macro expand-once' commands should use for looking up
    macros.  If we have a selected frame, this is the source location of
    its PC; otherwise, this is the last listing position.
 
-   If we have no macro information for the current location, return zero.
+   If we have no macro information for the current location, return
+   the user macro scope.
 
    The object returned is allocated using xmalloc; the caller is
    responsible for freeing it.  */
index 27e6fe6..7633c98 100644 (file)
@@ -46,6 +46,10 @@ struct macro_table
      #inclusion tree; everything else is #included from here.  */
   struct macro_source_file *main_source;
 
+  /* True if macros in this table can be redefined without issuing an
+     error.  */
+  int redef_ok;
+
   /* The table of macro definitions.  This is a splay tree (an ordered
      binary tree that stays balanced, effectively), sorted by macro
      name.  Where a macro gets defined more than once (presumably with
@@ -427,6 +431,14 @@ macro_main (struct macro_table *t)
 }
 
 
+void
+macro_allow_redefinitions (struct macro_table *t)
+{
+  gdb_assert (! t->obstack);
+  t->redef_ok = 1;
+}
+
+
 struct macro_source_file *
 macro_include (struct macro_source_file *source,
                int line,
@@ -731,13 +743,14 @@ macro_define_object (struct macro_source_file *source, int line,
                      const char *name, const char *replacement)
 {
   struct macro_table *t = source->table;
-  struct macro_key *k;
+  struct macro_key *k = NULL;
   struct macro_definition *d;
 
-  k = check_for_redefinition (source, line, 
-                              name, macro_object_like,
-                              0, 0,
-                              replacement);
+  if (! t->redef_ok)
+    k = check_for_redefinition (source, line, 
+                               name, macro_object_like,
+                               0, 0,
+                               replacement);
 
   /* If we're redefining a symbol, and the existing key would be
      identical to our new key, then the splay_tree_insert function
@@ -764,13 +777,14 @@ macro_define_function (struct macro_source_file *source, int line,
                        const char *replacement)
 {
   struct macro_table *t = source->table;
-  struct macro_key *k;
+  struct macro_key *k = NULL;
   struct macro_definition *d;
 
-  k = check_for_redefinition (source, line,
-                              name, macro_function_like,
-                              argc, argv,
-                              replacement);
+  if (! t->redef_ok)
+    k = check_for_redefinition (source, line,
+                               name, macro_function_like,
+                               argc, argv,
+                               replacement);
 
   /* See comments about duplicate keys in macro_define_object.  */
   if (k && ! key_compare (k, name, source, line))
@@ -873,6 +887,28 @@ macro_definition_location (struct macro_source_file *source,
 }
 
 
+/* Helper function for macro_for_each.  */
+static int
+foreach_macro (splay_tree_node node, void *fnp)
+{
+  macro_callback_fn *fn = (macro_callback_fn *) fnp;
+  struct macro_key *key = (struct macro_key *) node->key;
+  struct macro_definition *def = (struct macro_definition *) node->value;
+  (**fn) (key->name, def);
+  return 0;
+}
+
+/* Call FN for every macro in TABLE.  */
+void
+macro_for_each (struct macro_table *table, macro_callback_fn fn)
+{
+  /* Note that we pass in the address of 'fn' because, pedantically
+     speaking, we can't necessarily cast a pointer-to-function to a
+     void*.  */
+  splay_tree_foreach (table->definitions, foreach_macro, &fn);
+}
+
+
 \f
 /* Creating and freeing macro tables.  */
 
@@ -893,6 +929,7 @@ new_macro_table (struct obstack *obstack,
   t->obstack = obstack;
   t->bcache = b;
   t->main_source = NULL;
+  t->redef_ok = 0;
   t->definitions = (splay_tree_new_with_allocator
                     (macro_tree_compare,
                      ((splay_tree_delete_key_fn) macro_tree_delete_key),
index eb546bc..5ff36ea 100644 (file)
@@ -72,6 +72,8 @@ struct bcache;
 /* A table of all the macro definitions for a given compilation unit.  */
 struct macro_table;
 
+/* The definition of a single macro.  */
+struct macro_definition;
 
 /* A source file that participated in a compilation unit --- either a
    main file, or an #included file.  If a file is #included more than
@@ -189,6 +191,11 @@ struct macro_source_file *macro_set_main (struct macro_table *table,
 /* Return the main source file of the macro table TABLE.  */
 struct macro_source_file *macro_main (struct macro_table *table);
 
+/* Mark the macro table TABLE so that macros defined in this table can
+   be redefined without error.  Note that it invalid to call this if
+   TABLE is allocated on an obstack.  */
+void macro_allow_redefinitions (struct macro_table *table);
+
 
 /* Record a #inclusion.
    Record in SOURCE's macro table that, at line number LINE in SOURCE,
@@ -247,7 +254,6 @@ void macro_define_function (struct macro_source_file *source, int line,
 void macro_undef (struct macro_source_file *source, int line,
                   const char *name);
 
-
 /* Different kinds of macro definitions.  */
 enum macro_kind
 {
@@ -298,5 +304,13 @@ struct macro_source_file *(macro_definition_location
                             const char *name,
                             int *definition_line));
 
+/* Callback function when walking a macro table.  NAME is the name of
+   the macro, and DEFINITION is the definition.  */
+typedef void (*macro_callback_fn) (const char *name,
+                                  const struct macro_definition *definition);
+
+/* Call the function FN for each macro in the macro table TABLE.  */
+void macro_for_each (struct macro_table *table, macro_callback_fn fn);
+
 
 #endif /* MACROTAB_H */
index adcadd7..1a07bc1 100644 (file)
@@ -1,3 +1,7 @@
+2008-07-18  Tom Tromey  <tromey@redhat.com>
+
+       * gdb.base/macscp.exp: Add macro tests.
+
 2008-07-17  Paul Pluzhnikov  <ppluzhnikov@google.com>
 
        * gdb.base/foll-fork.exp: Fix for Linux/VDSO failure.
index ccefc85..90c2d95 100644 (file)
@@ -423,8 +423,52 @@ gdb_test "print M" \
     " = 0" \
     "print expression with macro in scope."
 
+gdb_test "macro define M 72" \
+  "" \
+  "user macro override"
+
+gdb_test "print M" \
+  " = 72" \
+  "choose user macro"
+
+gdb_test "macro undef M" \
+  "" \
+  "remove user override"
+
+gdb_test "print M" \
+    " = 0" \
+    "print expression with macro after removing override"
+
 gdb_test "next" "foo = 2;" "next to definition"
 
 gdb_test "print M" \
     "No symbol \"M\" in current context\." \
     "print expression with macro after undef."
+
+gdb_test "macro define M 5" \
+  "" \
+  "basic macro define"
+
+gdb_test "print M" \
+  " = 5" \
+  "expansion of defined macro"
+
+gdb_test "macro list" \
+  "macro define M 5" \
+  "basic macro list"
+
+gdb_test "macro define M(x) x" \
+  "" \
+  "basic redefine, macro with args"
+
+gdb_test "print M (7)" \
+  " = 7" \
+  "expansion of macro with arguments"
+
+gdb_test "macro undef M" \
+  "" \
+  "basic macro undef"
+
+gdb_test "print M" \
+    "No symbol \"M\" in current context\." \
+    "print expression with macro after user undef."