Commit d97371e0 by Neil Booth Committed by Neil Booth

cpplib.c (dtable): Update.

	* cpplib.c (dtable): Update.
	(end_directive): Decrement expansion prevention count.
	Clear state.in_expression.
	(prepare_directive_trad): Set state.in_expression.
	Increment expansion prevention count.
	* cpptrad.c (enum ls): New.
	(_cpp_overlay_buffer): Set overlaid_buffer.
	(_cpp_remove_overlay): Use overlaid_buffer.
	(_cpp_read_logcial_line_trad): Update buffer when it might
	have changed.
	(scan_out_logical_line): Handle state transitions for assertions
	and defined() in #if, and for funlike invocations including the
	directive case.  Handle '<' and '>' as a quote mechanism in
	#include.  Warn about unterminated macro invocations.
	* cpphash.h (struct lexer_state): New member in_expression.
	(struct cpp_reader): New member overlaid buffer.

From-SVN: r54732
parent 807b20b0
2002-06-18 Neil Booth <neil@daikokuya.demon.co.uk>
* cpplib.c (dtable): Update.
(end_directive): Decrement expansion prevention count.
Clear state.in_expression.
(prepare_directive_trad): Set state.in_expression.
Increment expansion prevention count.
* cpptrad.c (enum ls): New.
(_cpp_overlay_buffer): Set overlaid_buffer.
(_cpp_remove_overlay): Use overlaid_buffer.
(_cpp_read_logcial_line_trad): Update buffer when it might
have changed.
(scan_out_logical_line): Handle state transitions for assertions
and defined() in #if, and for funlike invocations including the
directive case. Handle '<' and '>' as a quote mechanism in
#include. Warn about unterminated macro invocations.
* cpphash.h (struct lexer_state): New member in_expression.
(struct cpp_reader): New member overlaid buffer.
2002-06-18 Hans-Peter Nilsson <hp@axis.com> 2002-06-18 Hans-Peter Nilsson <hp@axis.com>
* config/cris/arit.c (do_31div, __Udiv, __Umod): Mark prototype * config/cris/arit.c (do_31div, __Udiv, __Umod): Mark prototype
......
...@@ -211,6 +211,9 @@ struct lexer_state ...@@ -211,6 +211,9 @@ struct lexer_state
/* Nonzero if in a directive that takes angle-bracketed headers. */ /* Nonzero if in a directive that takes angle-bracketed headers. */
unsigned char angled_headers; unsigned char angled_headers;
/* Nonzero if in a #if or #elif directive. */
unsigned char in_expression;
/* Nonzero to save comments. Turned off if discard_comments, and in /* Nonzero to save comments. Turned off if discard_comments, and in
all directives apart from #define. */ all directives apart from #define. */
unsigned char save_comments; unsigned char save_comments;
...@@ -309,6 +312,9 @@ struct cpp_reader ...@@ -309,6 +312,9 @@ struct cpp_reader
/* Top of buffer stack. */ /* Top of buffer stack. */
cpp_buffer *buffer; cpp_buffer *buffer;
/* Overlaid buffer (can be different after processing #include). */
cpp_buffer *overlaid_buffer;
/* Lexer state. */ /* Lexer state. */
struct lexer_state state; struct lexer_state state;
......
...@@ -72,9 +72,7 @@ struct pragma_entry ...@@ -72,9 +72,7 @@ struct pragma_entry
means this directive should be handled even if -fpreprocessed is in means this directive should be handled even if -fpreprocessed is in
effect (these are the directives with callback hooks). effect (these are the directives with callback hooks).
EXPAND is set on directives that are always macro-expanded. If EXPAND is set on directives that are always macro-expanded. */
INCL is set, macro expansion is special-cased and EXPAND should not
be set. */
#define COND (1 << 0) #define COND (1 << 0)
#define IF_COND (1 << 1) #define IF_COND (1 << 1)
#define INCL (1 << 2) #define INCL (1 << 2)
...@@ -147,7 +145,7 @@ static void handle_assertion PARAMS ((cpp_reader *, const char *, int)); ...@@ -147,7 +145,7 @@ static void handle_assertion PARAMS ((cpp_reader *, const char *, int));
#define DIRECTIVE_TABLE \ #define DIRECTIVE_TABLE \
D(define, T_DEFINE = 0, KANDR, IN_I) /* 270554 */ \ D(define, T_DEFINE = 0, KANDR, IN_I) /* 270554 */ \
D(include, T_INCLUDE, KANDR, INCL) /* 52262 */ \ D(include, T_INCLUDE, KANDR, INCL | EXPAND) /* 52262 */ \
D(endif, T_ENDIF, KANDR, COND) /* 45855 */ \ D(endif, T_ENDIF, KANDR, COND) /* 45855 */ \
D(ifdef, T_IFDEF, KANDR, COND | IF_COND) /* 22000 */ \ D(ifdef, T_IFDEF, KANDR, COND | IF_COND) /* 22000 */ \
D(if, T_IF, KANDR, COND | IF_COND | EXPAND) /* 18162 */ \ D(if, T_IF, KANDR, COND | IF_COND | EXPAND) /* 18162 */ \
...@@ -159,9 +157,9 @@ D(elif, T_ELIF, STDC89, COND | EXPAND) /* 610 */ \ ...@@ -159,9 +157,9 @@ D(elif, T_ELIF, STDC89, COND | EXPAND) /* 610 */ \
D(error, T_ERROR, STDC89, 0) /* 475 */ \ D(error, T_ERROR, STDC89, 0) /* 475 */ \
D(pragma, T_PRAGMA, STDC89, IN_I) /* 195 */ \ D(pragma, T_PRAGMA, STDC89, IN_I) /* 195 */ \
D(warning, T_WARNING, EXTENSION, 0) /* 22 */ \ D(warning, T_WARNING, EXTENSION, 0) /* 22 */ \
D(include_next, T_INCLUDE_NEXT, EXTENSION, INCL) /* 19 */ \ D(include_next, T_INCLUDE_NEXT, EXTENSION, INCL | EXPAND) /* 19 */ \
D(ident, T_IDENT, EXTENSION, IN_I) /* 11 */ \ D(ident, T_IDENT, EXTENSION, IN_I) /* 11 */ \
D(import, T_IMPORT, EXTENSION, INCL) /* 0 ObjC */ \ D(import, T_IMPORT, EXTENSION, INCL | EXPAND) /* 0 ObjC */ \
D(assert, T_ASSERT, EXTENSION, 0) /* 0 SVR4 */ \ D(assert, T_ASSERT, EXTENSION, 0) /* 0 SVR4 */ \
D(unassert, T_UNASSERT, EXTENSION, 0) /* 0 SVR4 */ \ D(unassert, T_UNASSERT, EXTENSION, 0) /* 0 SVR4 */ \
SCCS_ENTRY /* 0 SVR4? */ SCCS_ENTRY /* 0 SVR4? */
...@@ -256,6 +254,9 @@ end_directive (pfile, skip_line) ...@@ -256,6 +254,9 @@ end_directive (pfile, skip_line)
{ {
if (CPP_OPTION (pfile, traditional)) if (CPP_OPTION (pfile, traditional))
{ {
/* Revert change of prepare_directive_trad. */
pfile->state.prevent_expansion--;
if (pfile->directive != &dtable[T_DEFINE]) if (pfile->directive != &dtable[T_DEFINE])
_cpp_remove_overlay (pfile); _cpp_remove_overlay (pfile);
} }
...@@ -273,6 +274,7 @@ end_directive (pfile, skip_line) ...@@ -273,6 +274,7 @@ end_directive (pfile, skip_line)
/* Restore state. */ /* Restore state. */
pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments); pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments);
pfile->state.in_directive = 0; pfile->state.in_directive = 0;
pfile->state.in_expression = 0;
pfile->state.angled_headers = 0; pfile->state.angled_headers = 0;
pfile->directive = 0; pfile->directive = 0;
} }
...@@ -291,6 +293,8 @@ prepare_directive_trad (pfile) ...@@ -291,6 +293,8 @@ prepare_directive_trad (pfile)
bool was_skipping = pfile->state.skipping; bool was_skipping = pfile->state.skipping;
pfile->state.skipping = false; pfile->state.skipping = false;
pfile->state.in_expression = (pfile->directive == &dtable[T_IF]
|| pfile->directive == &dtable[T_ELIF]);
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);
...@@ -300,6 +304,9 @@ prepare_directive_trad (pfile) ...@@ -300,6 +304,9 @@ prepare_directive_trad (pfile)
_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);
} }
/* Stop ISO C from expanding anything. */
pfile->state.prevent_expansion++;
} }
/* Output diagnostics for a directive DIR. INDENTED is non-zero if /* Output diagnostics for a directive DIR. INDENTED is non-zero if
......
...@@ -63,6 +63,15 @@ struct fun_macro ...@@ -63,6 +63,15 @@ struct fun_macro
unsigned int argc; unsigned int argc;
}; };
/* Lexing state. It is mostly used to prevent macro expansion. */
enum ls {ls_none = 0, /* Normal state. */
ls_fun_macro, /* When looking for '('. */
ls_defined, /* After defined. */
ls_defined_close, /* Looking for ')' of defined(). */
ls_hash, /* After # in preprocessor conditional. */
ls_predicate, /* After the predicate, maybe paren? */
ls_answer}; /* In answer to predicate. */
/* Lexing TODO: Maybe handle space in escaped newlines. Stop cpplex.c /* Lexing TODO: Maybe handle space in escaped newlines. Stop cpplex.c
from recognizing comments and directives during its lexing pass. */ from recognizing comments and directives during its lexing pass. */
...@@ -322,6 +331,7 @@ _cpp_overlay_buffer (pfile, start, len) ...@@ -322,6 +331,7 @@ _cpp_overlay_buffer (pfile, start, len)
{ {
cpp_buffer *buffer = pfile->buffer; cpp_buffer *buffer = pfile->buffer;
pfile->overlaid_buffer = buffer;
buffer->saved_cur = buffer->cur; buffer->saved_cur = buffer->cur;
buffer->saved_rlimit = buffer->rlimit; buffer->saved_rlimit = buffer->rlimit;
...@@ -336,7 +346,7 @@ void ...@@ -336,7 +346,7 @@ void
_cpp_remove_overlay (pfile) _cpp_remove_overlay (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
cpp_buffer *buffer = pfile->buffer; cpp_buffer *buffer = pfile->overlaid_buffer;
buffer->cur = buffer->saved_cur; buffer->cur = buffer->saved_cur;
buffer->rlimit = buffer->saved_rlimit; buffer->rlimit = buffer->saved_rlimit;
...@@ -363,6 +373,7 @@ _cpp_read_logical_line_trad (pfile) ...@@ -363,6 +373,7 @@ _cpp_read_logical_line_trad (pfile)
{ {
stop = buffer->return_at_eof; stop = buffer->return_at_eof;
_cpp_pop_buffer (pfile); _cpp_pop_buffer (pfile);
buffer = pfile->buffer;
} }
if (stop) if (stop)
...@@ -372,6 +383,7 @@ _cpp_read_logical_line_trad (pfile) ...@@ -372,6 +383,7 @@ _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;
scan_out_logical_line (pfile, NULL); scan_out_logical_line (pfile, NULL);
buffer = pfile->buffer;
buffer->cur = CUR (pfile->context); buffer->cur = CUR (pfile->context);
} }
while (pfile->state.skipping); while (pfile->state.skipping);
...@@ -426,9 +438,10 @@ scan_out_logical_line (pfile, macro) ...@@ -426,9 +438,10 @@ scan_out_logical_line (pfile, macro)
{ {
cpp_context *context; cpp_context *context;
const uchar *cur; const uchar *cur;
unsigned int c, paren_depth = 0, quote = 0;
uchar *out; uchar *out;
struct fun_macro fmacro; struct fun_macro fmacro;
unsigned int c, paren_depth = 0, quote = 0;
enum ls lex_state = ls_none;
fmacro.buff = NULL; fmacro.buff = NULL;
...@@ -446,13 +459,19 @@ scan_out_logical_line (pfile, macro) ...@@ -446,13 +459,19 @@ scan_out_logical_line (pfile, macro)
c = *cur++; c = *cur++;
*out++ = c; *out++ = c;
/* There are only a few entities we need to catch: comments, /* Whitespace should "continue" out of the switch,
identifiers, newlines, escaped newlines, # and '\0'. */ non-whitespace should "break" out of it. */
switch (c) switch (c)
{ {
case ' ':
case '\t':
case '\f':
case '\v':
continue;
case '\0': case '\0':
if (cur - 1 != RLIMIT (context)) if (cur - 1 != RLIMIT (context))
break; continue;
/* If this is a macro's expansion, pop it. */ /* If this is a macro's expansion, pop it. */
if (context->prev) if (context->prev)
...@@ -475,7 +494,7 @@ scan_out_logical_line (pfile, macro) ...@@ -475,7 +494,7 @@ scan_out_logical_line (pfile, macro)
case '\r': case '\n': case '\r': case '\n':
cur = handle_newline (pfile, cur - 1); cur = handle_newline (pfile, cur - 1);
if (pfile->state.parsing_args == 2) if (pfile->state.parsing_args == 2 && !pfile->state.in_directive)
{ {
/* Newlines in arguments become a space. */ /* Newlines in arguments become a space. */
out[-1] = ' '; out[-1] = ' ';
...@@ -483,6 +502,18 @@ scan_out_logical_line (pfile, macro) ...@@ -483,6 +502,18 @@ scan_out_logical_line (pfile, macro)
} }
goto done; goto done;
case '<':
if (pfile->state.angled_headers && !quote)
quote = '>';
break;
case '>':
if (pfile->state.angled_headers && c == quote)
{
pfile->state.angled_headers = false;
quote = 0;
}
break;
case '"': case '"':
case '\'': case '\'':
if (c == quote) if (c == quote)
...@@ -493,7 +524,11 @@ scan_out_logical_line (pfile, macro) ...@@ -493,7 +524,11 @@ scan_out_logical_line (pfile, macro)
case '\\': case '\\':
if (is_vspace (*cur)) if (is_vspace (*cur))
out--, cur = skip_escaped_newlines (pfile, cur - 1); {
out--;
cur = skip_escaped_newlines (pfile, cur - 1);
continue;
}
else else
{ {
/* Skip escaped quotes here, it's easier than above, but /* Skip escaped quotes here, it's easier than above, but
...@@ -515,6 +550,7 @@ scan_out_logical_line (pfile, macro) ...@@ -515,6 +550,7 @@ scan_out_logical_line (pfile, macro)
pfile->out.cur = out; pfile->out.cur = out;
cur = copy_comment (pfile, cur, macro != 0); cur = copy_comment (pfile, cur, macro != 0);
out = pfile->out.cur; out = pfile->out.cur;
continue;
} }
} }
break; break;
...@@ -530,26 +566,33 @@ scan_out_logical_line (pfile, macro) ...@@ -530,26 +566,33 @@ scan_out_logical_line (pfile, macro)
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
case 'Y': case 'Z': case 'Y': case 'Z':
if (quote == 0 || macro) if (!pfile->state.skipping && (quote == 0 || macro))
{ {
cpp_hashnode *node; cpp_hashnode *node;
uchar *out_start = out - 1;
pfile->out.cur = --out; pfile->out.cur = out_start;
node = lex_identifier (pfile, cur - 1); node = lex_identifier (pfile, cur - 1);
out = pfile->out.cur;
cur = CUR (context);
if (node->type == NT_MACRO if (node->type == NT_MACRO
&& !pfile->state.skipping /* Should we expand for ls_answer? */
&& pfile->state.parsing_args != 2 && lex_state == ls_none
&& !pfile->state.prevent_expansion && !pfile->state.prevent_expansion
&& !recursive_macro (pfile, node)) && !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_start, &fmacro);
lex_state = ls_fun_macro;
continue;
}
else else
{ {
/* Remove the object-like macro's name from the /* Remove the object-like macro's name from the
output, and push its replacement text. */ output, and push its replacement text. */
pfile->out.cur = out; pfile->out.cur = out_start;
push_replacement_text (pfile, node); push_replacement_text (pfile, node);
goto new_context; goto new_context;
} }
...@@ -558,12 +601,20 @@ scan_out_logical_line (pfile, macro) ...@@ -558,12 +601,20 @@ scan_out_logical_line (pfile, macro)
{ {
/* Found a parameter in the replacement text of a /* Found a parameter in the replacement text of a
#define. Remove its name from the output. */ #define. Remove its name from the output. */
pfile->out.cur = out; out = pfile->out.cur = out_start;
save_replacement_text (pfile, macro, node->arg_index); save_replacement_text (pfile, macro, node->arg_index);
} }
else if (lex_state == ls_hash)
out = pfile->out.cur; {
cur = CUR (context); lex_state = ls_predicate;
continue;
}
else if (pfile->state.in_expression
&& node == pfile->spec_nodes.n_defined)
{
lex_state = ls_defined;
continue;
}
} }
break; break;
...@@ -571,27 +622,18 @@ scan_out_logical_line (pfile, macro) ...@@ -571,27 +622,18 @@ scan_out_logical_line (pfile, macro)
if (quote == 0) if (quote == 0)
{ {
paren_depth++; paren_depth++;
if (pfile->state.parsing_args == 1) if (lex_state == ls_fun_macro)
{ {
const uchar *p = pfile->out.base + fmacro.offset; lex_state = ls_none;
pfile->state.parsing_args = 2;
/* Invoke a prior function-like macro if there is only paren_depth = 1;
white space in-between. */ out = pfile->out.base + fmacro.offset;
while (is_numchar (*p)) fmacro.args[0] = fmacro.offset;
p++;
while (is_space (*p))
p++;
if (p == out - 1)
{
pfile->state.parsing_args = 2;
paren_depth = 1;
out = pfile->out.base + fmacro.offset;
fmacro.args[0] = fmacro.offset;
}
else
pfile->state.parsing_args = 0;
} }
else if (lex_state == ls_predicate)
lex_state = ls_answer;
else if (lex_state == ls_defined)
lex_state = ls_defined_close;
} }
break; break;
...@@ -614,7 +656,7 @@ scan_out_logical_line (pfile, macro) ...@@ -614,7 +656,7 @@ scan_out_logical_line (pfile, macro)
/* A single zero-length argument is no argument. */ /* A single zero-length argument is no argument. */
if (fmacro.argc == 1 if (fmacro.argc == 1
&& m->paramc == 0 && m->paramc == 0
&& out == pfile->out.base + 1) && out == pfile->out.base + fmacro.offset + 1)
fmacro.argc = 0; fmacro.argc = 0;
if (_cpp_arguments_ok (pfile, m, fmacro.node, fmacro.argc)) if (_cpp_arguments_ok (pfile, m, fmacro.node, fmacro.argc))
...@@ -628,6 +670,8 @@ scan_out_logical_line (pfile, macro) ...@@ -628,6 +670,8 @@ scan_out_logical_line (pfile, macro)
goto new_context; goto new_context;
} }
} }
else if (lex_state == ls_answer || lex_state == ls_defined_close)
lex_state = ls_none;
} }
break; break;
...@@ -641,11 +685,34 @@ scan_out_logical_line (pfile, macro) ...@@ -641,11 +685,34 @@ scan_out_logical_line (pfile, macro)
if (_cpp_handle_directive (pfile, false /* indented */)) if (_cpp_handle_directive (pfile, false /* indented */))
goto start_logical_line; goto start_logical_line;
} }
if (pfile->state.in_expression)
{
lex_state = ls_hash;
continue;
}
break; break;
default: default:
break; break;
} }
if (lex_state == ls_none)
continue;
/* Some of these transitions of state are syntax errors. The
ISO preprocessor will issue errors later. */
if (lex_state == ls_fun_macro)
{
/* Missing '('. */
lex_state = ls_none;
pfile->state.parsing_args = 0;
}
else if (lex_state == ls_hash
|| lex_state == ls_predicate
|| lex_state == ls_defined)
lex_state = ls_none;
/* ls_answer and ls_defined_close keep going until ')'. */
} }
done: done:
...@@ -654,6 +721,12 @@ scan_out_logical_line (pfile, macro) ...@@ -654,6 +721,12 @@ scan_out_logical_line (pfile, macro)
pfile->out.cur = out - 1; pfile->out.cur = out - 1;
if (fmacro.buff) if (fmacro.buff)
_cpp_release_buff (pfile, fmacro.buff); _cpp_release_buff (pfile, fmacro.buff);
if (pfile->state.parsing_args == 2)
cpp_error (pfile, DL_ERROR,
"unterminated argument list invoking macro \"%s\"",
NODE_NAME (fmacro.node));
pfile->state.parsing_args = 0;
} }
/* Push a context holding the replacement text of the macro NODE on /* Push a context holding the replacement text of the macro NODE on
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment