From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 23262 invoked by alias); 9 May 2002 23:58:27 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 23253 invoked from network); 9 May 2002 23:58:24 -0000 Received: from unknown (HELO zwingli.cygnus.com) (208.245.165.35) by sources.redhat.com with SMTP; 9 May 2002 23:58:24 -0000 Received: by zwingli.cygnus.com (Postfix, from userid 442) id DC4F95EA11; Thu, 9 May 2002 18:58:22 -0500 (EST) From: Jim Blandy To: gdb-patches@sources.redhat.com Subject: RFA: add macro commands Message-Id: <20020509235822.DC4F95EA11@zwingli.cygnus.com> Date: Thu, 09 May 2002 16:58:00 -0000 X-SW-Source: 2002-05/txt/msg00307.txt.bz2 2002-05-09 Jim Blandy 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.", + ¯olist, "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.", + ¯olist); + add_alias_cmd ("exp", "expand", no_class, 1, ¯olist); + 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.", + ¯olist); + add_alias_cmd ("exp1", "expand-once", no_class, 1, ¯olist); + + 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))", + ¯olist); + + add_cmd + ("undef", no_class, macro_undef_command, + "Remove the definition of the C/C++ preprocessor macro with the" + " given name.", + ¯olist); + + 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: 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 */