Commit 417f3e3a by Zack Weinberg

[multiple changes]

2000-07-11  Zack Weinberg  <zack@wolery.cumb.org>

	* cpplex.c (parse_name): No longer inline (premature optimization).
	(do_pop_context): Fold into pop_context.
	(pop_context): Returns int.
	(lex_next): Hoist test for end of directive into pop_context.
	(push_macro_context): Returns int; takes just reader and token.
	Hoist test for excessive nesting to caller.
	(push_arg_context): Returns void; takes just reader and token.
	Do not call stringify_arg or get_raw_token.
	(get_raw_token): Convert tail recursion through	push_arg_context
	to a loop at this level.  Call stringify_arg here if appropriate.
	(maybe_paste_with_next): Convert tail recursion to a while loop.
	Hoist test of paste_level to caller.

	(stringify_arg): Push arg context at beginning.
	(cpp_get_token): Split out core into _cpp_get_token.  Call
	process_directive here.  Throw away CPP_PLACEMARKER tokens.
	(_cpp_get_token): Convert tail recursion through
	push_macro_context to a loop at this level.
	(_cpp_glue_header_name, is_macro_disabled, stringify_arg,
	_cpp_get_raw_token): Use _cpp_get_token.
	(_cpp_skip_rest_of_line): Drop the context stack directly; do
	not call pop_context.
	(_cpp_run_directive): Call lex_next directly.

	* cpphash.h: Prototype _cpp_get_token.
	* cppexp.c (lex): Use it.
	* cpphash.c (parse_define): Use it.
	* cpplib.c (get_define_node, do_undef, parse_include,
	read_line_number, do_line, do_ident, do_pragma, do_pragma_gcc,
	do_pragma_implementation, do_pragma_poison, do_pragma_dependency,
	parse_ifdef, validate_else): Use it.
	(cpp_push_buffer): Tweak error message; abort if anyone tries
	to push a buffer while macro expansions are stacked.

2000-07-11  Donn Terry  <donnte@microsoft.com>

	* cpplex.c (free_macro_args, save_token): Cast arg of free
	and/or xrealloc to PTR.
	(_cpp_init_input_buffer): Clear all fields of the base context.

From-SVN: r34972
parent 268afb99
2000-07-11 Zack Weinberg <zack@wolery.cumb.org>
* cpplex.c (parse_name): No longer inline (premature optimization).
(do_pop_context): Fold into pop_context.
(pop_context): Returns int.
(lex_next): Hoist test for end of directive into pop_context.
(push_macro_context): Returns int; takes just reader and token.
Hoist test for excessive nesting to caller.
(push_arg_context): Returns void; takes just reader and token.
Do not call stringify_arg or get_raw_token.
(get_raw_token): Convert tail recursion through push_arg_context
to a loop at this level. Call stringify_arg here if appropriate.
(maybe_paste_with_next): Convert tail recursion to a while loop.
Hoist test of paste_level to caller.
(stringify_arg): Push arg context at beginning.
(cpp_get_token): Split out core into _cpp_get_token. Call
process_directive here. Throw away CPP_PLACEMARKER tokens.
(_cpp_get_token): Convert tail recursion through
push_macro_context to a loop at this level.
(_cpp_glue_header_name, is_macro_disabled, stringify_arg,
_cpp_get_raw_token): Use _cpp_get_token.
(_cpp_skip_rest_of_line): Drop the context stack directly; do
not call pop_context.
(_cpp_run_directive): Call lex_next directly.
* cpphash.h: Prototype _cpp_get_token.
* cppexp.c (lex): Use it.
* cpphash.c (parse_define): Use it.
* cpplib.c (get_define_node, do_undef, parse_include,
read_line_number, do_line, do_ident, do_pragma, do_pragma_gcc,
do_pragma_implementation, do_pragma_poison, do_pragma_dependency,
parse_ifdef, validate_else): Use it.
(cpp_push_buffer): Tweak error message; abort if anyone tries
to push a buffer while macro expansions are stacked.
2000-07-11 Donn Terry <donnte@microsoft.com>
* cpplex.c (free_macro_args, save_token): Cast arg of free
and/or xrealloc to PTR.
(_cpp_init_input_buffer): Clear all fields of the base context.
Tue Jul 11 15:28:21 CDT 2000 Clinton Popetz <cpopetz@cygnus.com> Tue Jul 11 15:28:21 CDT 2000 Clinton Popetz <cpopetz@cygnus.com>
* gensupport.c (process_rtx): Make rtl checking stop * gensupport.c (process_rtx): Make rtl checking stop
......
...@@ -392,7 +392,7 @@ lex (pfile, skip_evaluation) ...@@ -392,7 +392,7 @@ lex (pfile, skip_evaluation)
const cpp_token *tok; const cpp_token *tok;
retry: retry:
tok = cpp_get_token (pfile); tok = _cpp_get_token (pfile);
switch (tok->type) switch (tok->type)
{ {
......
...@@ -354,7 +354,7 @@ parse_define (pfile) ...@@ -354,7 +354,7 @@ parse_define (pfile)
int prev_white = 0; int prev_white = 0;
/* The first token after the macro's name. */ /* The first token after the macro's name. */
token = cpp_get_token (pfile); token = _cpp_get_token (pfile);
/* Constraint 6.10.3.5 */ /* Constraint 6.10.3.5 */
if (is__va_args__ (pfile, token - 1)) if (is__va_args__ (pfile, token - 1))
......
...@@ -256,6 +256,7 @@ extern void _cpp_run_directive PARAMS ((cpp_reader *, ...@@ -256,6 +256,7 @@ extern void _cpp_run_directive PARAMS ((cpp_reader *,
const char *, size_t)); const char *, size_t));
extern unsigned int _cpp_get_line PARAMS ((cpp_reader *, extern unsigned int _cpp_get_line PARAMS ((cpp_reader *,
unsigned int *)); unsigned int *));
extern const cpp_token *_cpp_get_token PARAMS ((cpp_reader *));
extern const cpp_token *_cpp_get_raw_token PARAMS ((cpp_reader *)); extern const cpp_token *_cpp_get_raw_token PARAMS ((cpp_reader *));
extern void _cpp_push_token PARAMS ((cpp_reader *, const cpp_token*)); extern void _cpp_push_token PARAMS ((cpp_reader *, const cpp_token*));
extern const cpp_token *_cpp_glue_header_name PARAMS ((cpp_reader *)); extern const cpp_token *_cpp_glue_header_name PARAMS ((cpp_reader *));
......
...@@ -417,7 +417,7 @@ _cpp_glue_header_name (pfile) ...@@ -417,7 +417,7 @@ _cpp_glue_header_name (pfile)
for (;;) for (;;)
{ {
t = cpp_get_token (pfile); t = _cpp_get_token (pfile);
if (t->type == CPP_GREATER || t->type == CPP_EOF) if (t->type == CPP_GREATER || t->type == CPP_EOF)
break; break;
...@@ -947,7 +947,7 @@ skip_whitespace (pfile, in_directive) ...@@ -947,7 +947,7 @@ skip_whitespace (pfile, in_directive)
} }
/* Parse (append) an identifier. */ /* Parse (append) an identifier. */
static inline const U_CHAR * static const U_CHAR *
parse_name (pfile, tok, cur, rlimit) parse_name (pfile, tok, cur, rlimit)
cpp_reader *pfile; cpp_reader *pfile;
cpp_token *tok; cpp_token *tok;
...@@ -1960,7 +1960,7 @@ struct cpp_context ...@@ -1960,7 +1960,7 @@ struct cpp_context
const cpp_token **arg; /* Used for arg contexts only. */ const cpp_token **arg; /* Used for arg contexts only. */
} u; } u;
/* Pushed token to be returned by next call to cpp_get_token. */ /* Pushed token to be returned by next call to get_raw_token. */
const cpp_token *pushed_token; const cpp_token *pushed_token;
struct macro_args *args; /* 0 for arguments and object-like macros. */ struct macro_args *args; /* 0 for arguments and object-like macros. */
...@@ -1985,13 +1985,9 @@ static const cpp_token *parse_arg PARAMS ((cpp_reader *, int, unsigned int, ...@@ -1985,13 +1985,9 @@ static const cpp_token *parse_arg PARAMS ((cpp_reader *, int, unsigned int,
macro_args *, unsigned int *)); macro_args *, unsigned int *));
static int parse_args PARAMS ((cpp_reader *, cpp_hashnode *, macro_args *)); static int parse_args PARAMS ((cpp_reader *, cpp_hashnode *, macro_args *));
static void save_token PARAMS ((macro_args *, const cpp_token *)); static void save_token PARAMS ((macro_args *, const cpp_token *));
static const cpp_token *push_arg_context PARAMS ((cpp_reader *, static int pop_context PARAMS ((cpp_reader *));
const cpp_token *)); static int push_macro_context PARAMS ((cpp_reader *, const cpp_token *));
static int do_pop_context PARAMS ((cpp_reader *)); static void push_arg_context PARAMS ((cpp_reader *, const cpp_token *));
static const cpp_token *pop_context PARAMS ((cpp_reader *));
static const cpp_token *push_macro_context PARAMS ((cpp_reader *,
cpp_hashnode *,
const cpp_token *));
static void free_macro_args PARAMS ((macro_args *)); static void free_macro_args PARAMS ((macro_args *));
/* Free the storage allocated for macro arguments. */ /* Free the storage allocated for macro arguments. */
...@@ -2000,7 +1996,7 @@ free_macro_args (args) ...@@ -2000,7 +1996,7 @@ free_macro_args (args)
macro_args *args; macro_args *args;
{ {
if (args->tokens) if (args->tokens)
free (args->tokens); free ((PTR) args->tokens);
free (args->ends); free (args->ends);
free (args); free (args);
} }
...@@ -2069,7 +2065,7 @@ is_macro_disabled (pfile, expansion, token) ...@@ -2069,7 +2065,7 @@ is_macro_disabled (pfile, expansion, token)
prev_nme = pfile->no_expand_level; prev_nme = pfile->no_expand_level;
pfile->no_expand_level = context - pfile->contexts; pfile->no_expand_level = context - pfile->contexts;
next = cpp_get_token (pfile); next = _cpp_get_token (pfile);
restore_macro_expansion (pfile, prev_nme); restore_macro_expansion (pfile, prev_nme);
if (next->type != CPP_OPEN_PAREN) if (next->type != CPP_OPEN_PAREN)
{ {
...@@ -2096,7 +2092,8 @@ save_token (args, token) ...@@ -2096,7 +2092,8 @@ save_token (args, token)
{ {
args->capacity += args->capacity + 100; args->capacity += args->capacity + 100;
args->tokens = (const cpp_token **) args->tokens = (const cpp_token **)
xrealloc (args->tokens, args->capacity * sizeof (const cpp_token *)); xrealloc ((PTR) args->tokens,
args->capacity * sizeof (const cpp_token *));
} }
args->tokens[args->used++] = token; args->tokens[args->used++] = token;
} }
...@@ -2117,7 +2114,7 @@ parse_arg (pfile, var_args, paren_context, args, pcount) ...@@ -2117,7 +2114,7 @@ parse_arg (pfile, var_args, paren_context, args, pcount)
for (count = 0;; count++) for (count = 0;; count++)
{ {
token = cpp_get_token (pfile); token = _cpp_get_token (pfile);
switch (token->type) switch (token->type)
{ {
...@@ -2511,97 +2508,100 @@ maybe_paste_with_next (pfile, token) ...@@ -2511,97 +2508,100 @@ maybe_paste_with_next (pfile, token)
cpp_context *context = CURRENT_CONTEXT (pfile); cpp_context *context = CURRENT_CONTEXT (pfile);
/* Is this token on the LHS of ## ? */ /* Is this token on the LHS of ## ? */
if (!((context->flags & CONTEXT_PASTEL) && context->posn == context->count)
&& !(token->flags & PASTE_LEFT))
return token;
/* Prevent recursion, and possibly pushing back more than one token. */ while ((token->flags & PASTE_LEFT)
if (pfile->paste_level) || ((context->flags & CONTEXT_PASTEL)
return token; && context->posn == context->count))
/* Suppress macro expansion for next token, but don't conflict with
the other method of suppression. If it is an argument, macro
expansion within the argument will still occur. */
pfile->paste_level = pfile->cur_context;
second = cpp_get_token (pfile);
pfile->paste_level = 0;
/* Ignore placemarker argument tokens (cannot be from an empty macro
since macros are not expanded). */
if (token->type == CPP_PLACEMARKER)
pasted = duplicate_token (pfile, second);
else if (second->type == CPP_PLACEMARKER)
{ {
cpp_context *mac_context = CURRENT_CONTEXT (pfile) - 1; /* Suppress macro expansion for next token, but don't conflict
/* GCC has special extended semantics for a ## b where b is a with the other method of suppression. If it is an argument,
varargs parameter: a disappears if b consists of no tokens. macro expansion within the argument will still occur. */
This extension is deprecated. */ pfile->paste_level = pfile->cur_context;
if ((mac_context->u.list->flags & GNU_REST_ARGS) second = _cpp_get_token (pfile);
&& (mac_context->u.list->tokens[mac_context->posn - 1].val.aux + 1 pfile->paste_level = 0;
== (unsigned) mac_context->u.list->paramc))
/* Ignore placemarker argument tokens (cannot be from an empty
macro since macros are not expanded). */
if (token->type == CPP_PLACEMARKER)
pasted = duplicate_token (pfile, second);
else if (second->type == CPP_PLACEMARKER)
{ {
cpp_warning (pfile, "deprecated GNU ## extension used"); cpp_context *mac_context = CURRENT_CONTEXT (pfile) - 1;
pasted = duplicate_token (pfile, second); /* GCC has special extended semantics for a ## b where b is
a varargs parameter: a disappears if b consists of no
tokens. This extension is deprecated. */
if ((mac_context->u.list->flags & GNU_REST_ARGS)
&& (mac_context->u.list->tokens[mac_context->posn-1].val.aux + 1
== (unsigned) mac_context->u.list->paramc))
{
cpp_warning (pfile, "deprecated GNU ## extension used");
pasted = duplicate_token (pfile, second);
}
else
pasted = duplicate_token (pfile, token);
} }
else else
pasted = duplicate_token (pfile, token);
}
else
{
int digraph = 0;
enum cpp_ttype type = can_paste (pfile, token, second, &digraph);
if (type == CPP_EOF)
{ {
if (CPP_OPTION (pfile, warn_paste)) int digraph = 0;
cpp_warning (pfile, enum cpp_ttype type = can_paste (pfile, token, second, &digraph);
"pasting would not give a valid preprocessing token");
_cpp_push_token (pfile, second);
return token;
}
if (type == CPP_NAME || type == CPP_NUMBER) if (type == CPP_EOF)
{ {
/* Join spellings. */ if (CPP_OPTION (pfile, warn_paste))
U_CHAR *buf, *end; cpp_warning (pfile,
"pasting would not give a valid preprocessing token");
_cpp_push_token (pfile, second);
return token;
}
pasted = get_temp_token (pfile); if (type == CPP_NAME || type == CPP_NUMBER)
buf = (U_CHAR *) alloca (TOKEN_LEN (token) + TOKEN_LEN (second)); {
end = spell_token (pfile, token, buf); /* Join spellings. */
end = spell_token (pfile, second, end); U_CHAR *buf, *end;
*end = '\0';
pasted = get_temp_token (pfile);
buf = (U_CHAR *) alloca (TOKEN_LEN (token) + TOKEN_LEN (second));
end = spell_token (pfile, token, buf);
end = spell_token (pfile, second, end);
*end = '\0';
if (type == CPP_NAME) if (type == CPP_NAME)
pasted->val.node = cpp_lookup (pfile, buf, end - buf); pasted->val.node = cpp_lookup (pfile, buf, end - buf);
else
{
pasted->val.str.text = uxstrdup (buf);
pasted->val.str.len = end - buf;
}
}
else if (type == CPP_WCHAR || type == CPP_WSTRING)
pasted = duplicate_token (pfile, second);
else else
{ {
pasted->val.str.text = uxstrdup (buf); pasted = get_temp_token (pfile);
pasted->val.str.len = end - buf; pasted->val.integer = 0;
} }
}
else if (type == CPP_WCHAR || type == CPP_WSTRING) pasted->type = type;
pasted = duplicate_token (pfile, second); pasted->flags = digraph ? DIGRAPH : 0;
else
{
pasted = get_temp_token (pfile);
pasted->val.integer = 0;
} }
pasted->type = type; /* The pasted token gets the whitespace flags and position of the
pasted->flags = digraph ? DIGRAPH : 0; first token, the PASTE_LEFT flag of the second token, plus the
PASTED flag to indicate it is the result of a paste. However, we
want to preserve the DIGRAPH flag. */
pasted->flags &= ~(PREV_WHITE | BOL | PASTE_LEFT);
pasted->flags |= ((token->flags & (PREV_WHITE | BOL))
| (second->flags & PASTE_LEFT) | PASTED);
pasted->col = token->col;
pasted->line = token->line;
/* See if there is another token to be pasted onto the one we just
constructed. */
token = pasted;
context = CURRENT_CONTEXT (pfile);
/* and loop */
} }
return token;
/* The pasted token gets the whitespace flags and position of the
first token, the PASTE_LEFT flag of the second token, plus the
PASTED flag to indicate it is the result of a paste. However, we
want to preserve the DIGRAPH flag. */
pasted->flags &= ~(PREV_WHITE | BOL | PASTE_LEFT);
pasted->flags |= ((token->flags & (PREV_WHITE | BOL))
| (second->flags & PASTE_LEFT) | PASTED);
pasted->col = token->col;
pasted->line = token->line;
return maybe_paste_with_next (pfile, pasted);
} }
/* Convert a token sequence to a single string token according to the /* Convert a token sequence to a single string token according to the
...@@ -2617,13 +2617,14 @@ stringify_arg (pfile, token) ...@@ -2617,13 +2617,14 @@ stringify_arg (pfile, token)
unsigned int prev_value, backslash_count = 0; unsigned int prev_value, backslash_count = 0;
unsigned int buf_used = 0, whitespace = 0, buf_cap = INIT_SIZE; unsigned int buf_used = 0, whitespace = 0, buf_cap = INIT_SIZE;
push_arg_context (pfile, token);
prev_value = prevent_macro_expansion (pfile); prev_value = prevent_macro_expansion (pfile);
main_buf = (unsigned char *) xmalloc (buf_cap); main_buf = (unsigned char *) xmalloc (buf_cap);
result = get_temp_token (pfile); result = get_temp_token (pfile);
ASSIGN_FLAGS_AND_POS (result, token); ASSIGN_FLAGS_AND_POS (result, token);
for (; (token = cpp_get_token (pfile))->type != CPP_EOF; ) for (; (token = _cpp_get_token (pfile))->type != CPP_EOF; )
{ {
int escape; int escape;
unsigned char *buf; unsigned char *buf;
...@@ -2690,21 +2691,15 @@ expand_context_stack (pfile) ...@@ -2690,21 +2691,15 @@ expand_context_stack (pfile)
/* Push the context of macro NODE onto the context stack. TOKEN is /* Push the context of macro NODE onto the context stack. TOKEN is
the CPP_NAME token invoking the macro. */ the CPP_NAME token invoking the macro. */
static const cpp_token * static int
push_macro_context (pfile, node, token) push_macro_context (pfile, token)
cpp_reader *pfile; cpp_reader *pfile;
cpp_hashnode *node;
const cpp_token *token; const cpp_token *token;
{ {
unsigned char orig_flags; unsigned char orig_flags;
macro_args *args; macro_args *args;
cpp_context *context; cpp_context *context;
cpp_hashnode *node = token->val.node;
if (pfile->cur_context > CPP_STACK_MAX)
{
cpp_error (pfile, "infinite macro recursion invoking '%s'", node->name);
return token;
}
/* Token's flags may change when parsing args containing a nested /* Token's flags may change when parsing args containing a nested
invocation of this macro. */ invocation of this macro. */
...@@ -2731,7 +2726,7 @@ push_macro_context (pfile, node, token) ...@@ -2731,7 +2726,7 @@ push_macro_context (pfile, node, token)
if (error) if (error)
{ {
free_macro_args (args); free_macro_args (args);
return token; return 1;
} }
} }
...@@ -2753,12 +2748,12 @@ push_macro_context (pfile, node, token) ...@@ -2753,12 +2748,12 @@ push_macro_context (pfile, node, token)
be one, empty macros are a single placemarker token. */ be one, empty macros are a single placemarker token. */
MODIFY_FLAGS_AND_POS (&context->u.list->tokens[0], token, orig_flags); MODIFY_FLAGS_AND_POS (&context->u.list->tokens[0], token, orig_flags);
return cpp_get_token (pfile); return 0;
} }
/* Push an argument to the current macro onto the context stack. /* Push an argument to the current macro onto the context stack.
TOKEN is the MACRO_ARG token representing the argument expansion. */ TOKEN is the MACRO_ARG token representing the argument expansion. */
static const cpp_token * static void
push_arg_context (pfile, token) push_arg_context (pfile, token)
cpp_reader *pfile; cpp_reader *pfile;
const cpp_token *token; const cpp_token *token;
...@@ -2792,15 +2787,10 @@ push_arg_context (pfile, token) ...@@ -2792,15 +2787,10 @@ push_arg_context (pfile, token)
token->flags & (PREV_WHITE | BOL)); token->flags & (PREV_WHITE | BOL));
} }
if (token->flags & STRINGIFY_ARG)
return stringify_arg (pfile, token);
if (token->flags & PASTE_LEFT) if (token->flags & PASTE_LEFT)
context->flags |= CONTEXT_PASTEL; context->flags |= CONTEXT_PASTEL;
if (pfile->paste_level) if (pfile->paste_level)
context->flags |= CONTEXT_PASTER; context->flags |= CONTEXT_PASTER;
return get_raw_token (pfile);
} }
/* "Unget" a token. It is effectively inserted in the token queue and /* "Unget" a token. It is effectively inserted in the token queue and
...@@ -2859,58 +2849,92 @@ cpp_get_token (pfile) ...@@ -2859,58 +2849,92 @@ cpp_get_token (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
const cpp_token *token; const cpp_token *token;
cpp_hashnode *node; /* Loop till we hit a non-directive, non-placemarker token. */
/* Loop till we hit a non-directive, non-skipped, non-placemarker token. */
for (;;) for (;;)
{ {
token = get_raw_token (pfile); token = _cpp_get_token (pfile);
if (token->flags & BOL && token->type == CPP_HASH
if (token->type == CPP_PLACEMARKER)
continue;
if (token->type == CPP_HASH && token->flags & BOL
&& pfile->token_list.directive) && pfile->token_list.directive)
{ {
process_directive (pfile, token); process_directive (pfile, token);
continue; continue;
} }
return token;
}
}
/* The internal interface to return the next token. There are two
differences between the internal and external interfaces: the
internal interface may return a PLACEMARKER token, and it does not
process directives. */
const cpp_token *
_cpp_get_token (pfile)
cpp_reader *pfile;
{
const cpp_token *token;
cpp_hashnode *node;
/* Loop until we hit a non-macro token. */
for (;;)
{
token = get_raw_token (pfile);
/* Short circuit EOF. */ /* Short circuit EOF. */
if (token->type == CPP_EOF) if (token->type == CPP_EOF)
return token; return token;
if (pfile->skipping && ! pfile->token_list.directive) /* If we are skipping... */
if (pfile->skipping)
{ {
/* we still have to process directives, */
if (pfile->token_list.directive)
return token;
/* but everything else is ignored. */
_cpp_skip_rest_of_line (pfile); _cpp_skip_rest_of_line (pfile);
continue; continue;
} }
break;
}
/* If there's a potential control macro and we get here, then that /* If there's a potential control macro and we get here, then that
#ifndef didn't cover the entire file and its argument shouldn't #ifndef didn't cover the entire file and its argument shouldn't
be taken as a control macro. */ be taken as a control macro. */
pfile->potential_control_macro = 0; pfile->potential_control_macro = 0;
token = maybe_paste_with_next (pfile, token); /* See if there's a token to paste with this one. */
if (!pfile->paste_level)
token = maybe_paste_with_next (pfile, token);
if (token->type != CPP_NAME) /* If it isn't a macro, return it now. */
return token; if (token->type != CPP_NAME
|| token->val.node->type == T_VOID)
return token;
/* Is macro expansion disabled in general? */ /* Is macro expansion disabled in general? */
if (pfile->no_expand_level == pfile->cur_context || pfile->paste_level) if (pfile->no_expand_level == pfile->cur_context || pfile->paste_level)
return token; return token;
node = token->val.node; node = token->val.node;
if (node->type == T_VOID) if (node->type != T_MACRO)
return token; return special_symbol (pfile, node, token);
if (node->type == T_MACRO)
{
if (is_macro_disabled (pfile, node->value.expansion, token)) if (is_macro_disabled (pfile, node->value.expansion, token))
return token; return token;
return push_macro_context (pfile, node, token); if (pfile->cur_context > CPP_STACK_MAX)
{
cpp_error (pfile, "macros nested too deep invoking '%s'", node->name);
return token;
}
if (push_macro_context (pfile, token))
return token;
/* else loop */
} }
else
return special_symbol (pfile, node, token);
} }
/* Returns the next raw token, i.e. without performing macro /* Returns the next raw token, i.e. without performing macro
...@@ -2920,33 +2944,45 @@ get_raw_token (pfile) ...@@ -2920,33 +2944,45 @@ get_raw_token (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
const cpp_token *result; const cpp_token *result;
cpp_context *context = CURRENT_CONTEXT (pfile); cpp_context *context;
if (context->pushed_token) for (;;)
{
result = context->pushed_token;
context->pushed_token = 0;
}
else if (context->posn == context->count)
result = pop_context (pfile);
else
{ {
if (IS_ARG_CONTEXT (context)) context = CURRENT_CONTEXT (pfile);
if (context->pushed_token)
{ {
result = context->u.arg[context->posn++]; result = context->pushed_token;
if (result == 0) context->pushed_token = 0;
}
else if (context->posn == context->count)
{
if (pop_context (pfile))
return &eof_token;
continue;
}
else
{
if (IS_ARG_CONTEXT (context))
{ {
context->flags ^= CONTEXT_RAW;
result = context->u.arg[context->posn++]; result = context->u.arg[context->posn++];
if (result == 0)
{
context->flags ^= CONTEXT_RAW;
result = context->u.arg[context->posn++];
}
return result; /* Cannot be a CPP_MACRO_ARG */
} }
return result; /* Cannot be a CPP_MACRO_ARG */ result = &context->u.list->tokens[context->posn++];
} }
result = &context->u.list->tokens[context->posn++];
}
if (result->type == CPP_MACRO_ARG) if (result->type != CPP_MACRO_ARG)
result = push_arg_context (pfile, result); return result;
return result;
if (result->flags & STRINGIFY_ARG)
return stringify_arg (pfile, result);
push_arg_context (pfile, result);
}
} }
/* Internal interface to get the token without macro expanding. */ /* Internal interface to get the token without macro expanding. */
...@@ -2955,7 +2991,7 @@ _cpp_get_raw_token (pfile) ...@@ -2955,7 +2991,7 @@ _cpp_get_raw_token (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
int prev_nme = prevent_macro_expansion (pfile); int prev_nme = prevent_macro_expansion (pfile);
const cpp_token *result = cpp_get_token (pfile); const cpp_token *result = _cpp_get_token (pfile);
restore_macro_expansion (pfile, prev_nme); restore_macro_expansion (pfile, prev_nme);
return result; return result;
} }
...@@ -2973,16 +3009,6 @@ lex_next (pfile, clear) ...@@ -2973,16 +3009,6 @@ lex_next (pfile, clear)
const cpp_token *old_list = list->tokens; const cpp_token *old_list = list->tokens;
unsigned int old_used = list->tokens_used; unsigned int old_used = list->tokens_used;
/* If we are currently processing a directive, do not advance. 6.10
paragraph 2: A new-line character ends the directive even if it
occurs within what would otherwise be an invocation of a
function-like macro.
It is possible that clear == 1 too; e.g. "#if funlike_macro ("
since parse_args swallowed the directive's EOF. */
if (list->directive)
return 1;
if (clear) if (clear)
{ {
/* Release all temporary tokens. */ /* Release all temporary tokens. */
...@@ -3034,18 +3060,27 @@ lex_next (pfile, clear) ...@@ -3034,18 +3060,27 @@ lex_next (pfile, clear)
return 0; return 0;
} }
/* Pops a context of the context stack. If we're at the bottom, lexes /* Pops a context off the context stack. If we're at the bottom, lexes
the next logical line. Returns 1 if we're at the end of the the next logical line. Returns EOF if we're at the end of the
argument list to the # operator, or if it is illegal to "overflow" argument list to the # operator, or if it is illegal to "overflow"
into the rest of the file (e.g. 6.10.3.1.1). */ into the rest of the file (e.g. 6.10.3.1.1). */
static int static int
do_pop_context (pfile) pop_context (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
cpp_context *context; cpp_context *context;
if (pfile->cur_context == 0) if (pfile->cur_context == 0)
return lex_next (pfile, pfile->no_expand_level == UINT_MAX); {
/* If we are currently processing a directive, do not advance. 6.10
paragraph 2: A new-line character ends the directive even if it
occurs within what would otherwise be an invocation of a
function-like macro. */
if (pfile->token_list.directive)
return 1;
return lex_next (pfile, pfile->no_expand_level == UINT_MAX);
}
/* Argument contexts, when parsing args or handling # operator /* Argument contexts, when parsing args or handling # operator
return CPP_EOF at the end. */ return CPP_EOF at the end. */
...@@ -3064,16 +3099,6 @@ do_pop_context (pfile) ...@@ -3064,16 +3099,6 @@ do_pop_context (pfile)
return 0; return 0;
} }
/* Move down the context stack, and return the next raw token. */
static const cpp_token *
pop_context (pfile)
cpp_reader *pfile;
{
if (do_pop_context (pfile))
return &eof_token;
return get_raw_token (pfile);
}
/* Turn off macro expansion at the current context level. */ /* Turn off macro expansion at the current context level. */
static unsigned int static unsigned int
prevent_macro_expansion (pfile) prevent_macro_expansion (pfile)
...@@ -3286,18 +3311,26 @@ void ...@@ -3286,18 +3311,26 @@ void
_cpp_init_input_buffer (pfile) _cpp_init_input_buffer (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
cpp_context *base;
init_trigraph_map (); init_trigraph_map ();
_cpp_init_toklist (&pfile->token_list, DUMMY_TOKEN);
pfile->no_expand_level = UINT_MAX;
pfile->context_cap = 20; pfile->context_cap = 20;
pfile->contexts = (cpp_context *)
xmalloc (pfile->context_cap * sizeof (cpp_context));
pfile->cur_context = 0; pfile->cur_context = 0;
pfile->contexts[0].u.list = &pfile->token_list;
pfile->contexts[0].posn = 0; pfile->contexts = (cpp_context *)
pfile->contexts[0].count = 0; xmalloc (pfile->context_cap * sizeof (cpp_context));
pfile->no_expand_level = UINT_MAX;
_cpp_init_toklist (&pfile->token_list, DUMMY_TOKEN); /* Clear the base context. */
base = &pfile->contexts[0];
base->u.list = &pfile->token_list;
base->posn = 0;
base->count = 0;
base->args = 0;
base->level = 0;
base->flags = 0;
base->pushed_token = 0;
} }
/* Moves to the end of the directive line, popping contexts as /* Moves to the end of the directive line, popping contexts as
...@@ -3306,17 +3339,20 @@ void ...@@ -3306,17 +3339,20 @@ void
_cpp_skip_rest_of_line (pfile) _cpp_skip_rest_of_line (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
/* Get to base context. Clear parsing args and each contexts flags, /* Discard all stacked contexts. */
since these can cause pop_context to return without popping. */ int i;
pfile->no_expand_level = UINT_MAX; for (i = pfile->cur_context; i > 0; i--)
while (pfile->cur_context != 0) if (pfile->contexts[i].args)
{ free_macro_args (pfile->contexts[i].args);
pfile->contexts[pfile->cur_context].flags = 0;
do_pop_context (pfile); if (pfile->no_expand_level <= pfile->cur_context)
} pfile->no_expand_level = 0;
pfile->cur_context = 0;
pfile->contexts[pfile->cur_context].count = 0; /* Clear the base context, and clear the directive pointer so that
pfile->contexts[pfile->cur_context].posn = 0; get_raw_token will advance to the next line. */
pfile->contexts[0].count = 0;
pfile->contexts[0].posn = 0;
pfile->token_list.directive = 0; pfile->token_list.directive = 0;
} }
...@@ -3332,8 +3368,9 @@ _cpp_run_directive (pfile, dir, buf, count) ...@@ -3332,8 +3368,9 @@ _cpp_run_directive (pfile, dir, buf, count)
if (cpp_push_buffer (pfile, (const U_CHAR *)buf, count) != NULL) if (cpp_push_buffer (pfile, (const U_CHAR *)buf, count) != NULL)
{ {
unsigned int prev_lvl = 0; unsigned int prev_lvl = 0;
/* scan the line now, else prevent_macro_expansion won't work */
do_pop_context (pfile); /* Scan the line now, else prevent_macro_expansion won't work. */
lex_next (pfile, 1);
if (! (dir->flags & EXPAND)) if (! (dir->flags & EXPAND))
prev_lvl = prevent_macro_expansion (pfile); prev_lvl = prevent_macro_expansion (pfile);
......
...@@ -250,7 +250,7 @@ get_define_node (pfile) ...@@ -250,7 +250,7 @@ get_define_node (pfile)
const cpp_token *token; const cpp_token *token;
/* Skip any -C comments. */ /* Skip any -C comments. */
while ((token = cpp_get_token (pfile))->type == CPP_COMMENT) while ((token = _cpp_get_token (pfile))->type == CPP_COMMENT)
; ;
if (token->type != CPP_NAME) if (token->type != CPP_NAME)
...@@ -307,7 +307,7 @@ do_undef (pfile) ...@@ -307,7 +307,7 @@ do_undef (pfile)
{ {
cpp_hashnode *node = get_define_node (pfile); cpp_hashnode *node = get_define_node (pfile);
if (cpp_get_token (pfile)->type != CPP_EOF) if (_cpp_get_token (pfile)->type != CPP_EOF)
cpp_pedwarn (pfile, "junk on line after #undef"); cpp_pedwarn (pfile, "junk on line after #undef");
/* 6.10.3.5 paragraph 2: [#undef] is ignored if the specified identifier /* 6.10.3.5 paragraph 2: [#undef] is ignored if the specified identifier
...@@ -343,7 +343,7 @@ parse_include (pfile, dir, trail, strp, lenp, abp) ...@@ -343,7 +343,7 @@ parse_include (pfile, dir, trail, strp, lenp, abp)
unsigned int *lenp; unsigned int *lenp;
int *abp; int *abp;
{ {
const cpp_token *name = cpp_get_token (pfile); const cpp_token *name = _cpp_get_token (pfile);
if (name->type != CPP_STRING && name->type != CPP_HEADER_NAME) if (name->type != CPP_STRING && name->type != CPP_HEADER_NAME)
{ {
...@@ -361,7 +361,7 @@ parse_include (pfile, dir, trail, strp, lenp, abp) ...@@ -361,7 +361,7 @@ parse_include (pfile, dir, trail, strp, lenp, abp)
return 1; return 1;
} }
if (!trail && cpp_get_token (pfile)->type != CPP_EOF) if (!trail && _cpp_get_token (pfile)->type != CPP_EOF)
cpp_error (pfile, "junk at end of #%s", dir); cpp_error (pfile, "junk at end of #%s", dir);
*lenp = name->val.str.len; *lenp = name->val.str.len;
...@@ -459,7 +459,7 @@ read_line_number (pfile, num) ...@@ -459,7 +459,7 @@ read_line_number (pfile, num)
cpp_reader *pfile; cpp_reader *pfile;
int *num; int *num;
{ {
const cpp_token *tok = cpp_get_token (pfile); const cpp_token *tok = _cpp_get_token (pfile);
enum cpp_ttype type = tok->type; enum cpp_ttype type = tok->type;
const U_CHAR *p = tok->val.str.text; const U_CHAR *p = tok->val.str.text;
unsigned int len = tok->val.str.len; unsigned int len = tok->val.str.len;
...@@ -519,7 +519,7 @@ do_line (pfile) ...@@ -519,7 +519,7 @@ do_line (pfile)
unsigned int len; unsigned int len;
const cpp_token *tok; const cpp_token *tok;
tok = cpp_get_token (pfile); tok = _cpp_get_token (pfile);
type = tok->type; type = tok->type;
str = tok->val.str.text; str = tok->val.str.text;
len = tok->val.str.len; len = tok->val.str.len;
...@@ -535,7 +535,7 @@ do_line (pfile) ...@@ -535,7 +535,7 @@ do_line (pfile)
old_lineno = ip->lineno; old_lineno = ip->lineno;
ip->lineno = new_lineno; ip->lineno = new_lineno;
tok = cpp_get_token (pfile); tok = _cpp_get_token (pfile);
type = tok->type; type = tok->type;
str = tok->val.str.text; str = tok->val.str.text;
len = tok->val.str.len; len = tok->val.str.len;
...@@ -645,9 +645,9 @@ do_ident (pfile) ...@@ -645,9 +645,9 @@ do_ident (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
/* Next token should be a string constant. */ /* Next token should be a string constant. */
if (cpp_get_token (pfile)->type == CPP_STRING) if (_cpp_get_token (pfile)->type == CPP_STRING)
/* And then a newline. */ /* And then a newline. */
if (cpp_get_token (pfile)->type == CPP_EOF) if (_cpp_get_token (pfile)->type == CPP_EOF)
{ {
/* Good - ship it. */ /* Good - ship it. */
pass_thru_directive (pfile); pass_thru_directive (pfile);
...@@ -725,7 +725,7 @@ do_pragma (pfile) ...@@ -725,7 +725,7 @@ do_pragma (pfile)
const cpp_token *tok; const cpp_token *tok;
int pop; int pop;
tok = cpp_get_token (pfile); tok = _cpp_get_token (pfile);
if (tok->type == CPP_EOF) if (tok->type == CPP_EOF)
return 0; return 0;
else if (tok->type != CPP_NAME) else if (tok->type != CPP_NAME)
...@@ -746,7 +746,7 @@ do_pragma_gcc (pfile) ...@@ -746,7 +746,7 @@ do_pragma_gcc (pfile)
{ {
const cpp_token *tok; const cpp_token *tok;
tok = cpp_get_token (pfile); tok = _cpp_get_token (pfile);
if (tok->type == CPP_EOF) if (tok->type == CPP_EOF)
return 1; return 1;
else if (tok->type != CPP_NAME) else if (tok->type != CPP_NAME)
...@@ -780,13 +780,13 @@ do_pragma_implementation (pfile) ...@@ -780,13 +780,13 @@ do_pragma_implementation (pfile)
{ {
/* Be quiet about `#pragma implementation' for a file only if it hasn't /* Be quiet about `#pragma implementation' for a file only if it hasn't
been included yet. */ been included yet. */
const cpp_token *tok = cpp_get_token (pfile); const cpp_token *tok = _cpp_get_token (pfile);
char *copy; char *copy;
if (tok->type == CPP_EOF) if (tok->type == CPP_EOF)
return 0; return 0;
else if (tok->type != CPP_STRING else if (tok->type != CPP_STRING
|| cpp_get_token (pfile)->type != CPP_EOF) || _cpp_get_token (pfile)->type != CPP_EOF)
{ {
cpp_error (pfile, "malformed #pragma implementation"); cpp_error (pfile, "malformed #pragma implementation");
return 1; return 1;
...@@ -822,7 +822,7 @@ do_pragma_poison (pfile) ...@@ -822,7 +822,7 @@ do_pragma_poison (pfile)
for (;;) for (;;)
{ {
tok = cpp_get_token (pfile); tok = _cpp_get_token (pfile);
if (tok->type == CPP_EOF) if (tok->type == CPP_EOF)
break; break;
if (tok->type != CPP_NAME) if (tok->type != CPP_NAME)
...@@ -887,7 +887,7 @@ do_pragma_dependency (pfile) ...@@ -887,7 +887,7 @@ do_pragma_dependency (pfile)
cpp_warning (pfile, "cannot find source %c%s%c", left, name, right); cpp_warning (pfile, "cannot find source %c%s%c", left, name, right);
else if (ordering > 0) else if (ordering > 0)
{ {
const cpp_token *msg = cpp_get_token (pfile); const cpp_token *msg = _cpp_get_token (pfile);
cpp_warning (pfile, "current file is older than %c%s%c", cpp_warning (pfile, "current file is older than %c%s%c",
left, name, right); left, name, right);
...@@ -974,7 +974,7 @@ parse_ifdef (pfile, name) ...@@ -974,7 +974,7 @@ parse_ifdef (pfile, name)
enum cpp_ttype type; enum cpp_ttype type;
const cpp_hashnode *node = 0; const cpp_hashnode *node = 0;
const cpp_token *token = cpp_get_token (pfile); const cpp_token *token = _cpp_get_token (pfile);
type = token->type; type = token->type;
if (!CPP_TRADITIONAL (pfile)) if (!CPP_TRADITIONAL (pfile))
...@@ -983,7 +983,7 @@ parse_ifdef (pfile, name) ...@@ -983,7 +983,7 @@ parse_ifdef (pfile, name)
cpp_pedwarn (pfile, "#%s with no argument", name); cpp_pedwarn (pfile, "#%s with no argument", name);
else if (type != CPP_NAME) else if (type != CPP_NAME)
cpp_pedwarn (pfile, "#%s with invalid argument", name); cpp_pedwarn (pfile, "#%s with invalid argument", name);
else if (cpp_get_token (pfile)->type != CPP_EOF) else if (_cpp_get_token (pfile)->type != CPP_EOF)
cpp_pedwarn (pfile, "garbage at end of #%s", name); cpp_pedwarn (pfile, "garbage at end of #%s", name);
} }
...@@ -1186,7 +1186,7 @@ validate_else (pfile, directive) ...@@ -1186,7 +1186,7 @@ validate_else (pfile, directive)
cpp_reader *pfile; cpp_reader *pfile;
const U_CHAR *directive; const U_CHAR *directive;
{ {
if (CPP_PEDANTIC (pfile) && cpp_get_token (pfile)->type != CPP_EOF) if (CPP_PEDANTIC (pfile) && _cpp_get_token (pfile)->type != CPP_EOF)
cpp_pedwarn (pfile, "ISO C forbids text after #%s", directive); cpp_pedwarn (pfile, "ISO C forbids text after #%s", directive);
} }
...@@ -1515,9 +1515,14 @@ cpp_push_buffer (pfile, buffer, length) ...@@ -1515,9 +1515,14 @@ cpp_push_buffer (pfile, buffer, length)
cpp_buffer *new; cpp_buffer *new;
if (++pfile->buffer_stack_depth == CPP_STACK_MAX) if (++pfile->buffer_stack_depth == CPP_STACK_MAX)
{ {
cpp_fatal (pfile, "#include recursion too deep"); cpp_fatal (pfile, "#include nested too deep");
return NULL; return NULL;
} }
if (pfile->cur_context > 0)
{
cpp_ice (pfile, "buffer pushed with contexts stacked");
_cpp_skip_rest_of_line (pfile);
}
new = xobnew (pfile->buffer_ob, cpp_buffer); new = xobnew (pfile->buffer_ob, cpp_buffer);
memset (new, 0, sizeof (cpp_buffer)); memset (new, 0, sizeof (cpp_buffer));
......
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