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>
|
2002-06-12 Eric Christopher <echristo@redhat.com>
|
||||||
|
|
||||||
From Chris Demetriou <cgd@broadcom.com>
|
From Chris Demetriou <cgd@broadcom.com>
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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--;
|
||||||
|
Loading…
Reference in New Issue
Block a user