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:
Neil Booth 2002-06-13 06:25:28 +00:00 committed by Neil Booth
parent e4dadd2ad0
commit 974c43f1e3
4 changed files with 88 additions and 25 deletions

View File

@ -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>

View File

@ -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);
}

View File

@ -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

View File

@ -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--;