This is the mail archive of the gdb-patches@sources.redhat.com 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]

RFA: add macro commands



2002-05-09  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.

Index: gdb/Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.180.2.6
diff -c -r1.180.2.6 Makefile.in
*** gdb/Makefile.in	9 May 2002 20:03:35 -0000	1.180.2.6
--- gdb/Makefile.in	9 May 2002 23:49:14 -0000
***************
*** 539,545 ****
  	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 \
  	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 \
--- 539,545 ----
  	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 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 \
***************
*** 635,640 ****
--- 635,641 ----
  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
***************
*** 673,679 ****
  	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 \
  	c-lang.h ch-lang.h f-lang.h \
  	jv-lang.h \
  	m2-lang.h  p-lang.h \
--- 674,680 ----
  	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 macroscope.h \
  	c-lang.h ch-lang.h f-lang.h \
  	jv-lang.h \
  	m2-lang.h  p-lang.h \
***************
*** 716,722 ****
  	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 \
  	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 \
--- 717,723 ----
  	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 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 \
***************
*** 2123,2128 ****
--- 2124,2134 ----
  
  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)
Index: gdb/macrocmd.c
===================================================================
RCS file: gdb/macrocmd.c
diff -N gdb/macrocmd.c
*** gdb/macrocmd.c	1 Jan 1970 00:00:00 -0000
--- gdb/macrocmd.c	9 May 2002 23:49:15 -0000
***************
*** 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"
+ 
+ 
+ /* 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);
+ }
+ 
+ 
+ 
+ /* Macro expansion commands.  */
+ 
+ 
+ static void
+ macro_expand_command (char *exp, int from_tty)
+ {
+   struct macro_scope *ms = 0;
+   char *expanded = 0;
+   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 = 0;
+   char *expanded = 0;
+   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 = 0;
+   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);
+ }
+ 
+ 
+ 
+ /* 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.");
+ }
+ 
+ 
+ 
+ /* 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);
+ }
Index: gdb/macroscope.c
===================================================================
RCS file: gdb/macroscope.c
diff -N gdb/macroscope.c
*** gdb/macroscope.c	1 Jan 1970 00:00:00 -0000
--- gdb/macroscope.c	9 May 2002 23:49:15 -0000
***************
*** 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);
+ }
Index: gdb/macroscope.h
===================================================================
RCS file: gdb/macroscope.h
diff -N gdb/macroscope.h
*** gdb/macroscope.h	1 Jan 1970 00:00:00 -0000
--- gdb/macroscope.h	9 May 2002 23:49:15 -0000
***************
*** 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 */


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