Commit cbc69f84 by Neil Booth Committed by Neil Booth

cpphash.h (_cpp_create_definition): Update prototype.

	* cpphash.h (_cpp_create_definition): Update prototype.
	(_cpp_push_text_context, _cpp_create_trad_definition): New.
	( cpp_lex_identifier_trad): New.
	(_cpp_set_trad_context): New.
	* cppinit.c (cpp_finish_options): Don't conditionalize builtins.
	* cpplib.c (SEEN_EOL): Update.
	(lex_macro_node): Update for -traditional.
	(cpp_push_buffer, _cpp_pop_buffer): Similarly.
	* cppmacro.c (_cpp_create_definition): Split into
	create_iso_definition() and _cpp_create_trad_definition().
	(warn_of_redefinition): Update prototype; handle traditional
	macros.
	(_cpp_push_text_context): New.
	* cpptrad.c (skip_whitespace, push_replacement_text): New.
	(lex_identifier): Call ht_lookup with correct start.
	(_cpp_lex_identifier_tradm _cpp_create_trad_definition,
	_cpp_set_trad_context): New.
	(scan_out_logical_line): Update to handle changing contexts.

From-SVN: r54293
parent dbf87f32
2002-06-05 Neil Booth <neil@daikokuya.demon.co.uk>
* cpphash.h (_cpp_create_definition): Update prototype.
(_cpp_push_text_context, _cpp_create_trad_definition): New.
( cpp_lex_identifier_trad): New.
(_cpp_set_trad_context): New.
* cppinit.c (cpp_finish_options): Don't conditionalize builtins.
* cpplib.c (SEEN_EOL): Update.
(lex_macro_node): Update for -traditional.
(cpp_push_buffer, _cpp_pop_buffer): Similarly.
* cppmacro.c (_cpp_create_definition): Split into
create_iso_definition() and _cpp_create_trad_definition().
(warn_of_redefinition): Update prototype; handle traditional
macros.
(_cpp_push_text_context): New.
* cpptrad.c (skip_whitespace, push_replacement_text): New.
(lex_identifier): Call ht_lookup with correct start.
(_cpp_lex_identifier_tradm _cpp_create_trad_definition,
_cpp_set_trad_context): New.
(scan_out_logical_line): Update to handle changing contexts.
Wed Jun 5 20:42:31 2002 J"orn Rennecke <joern.rennecke@superh.com> Wed Jun 5 20:42:31 2002 J"orn Rennecke <joern.rennecke@superh.com>
* config.gcc (sh-*-elf*, sh64*-*-elf*): Unify. * config.gcc (sh-*-elf*, sh64*-*-elf*): Unify.
......
...@@ -424,8 +424,11 @@ extern int _cpp_begin_message PARAMS ((cpp_reader *, int, ...@@ -424,8 +424,11 @@ extern int _cpp_begin_message PARAMS ((cpp_reader *, int,
/* In cppmacro.c */ /* In cppmacro.c */
extern void _cpp_free_definition PARAMS ((cpp_hashnode *)); extern void _cpp_free_definition PARAMS ((cpp_hashnode *));
extern int _cpp_create_definition PARAMS ((cpp_reader *, cpp_hashnode *)); extern bool _cpp_create_definition PARAMS ((cpp_reader *, cpp_hashnode *));
extern void _cpp_pop_context PARAMS ((cpp_reader *)); extern void _cpp_pop_context PARAMS ((cpp_reader *));
extern void _cpp_push_text_context PARAMS ((cpp_reader *, cpp_hashnode *,
const uchar *, const uchar*));
extern bool _cpp_create_trad_definition PARAMS ((cpp_reader *, cpp_macro *));
/* In cpphash.c */ /* In cpphash.c */
extern void _cpp_init_hashtable PARAMS ((cpp_reader *, hash_table *)); extern void _cpp_init_hashtable PARAMS ((cpp_reader *, hash_table *));
...@@ -478,6 +481,8 @@ extern void _cpp_pop_buffer PARAMS ((cpp_reader *)); ...@@ -478,6 +481,8 @@ extern void _cpp_pop_buffer PARAMS ((cpp_reader *));
extern bool _cpp_read_logical_line_trad PARAMS ((cpp_reader *)); extern bool _cpp_read_logical_line_trad PARAMS ((cpp_reader *));
extern void _cpp_overlay_buffer PARAMS ((cpp_reader *pfile, const uchar *, extern void _cpp_overlay_buffer PARAMS ((cpp_reader *pfile, const uchar *,
size_t)); size_t));
extern cpp_hashnode *_cpp_lex_identifier_trad PARAMS ((cpp_reader *));
extern void _cpp_set_trad_context PARAMS ((cpp_reader *));
/* Utility routines and macros. */ /* Utility routines and macros. */
#define DSC(str) (const uchar *)str, sizeof str - 1 #define DSC(str) (const uchar *)str, sizeof str - 1
......
...@@ -995,12 +995,10 @@ cpp_finish_options (pfile) ...@@ -995,12 +995,10 @@ cpp_finish_options (pfile)
struct pending_option *p; struct pending_option *p;
_cpp_do_file_change (pfile, LC_RENAME, _("<built-in>"), 1, 0); _cpp_do_file_change (pfile, LC_RENAME, _("<built-in>"), 1, 0);
if (!CPP_OPTION (pfile, traditional) /* REMOVEME */) init_builtins (pfile);
init_builtins (pfile);
_cpp_do_file_change (pfile, LC_RENAME, _("<command line>"), 1, 0); _cpp_do_file_change (pfile, LC_RENAME, _("<command line>"), 1, 0);
if (!CPP_OPTION (pfile, traditional) /* REMOVEME */) for (p = CPP_OPTION (pfile, pending)->directive_head; p; p = p->next)
for (p = CPP_OPTION (pfile, pending)->directive_head; p; p = p->next) (*p->handler) (pfile, p->arg);
(*p->handler) (pfile, p->arg);
/* Scan -imacros files after -D, -U, but before -include. /* Scan -imacros files after -D, -U, but before -include.
pfile->next_include_file is NULL, so _cpp_pop_buffer does not pfile->next_include_file is NULL, so _cpp_pop_buffer does not
......
...@@ -202,7 +202,8 @@ static const directive linemarker_dir = ...@@ -202,7 +202,8 @@ static const directive linemarker_dir =
do_linemarker, U"#", 1, KANDR, IN_I do_linemarker, U"#", 1, KANDR, IN_I
}; };
#define SEEN_EOL() (pfile->cur_token[-1].type == CPP_EOF) #define SEEN_EOL() (CPP_OPTION (pfile, traditional) \
|| pfile->cur_token[-1].type == CPP_EOF)
/* Skip any remaining tokens in a directive. */ /* Skip any remaining tokens in a directive. */
static void static void
...@@ -447,7 +448,6 @@ lex_macro_node (pfile) ...@@ -447,7 +448,6 @@ lex_macro_node (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
cpp_hashnode *node; cpp_hashnode *node;
const cpp_token *token = _cpp_lex_token (pfile);
/* The token immediately after #define must be an identifier. That /* The token immediately after #define must be an identifier. That
identifier may not be "defined", per C99 6.10.8p4. identifier may not be "defined", per C99 6.10.8p4.
...@@ -459,39 +459,43 @@ lex_macro_node (pfile) ...@@ -459,39 +459,43 @@ lex_macro_node (pfile)
Note that if we're copying comments into macro expansions, we Note that if we're copying comments into macro expansions, we
could encounter comment tokens here, so eat them all up first. */ could encounter comment tokens here, so eat them all up first. */
if (! CPP_OPTION (pfile, discard_comments_in_macro_exp)) if (CPP_OPTION (pfile, traditional))
node = _cpp_lex_identifier_trad (pfile);
else
{ {
while (token->type == CPP_COMMENT) const cpp_token *token = _cpp_lex_token (pfile);
token = _cpp_lex_token (pfile);
} if (! CPP_OPTION (pfile, discard_comments_in_macro_exp))
{
while (token->type == CPP_COMMENT)
token = _cpp_lex_token (pfile);
}
if (token->type != CPP_NAME)
{
if (token->type == CPP_EOF) if (token->type == CPP_EOF)
cpp_error (pfile, DL_ERROR, "no macro name given in #%s directive", {
pfile->directive->name); cpp_error (pfile, DL_ERROR, "no macro name given in #%s directive",
else if (token->flags & NAMED_OP) pfile->directive->name);
cpp_error (pfile, DL_ERROR, return NULL;
"\"%s\" cannot be used as a macro name as it is an operator in C++", }
NODE_NAME (token->val.node));
if (token->type == CPP_NAME || (token->flags & NAMED_OP))
node = token->val.node;
else else
cpp_error (pfile, DL_ERROR, "macro names must be identifiers"); node = NULL;
return 0;
} }
node = token->val.node; if (!node)
if (node->flags & NODE_POISONED) cpp_error (pfile, DL_ERROR, "macro names must be identifiers");
return 0; else if (node->flags & NODE_OPERATOR)
cpp_error (pfile, DL_ERROR,
if (node == pfile->spec_nodes.n_defined) "\"%s\" cannot be used as a macro name as it is an operator in C++",
{ NODE_NAME (node));
cpp_error (pfile, DL_ERROR, "\"%s\" cannot be used as a macro name", else if (node == pfile->spec_nodes.n_defined)
NODE_NAME (node)); cpp_error (pfile, DL_ERROR, "\"defined\" cannot be used as a macro name");
return 0; else if (! (node->flags & NODE_POISONED))
} return node;
return node; return NULL;
} }
/* Process a #define directive. Most work is done in cppmacro.c. */ /* Process a #define directive. Most work is done in cppmacro.c. */
...@@ -1890,6 +1894,9 @@ cpp_push_buffer (pfile, buffer, len, from_stage3, return_at_eof) ...@@ -1890,6 +1894,9 @@ cpp_push_buffer (pfile, buffer, len, from_stage3, return_at_eof)
pfile->buffer = new; pfile->buffer = new;
if (CPP_OPTION (pfile, traditional))
_cpp_set_trad_context (pfile);
return new; return new;
} }
...@@ -1934,6 +1941,9 @@ _cpp_pop_buffer (pfile) ...@@ -1934,6 +1941,9 @@ _cpp_pop_buffer (pfile)
_cpp_maybe_push_include_file (pfile); _cpp_maybe_push_include_file (pfile);
} }
} }
if (pfile->buffer && CPP_OPTION (pfile, traditional))
_cpp_set_trad_context (pfile);
} }
/* Enter all recognised directives in the hash table. */ /* Enter all recognised directives in the hash table. */
......
...@@ -62,13 +62,14 @@ static bool paste_tokens PARAMS ((cpp_reader *, const cpp_token **, ...@@ -62,13 +62,14 @@ static bool paste_tokens PARAMS ((cpp_reader *, const cpp_token **,
static void replace_args PARAMS ((cpp_reader *, cpp_hashnode *, cpp_macro *, static void replace_args PARAMS ((cpp_reader *, cpp_hashnode *, cpp_macro *,
macro_arg *)); macro_arg *));
static _cpp_buff *funlike_invocation_p PARAMS ((cpp_reader *, cpp_hashnode *)); static _cpp_buff *funlike_invocation_p PARAMS ((cpp_reader *, cpp_hashnode *));
static bool create_iso_definition PARAMS ((cpp_reader *, cpp_macro *));
/* #define directive parsing and handling. */ /* #define directive parsing and handling. */
static cpp_token *alloc_expansion_token PARAMS ((cpp_reader *, cpp_macro *)); static cpp_token *alloc_expansion_token PARAMS ((cpp_reader *, cpp_macro *));
static cpp_token *lex_expansion_token PARAMS ((cpp_reader *, cpp_macro *)); static cpp_token *lex_expansion_token PARAMS ((cpp_reader *, cpp_macro *));
static int warn_of_redefinition PARAMS ((const cpp_hashnode *, static bool warn_of_redefinition PARAMS ((cpp_reader *, const cpp_hashnode *,
const cpp_macro *)); const cpp_macro *));
static int save_parameter PARAMS ((cpp_reader *, cpp_macro *, cpp_hashnode *)); static int save_parameter PARAMS ((cpp_reader *, cpp_macro *, cpp_hashnode *));
static int parse_params PARAMS ((cpp_reader *, cpp_macro *)); static int parse_params PARAMS ((cpp_reader *, cpp_macro *));
static void check_trad_stringification PARAMS ((cpp_reader *, static void check_trad_stringification PARAMS ((cpp_reader *,
...@@ -917,6 +918,22 @@ push_token_context (pfile, macro, first, count) ...@@ -917,6 +918,22 @@ push_token_context (pfile, macro, first, count)
LAST (context).token = first + count; LAST (context).token = first + count;
} }
/* Push a traditional macro's replacement text. */
void
_cpp_push_text_context (pfile, macro, start, end)
cpp_reader *pfile;
cpp_hashnode *macro;
const uchar *start, *end;
{
cpp_context *context = next_context (pfile);
context->direct_p = true;
context->macro = macro;
context->buff = NULL;
CUR (context) = start;
RLIMIT (context) = end;
}
/* Expand an argument ARG before replacing parameters in a /* Expand an argument ARG before replacing parameters in a
function-like macro. This works by pushing a context with the function-like macro. This works by pushing a context with the
argument's tokens, and then expanding that into a temporary buffer argument's tokens, and then expanding that into a temporary buffer
...@@ -1127,8 +1144,9 @@ _cpp_backup_tokens (pfile, count) ...@@ -1127,8 +1144,9 @@ _cpp_backup_tokens (pfile, count)
/* #define directive parsing and handling. */ /* #define directive parsing and handling. */
/* Returns non-zero if a macro redefinition warning is required. */ /* Returns non-zero if a macro redefinition warning is required. */
static int static bool
warn_of_redefinition (node, macro2) warn_of_redefinition (pfile, node, macro2)
cpp_reader *pfile;
const cpp_hashnode *node; const cpp_hashnode *node;
const cpp_macro *macro2; const cpp_macro *macro2;
{ {
...@@ -1137,7 +1155,7 @@ warn_of_redefinition (node, macro2) ...@@ -1137,7 +1155,7 @@ warn_of_redefinition (node, macro2)
/* Some redefinitions need to be warned about regardless. */ /* Some redefinitions need to be warned about regardless. */
if (node->flags & NODE_WARN) if (node->flags & NODE_WARN)
return 1; return true;
/* Redefinition of a macro is allowed if and only if the old and new /* Redefinition of a macro is allowed if and only if the old and new
definitions are the same. (6.10.3 paragraph 2). */ definitions are the same. (6.10.3 paragraph 2). */
...@@ -1148,19 +1166,22 @@ warn_of_redefinition (node, macro2) ...@@ -1148,19 +1166,22 @@ warn_of_redefinition (node, macro2)
|| macro1->paramc != macro2->paramc || macro1->paramc != macro2->paramc
|| macro1->fun_like != macro2->fun_like || macro1->fun_like != macro2->fun_like
|| macro1->variadic != macro2->variadic) || macro1->variadic != macro2->variadic)
return 1; return true;
/* Check each token. */
for (i = 0; i < macro1->count; i++)
if (! _cpp_equiv_tokens (&macro1->exp.tokens[i], &macro2->exp.tokens[i]))
return 1;
/* Check parameter spellings. */ /* Check parameter spellings. */
for (i = 0; i < macro1->paramc; i++) for (i = 0; i < macro1->paramc; i++)
if (macro1->params[i] != macro2->params[i]) if (macro1->params[i] != macro2->params[i])
return 1; return true;
return 0; /* Check the replacement text or tokens. */
if (CPP_OPTION (pfile, traditional))
return memcmp (macro1->exp.text, macro2->exp.text, macro1->count);
for (i = 0; i < macro1->count; i++)
if (!_cpp_equiv_tokens (&macro1->exp.tokens[i], &macro2->exp.tokens[i]))
return true;
return false;
} }
/* Free the definition of hashnode H. */ /* Free the definition of hashnode H. */
...@@ -1316,24 +1337,13 @@ lex_expansion_token (pfile, macro) ...@@ -1316,24 +1337,13 @@ lex_expansion_token (pfile, macro)
return token; return token;
} }
/* Parse a macro and save its expansion. Returns non-zero on success. */ static bool
int create_iso_definition (pfile, macro)
_cpp_create_definition (pfile, node)
cpp_reader *pfile; cpp_reader *pfile;
cpp_hashnode *node; cpp_macro *macro;
{ {
cpp_macro *macro; cpp_token *token;
cpp_token *token, *saved_cur_token;
const cpp_token *ctoken; const cpp_token *ctoken;
unsigned int i, ok = 1;
macro = (cpp_macro *) _cpp_aligned_alloc (pfile, sizeof (cpp_macro));
macro->line = pfile->directive_line;
macro->params = 0;
macro->paramc = 0;
macro->variadic = 0;
macro->count = 0;
macro->fun_like = 0;
/* Get the first token of the expansion (or the '(' of a /* Get the first token of the expansion (or the '(' of a
function-like macro). */ function-like macro). */
...@@ -1341,10 +1351,10 @@ _cpp_create_definition (pfile, node) ...@@ -1341,10 +1351,10 @@ _cpp_create_definition (pfile, node)
if (ctoken->type == CPP_OPEN_PAREN && !(ctoken->flags & PREV_WHITE)) if (ctoken->type == CPP_OPEN_PAREN && !(ctoken->flags & PREV_WHITE))
{ {
ok = parse_params (pfile, macro); bool ok = parse_params (pfile, macro);
macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff); macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
if (!ok) if (!ok)
goto cleanup2; return false;
/* Success. Commit the parameter array. */ /* Success. Commit the parameter array. */
BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->params[macro->paramc]; BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->params[macro->paramc];
...@@ -1354,8 +1364,6 @@ _cpp_create_definition (pfile, node) ...@@ -1354,8 +1364,6 @@ _cpp_create_definition (pfile, node)
cpp_error (pfile, DL_PEDWARN, cpp_error (pfile, DL_PEDWARN,
"ISO C requires whitespace after the macro name"); "ISO C requires whitespace after the macro name");
saved_cur_token = pfile->cur_token;
if (macro->fun_like) if (macro->fun_like)
token = lex_expansion_token (pfile, macro); token = lex_expansion_token (pfile, macro);
else else
...@@ -1381,10 +1389,9 @@ _cpp_create_definition (pfile, node) ...@@ -1381,10 +1389,9 @@ _cpp_create_definition (pfile, node)
/* Let assembler get away with murder. */ /* Let assembler get away with murder. */
else if (CPP_OPTION (pfile, lang) != CLK_ASM) else if (CPP_OPTION (pfile, lang) != CLK_ASM)
{ {
ok = 0;
cpp_error (pfile, DL_ERROR, cpp_error (pfile, DL_ERROR,
"'#' is not followed by a macro parameter"); "'#' is not followed by a macro parameter");
goto cleanup1; return false;
} }
} }
...@@ -1401,10 +1408,9 @@ _cpp_create_definition (pfile, node) ...@@ -1401,10 +1408,9 @@ _cpp_create_definition (pfile, node)
if (macro->count == 0 || token->type == CPP_EOF) if (macro->count == 0 || token->type == CPP_EOF)
{ {
ok = 0;
cpp_error (pfile, DL_ERROR, cpp_error (pfile, DL_ERROR,
"'##' cannot appear at either end of a macro expansion"); "'##' cannot appear at either end of a macro expansion");
goto cleanup1; return false;
} }
token[-1].flags |= PASTE_LEFT; token[-1].flags |= PASTE_LEFT;
...@@ -1425,25 +1431,68 @@ _cpp_create_definition (pfile, node) ...@@ -1425,25 +1431,68 @@ _cpp_create_definition (pfile, node)
/* Commit the memory. */ /* Commit the memory. */
BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->exp.tokens[macro->count]; BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->exp.tokens[macro->count];
/* Implement the macro-defined-to-itself optimisation. */ return true;
if (macro->count == 1 && !macro->fun_like }
&& macro->exp.tokens[0].type == CPP_NAME
&& macro->exp.tokens[0].val.node == node) /* Parse a macro and save its expansion. Returns non-zero on success. */
node->flags |= NODE_DISABLED; bool
_cpp_create_definition (pfile, node)
cpp_reader *pfile;
cpp_hashnode *node;
{
cpp_macro *macro;
unsigned int i;
bool ok;
macro = (cpp_macro *) _cpp_aligned_alloc (pfile, sizeof (cpp_macro));
macro->line = pfile->directive_line;
macro->params = 0;
macro->paramc = 0;
macro->variadic = 0;
macro->count = 0;
macro->fun_like = 0;
/* To suppress some diagnostics. */ /* To suppress some diagnostics. */
macro->syshdr = pfile->map->sysp != 0; macro->syshdr = pfile->map->sysp != 0;
if (CPP_OPTION (pfile, traditional))
ok = _cpp_create_trad_definition (pfile, macro);
else
{
cpp_token *saved_cur_token = pfile->cur_token;
ok = create_iso_definition (pfile, macro);
/* Restore lexer position because of games lex_expansion_token()
plays lexing the macro. We set the type for SEEN_EOL() in
cpplib.c.
Longer term we should lex the whole line before coming here,
and just copy the expansion. */
saved_cur_token[-1].type = pfile->cur_token[-1].type;
pfile->cur_token = saved_cur_token;
/* Stop the lexer accepting __VA_ARGS__. */
pfile->state.va_args_ok = 0;
}
/* Clear the fast argument lookup indices. */
for (i = macro->paramc; i-- > 0; )
macro->params[i]->arg_index = 0;
if (!ok)
return ok;
if (node->type != NT_VOID) if (node->type != NT_VOID)
{ {
if (warn_of_redefinition (node, macro)) if (warn_of_redefinition (pfile, node, macro))
{ {
cpp_error_with_line (pfile, DL_PEDWARN, pfile->directive_line, 0, cpp_error_with_line (pfile, DL_PEDWARN, pfile->directive_line, 0,
"\"%s\" redefined", NODE_NAME (node)); "\"%s\" redefined", NODE_NAME (node));
if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)) if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
cpp_error_with_line (pfile, DL_PEDWARN, node->value.macro->line, 0, cpp_error_with_line (pfile, DL_PEDWARN,
"this is the location of the previous definition"); node->value.macro->line, 0,
"this is the location of the previous definition");
} }
_cpp_free_definition (node); _cpp_free_definition (node);
} }
...@@ -1454,21 +1503,6 @@ _cpp_create_definition (pfile, node) ...@@ -1454,21 +1503,6 @@ _cpp_create_definition (pfile, node)
if (! ustrncmp (NODE_NAME (node), DSC ("__STDC_"))) if (! ustrncmp (NODE_NAME (node), DSC ("__STDC_")))
node->flags |= NODE_WARN; node->flags |= NODE_WARN;
cleanup1:
/* Set type for SEEN_EOL() in cpplib.c, restore the lexer position. */
saved_cur_token[-1].type = pfile->cur_token[-1].type;
pfile->cur_token = saved_cur_token;
cleanup2:
/* Stop the lexer accepting __VA_ARGS__. */
pfile->state.va_args_ok = 0;
/* Clear the fast argument lookup indices. */
for (i = macro->paramc; i-- > 0; )
macro->params[i]->arg_index = 0;
return ok; return ok;
} }
......
...@@ -23,16 +23,19 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ ...@@ -23,16 +23,19 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Lexing TODO: Handle -C, maybe -CC, and space in escaped newlines. /* Lexing TODO: Handle -C, maybe -CC, and space in escaped newlines.
Stop cpplex.c from recognizing comments and directives during its Stop cpplex.c from recognizing comments and directives during its
lexing pass. Get rid of line_base usage - seems pointless? */ lexing pass. Get rid of line_base usage - seems pointless? Do we
get escaped newline at EOF correct? */
static const uchar *handle_newline PARAMS ((cpp_reader *, const uchar *)); static const uchar *handle_newline PARAMS ((cpp_reader *, const uchar *));
static const uchar *skip_escaped_newlines PARAMS ((cpp_reader *, static const uchar *skip_escaped_newlines PARAMS ((cpp_reader *,
const uchar *)); const uchar *));
static const uchar *skip_whitespace PARAMS ((cpp_reader *, const uchar *));
static cpp_hashnode *lex_identifier PARAMS ((cpp_reader *, const uchar *)); static cpp_hashnode *lex_identifier PARAMS ((cpp_reader *, const uchar *));
static const uchar *skip_comment PARAMS ((cpp_reader *, const uchar *)); static const uchar *skip_comment PARAMS ((cpp_reader *, const uchar *));
static void scan_out_logical_line PARAMS ((cpp_reader *pfile)); static void scan_out_logical_line PARAMS ((cpp_reader *pfile));
static void check_output_buffer PARAMS ((cpp_reader *, size_t)); static void check_output_buffer PARAMS ((cpp_reader *, size_t));
static void restore_buff PARAMS ((cpp_reader *)); static void restore_buff PARAMS ((cpp_reader *));
static void push_replacement_text PARAMS ((cpp_reader *, cpp_hashnode *));
/* Ensures we have N bytes' space in the output buffer, and /* Ensures we have N bytes' space in the output buffer, and
reallocates it if not. */ reallocates it if not. */
...@@ -118,6 +121,47 @@ skip_comment (pfile, cur) ...@@ -118,6 +121,47 @@ skip_comment (pfile, cur)
return cur; return cur;
} }
/* Skip any horizontal whitespace and comments beginning at CUR,
returning the following character. */
static const uchar *
skip_whitespace (pfile, cur)
cpp_reader *pfile;
const uchar *cur;
{
const uchar *tmp;
for (;;)
{
while (is_nvspace (*cur) && *cur != 0)
cur++;
if (*cur == '\0' && cur != RLIMIT (pfile->context))
continue;
if (*cur == '\\')
{
tmp = cur;
cur = skip_escaped_newlines (pfile, cur);
if (tmp != cur)
continue;
}
if (*cur == '/')
{
tmp = skip_escaped_newlines (pfile, cur + 1);
if (*tmp == '*')
{
cur = skip_comment (pfile, tmp + 1);
continue;
}
}
break;
}
return cur;
}
/* Lexes and outputs an identifier starting at CUR, which is assumed /* Lexes and outputs an identifier starting at CUR, which is assumed
to point to a valid first character of an identifier. Returns to point to a valid first character of an identifier. Returns
the hashnode, and updates trad_out_cur. */ the hashnode, and updates trad_out_cur. */
...@@ -128,6 +172,7 @@ lex_identifier (pfile, cur) ...@@ -128,6 +172,7 @@ lex_identifier (pfile, cur)
{ {
size_t len; size_t len;
uchar *out = pfile->trad_out_cur; uchar *out = pfile->trad_out_cur;
cpp_hashnode *result;
do do
{ {
...@@ -140,9 +185,27 @@ lex_identifier (pfile, cur) ...@@ -140,9 +185,27 @@ lex_identifier (pfile, cur)
CUR (pfile->context) = cur; CUR (pfile->context) = cur;
len = out - pfile->trad_out_cur; len = out - pfile->trad_out_cur;
result = (cpp_hashnode *) ht_lookup (pfile->hash_table, pfile->trad_out_cur,
len, HT_ALLOC);
pfile->trad_out_cur = out; pfile->trad_out_cur = out;
return (cpp_hashnode *) ht_lookup (pfile->hash_table, pfile->trad_out_cur, return result;
len, HT_ALLOC); }
/* Reads an identifier, returning its hashnode. If the next token is
not an identifier, returns NULL. */
cpp_hashnode *
_cpp_lex_identifier_trad (pfile)
cpp_reader *pfile;
{
const uchar *cur = skip_whitespace (pfile, CUR (pfile->context));
if (!ISIDST (*cur))
{
CUR (pfile->context) = cur;
return NULL;
}
return lex_identifier (pfile, cur);
} }
/* Overlays the true file buffer temporarily with text of length LEN /* Overlays the true file buffer temporarily with text of length LEN
...@@ -226,11 +289,14 @@ static void ...@@ -226,11 +289,14 @@ static void
scan_out_logical_line (pfile) scan_out_logical_line (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
cpp_context *context = pfile->context; cpp_context *context;
const uchar *cur = CUR (context); const uchar *cur;
unsigned int c, quote = 0; unsigned int c, quote = 0;
uchar *out; uchar *out;
new_context:
context = pfile->context;
cur = CUR (context);
check_output_buffer (pfile, RLIMIT (context) - cur); check_output_buffer (pfile, RLIMIT (context) - cur);
out = pfile->trad_out_cur; out = pfile->trad_out_cur;
...@@ -246,6 +312,16 @@ scan_out_logical_line (pfile) ...@@ -246,6 +312,16 @@ scan_out_logical_line (pfile)
case '\0': case '\0':
if (cur - 1 != RLIMIT (context)) if (cur - 1 != RLIMIT (context))
break; break;
/* If this is a macro's expansion, pop it. */
if (context->prev)
{
pfile->trad_out_cur = out - 1;
_cpp_pop_context (pfile);
goto new_context;
}
/* Premature end of file. Fake a new line. */
cur--; cur--;
if (!pfile->buffer->from_stage3) if (!pfile->buffer->from_stage3)
cpp_error (pfile, DL_PEDWARN, "no newline at end of file"); cpp_error (pfile, DL_PEDWARN, "no newline at end of file");
...@@ -254,11 +330,10 @@ scan_out_logical_line (pfile) ...@@ -254,11 +330,10 @@ scan_out_logical_line (pfile)
case '\r': case '\n': case '\r': case '\n':
cur = handle_newline (pfile, cur - 1); cur = handle_newline (pfile, cur - 1);
out[-1] = '\0';
finish_output: finish_output:
out[-1] = '\n';
out[0] = '\0';
CUR (context) = cur; CUR (context) = cur;
pfile->trad_out_cur = out; pfile->trad_out_cur = out - 1;
return; return;
case '"': case '"':
...@@ -309,6 +384,13 @@ scan_out_logical_line (pfile) ...@@ -309,6 +384,13 @@ scan_out_logical_line (pfile)
pfile->trad_out_cur = --out; pfile->trad_out_cur = --out;
node = lex_identifier (pfile, cur - 1); node = lex_identifier (pfile, cur - 1);
if (node->type == NT_MACRO)
{
/* Remove the macro name from the output. */
pfile->trad_out_cur = out;
push_replacement_text (pfile, node);
goto new_context;
}
out = pfile->trad_out_cur; out = pfile->trad_out_cur;
cur = CUR (context); cur = CUR (context);
} }
...@@ -319,3 +401,69 @@ scan_out_logical_line (pfile) ...@@ -319,3 +401,69 @@ scan_out_logical_line (pfile)
} }
} }
} }
/* Push a context holding the replacement text of the macro NODE on
the context stack. Doesn't yet handle special built-ins or
function-like macros. */
static void
push_replacement_text (pfile, node)
cpp_reader *pfile;
cpp_hashnode *node;
{
cpp_macro *macro = node->value.macro;
_cpp_push_text_context (pfile, node,
macro->exp.text,
macro->exp.text + macro->count);
}
/* Analyze and save the replacement text of a macro. */
bool
_cpp_create_trad_definition (pfile, macro)
cpp_reader *pfile;
cpp_macro *macro;
{
const uchar *cur, *limit;
uchar *exp;
size_t len;
/* Skip leading whitespace now. */
CUR (pfile->context) = skip_whitespace (pfile, CUR (pfile->context));
pfile->trad_out_cur = pfile->trad_out_base;
scan_out_logical_line (pfile);
/* Skip trailing white space. */
cur = pfile->trad_out_base;
limit = pfile->trad_out_cur;
while (limit > cur && is_space (limit[-1]))
limit--;
len = (size_t) (limit - cur);
exp = _cpp_unaligned_alloc (pfile, len + 1);
memcpy (exp, cur, len);
exp[len] = '\0';
macro->exp.text = exp;
/* Include NUL. */
macro->count = len;
return true;
}
/* Prepare to be able to scan the current buffer. */
void
_cpp_set_trad_context (pfile)
cpp_reader *pfile;
{
cpp_buffer *buffer = pfile->buffer;
cpp_context *context = pfile->context;
if (pfile->context->prev)
abort ();
pfile->trad_out_cur = pfile->trad_out_base;
CUR (context) = buffer->cur;
RLIMIT (context) = buffer->rlimit;
check_output_buffer (pfile, RLIMIT (context) - CUR (context));
}
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