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> 2002-06-12 Eric Christopher <echristo@redhat.com>
From Chris Demetriou <cgd@broadcom.com> From Chris Demetriou <cgd@broadcom.com>

View File

@ -256,7 +256,7 @@ end_directive (pfile, skip_line)
{ {
if (CPP_OPTION (pfile, traditional)) if (CPP_OPTION (pfile, traditional))
{ {
if (pfile->directive == &dtable[T_DEFINE]) if (!pfile->directive || pfile->directive == &dtable[T_DEFINE])
skip_line = false; skip_line = false;
else else
_cpp_remove_overlay (pfile); _cpp_remove_overlay (pfile);
@ -290,12 +290,15 @@ prepare_directive_trad (pfile)
else else
{ {
bool no_expand = ! (pfile->directive->flags & EXPAND); bool no_expand = ! (pfile->directive->flags & EXPAND);
bool was_skipping = pfile->state.skipping;
pfile->state.skipping = false;
if (no_expand) if (no_expand)
pfile->state.prevent_expansion++; pfile->state.prevent_expansion++;
_cpp_read_logical_line_trad (pfile); _cpp_read_logical_line_trad (pfile);
if (no_expand) if (no_expand)
pfile->state.prevent_expansion--; pfile->state.prevent_expansion--;
pfile->state.skipping = was_skipping;
_cpp_overlay_buffer (pfile, pfile->out.base, _cpp_overlay_buffer (pfile, pfile->out.base,
pfile->out.cur - 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; context->buff = NULL;
CUR (context) = start; CUR (context) = start;
RLIMIT (context) = start + len; RLIMIT (context) = start + len;
macro->flags |= NODE_DISABLED;
} }
/* Expand an argument ARG before replacing parameters in a /* 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 check_output_buffer PARAMS ((cpp_reader *, size_t));
static void push_replacement_text PARAMS ((cpp_reader *, cpp_hashnode *)); static void push_replacement_text PARAMS ((cpp_reader *, cpp_hashnode *));
static bool scan_parameters PARAMS ((cpp_reader *, cpp_macro *)); 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 *, static void save_replacement_text PARAMS ((cpp_reader *, cpp_macro *,
unsigned int)); unsigned int));
static void maybe_start_funlike PARAMS ((cpp_reader *, cpp_hashnode *, static void maybe_start_funlike PARAMS ((cpp_reader *, cpp_hashnode *,
@ -304,9 +305,10 @@ bool
_cpp_read_logical_line_trad (pfile) _cpp_read_logical_line_trad (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
cpp_buffer *buffer; cpp_buffer *buffer = pfile->buffer;
buffer = pfile->buffer; do
{
if (buffer->cur == buffer->rlimit) if (buffer->cur == buffer->rlimit)
{ {
bool stop = true; bool stop = true;
@ -324,10 +326,10 @@ _cpp_read_logical_line_trad (pfile)
CUR (pfile->context) = buffer->cur; CUR (pfile->context) = buffer->cur;
RLIMIT (pfile->context) = buffer->rlimit; RLIMIT (pfile->context) = buffer->rlimit;
pfile->out.cur = pfile->out.base;
pfile->out.first_line = pfile->line;
scan_out_logical_line (pfile, NULL); scan_out_logical_line (pfile, NULL);
buffer->cur = CUR (pfile->context); buffer->cur = CUR (pfile->context);
}
while (pfile->state.skipping);
return true; return true;
} }
@ -384,6 +386,10 @@ scan_out_logical_line (pfile, macro)
struct fun_macro fmacro; struct fun_macro fmacro;
fmacro.buff = NULL; fmacro.buff = NULL;
start_logical_line:
pfile->out.cur = pfile->out.base;
pfile->out.first_line = pfile->line;
new_context: new_context:
context = pfile->context; context = pfile->context;
cur = CUR (context); cur = CUR (context);
@ -483,8 +489,10 @@ scan_out_logical_line (pfile, macro)
node = lex_identifier (pfile, cur - 1); node = lex_identifier (pfile, cur - 1);
if (node->type == NT_MACRO if (node->type == NT_MACRO
&& !pfile->state.skipping
&& pfile->state.parsing_args != 2 && pfile->state.parsing_args != 2
&& !pfile->state.prevent_expansion) && !pfile->state.prevent_expansion
&& !recursive_macro (pfile, node))
{ {
if (node->value.macro->fun_like) if (node->value.macro->fun_like)
maybe_start_funlike (pfile, node, out, &fmacro); maybe_start_funlike (pfile, node, out, &fmacro);
@ -582,10 +590,7 @@ scan_out_logical_line (pfile, macro)
preprocessor lex the next token. */ preprocessor lex the next token. */
pfile->buffer->cur = cur; pfile->buffer->cur = cur;
if (_cpp_handle_directive (pfile, false /* indented */)) if (_cpp_handle_directive (pfile, false /* indented */))
{ goto start_logical_line;
cur = CUR (context);
goto done;
}
} }
break; break;
@ -615,6 +620,48 @@ push_replacement_text (pfile, node)
_cpp_push_text_context (pfile, node, macro->exp.text, macro->count); _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 /* Push a context holding the replacement text of the macro NODE on
the context stack. NODE is either object-like, or a function-like the context stack. NODE is either object-like, or a function-like
macro with no arguments. */ macro with no arguments. */
@ -804,7 +851,6 @@ _cpp_create_trad_definition (pfile, macro)
/* Skip leading whitespace in the replacement text. */ /* Skip leading whitespace in the replacement text. */
CUR (pfile->context) = skip_whitespace (pfile, CUR (pfile->context)); CUR (pfile->context) = skip_whitespace (pfile, CUR (pfile->context));
pfile->out.cur = pfile->out.base;
pfile->state.prevent_expansion++; pfile->state.prevent_expansion++;
scan_out_logical_line (pfile, macro); scan_out_logical_line (pfile, macro);
pfile->state.prevent_expansion--; pfile->state.prevent_expansion--;