This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: RFA: Patch: implement missing macro functions


>>>>> "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"
 
 
 /* The `macro' prefix command.  */
@@ -189,31 +190,159 @@
 
 /* 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."),
 	   &macrolist);
 
-  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);
+}
+
+
 
 /* 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}.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]