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.
This commit is contained in:
parent
2e2761252b
commit
6821892ed4
5 changed files with 475 additions and 3 deletions
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
287
gdb/macrocmd.c
Normal file
287
gdb/macrocmd.c
Normal file
|
@ -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"
|
||||
|
||||
|
||||
/* 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 = 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 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);
|
||||
}
|
107
gdb/macroscope.c
Normal file
107
gdb/macroscope.c
Normal file
|
@ -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);
|
||||
}
|
63
gdb/macroscope.h
Normal file
63
gdb/macroscope.h
Normal file
|
@ -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 */
|
Loading…
Reference in a new issue