cpplib.c (end_directive): Handle line skipping.
* cpplib.c (end_directive): Handle line skipping. Only remove the rest of the line if the directive was valid. * cppmacro.c (_cpp_push_text_context): Set NODE_DISABLED when expanding a traditional macro. * cpptrad.c (recursive_macro): New. (read_logical_line_trad): Handle skipping. (scan_out_logical_line): Continue after a successful directive. Don't expand macros whilst skipping, or if recursing. (_cpp_create_trad_definition): scan_out_logical_line now sets the output current position. From-SVN: r54573
This commit is contained in:
parent
e4dadd2ad0
commit
974c43f1e3
|
@ -1,3 +1,16 @@
|
|||
2002-06-13 Neil Booth <neil@daikokuya.demon.co.uk>
|
||||
|
||||
* cpplib.c (end_directive): Handle line skipping. Only remove
|
||||
the rest of the line if the directive was valid.
|
||||
* cppmacro.c (_cpp_push_text_context): Set NODE_DISABLED when
|
||||
expanding a traditional macro.
|
||||
* cpptrad.c (recursive_macro): New.
|
||||
(read_logical_line_trad): Handle skipping.
|
||||
(scan_out_logical_line): Continue after a successful directive.
|
||||
Don't expand macros whilst skipping, or if recursing.
|
||||
(_cpp_create_trad_definition): scan_out_logical_line now sets
|
||||
the output current position.
|
||||
|
||||
2002-06-12 Eric Christopher <echristo@redhat.com>
|
||||
|
||||
From Chris Demetriou <cgd@broadcom.com>
|
||||
|
|
|
@ -256,7 +256,7 @@ end_directive (pfile, skip_line)
|
|||
{
|
||||
if (CPP_OPTION (pfile, traditional))
|
||||
{
|
||||
if (pfile->directive == &dtable[T_DEFINE])
|
||||
if (!pfile->directive || pfile->directive == &dtable[T_DEFINE])
|
||||
skip_line = false;
|
||||
else
|
||||
_cpp_remove_overlay (pfile);
|
||||
|
@ -290,12 +290,15 @@ prepare_directive_trad (pfile)
|
|||
else
|
||||
{
|
||||
bool no_expand = ! (pfile->directive->flags & EXPAND);
|
||||
bool was_skipping = pfile->state.skipping;
|
||||
|
||||
pfile->state.skipping = false;
|
||||
if (no_expand)
|
||||
pfile->state.prevent_expansion++;
|
||||
_cpp_read_logical_line_trad (pfile);
|
||||
if (no_expand)
|
||||
pfile->state.prevent_expansion--;
|
||||
pfile->state.skipping = was_skipping;
|
||||
_cpp_overlay_buffer (pfile, pfile->out.base,
|
||||
pfile->out.cur - pfile->out.base);
|
||||
}
|
||||
|
|
|
@ -947,6 +947,7 @@ _cpp_push_text_context (pfile, macro, start, len)
|
|||
context->buff = NULL;
|
||||
CUR (context) = start;
|
||||
RLIMIT (context) = start + len;
|
||||
macro->flags |= NODE_DISABLED;
|
||||
}
|
||||
|
||||
/* Expand an argument ARG before replacing parameters in a
|
||||
|
|
|
@ -82,6 +82,7 @@ static void scan_out_logical_line PARAMS ((cpp_reader *pfile, cpp_macro *));
|
|||
static void check_output_buffer PARAMS ((cpp_reader *, size_t));
|
||||
static void push_replacement_text PARAMS ((cpp_reader *, cpp_hashnode *));
|
||||
static bool scan_parameters PARAMS ((cpp_reader *, cpp_macro *));
|
||||
static bool recursive_macro PARAMS ((cpp_reader *, cpp_hashnode *));
|
||||
static void save_replacement_text PARAMS ((cpp_reader *, cpp_macro *,
|
||||
unsigned int));
|
||||
static void maybe_start_funlike PARAMS ((cpp_reader *, cpp_hashnode *,
|
||||
|
@ -304,30 +305,31 @@ bool
|
|||
_cpp_read_logical_line_trad (pfile)
|
||||
cpp_reader *pfile;
|
||||
{
|
||||
cpp_buffer *buffer;
|
||||
cpp_buffer *buffer = pfile->buffer;
|
||||
|
||||
buffer = pfile->buffer;
|
||||
if (buffer->cur == buffer->rlimit)
|
||||
do
|
||||
{
|
||||
bool stop = true;
|
||||
|
||||
/* Don't pop the last buffer. */
|
||||
if (buffer->prev)
|
||||
if (buffer->cur == buffer->rlimit)
|
||||
{
|
||||
stop = buffer->return_at_eof;
|
||||
_cpp_pop_buffer (pfile);
|
||||
bool stop = true;
|
||||
|
||||
/* Don't pop the last buffer. */
|
||||
if (buffer->prev)
|
||||
{
|
||||
stop = buffer->return_at_eof;
|
||||
_cpp_pop_buffer (pfile);
|
||||
}
|
||||
|
||||
if (stop)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stop)
|
||||
return false;
|
||||
CUR (pfile->context) = buffer->cur;
|
||||
RLIMIT (pfile->context) = buffer->rlimit;
|
||||
scan_out_logical_line (pfile, NULL);
|
||||
buffer->cur = CUR (pfile->context);
|
||||
}
|
||||
|
||||
CUR (pfile->context) = buffer->cur;
|
||||
RLIMIT (pfile->context) = buffer->rlimit;
|
||||
pfile->out.cur = pfile->out.base;
|
||||
pfile->out.first_line = pfile->line;
|
||||
scan_out_logical_line (pfile, NULL);
|
||||
buffer->cur = CUR (pfile->context);
|
||||
while (pfile->state.skipping);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -384,6 +386,10 @@ scan_out_logical_line (pfile, macro)
|
|||
struct fun_macro fmacro;
|
||||
|
||||
fmacro.buff = NULL;
|
||||
|
||||
start_logical_line:
|
||||
pfile->out.cur = pfile->out.base;
|
||||
pfile->out.first_line = pfile->line;
|
||||
new_context:
|
||||
context = pfile->context;
|
||||
cur = CUR (context);
|
||||
|
@ -483,8 +489,10 @@ scan_out_logical_line (pfile, macro)
|
|||
node = lex_identifier (pfile, cur - 1);
|
||||
|
||||
if (node->type == NT_MACRO
|
||||
&& !pfile->state.skipping
|
||||
&& pfile->state.parsing_args != 2
|
||||
&& !pfile->state.prevent_expansion)
|
||||
&& !pfile->state.prevent_expansion
|
||||
&& !recursive_macro (pfile, node))
|
||||
{
|
||||
if (node->value.macro->fun_like)
|
||||
maybe_start_funlike (pfile, node, out, &fmacro);
|
||||
|
@ -582,10 +590,7 @@ scan_out_logical_line (pfile, macro)
|
|||
preprocessor lex the next token. */
|
||||
pfile->buffer->cur = cur;
|
||||
if (_cpp_handle_directive (pfile, false /* indented */))
|
||||
{
|
||||
cur = CUR (context);
|
||||
goto done;
|
||||
}
|
||||
goto start_logical_line;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -615,6 +620,48 @@ push_replacement_text (pfile, node)
|
|||
_cpp_push_text_context (pfile, node, macro->exp.text, macro->count);
|
||||
}
|
||||
|
||||
/* Returns TRUE if traditional macro recursion is detected. */
|
||||
static bool
|
||||
recursive_macro (pfile, node)
|
||||
cpp_reader *pfile;
|
||||
cpp_hashnode *node;
|
||||
{
|
||||
bool recursing = node->flags & NODE_DISABLED;
|
||||
|
||||
/* Object-like macros that are already expanding are necessarily
|
||||
recursive.
|
||||
|
||||
However, it is possible to have traditional function-like macros
|
||||
that are not infinitely recursive but recurse to any given depth.
|
||||
Further, it is easy to construct examples that get ever longer
|
||||
until the point they stop recursing. So there is no easy way to
|
||||
detect true recursion; instead we assume any expansion more than
|
||||
20 deep since the first invocation of this macro must be
|
||||
recursing. */
|
||||
if (recursing && node->value.macro->fun_like)
|
||||
{
|
||||
size_t depth = 0;
|
||||
cpp_context *context = pfile->context;
|
||||
|
||||
do
|
||||
{
|
||||
depth++;
|
||||
if (context->macro == node && depth > 20)
|
||||
break;
|
||||
context = context->prev;
|
||||
}
|
||||
while (context);
|
||||
recursing = context != NULL;
|
||||
}
|
||||
|
||||
if (recursing)
|
||||
cpp_error (pfile, DL_ERROR,
|
||||
"detected recursion whilst expanding macro \"%s\"",
|
||||
NODE_NAME (node));
|
||||
|
||||
return recursing;
|
||||
}
|
||||
|
||||
/* Push a context holding the replacement text of the macro NODE on
|
||||
the context stack. NODE is either object-like, or a function-like
|
||||
macro with no arguments. */
|
||||
|
@ -804,7 +851,6 @@ _cpp_create_trad_definition (pfile, macro)
|
|||
/* Skip leading whitespace in the replacement text. */
|
||||
CUR (pfile->context) = skip_whitespace (pfile, CUR (pfile->context));
|
||||
|
||||
pfile->out.cur = pfile->out.base;
|
||||
pfile->state.prevent_expansion++;
|
||||
scan_out_logical_line (pfile, macro);
|
||||
pfile->state.prevent_expansion--;
|
||||
|
|
Loading…
Reference in New Issue