Add commands for manually expanding macros and showing their
authorJim Blandy <jimb@codesourcery.com>
Thu, 16 May 2002 21:15:53 +0000 (21:15 +0000)
committerJim Blandy <jimb@codesourcery.com>
Thu, 16 May 2002 21:15:53 +0000 (21:15 +0000)
definitions.
* macrocmd.c, macroscope.c, macroscope.h: New files.
* Makefile.in (SFILES): Add macrocmd.c, macroscope.c.
(macroscope_h): New variable.
(HFILES_NO_SRCDIR): Add macroscope.h.
(COMMON_OBS): Add macrocmd.o, macroscope.o.
(macroscope.o, macrocmd.o): New rules.

gdb/ChangeLog
gdb/Makefile.in
gdb/macrocmd.c [new file with mode: 0644]
gdb/macroscope.c [new file with mode: 0644]
gdb/macroscope.h [new file with mode: 0644]

index 1cd20642304c6192041124cbd98a7cb3d1ca2a64..7d38fd839b070643f2f2fb8cf24315b2da3dca65 100644 (file)
@@ -1,5 +1,14 @@
 2002-05-16  Jim Blandy  <jimb@redhat.com>
 
+       Add commands for manually expanding macros and showing their
+       definitions.
+       * macrocmd.c, macroscope.c, macroscope.h: New files.
+       * Makefile.in (SFILES): Add macrocmd.c, macroscope.c.
+       (macroscope_h): New variable.
+       (HFILES_NO_SRCDIR): Add macroscope.h.
+       (COMMON_OBS): Add macrocmd.o, macroscope.o.
+       (macroscope.o, macrocmd.o): New rules.
+
        Teach the Dwarf 2 reader to read macro information.
        * dwarf2read.c: #include "macrotab.h".
        (dwarf_macinfo_buffer): New variable.
index dfcbf8c988778053fca79fda44154f0153b97589..333cbc39e54d2dfe023b98053b5832cda4c505f5 100644 (file)
@@ -539,7 +539,7 @@ SFILES = ax-general.c ax-gdb.c bcache.c blockframe.c breakpoint.c \
        m2-exp.y m2-lang.c m2-typeprint.c m2-valprint.c main.c maint.c \
        memattr.c mem-break.c minsyms.c mipsread.c nlmread.c objfiles.c \
        p-exp.y p-lang.c p-typeprint.c p-valprint.c parse.c \
-       macrotab.c macroexp.c \
+       macrotab.c macroexp.c macrocmd.c macroscope.c \
        printcmd.c remote.c remote-nrom.c scm-exp.c scm-lang.c \
        scm-valprint.c source.c stabsread.c stack.c symfile.c \
        symmisc.c symtab.c linespec.c target.c thread.c top.c tracepoint.c \
@@ -639,6 +639,7 @@ language_h =        language.h
 linespec_h =   linespec.h
 macroexp_h =   macroexp.h
 macrotab_h =    macrotab.h $(obstack_h) $(bcache_h)
+macroscope_h =  macroscope.h $(macrotab_h) $(symtab_h)
 memattr_h =     memattr.h
 monitor_h =    monitor.h
 objfiles_h =   objfiles.h
@@ -677,7 +678,7 @@ HFILES_NO_SRCDIR = bcache.h buildsym.h call-cmds.h coff-solib.h defs.h \
        gdb-stabs.h $(inferior_h) language.h minimon.h monitor.h \
        objfiles.h parser-defs.h serial.h solib.h \
        symfile.h stabsread.h target.h terminal.h typeprint.h xcoffsolib.h \
-       macrotab.h macroexp.h \
+       macrotab.h macroexp.h macroscope.h \
        c-lang.h ch-lang.h f-lang.h \
        jv-lang.h \
        m2-lang.h  p-lang.h \
@@ -720,7 +721,7 @@ COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \
        source.o values.o eval.o valops.o valarith.o valprint.o printcmd.o \
        symtab.o symfile.o symmisc.o linespec.o infcmd.o infrun.o \
        expprint.o environ.o stack.o thread.o \
-       macrotab.o macroexp.o \
+       macrotab.o macrocmd.o macroexp.o macroscope.o \
        event-loop.o event-top.o inf-loop.o completer.o \
        gdbarch.o arch-utils.o gdbtypes.o copying.o $(DEPFILES) \
        memattr.o mem-break.o target.o parse.o language.o $(YYOBJ) buildsym.o \
@@ -2142,6 +2143,11 @@ macroexp.o: macroexp.c $(defs_h) $(macrotab_h)
 macrotab.o: macrotab.c $(defs_h) $(obstack_h) $(objfiles_h) $(symtab_h) \
        $(macrotab_h) $(splay_tree_h) gdb_assert.h $(bcache_h)
 
+macroscope.o: macroscope.c $(defs_h) $(macroscope_h)
+
+macrocmd.o: macrocmd.c $(defs_h) $(macrotab_h) $(macroexp_h) \
+       $(macroscope_h) $(command_h) $(gdbcmd_h)
+
 target.o: target.c $(bfd_h) $(defs_h) $(gdbcmd_h) $(inferior_h) \
        $(objfiles_h) $(symfile_h) $(target_h) $(gdb_string_h) $(regcache_h)
 
diff --git a/gdb/macrocmd.c b/gdb/macrocmd.c
new file mode 100644 (file)
index 0000000..1d14735
--- /dev/null
@@ -0,0 +1,287 @@
+/* C preprocessor macro expansion commands for GDB.
+   Copyright 2002 Free Software Foundation, Inc.
+   Contributed by Red Hat, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+
+#include "defs.h"
+#include "macrotab.h"
+#include "macroexp.h"
+#include "macroscope.h"
+#include "command.h"
+#include "gdbcmd.h"
+
+\f
+/* The `macro' prefix command.  */
+
+static struct cmd_list_element *macrolist;
+
+static void
+macro_command (char *arg, int from_tty)
+{
+  printf_unfiltered
+    ("\"macro\" must be followed by the name of a macro command.\n");
+  help_list (macrolist, "macro ", -1, gdb_stdout);
+}
+
+
+\f
+/* Macro expansion commands.  */
+
+
+static void
+macro_expand_command (char *exp, int from_tty)
+{
+  struct macro_scope *ms = NULL;
+  char *expanded = NULL;
+  struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms);
+  make_cleanup (free_current_contents, &expanded);
+
+  /* You know, when the user doesn't specify any expression, it would be
+     really cool if this defaulted to the last expression evaluated.
+     Then it would be easy to ask, "Hey, what did I just evaluate?"  But
+     at the moment, the `print' commands don't save the last expression
+     evaluated, just its value.  */
+  if (! exp || ! *exp)
+    error ("You must follow the `macro expand' command with the"
+           " expression you\n"
+           "want to expand.");
+
+  ms = default_macro_scope ();
+  if (ms)
+    {
+      expanded = macro_expand (exp, standard_macro_lookup, ms);
+      fputs_filtered ("expands to: ", gdb_stdout);
+      fputs_filtered (expanded, gdb_stdout);
+      fputs_filtered ("\n", gdb_stdout);
+    }
+  else
+    fputs_filtered ("GDB has no preprocessor macro information for "
+                    "that code.\n",
+                    gdb_stdout);
+
+  do_cleanups (cleanup_chain);
+  return;
+}
+
+
+static void
+macro_expand_once_command (char *exp, int from_tty)
+{
+  struct macro_scope *ms = NULL;
+  char *expanded = NULL;
+  struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms);
+  make_cleanup (free_current_contents, &expanded);
+
+  /* You know, when the user doesn't specify any expression, it would be
+     really cool if this defaulted to the last expression evaluated.
+     And it should set the once-expanded text as the new `last
+     expression'.  That way, you could just hit return over and over and
+     see the expression expanded one level at a time.  */
+  if (! exp || ! *exp)
+    error ("You must follow the `macro expand-once' command with"
+           " the expression\n"
+           "you want to expand.");
+
+  ms = default_macro_scope ();
+  if (ms)
+    {
+      expanded = macro_expand_once (exp, standard_macro_lookup, ms);
+      fputs_filtered ("expands to: ", gdb_stdout);
+      fputs_filtered (expanded, gdb_stdout);
+      fputs_filtered ("\n", gdb_stdout);
+    }
+  else
+    fputs_filtered ("GDB has no preprocessor macro information for "
+                    "that code.\n",
+                    gdb_stdout);
+
+  do_cleanups (cleanup_chain);
+  return;
+}
+
+
+static void
+show_pp_source_pos (struct ui_file *stream,
+                    struct macro_source_file *file,
+                    int line)
+{
+  fprintf_filtered (stream, "%s:%d\n", file->filename, line);
+
+  while (file->included_by)
+    {
+      fprintf_filtered (gdb_stdout, "  included at %s:%d\n",
+                        file->included_by->filename,
+                        file->included_at_line);
+      file = file->included_by;
+    }
+}
+
+
+static void
+show_macro_command (char *name, int from_tty)
+{
+  struct macro_scope *ms = NULL;
+  struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms);
+  struct macro_definition *d;
+  
+  if (! name || ! *name)
+    error ("You must follow the `show macro' command with the name"
+           " of the macro\n"
+           "whose definition you want to see.");
+
+  ms = default_macro_scope ();
+  if (! ms)
+    error ("GDB has no preprocessor macro information for that code.\n");
+
+  d = macro_lookup_definition (ms->file, ms->line, name);
+  if (d)
+    {
+      int line;
+      struct macro_source_file *file
+        = macro_definition_location (ms->file, ms->line, name, &line);
+
+      fprintf_filtered (gdb_stdout, "Defined at ");
+      show_pp_source_pos (gdb_stdout, file, line);
+      fprintf_filtered (gdb_stdout, "#define %s", name);
+      if (d->kind == macro_function_like)
+        {
+          int i;
+
+          fputs_filtered ("(", gdb_stdout);
+          for (i = 0; i < d->argc; i++)
+            {
+              fputs_filtered (d->argv[i], gdb_stdout);
+              if (i + 1 < d->argc)
+                fputs_filtered (", ", gdb_stdout);
+            }
+          fputs_filtered (")", gdb_stdout);
+        }
+      fprintf_filtered (gdb_stdout, " %s\n", d->replacement);
+    }
+  else
+    {
+      fprintf_filtered (gdb_stdout,
+                        "The symbol `%s' has no definition as a C/C++"
+                        " preprocessor macro\n"
+                        "at ", name);
+      show_pp_source_pos (gdb_stdout, ms->file, ms->line);
+    }
+
+  do_cleanups (cleanup_chain);
+}
+
+
+\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
+macro_define_command (char *exp, int from_tty)
+{
+  error ("Command not implemented yet.");
+}
+
+
+static void
+macro_undef_command (char *exp, int from_tty)
+{
+  error ("Command not implemented yet.");
+}
+
+
+static void
+macro_list_command (char *exp, int from_tty)
+{
+  error ("Command not implemented yet.");
+}
+
+
+\f
+/* Initializing the `macrocmd' module.  */
+
+void
+_initialize_macrocmd (void)
+{
+  struct cmd_list_element *c;
+
+  /* We introduce a new command prefix, `macro', under which we'll put
+     the various commands for working with preprocessor macros.  */
+  add_prefix_cmd
+    ("macro", class_info, macro_command,
+     "Prefix for commands dealing with C preprocessor macros.",
+     &macrolist, "macro ", 0, &cmdlist);
+
+  add_cmd
+    ("expand", no_class, macro_expand_command,
+     "Fully expand any C/C++ preprocessor macro invocations in EXPRESSION.\n"
+     "Show the expanded expression.",
+     &macrolist);
+  add_alias_cmd ("exp", "expand", no_class, 1, &macrolist);
+  add_cmd
+    ("expand-once", no_class, macro_expand_once_command,
+     "Expand C/C++ preprocessor macro invocations appearing directly in"
+     " EXPRESSION.\n"
+     "Show the expanded expression.\n"
+     "\n"
+     "This command differs from `macro expand' in that it only expands macro\n"
+     "invocations that appear directly in EXPRESSION; if expanding a macro\n"
+     "introduces further macro invocations, those are left unexpanded.\n"
+     "\n"
+     "`macro expand-once' helps you see how a particular macro expands,\n"
+     "whereas `macro expand' shows you how all the macros involved in an\n"
+     "expression work together to yield a pre-processed expression.",
+     &macrolist);
+  add_alias_cmd ("exp1", "expand-once", no_class, 1, &macrolist);
+
+  add_cmd
+    ("macro", no_class, show_macro_command,
+     "Show the definition of MACRO, and its source location.",
+     &showlist);
+
+  add_cmd
+    ("define", no_class, macro_define_command,
+     "Define a new C/C++ preprocessor macro.\n"
+     "The GDB command `macro define DEFINITION' is equivalent to placing a\n"
+     "preprocessor directive of the form `#define DEFINITION' such that the\n"
+     "definition is visible in all the inferior's source files.\n"
+     "For example:\n"
+     "  (gdb) macro define PI (3.1415926)\n"
+     "  (gdb) macro define MIN(x,y) ((x) < (y) ? (x) : (y))",
+     &macrolist);
+
+  add_cmd
+    ("undef", no_class, macro_undef_command,
+     "Remove the definition of the C/C++ preprocessor macro with the"
+     " given name.",
+     &macrolist);
+
+  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);
+}
diff --git a/gdb/macroscope.c b/gdb/macroscope.c
new file mode 100644 (file)
index 0000000..4441be3
--- /dev/null
@@ -0,0 +1,107 @@
+/* Functions for deciding which macros are currently in scope.
+   Copyright 2002 Free Software Foundation, Inc.
+   Contributed by Red Hat, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+
+#include "macroscope.h"
+#include "symtab.h"
+#include "target.h"
+#include "frame.h"
+#include "inferior.h"
+
+
+struct macro_scope *
+sal_macro_scope (struct symtab_and_line sal)
+{
+  struct macro_source_file *main;
+  struct macro_scope *ms;
+
+  if (! sal.symtab
+      || ! sal.symtab->macro_table)
+    return 0;
+
+  ms = (struct macro_scope *) xmalloc (sizeof (*ms));
+
+  main = macro_main (sal.symtab->macro_table);
+  ms->file = macro_lookup_inclusion (main, sal.symtab->filename);
+
+  if (! ms->file)
+    internal_error
+      (__FILE__, __LINE__,
+       "\n"
+       "the symtab `%s' refers to a preprocessor macro table which doesn't\n"
+       "have any record of processing a file by that name.\n",
+       sal.symtab->filename);
+
+  ms->line = sal.line;
+
+  return ms;
+}
+
+
+struct macro_scope *
+default_macro_scope ()
+{
+  struct symtab_and_line sal;
+  struct macro_source_file *main;
+  struct macro_scope *ms;
+
+  /* If there's a selected frame, use its PC.  */ 
+  if (selected_frame)
+    sal = find_pc_line (selected_frame->pc, 0);
+  
+  /* If the target has any registers at all, then use its PC.  Why we
+     would have registers but no stack, I'm not sure.  */
+  else if (target_has_registers)
+    sal = find_pc_line (read_pc (), 0);
+
+  /* If all else fails, fall back to the current listing position.  */
+  else
+    {
+      /* Don't call select_source_symtab here.  That can raise an
+         error if symbols aren't loaded, but GDB calls the expression
+         evaluator in all sorts of contexts.
+
+         For example, commands like `set width' call the expression
+         evaluator to evaluate their numeric arguments.  If the
+         current language is C, then that may call this function to
+         choose a scope for macro expansion.  If you don't have any
+         symbol files loaded, then select_source_symtab will raise an
+         error.  But `set width' shouldn't raise an error just because
+         it can't decide which scope to macro-expand its argument in.  */
+      sal.symtab = current_source_symtab;
+      sal.line = current_source_line;
+    }
+
+  return sal_macro_scope (sal);
+}
+
+
+/* Look up the definition of the macro named NAME in scope at the source
+   location given by BATON, which must be a pointer to a `struct
+   macro_scope' structure.  */
+struct macro_definition *
+standard_macro_lookup (const char *name, void *baton)
+{
+  struct macro_scope *ms = (struct macro_scope *) baton;
+
+  return macro_lookup_definition (ms->file, ms->line, name);
+}
diff --git a/gdb/macroscope.h b/gdb/macroscope.h
new file mode 100644 (file)
index 0000000..fc10b6d
--- /dev/null
@@ -0,0 +1,63 @@
+/* Interface to functions for deciding which macros are currently in scope.
+   Copyright 2002 Free Software Foundation, Inc.
+   Contributed by Red Hat, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef MACROSCOPE_H
+#define MACROSCOPE_H
+
+#include "macrotab.h"
+#include "symtab.h"
+
+
+/* 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.  */
+struct macro_scope {
+  struct macro_source_file *file;
+  int line;
+};
+
+
+/* Return a `struct macro_scope' object corresponding to the symtab
+   and line given in SAL.  If we have no macro information for that
+   location, or if SAL's pc is zero, return zero.  */
+struct macro_scope *sal_macro_scope (struct symtab_and_line sal);
+
+
+/* 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.
+
+   The object returned is allocated using xmalloc; the caller is
+   responsible for freeing it.  */
+struct macro_scope *default_macro_scope (void);
+
+
+/* Look up the definition of the macro named NAME in scope at the source
+   location given by BATON, which must be a pointer to a `struct
+   macro_scope' structure.  This function is suitable for use as
+   a macro_lookup_ftype function.  */
+struct macro_definition *standard_macro_lookup (const char *name, void *baton);
+
+
+#endif /* MACROSCOPE_H */