mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-21 08:03:41 +08:00
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
This commit is contained in:
parent
dbf87f32ae
commit
cbc69f844e
@ -1,3 +1,24 @@
|
||||
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>
|
||||
|
||||
* config.gcc (sh-*-elf*, sh64*-*-elf*): Unify.
|
||||
|
@ -424,8 +424,11 @@ extern int _cpp_begin_message PARAMS ((cpp_reader *, int,
|
||||
|
||||
/* In cppmacro.c */
|
||||
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_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 */
|
||||
extern void _cpp_init_hashtable PARAMS ((cpp_reader *, hash_table *));
|
||||
@ -478,6 +481,8 @@ extern void _cpp_pop_buffer PARAMS ((cpp_reader *));
|
||||
extern bool _cpp_read_logical_line_trad PARAMS ((cpp_reader *));
|
||||
extern void _cpp_overlay_buffer PARAMS ((cpp_reader *pfile, const uchar *,
|
||||
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. */
|
||||
#define DSC(str) (const uchar *)str, sizeof str - 1
|
||||
|
@ -995,12 +995,10 @@ cpp_finish_options (pfile)
|
||||
struct pending_option *p;
|
||||
|
||||
_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);
|
||||
if (!CPP_OPTION (pfile, traditional) /* REMOVEME */)
|
||||
for (p = CPP_OPTION (pfile, pending)->directive_head; p; p = p->next)
|
||||
(*p->handler) (pfile, p->arg);
|
||||
for (p = CPP_OPTION (pfile, pending)->directive_head; p; p = p->next)
|
||||
(*p->handler) (pfile, p->arg);
|
||||
|
||||
/* Scan -imacros files after -D, -U, but before -include.
|
||||
pfile->next_include_file is NULL, so _cpp_pop_buffer does not
|
||||
|
66
gcc/cpplib.c
66
gcc/cpplib.c
@ -202,7 +202,8 @@ static const directive linemarker_dir =
|
||||
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. */
|
||||
static void
|
||||
@ -447,7 +448,6 @@ lex_macro_node (pfile)
|
||||
cpp_reader *pfile;
|
||||
{
|
||||
cpp_hashnode *node;
|
||||
const cpp_token *token = _cpp_lex_token (pfile);
|
||||
|
||||
/* The token immediately after #define must be an identifier. That
|
||||
identifier may not be "defined", per C99 6.10.8p4.
|
||||
@ -459,39 +459,43 @@ lex_macro_node (pfile)
|
||||
Note that if we're copying comments into macro expansions, we
|
||||
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)
|
||||
token = _cpp_lex_token (pfile);
|
||||
}
|
||||
const cpp_token *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)
|
||||
cpp_error (pfile, DL_ERROR, "no macro name given in #%s directive",
|
||||
pfile->directive->name);
|
||||
else if (token->flags & NAMED_OP)
|
||||
cpp_error (pfile, DL_ERROR,
|
||||
"\"%s\" cannot be used as a macro name as it is an operator in C++",
|
||||
NODE_NAME (token->val.node));
|
||||
{
|
||||
cpp_error (pfile, DL_ERROR, "no macro name given in #%s directive",
|
||||
pfile->directive->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (token->type == CPP_NAME || (token->flags & NAMED_OP))
|
||||
node = token->val.node;
|
||||
else
|
||||
cpp_error (pfile, DL_ERROR, "macro names must be identifiers");
|
||||
|
||||
return 0;
|
||||
node = NULL;
|
||||
}
|
||||
|
||||
node = token->val.node;
|
||||
if (node->flags & NODE_POISONED)
|
||||
return 0;
|
||||
if (!node)
|
||||
cpp_error (pfile, DL_ERROR, "macro names must be identifiers");
|
||||
else if (node->flags & NODE_OPERATOR)
|
||||
cpp_error (pfile, DL_ERROR,
|
||||
"\"%s\" cannot be used as a macro name as it is an operator in C++",
|
||||
NODE_NAME (node));
|
||||
else if (node == pfile->spec_nodes.n_defined)
|
||||
cpp_error (pfile, DL_ERROR, "\"defined\" cannot be used as a macro name");
|
||||
else if (! (node->flags & NODE_POISONED))
|
||||
return node;
|
||||
|
||||
if (node == pfile->spec_nodes.n_defined)
|
||||
{
|
||||
cpp_error (pfile, DL_ERROR, "\"%s\" cannot be used as a macro name",
|
||||
NODE_NAME (node));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return node;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
|
||||
pfile->buffer = new;
|
||||
|
||||
if (CPP_OPTION (pfile, traditional))
|
||||
_cpp_set_trad_context (pfile);
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
@ -1934,6 +1941,9 @@ _cpp_pop_buffer (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. */
|
||||
|
152
gcc/cppmacro.c
152
gcc/cppmacro.c
@ -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 *,
|
||||
macro_arg *));
|
||||
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. */
|
||||
|
||||
static cpp_token *alloc_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 *,
|
||||
const cpp_macro *));
|
||||
static bool warn_of_redefinition PARAMS ((cpp_reader *, const cpp_hashnode *,
|
||||
const cpp_macro *));
|
||||
static int save_parameter PARAMS ((cpp_reader *, cpp_macro *, cpp_hashnode *));
|
||||
static int parse_params PARAMS ((cpp_reader *, cpp_macro *));
|
||||
static void check_trad_stringification PARAMS ((cpp_reader *,
|
||||
@ -917,6 +918,22 @@ push_token_context (pfile, macro, 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
|
||||
function-like macro. This works by pushing a context with the
|
||||
argument's tokens, and then expanding that into a temporary buffer
|
||||
@ -1127,8 +1144,9 @@ _cpp_backup_tokens (pfile, count)
|
||||
/* #define directive parsing and handling. */
|
||||
|
||||
/* Returns non-zero if a macro redefinition warning is required. */
|
||||
static int
|
||||
warn_of_redefinition (node, macro2)
|
||||
static bool
|
||||
warn_of_redefinition (pfile, node, macro2)
|
||||
cpp_reader *pfile;
|
||||
const cpp_hashnode *node;
|
||||
const cpp_macro *macro2;
|
||||
{
|
||||
@ -1137,7 +1155,7 @@ warn_of_redefinition (node, macro2)
|
||||
|
||||
/* Some redefinitions need to be warned about regardless. */
|
||||
if (node->flags & NODE_WARN)
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
/* Redefinition of a macro is allowed if and only if the old and new
|
||||
definitions are the same. (6.10.3 paragraph 2). */
|
||||
@ -1148,19 +1166,22 @@ warn_of_redefinition (node, macro2)
|
||||
|| macro1->paramc != macro2->paramc
|
||||
|| macro1->fun_like != macro2->fun_like
|
||||
|| macro1->variadic != macro2->variadic)
|
||||
return 1;
|
||||
|
||||
/* Check each token. */
|
||||
for (i = 0; i < macro1->count; i++)
|
||||
if (! _cpp_equiv_tokens (¯o1->exp.tokens[i], ¯o2->exp.tokens[i]))
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
/* Check parameter spellings. */
|
||||
for (i = 0; i < macro1->paramc; 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 (¯o1->exp.tokens[i], ¯o2->exp.tokens[i]))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Free the definition of hashnode H. */
|
||||
@ -1316,24 +1337,13 @@ lex_expansion_token (pfile, macro)
|
||||
return token;
|
||||
}
|
||||
|
||||
/* Parse a macro and save its expansion. Returns non-zero on success. */
|
||||
int
|
||||
_cpp_create_definition (pfile, node)
|
||||
static bool
|
||||
create_iso_definition (pfile, macro)
|
||||
cpp_reader *pfile;
|
||||
cpp_hashnode *node;
|
||||
cpp_macro *macro;
|
||||
{
|
||||
cpp_macro *macro;
|
||||
cpp_token *token, *saved_cur_token;
|
||||
cpp_token *token;
|
||||
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
|
||||
function-like macro). */
|
||||
@ -1341,10 +1351,10 @@ _cpp_create_definition (pfile, node)
|
||||
|
||||
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);
|
||||
if (!ok)
|
||||
goto cleanup2;
|
||||
return false;
|
||||
|
||||
/* Success. Commit the parameter array. */
|
||||
BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->params[macro->paramc];
|
||||
@ -1354,8 +1364,6 @@ _cpp_create_definition (pfile, node)
|
||||
cpp_error (pfile, DL_PEDWARN,
|
||||
"ISO C requires whitespace after the macro name");
|
||||
|
||||
saved_cur_token = pfile->cur_token;
|
||||
|
||||
if (macro->fun_like)
|
||||
token = lex_expansion_token (pfile, macro);
|
||||
else
|
||||
@ -1381,10 +1389,9 @@ _cpp_create_definition (pfile, node)
|
||||
/* Let assembler get away with murder. */
|
||||
else if (CPP_OPTION (pfile, lang) != CLK_ASM)
|
||||
{
|
||||
ok = 0;
|
||||
cpp_error (pfile, DL_ERROR,
|
||||
"'#' is not followed by a macro parameter");
|
||||
goto cleanup1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1401,10 +1408,9 @@ _cpp_create_definition (pfile, node)
|
||||
|
||||
if (macro->count == 0 || token->type == CPP_EOF)
|
||||
{
|
||||
ok = 0;
|
||||
cpp_error (pfile, DL_ERROR,
|
||||
"'##' cannot appear at either end of a macro expansion");
|
||||
goto cleanup1;
|
||||
return false;
|
||||
}
|
||||
|
||||
token[-1].flags |= PASTE_LEFT;
|
||||
@ -1425,25 +1431,68 @@ _cpp_create_definition (pfile, node)
|
||||
/* Commit the memory. */
|
||||
BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->exp.tokens[macro->count];
|
||||
|
||||
/* Implement the macro-defined-to-itself optimisation. */
|
||||
if (macro->count == 1 && !macro->fun_like
|
||||
&& macro->exp.tokens[0].type == CPP_NAME
|
||||
&& macro->exp.tokens[0].val.node == node)
|
||||
node->flags |= NODE_DISABLED;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Parse a macro and save its expansion. Returns non-zero on success. */
|
||||
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. */
|
||||
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 (warn_of_redefinition (node, macro))
|
||||
if (warn_of_redefinition (pfile, node, macro))
|
||||
{
|
||||
cpp_error_with_line (pfile, DL_PEDWARN, pfile->directive_line, 0,
|
||||
"\"%s\" redefined", NODE_NAME (node));
|
||||
|
||||
if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
|
||||
cpp_error_with_line (pfile, DL_PEDWARN, node->value.macro->line, 0,
|
||||
"this is the location of the previous definition");
|
||||
cpp_error_with_line (pfile, DL_PEDWARN,
|
||||
node->value.macro->line, 0,
|
||||
"this is the location of the previous definition");
|
||||
}
|
||||
_cpp_free_definition (node);
|
||||
}
|
||||
@ -1454,21 +1503,6 @@ _cpp_create_definition (pfile, node)
|
||||
if (! ustrncmp (NODE_NAME (node), DSC ("__STDC_")))
|
||||
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;
|
||||
}
|
||||
|
||||
|
164
gcc/cpptrad.c
164
gcc/cpptrad.c
@ -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.
|
||||
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 *skip_escaped_newlines PARAMS ((cpp_reader *,
|
||||
const uchar *));
|
||||
static const uchar *skip_whitespace 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 void scan_out_logical_line PARAMS ((cpp_reader *pfile));
|
||||
static void check_output_buffer PARAMS ((cpp_reader *, size_t));
|
||||
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
|
||||
reallocates it if not. */
|
||||
@ -118,6 +121,47 @@ skip_comment (pfile, 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
|
||||
to point to a valid first character of an identifier. Returns
|
||||
the hashnode, and updates trad_out_cur. */
|
||||
@ -128,6 +172,7 @@ lex_identifier (pfile, cur)
|
||||
{
|
||||
size_t len;
|
||||
uchar *out = pfile->trad_out_cur;
|
||||
cpp_hashnode *result;
|
||||
|
||||
do
|
||||
{
|
||||
@ -140,9 +185,27 @@ lex_identifier (pfile, cur)
|
||||
|
||||
CUR (pfile->context) = 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;
|
||||
return (cpp_hashnode *) ht_lookup (pfile->hash_table, pfile->trad_out_cur,
|
||||
len, HT_ALLOC);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* 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
|
||||
@ -226,11 +289,14 @@ static void
|
||||
scan_out_logical_line (pfile)
|
||||
cpp_reader *pfile;
|
||||
{
|
||||
cpp_context *context = pfile->context;
|
||||
const uchar *cur = CUR (context);
|
||||
cpp_context *context;
|
||||
const uchar *cur;
|
||||
unsigned int c, quote = 0;
|
||||
uchar *out;
|
||||
|
||||
new_context:
|
||||
context = pfile->context;
|
||||
cur = CUR (context);
|
||||
check_output_buffer (pfile, RLIMIT (context) - cur);
|
||||
out = pfile->trad_out_cur;
|
||||
|
||||
@ -246,6 +312,16 @@ scan_out_logical_line (pfile)
|
||||
case '\0':
|
||||
if (cur - 1 != RLIMIT (context))
|
||||
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--;
|
||||
if (!pfile->buffer->from_stage3)
|
||||
cpp_error (pfile, DL_PEDWARN, "no newline at end of file");
|
||||
@ -254,11 +330,10 @@ scan_out_logical_line (pfile)
|
||||
|
||||
case '\r': case '\n':
|
||||
cur = handle_newline (pfile, cur - 1);
|
||||
out[-1] = '\0';
|
||||
finish_output:
|
||||
out[-1] = '\n';
|
||||
out[0] = '\0';
|
||||
CUR (context) = cur;
|
||||
pfile->trad_out_cur = out;
|
||||
pfile->trad_out_cur = out - 1;
|
||||
return;
|
||||
|
||||
case '"':
|
||||
@ -309,6 +384,13 @@ scan_out_logical_line (pfile)
|
||||
|
||||
pfile->trad_out_cur = --out;
|
||||
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;
|
||||
cur = CUR (context);
|
||||
}
|
||||
@ -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));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user