Expand preprocessor macros in C expressions.

* c-lang.h: #include "macroexp.h", for macro_lookup_ftype.
(scan_macro_expansion, scanning_macro_expansion,
finished_macro_expansion): New function declarations.
(expression_macro_lookup_func, expression_macro_lookup_baton): New
variable declarations.
* parser-defs.h (expression_context_pc): New declaration.
* parse.c (expression_context_pc): New variable.
(parse_exp_1): Set expression_context_pc, as well as
expression_context_block.
* c-exp.y (yylex): If we're not already reading the result of a
macro expansion, try to macro-expand the next token.  When we're
done scanning a macro expansion, switch back to the mainline text.
Commas and `if's in a macro's expansion don't terminate the input.
* c-lang.c: #include "macroscope.h" and "gdb_assert.h".
(macro_original_text, macro_expanded_text,
expression_macro_lookup_func, expression_macro_lookup_baton): New
variables.
(scan_macro_expansion, scanning_macro_expansion,
finished_macro_expansion, scan_macro_cleanup, null_macro_lookup,
c_preprocess_and_parse): New functions.
(c_language_defn, cplus_language_defn, asm_language_defn): Call
c_preprocess_and_parse, instead of c_parse.
* Makefile.in (c_lang_h): Note that this #includes macroexp.h.
(c-lang.o): Note dependency on macroscope.h and gdb_assert.h.
This commit is contained in:
Jim Blandy 2002-05-17 17:57:48 +00:00
parent 1c509ca821
commit 84f0252a03
7 changed files with 211 additions and 11 deletions

View file

@ -1,3 +1,31 @@
2002-05-17 Jim Blandy <jimb@redhat.com>
Expand preprocessor macros in C expressions.
* c-lang.h: #include "macroexp.h", for macro_lookup_ftype.
(scan_macro_expansion, scanning_macro_expansion,
finished_macro_expansion): New function declarations.
(expression_macro_lookup_func, expression_macro_lookup_baton): New
variable declarations.
* parser-defs.h (expression_context_pc): New declaration.
* parse.c (expression_context_pc): New variable.
(parse_exp_1): Set expression_context_pc, as well as
expression_context_block.
* c-exp.y (yylex): If we're not already reading the result of a
macro expansion, try to macro-expand the next token. When we're
done scanning a macro expansion, switch back to the mainline text.
Commas and `if's in a macro's expansion don't terminate the input.
* c-lang.c: #include "macroscope.h" and "gdb_assert.h".
(macro_original_text, macro_expanded_text,
expression_macro_lookup_func, expression_macro_lookup_baton): New
variables.
(scan_macro_expansion, scanning_macro_expansion,
finished_macro_expansion, scan_macro_cleanup, null_macro_lookup,
c_preprocess_and_parse): New functions.
(c_language_defn, cplus_language_defn, asm_language_defn): Call
c_preprocess_and_parse, instead of c_parse.
* Makefile.in (c_lang_h): Note that this #includes macroexp.h.
(c-lang.o): Note dependency on macroscope.h and gdb_assert.h.
Fri May 17 14:26:19 2002 J"orn Rennecke <joern.rennecke@superh.com>
* sh-tdep.c (gdb_print_insn_sh64): Delete.

View file

@ -600,7 +600,7 @@ bcache_h = bcache.h
builtin_regs_h = builtin-regs.h
breakpoint_h = breakpoint.h $(frame_h) $(value_h)
buildsym_h = buildsym.h
c_lang_h = c-lang.h $(value_h)
c_lang_h = c-lang.h $(value_h) $(macroexp_h)
call_cmds_h = call-cmds.h
cli_cmds_h = $(srcdir)/cli/cli-cmds.h
cli_decode_h = $(srcdir)/cli/cli-decode.h $(command_h)
@ -1318,7 +1318,8 @@ builtin-regs.o: builtin-regs.c $(defs.h) $(builtin_regs_h) $(gdbtypes_h) \
$(gdb_string_h) $(value_h) $(frame_h)
c-lang.o: c-lang.c $(c_lang_h) $(defs_h) $(expression_h) $(gdbtypes_h) \
$(language_h) $(parser_defs_h) $(symtab_h)
$(language_h) $(parser_defs_h) $(symtab_h) $(macroscope_h) \
gdb_assert.h
c-typeprint.o: c-typeprint.c $(c_lang_h) $(defs_h) $(expression_h) \
$(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) $(language_h) $(symtab_h) \

View file

@ -1246,6 +1246,17 @@ yylex ()
retry:
/* Check if this is a macro invocation that we need to expand. */
if (! scanning_macro_expansion ())
{
char *expanded = macro_expand_next (&lexptr,
expression_macro_lookup_func,
expression_macro_lookup_baton);
if (expanded)
scan_macro_expansion (expanded);
}
prev_lexptr = lexptr;
unquoted_expr = 1;
@ -1271,7 +1282,17 @@ yylex ()
switch (c = *tokstart)
{
case 0:
return 0;
/* If we were just scanning the result of a macro expansion,
then we need to resume scanning the original text.
Otherwise, we were already scanning the original text, and
we're really done. */
if (scanning_macro_expansion ())
{
finished_macro_expansion ();
goto retry;
}
else
return 0;
case ' ':
case '\t':
@ -1324,7 +1345,9 @@ yylex ()
return c;
case ',':
if (comma_terminates && paren_depth == 0)
if (comma_terminates
&& paren_depth == 0
&& ! scanning_macro_expansion ())
return 0;
lexptr++;
return c;
@ -1503,9 +1526,13 @@ yylex ()
c = tokstart[++namelen];
}
/* The token "if" terminates the expression and is NOT
removed from the input stream. */
if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
/* The token "if" terminates the expression and is NOT removed from
the input stream. It doesn't count if it appears in the
expansion of a macro. */
if (namelen == 2
&& tokstart[0] == 'i'
&& tokstart[1] == 'f'
&& ! scanning_macro_expansion ())
{
return 0;
}

View file

@ -27,6 +27,8 @@
#include "language.h"
#include "c-lang.h"
#include "valprint.h"
#include "macroscope.h"
#include "gdb_assert.h"
extern void _initialize_c_language (void);
static void c_emit_char (int c, struct ui_file * stream, int quoter);
@ -371,7 +373,128 @@ c_create_fundamental_type (struct objfile *objfile, int typeid)
return (type);
}
/* Preprocessing and parsing C and C++ expressions. */
/* When we find that lexptr (the global var defined in parse.c) is
pointing at a macro invocation, we expand the invocation, and call
scan_macro_expansion to save the old lexptr here and point lexptr
into the expanded text. When we reach the end of that, we call
end_macro_expansion to pop back to the value we saved here. The
macro expansion code promises to return only fully-expanded text,
so we don't need to "push" more than one level.
This is disgusting, of course. It would be cleaner to do all macro
expansion beforehand, and then hand that to lexptr. But we don't
really know where the expression ends. Remember, in a command like
(gdb) break *ADDRESS if CONDITION
we evaluate ADDRESS in the scope of the current frame, but we
evaluate CONDITION in the scope of the breakpoint's location. So
it's simply wrong to try to macro-expand the whole thing at once. */
static char *macro_original_text;
static char *macro_expanded_text;
void
scan_macro_expansion (char *expansion)
{
/* We'd better not be trying to push the stack twice. */
gdb_assert (! macro_original_text);
gdb_assert (! macro_expanded_text);
/* Save the old lexptr value, so we can return to it when we're done
parsing the expanded text. */
macro_original_text = lexptr;
lexptr = expansion;
/* Save the expanded text, so we can free it when we're finished. */
macro_expanded_text = expansion;
}
int
scanning_macro_expansion ()
{
return macro_original_text != 0;
}
void
finished_macro_expansion ()
{
/* There'd better be something to pop back to, and we better have
saved a pointer to the start of the expanded text. */
gdb_assert (macro_original_text);
gdb_assert (macro_expanded_text);
/* Pop back to the original text. */
lexptr = macro_original_text;
macro_original_text = 0;
/* Free the expanded text. */
xfree (macro_expanded_text);
macro_expanded_text = 0;
}
static void
scan_macro_cleanup (void *dummy)
{
if (macro_original_text)
finished_macro_expansion ();
}
/* We set these global variables before calling c_parse, to tell it
how it to find macro definitions for the expression at hand. */
macro_lookup_ftype *expression_macro_lookup_func;
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 ()
{
/* Set up a lookup function for the macro expander. */
struct macro_scope *scope = 0;
struct cleanup *back_to = make_cleanup (free_current_contents, &scope);
if (expression_context_block)
scope = sal_macro_scope (find_pc_line (expression_context_pc, 0));
else
scope = default_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;
}
gdb_assert (! macro_original_text);
make_cleanup (scan_macro_cleanup, 0);
{
int result = c_parse ();
do_cleanups (back_to);
return result;
}
}
/* Table mapping opcodes into strings for printing operators
and precedences of the operators. */
@ -439,7 +562,7 @@ const struct language_defn c_language_defn =
range_check_off,
type_check_off,
case_sensitive_on,
c_parse,
c_preprocess_and_parse,
c_error,
evaluate_subexp_standard,
c_printchar, /* Print a character constant */
@ -491,7 +614,7 @@ const struct language_defn cplus_language_defn =
range_check_off,
type_check_off,
case_sensitive_on,
c_parse,
c_preprocess_and_parse,
c_error,
evaluate_subexp_standard,
c_printchar, /* Print a character constant */
@ -520,7 +643,7 @@ const struct language_defn asm_language_defn =
range_check_off,
type_check_off,
case_sensitive_on,
c_parse,
c_preprocess_and_parse,
c_error,
evaluate_subexp_standard,
c_printchar, /* Print a character constant */

View file

@ -24,6 +24,7 @@
#define C_LANG_H 1
#include "value.h"
#include "macroexp.h"
extern int c_parse (void); /* Defined in c-exp.y */
@ -49,6 +50,13 @@ extern void c_printstr (struct ui_file * stream, char *string,
unsigned int length, int width,
int force_ellipses);
extern void scan_macro_expansion (char *expansion);
extern int scanning_macro_expansion (void);
extern void finished_macro_expansion (void);
extern macro_lookup_ftype *expression_macro_lookup_func;
extern void *expression_macro_lookup_baton;
extern struct type *c_create_fundamental_type (struct objfile *, int);
extern struct type **const (c_builtin_types[]);

View file

@ -71,6 +71,7 @@ struct expression *expout;
int expout_size;
int expout_ptr;
struct block *expression_context_block;
CORE_ADDR expression_context_pc;
struct block *innermost_block;
int arglist_len;
union type_stack_elt *type_stack;
@ -1140,7 +1141,13 @@ parse_exp_1 (char **stringptr, struct block *block, int comma)
old_chain = make_cleanup (free_funcalls, 0 /*ignore*/);
funcall_chain = 0;
expression_context_block = block ? block : get_selected_block (0);
if (block)
{
expression_context_block = block;
expression_context_pc = block->startaddr;
}
else
expression_context_block = get_selected_block (&expression_context_pc);
namecopy = (char *) alloca (strlen (lexptr) + 1);
expout_size = 10;

View file

@ -37,6 +37,12 @@ extern int expout_ptr;
extern struct block *expression_context_block;
/* If expression_context_block is non-zero, then this is the PC within
the block that we want to evaluate expressions at. When debugging
C or C++ code, we use this to find the exact line we're at, and
then look up the macro definitions active at that point. */
CORE_ADDR expression_context_pc;
/* The innermost context required by the stack and register variables
we've encountered so far. */
extern struct block *innermost_block;