c-lex.c (cb_def_pragma): Update.
* c-lex.c (cb_def_pragma): Update. (c_lex): Update, and skip padding. * cppexp.c (lex, parse_defined): Update, remove unused variable. * cpphash.h (struct toklist): Delete. (union utoken): New. (struct cpp_context): Update. (struct cpp_reader): New members eof, avoid_paste. (_cpp_temp_token): New. * cppinit.c (cpp_create_reader): Update. * cpplex.c (_cpp_temp_token): New. (_cpp_lex_direct): Add PREV_WHITE when parsing args. (cpp_output_token): Don't print leading whitespace. (cpp_output_line): Update. * cpplib.c (glue_header_name, parse_include, get__Pragma_string, do_include_common, do_line, do_ident, do_pragma, do_pragma_dependency, _cpp_do__Pragma, parse_answer, parse_assertion): Update. (get_token_no_padding): New. * cpplib.h (CPP_PADDING): New. (AVOID_LPASTE): Delete. (struct cpp_token): New union member source. (cpp_get_token): Update. * cppmacro.c (macro_arg): Convert to use pointers to const tokens. (builtin_macro, paste_all_tokens, paste_tokens, funlike_invocation_p, replace_args, quote_string, stringify_arg, parse_arg, next_context, enter_macro_context, expand_arg, _cpp_pop_context, cpp_scan_nooutput, _cpp_backup_tokens, _cpp_create_definition): Update. (push_arg_context): Delete. (padding_token, push_token_context, push_ptoken_context): New. (make_string_token, make_number_token): Update, rename. (cpp_get_token): Update to handle tokens as pointers to const, and insert padding appropriately. * cppmain.c (struct printer): New member prev. (check_multiline_token): Constify. (do_preprocessing, cb_line_change): Update. (scan_translation_unit): Update to handle spacing. * scan-decls.c (get_a_token): New. (skip_to_closing_brace, scan_decls): Update. * fix-header.c (read_scan_file): Update. * doc/cpp.texi: Update. * gcc.dg/cpp/macro10.c: New test. * gcc.dg/cpp/strify3.c: New test. * gcc.dg/cpp/spacing1.c: Add tests. * gcc.dg/cpp/19990703-1.c: Remove bogus test. * gcc.dg/cpp/20000625-2.c: Fudge to pass. From-SVN: r45793
This commit is contained in:
parent
ad43d46f3a
commit
4ed5bcfb1e
19 changed files with 799 additions and 571 deletions
|
@ -1,3 +1,47 @@
|
|||
2001-09-24 Neil Booth <neil@daikokuya.demon.co.uk>
|
||||
|
||||
* c-lex.c (cb_def_pragma): Update.
|
||||
(c_lex): Update, and skip padding.
|
||||
* cppexp.c (lex, parse_defined): Update, remove unused variable.
|
||||
* cpphash.h (struct toklist): Delete.
|
||||
(union utoken): New.
|
||||
(struct cpp_context): Update.
|
||||
(struct cpp_reader): New members eof, avoid_paste.
|
||||
(_cpp_temp_token): New.
|
||||
* cppinit.c (cpp_create_reader): Update.
|
||||
* cpplex.c (_cpp_temp_token): New.
|
||||
(_cpp_lex_direct): Add PREV_WHITE when parsing args.
|
||||
(cpp_output_token): Don't print leading whitespace.
|
||||
(cpp_output_line): Update.
|
||||
* cpplib.c (glue_header_name, parse_include, get__Pragma_string,
|
||||
do_include_common, do_line, do_ident, do_pragma,
|
||||
do_pragma_dependency, _cpp_do__Pragma, parse_answer,
|
||||
parse_assertion): Update.
|
||||
(get_token_no_padding): New.
|
||||
* cpplib.h (CPP_PADDING): New.
|
||||
(AVOID_LPASTE): Delete.
|
||||
(struct cpp_token): New union member source.
|
||||
(cpp_get_token): Update.
|
||||
* cppmacro.c (macro_arg): Convert to use pointers to const tokens.
|
||||
(builtin_macro, paste_all_tokens, paste_tokens, funlike_invocation_p,
|
||||
replace_args, quote_string, stringify_arg, parse_arg, next_context,
|
||||
enter_macro_context, expand_arg, _cpp_pop_context, cpp_scan_nooutput,
|
||||
_cpp_backup_tokens, _cpp_create_definition): Update.
|
||||
(push_arg_context): Delete.
|
||||
(padding_token, push_token_context, push_ptoken_context): New.
|
||||
(make_string_token, make_number_token): Update, rename.
|
||||
(cpp_get_token): Update to handle tokens as pointers to const,
|
||||
and insert padding appropriately.
|
||||
* cppmain.c (struct printer): New member prev.
|
||||
(check_multiline_token): Constify.
|
||||
(do_preprocessing, cb_line_change): Update.
|
||||
(scan_translation_unit): Update to handle spacing.
|
||||
* scan-decls.c (get_a_token): New.
|
||||
(skip_to_closing_brace, scan_decls): Update.
|
||||
* fix-header.c (read_scan_file): Update.
|
||||
|
||||
* doc/cpp.texi: Update.
|
||||
|
||||
2001-09-24 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
|
||||
|
||||
* c-aux-info.c (affix_data_type): Use ATTRIBUTE_MALLOC. Avoid
|
||||
|
|
42
gcc/c-lex.c
42
gcc/c-lex.c
|
@ -335,13 +335,13 @@ cb_def_pragma (pfile, line)
|
|||
if (warn_unknown_pragmas > in_system_header)
|
||||
{
|
||||
const unsigned char *space, *name = 0;
|
||||
cpp_token s;
|
||||
const cpp_token *s;
|
||||
|
||||
cpp_get_token (pfile, &s);
|
||||
space = cpp_token_as_text (pfile, &s);
|
||||
cpp_get_token (pfile, &s);
|
||||
if (s.type == CPP_NAME)
|
||||
name = cpp_token_as_text (pfile, &s);
|
||||
s = cpp_get_token (pfile);
|
||||
space = cpp_token_as_text (pfile, s);
|
||||
s = cpp_get_token (pfile);
|
||||
if (s->type == CPP_NAME)
|
||||
name = cpp_token_as_text (pfile, s);
|
||||
|
||||
lineno = SOURCE_LINE (map, line);
|
||||
if (name)
|
||||
|
@ -767,12 +767,13 @@ int
|
|||
c_lex (value)
|
||||
tree *value;
|
||||
{
|
||||
cpp_token tok;
|
||||
enum cpp_ttype type;
|
||||
const cpp_token *tok;
|
||||
|
||||
retry:
|
||||
timevar_push (TV_CPP);
|
||||
cpp_get_token (parse_in, &tok);
|
||||
do
|
||||
tok = cpp_get_token (parse_in);
|
||||
while (tok->type == CPP_PADDING);
|
||||
timevar_pop (TV_CPP);
|
||||
|
||||
/* The C++ front end does horrible things with the current line
|
||||
|
@ -781,37 +782,36 @@ c_lex (value)
|
|||
lineno = src_lineno;
|
||||
|
||||
*value = NULL_TREE;
|
||||
type = tok.type;
|
||||
switch (type)
|
||||
switch (tok->type)
|
||||
{
|
||||
case CPP_OPEN_BRACE: indent_level++; break;
|
||||
case CPP_CLOSE_BRACE: indent_level--; break;
|
||||
|
||||
/* Issue this error here, where we can get at tok.val.c. */
|
||||
/* Issue this error here, where we can get at tok->val.c. */
|
||||
case CPP_OTHER:
|
||||
if (ISGRAPH (tok.val.c))
|
||||
error ("stray '%c' in program", tok.val.c);
|
||||
if (ISGRAPH (tok->val.c))
|
||||
error ("stray '%c' in program", tok->val.c);
|
||||
else
|
||||
error ("stray '\\%o' in program", tok.val.c);
|
||||
error ("stray '\\%o' in program", tok->val.c);
|
||||
goto retry;
|
||||
|
||||
case CPP_NAME:
|
||||
*value = HT_IDENT_TO_GCC_IDENT (HT_NODE (tok.val.node));
|
||||
*value = HT_IDENT_TO_GCC_IDENT (HT_NODE (tok->val.node));
|
||||
break;
|
||||
|
||||
case CPP_NUMBER:
|
||||
*value = lex_number ((const char *)tok.val.str.text, tok.val.str.len);
|
||||
*value = lex_number ((const char *)tok->val.str.text, tok->val.str.len);
|
||||
break;
|
||||
|
||||
case CPP_CHAR:
|
||||
case CPP_WCHAR:
|
||||
*value = lex_charconst (&tok);
|
||||
*value = lex_charconst (tok);
|
||||
break;
|
||||
|
||||
case CPP_STRING:
|
||||
case CPP_WSTRING:
|
||||
*value = lex_string ((const char *)tok.val.str.text,
|
||||
tok.val.str.len, tok.type == CPP_WSTRING);
|
||||
*value = lex_string ((const char *)tok->val.str.text,
|
||||
tok->val.str.len, tok->type == CPP_WSTRING);
|
||||
break;
|
||||
|
||||
/* These tokens should not be visible outside cpplib. */
|
||||
|
@ -823,7 +823,7 @@ c_lex (value)
|
|||
default: break;
|
||||
}
|
||||
|
||||
return type;
|
||||
return tok->type;
|
||||
}
|
||||
|
||||
#define ERROR(msgid) do { error(msgid); goto syntax_error; } while(0)
|
||||
|
|
39
gcc/cppexp.c
39
gcc/cppexp.c
|
@ -36,7 +36,7 @@ static HOST_WIDEST_INT right_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT,
|
|||
unsigned HOST_WIDEST_INT));
|
||||
static struct op parse_number PARAMS ((cpp_reader *, const cpp_token *));
|
||||
static struct op parse_defined PARAMS ((cpp_reader *));
|
||||
static struct op lex PARAMS ((cpp_reader *, int, cpp_token *));
|
||||
static struct op lex PARAMS ((cpp_reader *, int));
|
||||
static const unsigned char *op_as_text PARAMS ((cpp_reader *, enum cpp_ttype));
|
||||
|
||||
struct op
|
||||
|
@ -217,44 +217,40 @@ parse_defined (pfile)
|
|||
{
|
||||
int paren = 0;
|
||||
cpp_hashnode *node = 0;
|
||||
cpp_token token;
|
||||
const cpp_token *token;
|
||||
struct op op;
|
||||
|
||||
/* Don't expand macros. */
|
||||
pfile->state.prevent_expansion++;
|
||||
|
||||
cpp_get_token (pfile, &token);
|
||||
if (token.type == CPP_OPEN_PAREN)
|
||||
token = cpp_get_token (pfile);
|
||||
if (token->type == CPP_OPEN_PAREN)
|
||||
{
|
||||
paren = 1;
|
||||
cpp_get_token (pfile, &token);
|
||||
token = cpp_get_token (pfile);
|
||||
}
|
||||
|
||||
if (token.type == CPP_NAME)
|
||||
if (token->type == CPP_NAME)
|
||||
{
|
||||
node = token.val.node;
|
||||
if (paren)
|
||||
node = token->val.node;
|
||||
if (paren && cpp_get_token (pfile)->type != CPP_CLOSE_PAREN)
|
||||
{
|
||||
cpp_get_token (pfile, &token);
|
||||
if (token.type != CPP_CLOSE_PAREN)
|
||||
{
|
||||
cpp_error (pfile, "missing ')' after \"defined\"");
|
||||
node = 0;
|
||||
}
|
||||
cpp_error (pfile, "missing ')' after \"defined\"");
|
||||
node = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cpp_error (pfile, "operator \"defined\" requires an identifier");
|
||||
if (token.flags & NAMED_OP)
|
||||
if (token->flags & NAMED_OP)
|
||||
{
|
||||
cpp_token op;
|
||||
|
||||
op.flags = 0;
|
||||
op.type = token.type;
|
||||
op.type = token->type;
|
||||
cpp_error (pfile,
|
||||
"(\"%s\" is an alternative token for \"%s\" in C++)",
|
||||
cpp_token_as_text (pfile, &token),
|
||||
cpp_token_as_text (pfile, token),
|
||||
cpp_token_as_text (pfile, &op));
|
||||
}
|
||||
}
|
||||
|
@ -282,14 +278,12 @@ parse_defined (pfile)
|
|||
CPP_EOF, or the type of an operator token. */
|
||||
|
||||
static struct op
|
||||
lex (pfile, skip_evaluation, token)
|
||||
lex (pfile, skip_evaluation)
|
||||
cpp_reader *pfile;
|
||||
int skip_evaluation;
|
||||
cpp_token *token;
|
||||
{
|
||||
struct op op;
|
||||
|
||||
cpp_get_token (pfile, token);
|
||||
const cpp_token *token = cpp_get_token (pfile);
|
||||
|
||||
switch (token->type)
|
||||
{
|
||||
|
@ -578,7 +572,6 @@ _cpp_parse_expr (pfile)
|
|||
struct op init_stack[INIT_STACK_SIZE];
|
||||
struct op *stack = init_stack;
|
||||
struct op *limit = stack + INIT_STACK_SIZE;
|
||||
cpp_token token;
|
||||
register struct op *top = stack + 1;
|
||||
int skip_evaluation = 0;
|
||||
int result;
|
||||
|
@ -603,7 +596,7 @@ _cpp_parse_expr (pfile)
|
|||
struct op op;
|
||||
|
||||
/* Read a token */
|
||||
op = lex (pfile, skip_evaluation, &token);
|
||||
op = lex (pfile, skip_evaluation);
|
||||
lex_count++;
|
||||
|
||||
/* If the token is an operand, push its value and get next
|
||||
|
|
|
@ -95,11 +95,10 @@ struct search_path
|
|||
/* #include types. */
|
||||
enum include_type {IT_INCLUDE, IT_INCLUDE_NEXT, IT_IMPORT, IT_CMDLINE};
|
||||
|
||||
typedef struct toklist toklist;
|
||||
struct toklist
|
||||
union utoken
|
||||
{
|
||||
cpp_token *first;
|
||||
cpp_token *limit;
|
||||
const cpp_token *token;
|
||||
const cpp_token **ptoken;
|
||||
};
|
||||
|
||||
typedef struct tokenrun tokenrun;
|
||||
|
@ -117,10 +116,14 @@ struct cpp_context
|
|||
|
||||
/* Contexts other than the base context are contiguous tokens.
|
||||
e.g. macro expansions, expanded argument tokens. */
|
||||
struct toklist list;
|
||||
union utoken first;
|
||||
union utoken last;
|
||||
|
||||
/* For a macro context, these are the macro and its arguments. */
|
||||
cpp_macro *macro;
|
||||
|
||||
/* True if utoken element is token, else ptoken. */
|
||||
bool direct_p;
|
||||
};
|
||||
|
||||
struct lexer_state
|
||||
|
@ -294,6 +297,10 @@ struct cpp_reader
|
|||
cpp_token date;
|
||||
cpp_token time;
|
||||
|
||||
/* EOF token, and a token forcing paste avoidance. */
|
||||
cpp_token avoid_paste;
|
||||
cpp_token eof;
|
||||
|
||||
/* Opaque handle to the dependencies of mkdeps.c. Used by -M etc. */
|
||||
struct deps *deps;
|
||||
|
||||
|
@ -398,6 +405,7 @@ extern void _cpp_pop_file_buffer PARAMS ((cpp_reader *,
|
|||
extern int _cpp_parse_expr PARAMS ((cpp_reader *));
|
||||
|
||||
/* In cpplex.c */
|
||||
extern cpp_token *_cpp_temp_token PARAMS ((cpp_reader *));
|
||||
extern const cpp_token *_cpp_lex_token PARAMS ((cpp_reader *));
|
||||
extern cpp_token *_cpp_lex_direct PARAMS ((cpp_reader *));
|
||||
extern int _cpp_equiv_tokens PARAMS ((const cpp_token *,
|
||||
|
|
|
@ -510,8 +510,12 @@ cpp_create_reader (table, lang)
|
|||
/* Initialize lexer state. */
|
||||
pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments);
|
||||
|
||||
/* Indicate date and time not yet calculated. */
|
||||
/* Set up static tokens. */
|
||||
pfile->date.type = CPP_EOF;
|
||||
pfile->avoid_paste.type = CPP_PADDING;
|
||||
pfile->avoid_paste.val.source = NULL;
|
||||
pfile->eof.type = CPP_EOF;
|
||||
pfile->eof.flags = 0;
|
||||
|
||||
/* Create a token buffer for the lexer. */
|
||||
_cpp_init_tokenrun (&pfile->base_run, 250);
|
||||
|
|
50
gcc/cpplex.c
50
gcc/cpplex.c
|
@ -931,6 +931,29 @@ next_tokenrun (run)
|
|||
return run->next;
|
||||
}
|
||||
|
||||
/* Allocate a single token that is invalidated at the same time as the
|
||||
rest of the tokens on the line. Has its line and col set to the
|
||||
same as the last lexed token, so that diagnostics appear in the
|
||||
right place. */
|
||||
cpp_token *
|
||||
_cpp_temp_token (pfile)
|
||||
cpp_reader *pfile;
|
||||
{
|
||||
cpp_token *old, *result;
|
||||
|
||||
old = pfile->cur_token - 1;
|
||||
if (pfile->cur_token == pfile->cur_run->limit)
|
||||
{
|
||||
pfile->cur_run = next_tokenrun (pfile->cur_run);
|
||||
pfile->cur_token = pfile->cur_run->base;
|
||||
}
|
||||
|
||||
result = pfile->cur_token++;
|
||||
result->line = old->line;
|
||||
result->col = old->col;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Lex a token into RESULT (external interface). Takes care of issues
|
||||
like directive handling, token lookahead, multiple include
|
||||
opimisation and skipping. */
|
||||
|
@ -1057,6 +1080,8 @@ _cpp_lex_direct (pfile)
|
|||
buffer->saved_flags = BOL;
|
||||
if (! pfile->state.in_directive)
|
||||
{
|
||||
if (pfile->state.parsing_args == 2)
|
||||
buffer->saved_flags |= PREV_WHITE;
|
||||
if (!pfile->keep_tokens)
|
||||
{
|
||||
pfile->cur_run = &pfile->base_run;
|
||||
|
@ -1476,17 +1501,14 @@ cpp_type2name (type)
|
|||
return (const char *) token_spellings[type].name;
|
||||
}
|
||||
|
||||
/* Writes the spelling of token to FP. Separate from cpp_spell_token
|
||||
for efficiency - to avoid double-buffering. Also, outputs a space
|
||||
if PREV_WHITE is flagged. */
|
||||
/* Writes the spelling of token to FP, without any preceding space.
|
||||
Separated from cpp_spell_token for efficiency - to avoid stdio
|
||||
double-buffering. */
|
||||
void
|
||||
cpp_output_token (token, fp)
|
||||
const cpp_token *token;
|
||||
FILE *fp;
|
||||
{
|
||||
if (token->flags & PREV_WHITE)
|
||||
putc (' ', fp);
|
||||
|
||||
switch (TOKEN_SPELL (token))
|
||||
{
|
||||
case SPELL_OPERATOR:
|
||||
|
@ -1729,20 +1751,22 @@ cpp_avoid_paste (pfile, token1, token2)
|
|||
}
|
||||
|
||||
/* Output all the remaining tokens on the current line, and a newline
|
||||
character, to FP. Leading whitespace is removed. */
|
||||
character, to FP. Leading whitespace is removed. If there are
|
||||
macros, special token padding is not performed. */
|
||||
void
|
||||
cpp_output_line (pfile, fp)
|
||||
cpp_reader *pfile;
|
||||
FILE *fp;
|
||||
{
|
||||
cpp_token token;
|
||||
const cpp_token *token;
|
||||
|
||||
cpp_get_token (pfile, &token);
|
||||
token.flags &= ~PREV_WHITE;
|
||||
while (token.type != CPP_EOF)
|
||||
token = cpp_get_token (pfile);
|
||||
while (token->type != CPP_EOF)
|
||||
{
|
||||
cpp_output_token (&token, fp);
|
||||
cpp_get_token (pfile, &token);
|
||||
cpp_output_token (token, fp);
|
||||
token = cpp_get_token (pfile);
|
||||
if (token->flags & PREV_WHITE)
|
||||
putc (' ', fp);
|
||||
}
|
||||
|
||||
putc ('\n', fp);
|
||||
|
|
187
gcc/cpplib.c
187
gcc/cpplib.c
|
@ -86,8 +86,8 @@ static void directive_diagnostics
|
|||
PARAMS ((cpp_reader *, const directive *, int));
|
||||
static void run_directive PARAMS ((cpp_reader *, int,
|
||||
const char *, size_t));
|
||||
static int glue_header_name PARAMS ((cpp_reader *, cpp_token *));
|
||||
static int parse_include PARAMS ((cpp_reader *, cpp_token *));
|
||||
static const cpp_token *glue_header_name PARAMS ((cpp_reader *));
|
||||
static const cpp_token *parse_include PARAMS ((cpp_reader *));
|
||||
static void push_conditional PARAMS ((cpp_reader *, int, int,
|
||||
const cpp_hashnode *));
|
||||
static unsigned int read_flag PARAMS ((cpp_reader *, unsigned int));
|
||||
|
@ -100,7 +100,8 @@ static void do_pragma_once PARAMS ((cpp_reader *));
|
|||
static void do_pragma_poison PARAMS ((cpp_reader *));
|
||||
static void do_pragma_system_header PARAMS ((cpp_reader *));
|
||||
static void do_pragma_dependency PARAMS ((cpp_reader *));
|
||||
static int get__Pragma_string PARAMS ((cpp_reader *, cpp_token *));
|
||||
static const cpp_token *get_token_no_padding PARAMS ((cpp_reader *));
|
||||
static const cpp_token *get__Pragma_string PARAMS ((cpp_reader *));
|
||||
static unsigned char *destringize PARAMS ((const cpp_string *,
|
||||
unsigned int *));
|
||||
static int parse_answer PARAMS ((cpp_reader *, struct answer **, int));
|
||||
|
@ -485,13 +486,13 @@ do_undef (pfile)
|
|||
|
||||
/* Helper routine used by parse_include. Reinterpret the current line
|
||||
as an h-char-sequence (< ... >); we are looking at the first token
|
||||
after the <. Returns zero on success. */
|
||||
static int
|
||||
glue_header_name (pfile, header)
|
||||
after the <. Returns the header as a token, or NULL on failure. */
|
||||
static const cpp_token *
|
||||
glue_header_name (pfile)
|
||||
cpp_reader *pfile;
|
||||
cpp_token *header;
|
||||
{
|
||||
cpp_token token;
|
||||
cpp_token *header = NULL;
|
||||
const cpp_token *token;
|
||||
unsigned char *buffer, *token_mem;
|
||||
size_t len, total_len = 0, capacity = 1024;
|
||||
|
||||
|
@ -501,25 +502,25 @@ glue_header_name (pfile, header)
|
|||
buffer = (unsigned char *) xmalloc (capacity);
|
||||
for (;;)
|
||||
{
|
||||
cpp_get_token (pfile, &token);
|
||||
token = cpp_get_token (pfile);
|
||||
|
||||
if (token.type == CPP_GREATER || token.type == CPP_EOF)
|
||||
if (token->type == CPP_GREATER || token->type == CPP_EOF)
|
||||
break;
|
||||
|
||||
len = cpp_token_len (&token);
|
||||
len = cpp_token_len (token);
|
||||
if (total_len + len > capacity)
|
||||
{
|
||||
capacity = (capacity + len) * 2;
|
||||
buffer = (unsigned char *) xrealloc (buffer, capacity);
|
||||
}
|
||||
|
||||
if (token.flags & PREV_WHITE)
|
||||
if (token->flags & PREV_WHITE)
|
||||
buffer[total_len++] = ' ';
|
||||
|
||||
total_len = cpp_spell_token (pfile, &token, &buffer[total_len]) - buffer;
|
||||
total_len = cpp_spell_token (pfile, token, &buffer[total_len]) - buffer;
|
||||
}
|
||||
|
||||
if (token.type == CPP_EOF)
|
||||
if (token->type == CPP_EOF)
|
||||
cpp_error (pfile, "missing terminating > character");
|
||||
else
|
||||
{
|
||||
|
@ -527,6 +528,7 @@ glue_header_name (pfile, header)
|
|||
memcpy (token_mem, buffer, total_len);
|
||||
token_mem[total_len] = '\0';
|
||||
|
||||
header = _cpp_temp_token (pfile);
|
||||
header->type = CPP_HEADER_NAME;
|
||||
header->flags &= ~PREV_WHITE;
|
||||
header->val.str.len = total_len;
|
||||
|
@ -534,17 +536,17 @@ glue_header_name (pfile, header)
|
|||
}
|
||||
|
||||
free ((PTR) buffer);
|
||||
return token.type == CPP_EOF;
|
||||
return header;
|
||||
}
|
||||
|
||||
/* Parse the header name of #include, #include_next, #import and
|
||||
#pragma dependency. Returns zero on success. */
|
||||
static int
|
||||
parse_include (pfile, header)
|
||||
/* Returns the header string of #include, #include_next, #import and
|
||||
#pragma dependency. Returns NULL on error. */
|
||||
static const cpp_token *
|
||||
parse_include (pfile)
|
||||
cpp_reader *pfile;
|
||||
cpp_token *header;
|
||||
{
|
||||
const unsigned char *dir;
|
||||
const cpp_token *header;
|
||||
|
||||
if (pfile->directive == &dtable[T_PRAGMA])
|
||||
dir = U"pragma dependency";
|
||||
|
@ -552,25 +554,27 @@ parse_include (pfile, header)
|
|||
dir = pfile->directive->name;
|
||||
|
||||
/* Allow macro expansion. */
|
||||
cpp_get_token (pfile, header);
|
||||
header = cpp_get_token (pfile);
|
||||
if (header->type != CPP_STRING && header->type != CPP_HEADER_NAME)
|
||||
{
|
||||
if (header->type != CPP_LESS)
|
||||
{
|
||||
cpp_error (pfile, "#%s expects \"FILENAME\" or <FILENAME>", dir);
|
||||
return 1;
|
||||
return NULL;
|
||||
}
|
||||
if (glue_header_name (pfile, header))
|
||||
return 1;
|
||||
|
||||
header = glue_header_name (pfile);
|
||||
if (header == NULL)
|
||||
return header;
|
||||
}
|
||||
|
||||
if (header->val.str.len == 0)
|
||||
{
|
||||
cpp_error (pfile, "empty file name in #%s", dir);
|
||||
return 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return header;
|
||||
}
|
||||
|
||||
/* Handle #include, #include_next and #import. */
|
||||
|
@ -579,7 +583,7 @@ do_include_common (pfile, type)
|
|||
cpp_reader *pfile;
|
||||
enum include_type type;
|
||||
{
|
||||
cpp_token header;
|
||||
const cpp_token *header;
|
||||
|
||||
/* For #include_next, if this is the primary source file, warn and
|
||||
use the normal search logic. */
|
||||
|
@ -595,7 +599,8 @@ do_include_common (pfile, type)
|
|||
"#import is obsolete, use an #ifndef wrapper in the header file");
|
||||
}
|
||||
|
||||
if (!parse_include (pfile, &header))
|
||||
header = parse_include (pfile);
|
||||
if (header)
|
||||
{
|
||||
/* Prevent #include recursion. */
|
||||
if (pfile->line_maps.depth >= CPP_STACK_MAX)
|
||||
|
@ -607,9 +612,9 @@ do_include_common (pfile, type)
|
|||
skip_rest_of_line (pfile);
|
||||
if (pfile->cb.include)
|
||||
(*pfile->cb.include) (pfile, pfile->directive_line,
|
||||
pfile->directive->name, &header);
|
||||
pfile->directive->name, header);
|
||||
|
||||
_cpp_execute_include (pfile, &header, type);
|
||||
_cpp_execute_include (pfile, header, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -693,7 +698,7 @@ static void
|
|||
do_line (pfile)
|
||||
cpp_reader *pfile;
|
||||
{
|
||||
cpp_token token;
|
||||
const cpp_token *token;
|
||||
const char *new_file = pfile->map->to_file;
|
||||
unsigned long new_lineno;
|
||||
unsigned int cap, new_sysp = pfile->map->sysp;
|
||||
|
@ -708,12 +713,13 @@ do_line (pfile)
|
|||
_cpp_backup_tokens (pfile, 1);
|
||||
|
||||
/* #line commands expand macros. */
|
||||
cpp_get_token (pfile, &token);
|
||||
if (token.type != CPP_NUMBER
|
||||
|| strtoul_for_line (token.val.str.text, token.val.str.len, &new_lineno))
|
||||
token = cpp_get_token (pfile);
|
||||
if (token->type != CPP_NUMBER
|
||||
|| strtoul_for_line (token->val.str.text, token->val.str.len,
|
||||
&new_lineno))
|
||||
{
|
||||
cpp_error (pfile, "\"%s\" after #line is not a positive integer",
|
||||
cpp_token_as_text (pfile, &token));
|
||||
cpp_token_as_text (pfile, token));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -721,10 +727,10 @@ do_line (pfile)
|
|||
&& (new_lineno == 0 || new_lineno > cap))
|
||||
cpp_pedwarn (pfile, "line number out of range");
|
||||
|
||||
cpp_get_token (pfile, &token);
|
||||
if (token.type == CPP_STRING)
|
||||
token = cpp_get_token (pfile);
|
||||
if (token->type == CPP_STRING)
|
||||
{
|
||||
new_file = (const char *) token.val.str.text;
|
||||
new_file = (const char *) token->val.str.text;
|
||||
|
||||
/* Only accept flags for the # 55 form. */
|
||||
if (pfile->state.line_extension)
|
||||
|
@ -755,10 +761,10 @@ do_line (pfile)
|
|||
}
|
||||
check_eol (pfile);
|
||||
}
|
||||
else if (token.type != CPP_EOF)
|
||||
else if (token->type != CPP_EOF)
|
||||
{
|
||||
cpp_error (pfile, "\"%s\" is not a valid filename",
|
||||
cpp_token_as_text (pfile, &token));
|
||||
cpp_token_as_text (pfile, token));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -827,13 +833,12 @@ static void
|
|||
do_ident (pfile)
|
||||
cpp_reader *pfile;
|
||||
{
|
||||
cpp_token str;
|
||||
const cpp_token *str = cpp_get_token (pfile);
|
||||
|
||||
cpp_get_token (pfile, &str);
|
||||
if (str.type != CPP_STRING)
|
||||
cpp_error (pfile, "invalid #ident");
|
||||
if (str->type != CPP_STRING)
|
||||
cpp_error (pfile, "invalid #ident directive");
|
||||
else if (pfile->cb.ident)
|
||||
(*pfile->cb.ident) (pfile, pfile->directive_line, &str.val.str);
|
||||
(*pfile->cb.ident) (pfile, pfile->directive_line, &str->val.str);
|
||||
|
||||
check_eol (pfile);
|
||||
}
|
||||
|
@ -950,7 +955,7 @@ do_pragma (pfile)
|
|||
{
|
||||
pragma_cb handler = NULL;
|
||||
const struct pragma_entry *p;
|
||||
cpp_token tok;
|
||||
const cpp_token *token;
|
||||
unsigned int count = 0;
|
||||
|
||||
p = pfile->pragmas;
|
||||
|
@ -958,10 +963,10 @@ do_pragma (pfile)
|
|||
|
||||
new_space:
|
||||
count++;
|
||||
cpp_get_token (pfile, &tok);
|
||||
if (tok.type == CPP_NAME)
|
||||
token = cpp_get_token (pfile);
|
||||
if (token->type == CPP_NAME)
|
||||
{
|
||||
const cpp_hashnode *node = tok.val.node;
|
||||
const cpp_hashnode *node = token->val.node;
|
||||
size_t len = NODE_LEN (node);
|
||||
|
||||
while (p)
|
||||
|
@ -990,7 +995,7 @@ do_pragma (pfile)
|
|||
themselves. Stand-alone CPP must ignore us, otherwise it will
|
||||
prefix the directive with spaces, hence the 1. Ugh. */
|
||||
if (pfile->cb.line_change)
|
||||
(*pfile->cb.line_change)(pfile, &tok, 1);
|
||||
(*pfile->cb.line_change)(pfile, token, 1);
|
||||
|
||||
if (handler)
|
||||
(*handler) (pfile);
|
||||
|
@ -1078,22 +1083,22 @@ static void
|
|||
do_pragma_dependency (pfile)
|
||||
cpp_reader *pfile;
|
||||
{
|
||||
cpp_token header, msg;
|
||||
const cpp_token *header;
|
||||
int ordering;
|
||||
|
||||
if (parse_include (pfile, &header))
|
||||
header = parse_include (pfile);
|
||||
if (!header)
|
||||
return;
|
||||
|
||||
ordering = _cpp_compare_file_date (pfile, &header);
|
||||
ordering = _cpp_compare_file_date (pfile, header);
|
||||
if (ordering < 0)
|
||||
cpp_warning (pfile, "cannot find source %s",
|
||||
cpp_token_as_text (pfile, &header));
|
||||
cpp_token_as_text (pfile, header));
|
||||
else if (ordering > 0)
|
||||
{
|
||||
cpp_warning (pfile, "current file is older than %s",
|
||||
cpp_token_as_text (pfile, &header));
|
||||
cpp_get_token (pfile, &msg);
|
||||
if (msg.type != CPP_EOF)
|
||||
cpp_token_as_text (pfile, header));
|
||||
if (cpp_get_token (pfile)->type != CPP_EOF)
|
||||
{
|
||||
_cpp_backup_tokens (pfile, 1);
|
||||
do_diagnostic (pfile, WARNING, 0);
|
||||
|
@ -1101,24 +1106,38 @@ do_pragma_dependency (pfile)
|
|||
}
|
||||
}
|
||||
|
||||
/* Check syntax is "(string-literal)". Returns 0 on success. */
|
||||
static int
|
||||
get__Pragma_string (pfile, string)
|
||||
/* Get a token but skip padding. */
|
||||
static const cpp_token *
|
||||
get_token_no_padding (pfile)
|
||||
cpp_reader *pfile;
|
||||
cpp_token *string;
|
||||
{
|
||||
cpp_token paren;
|
||||
for (;;)
|
||||
{
|
||||
const cpp_token *result = cpp_get_token (pfile);
|
||||
if (result->type != CPP_PADDING)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
cpp_get_token (pfile, &paren);
|
||||
if (paren.type != CPP_OPEN_PAREN)
|
||||
return 1;
|
||||
/* Check syntax is "(string-literal)". Returns the string on success,
|
||||
or NULL on failure. */
|
||||
static const cpp_token *
|
||||
get__Pragma_string (pfile)
|
||||
cpp_reader *pfile;
|
||||
{
|
||||
const cpp_token *string;
|
||||
|
||||
cpp_get_token (pfile, string);
|
||||
if (get_token_no_padding (pfile)->type != CPP_OPEN_PAREN)
|
||||
return NULL;
|
||||
|
||||
string = get_token_no_padding (pfile);
|
||||
if (string->type != CPP_STRING && string->type != CPP_WSTRING)
|
||||
return 1;
|
||||
return NULL;
|
||||
|
||||
cpp_get_token (pfile, &paren);
|
||||
return paren.type != CPP_CLOSE_PAREN;
|
||||
if (get_token_no_padding (pfile)->type != CPP_CLOSE_PAREN)
|
||||
return NULL;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
/* Returns a malloced buffer containing a destringized cpp_string by
|
||||
|
@ -1148,11 +1167,11 @@ void
|
|||
_cpp_do__Pragma (pfile)
|
||||
cpp_reader *pfile;
|
||||
{
|
||||
cpp_token string;
|
||||
const cpp_token *string = get__Pragma_string (pfile);
|
||||
unsigned char *buffer;
|
||||
unsigned int len;
|
||||
|
||||
if (get__Pragma_string (pfile, &string))
|
||||
if (!string)
|
||||
cpp_error (pfile, "_Pragma takes a parenthesized string literal");
|
||||
else
|
||||
{
|
||||
|
@ -1167,7 +1186,7 @@ _cpp_do__Pragma (pfile)
|
|||
Getting these correct line markers is a little tricky. */
|
||||
|
||||
unsigned int orig_line = pfile->line;
|
||||
buffer = destringize (&string.val.str, &len);
|
||||
buffer = destringize (&string->val.str, &len);
|
||||
run_directive (pfile, T_PRAGMA, (char *) buffer, len);
|
||||
free ((PTR) buffer);
|
||||
pfile->line = orig_line;
|
||||
|
@ -1386,7 +1405,7 @@ parse_answer (pfile, answerp, type)
|
|||
struct answer **answerp;
|
||||
int type;
|
||||
{
|
||||
cpp_token paren, *token;
|
||||
const cpp_token *paren;
|
||||
struct answer *answer;
|
||||
|
||||
if (POOL_FRONT (&pfile->macro_pool) + sizeof (struct answer) >
|
||||
|
@ -1397,10 +1416,10 @@ parse_answer (pfile, answerp, type)
|
|||
|
||||
/* In a conditional, it is legal to not have an open paren. We
|
||||
should save the following token in this case. */
|
||||
cpp_get_token (pfile, &paren);
|
||||
paren = cpp_get_token (pfile);
|
||||
|
||||
/* If not a paren, see if we're OK. */
|
||||
if (paren.type != CPP_OPEN_PAREN)
|
||||
if (paren->type != CPP_OPEN_PAREN)
|
||||
{
|
||||
/* In a conditional no answer is a test for any answer. It
|
||||
could be followed by any token. */
|
||||
|
@ -1411,7 +1430,7 @@ parse_answer (pfile, answerp, type)
|
|||
}
|
||||
|
||||
/* #unassert with no answer is valid - it removes all answers. */
|
||||
if (type == T_UNASSERT && paren.type == CPP_EOF)
|
||||
if (type == T_UNASSERT && paren->type == CPP_EOF)
|
||||
return 0;
|
||||
|
||||
cpp_error (pfile, "missing '(' after predicate");
|
||||
|
@ -1420,7 +1439,7 @@ parse_answer (pfile, answerp, type)
|
|||
|
||||
for (;;)
|
||||
{
|
||||
token = &answer->first[answer->count];
|
||||
cpp_token *token = &answer->first[answer->count];
|
||||
/* Check we have room for the token. */
|
||||
if ((unsigned char *) (token + 1) >= POOL_LIMIT (&pfile->macro_pool))
|
||||
{
|
||||
|
@ -1429,7 +1448,7 @@ parse_answer (pfile, answerp, type)
|
|||
token = &answer->first[answer->count];
|
||||
}
|
||||
|
||||
cpp_get_token (pfile, token);
|
||||
*token = *cpp_get_token (pfile);
|
||||
if (token->type == CPP_CLOSE_PAREN)
|
||||
break;
|
||||
|
||||
|
@ -1466,25 +1485,25 @@ parse_assertion (pfile, answerp, type)
|
|||
int type;
|
||||
{
|
||||
cpp_hashnode *result = 0;
|
||||
cpp_token predicate;
|
||||
const cpp_token *predicate;
|
||||
|
||||
/* We don't expand predicates or answers. */
|
||||
pfile->state.prevent_expansion++;
|
||||
|
||||
*answerp = 0;
|
||||
cpp_get_token (pfile, &predicate);
|
||||
if (predicate.type == CPP_EOF)
|
||||
predicate = cpp_get_token (pfile);
|
||||
if (predicate->type == CPP_EOF)
|
||||
cpp_error (pfile, "assertion without predicate");
|
||||
else if (predicate.type != CPP_NAME)
|
||||
else if (predicate->type != CPP_NAME)
|
||||
cpp_error (pfile, "predicate must be an identifier");
|
||||
else if (parse_answer (pfile, answerp, type) == 0)
|
||||
{
|
||||
unsigned int len = NODE_LEN (predicate.val.node);
|
||||
unsigned int len = NODE_LEN (predicate->val.node);
|
||||
unsigned char *sym = alloca (len + 1);
|
||||
|
||||
/* Prefix '#' to get it out of macro namespace. */
|
||||
sym[0] = '#';
|
||||
memcpy (sym + 1, NODE_NAME (predicate.val.node), len);
|
||||
memcpy (sym + 1, NODE_NAME (predicate->val.node), len);
|
||||
result = cpp_lookup (pfile, sym, len + 1);
|
||||
}
|
||||
|
||||
|
|
10
gcc/cpplib.h
10
gcc/cpplib.h
|
@ -134,6 +134,7 @@ struct file_name_map_list;
|
|||
\
|
||||
TK(CPP_COMMENT, SPELL_STRING) /* Only if output comments. */ \
|
||||
TK(CPP_MACRO_ARG, SPELL_NONE) /* Macro argument. */ \
|
||||
OP(CPP_PADDING, "") /* Whitespace for cpp0. */ \
|
||||
OP(CPP_EOF, "EOL") /* End of line or file. */
|
||||
|
||||
#define OP(e, s) e,
|
||||
|
@ -164,8 +165,7 @@ struct cpp_string
|
|||
#define PASTE_LEFT (1 << 3) /* If on LHS of a ## operator. */
|
||||
#define NAMED_OP (1 << 4) /* C++ named operators. */
|
||||
#define NO_EXPAND (1 << 5) /* Do not macro-expand this token. */
|
||||
#define AVOID_LPASTE (1 << 6) /* Check left for accidental pastes. */
|
||||
#define BOL (1 << 7) /* Token at beginning of line. */
|
||||
#define BOL (1 << 6) /* Token at beginning of line. */
|
||||
|
||||
/* A preprocessing token. This has been carefully packed and should
|
||||
occupy 12 bytes on 32-bit hosts and 16 bytes on 64-bit hosts. */
|
||||
|
@ -179,6 +179,7 @@ struct cpp_token
|
|||
union
|
||||
{
|
||||
cpp_hashnode *node; /* An identifier. */
|
||||
const cpp_token *source; /* Inherit padding from this token. */
|
||||
struct cpp_string str; /* A string, or number. */
|
||||
unsigned int arg_no; /* Argument no. for a CPP_MACRO_ARG. */
|
||||
unsigned char c; /* Character represented by CPP_OTHER. */
|
||||
|
@ -235,6 +236,9 @@ struct cpp_options
|
|||
/* The language we're preprocessing. */
|
||||
enum c_lang lang;
|
||||
|
||||
/* Nonzero means to return spacing characters for stand-alone CPP. */
|
||||
unsigned char spacing;
|
||||
|
||||
/* Non-0 means -v, so print the full set of include dirs. */
|
||||
unsigned char verbose;
|
||||
|
||||
|
@ -497,7 +501,7 @@ extern int cpp_avoid_paste PARAMS ((cpp_reader *, const cpp_token *,
|
|||
const cpp_token *));
|
||||
extern enum cpp_ttype cpp_can_paste PARAMS ((cpp_reader *, const cpp_token *,
|
||||
const cpp_token *, int *));
|
||||
extern void cpp_get_token PARAMS ((cpp_reader *, cpp_token *));
|
||||
extern const cpp_token *cpp_get_token PARAMS ((cpp_reader *));
|
||||
extern const unsigned char *cpp_macro_definition PARAMS ((cpp_reader *,
|
||||
const cpp_hashnode *));
|
||||
extern void _cpp_backup_tokens PARAMS ((cpp_reader *, unsigned int));
|
||||
|
|
733
gcc/cppmacro.c
733
gcc/cppmacro.c
File diff suppressed because it is too large
Load diff
|
@ -32,6 +32,7 @@ struct printer
|
|||
{
|
||||
FILE *outf; /* Stream to write to. */
|
||||
const struct line_map *map; /* Logical to physical line mappings. */
|
||||
const cpp_token *prev; /* Previous token. */
|
||||
unsigned int line; /* Line currently being written. */
|
||||
unsigned char printed; /* Nonzero if something output at line. */
|
||||
};
|
||||
|
@ -43,7 +44,7 @@ static void setup_callbacks PARAMS ((void));
|
|||
|
||||
/* General output routines. */
|
||||
static void scan_translation_unit PARAMS ((cpp_reader *));
|
||||
static void check_multiline_token PARAMS ((cpp_string *));
|
||||
static void check_multiline_token PARAMS ((const cpp_string *));
|
||||
static int dump_macro PARAMS ((cpp_reader *, cpp_hashnode *, void *));
|
||||
|
||||
static void print_line PARAMS ((const struct line_map *, unsigned int,
|
||||
|
@ -144,6 +145,7 @@ do_preprocessing (argc, argv)
|
|||
cause a linemarker to be output by maybe_print_line. */
|
||||
print.line = (unsigned int) -1;
|
||||
print.printed = 0;
|
||||
print.prev = 0;
|
||||
print.map = 0;
|
||||
|
||||
/* Open the output now. We must do so even if no_output is on,
|
||||
|
@ -219,22 +221,43 @@ static void
|
|||
scan_translation_unit (pfile)
|
||||
cpp_reader *pfile;
|
||||
{
|
||||
unsigned int index;
|
||||
cpp_token tokens[2], *token;
|
||||
bool avoid_paste = false;
|
||||
const cpp_token *source = NULL;
|
||||
|
||||
for (index = 0;; index = 1 - index)
|
||||
for (;;)
|
||||
{
|
||||
token = &tokens[index];
|
||||
cpp_get_token (pfile, token);
|
||||
const cpp_token *token = cpp_get_token (pfile);
|
||||
|
||||
if (token->type == CPP_PADDING)
|
||||
{
|
||||
avoid_paste = true;
|
||||
if (source == NULL
|
||||
|| (!(source->flags & PREV_WHITE) && token->val.source == NULL))
|
||||
source = token->val.source;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (token->type == CPP_EOF)
|
||||
break;
|
||||
|
||||
if ((token->flags & (PREV_WHITE | AVOID_LPASTE | BOL)) == AVOID_LPASTE
|
||||
&& cpp_avoid_paste (pfile, &tokens[1 - index], token))
|
||||
token->flags |= PREV_WHITE;
|
||||
/* Subtle logic to output a space if and only if necessary. */
|
||||
if (avoid_paste)
|
||||
{
|
||||
if (source == NULL)
|
||||
source = token;
|
||||
if (source->flags & PREV_WHITE
|
||||
|| (print.prev && cpp_avoid_paste (pfile, print.prev, token))
|
||||
|| (print.prev == NULL && token->type == CPP_HASH))
|
||||
putc (' ', print.outf);
|
||||
}
|
||||
else if (token->flags & PREV_WHITE)
|
||||
putc (' ', print.outf);
|
||||
|
||||
avoid_paste = false;
|
||||
source = NULL;
|
||||
print.prev = token;
|
||||
cpp_output_token (token, print.outf);
|
||||
|
||||
if (token->type == CPP_STRING || token->type == CPP_WSTRING
|
||||
|| token->type == CPP_COMMENT)
|
||||
check_multiline_token (&token->val.str);
|
||||
|
@ -244,7 +267,7 @@ scan_translation_unit (pfile)
|
|||
/* Adjust print.line for newlines embedded in tokens. */
|
||||
static void
|
||||
check_multiline_token (str)
|
||||
cpp_string *str;
|
||||
const cpp_string *str;
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
|
@ -324,6 +347,7 @@ cb_line_change (pfile, token, parsing_args)
|
|||
|
||||
maybe_print_line (print.map, token->line);
|
||||
print.printed = 1;
|
||||
print.prev = 0;
|
||||
|
||||
/* Supply enough spaces to put this token in its original column,
|
||||
one space per column greater than 2, since scan_translation_unit
|
||||
|
|
|
@ -1515,10 +1515,10 @@ token pasting.
|
|||
However, two tokens that don't together form a valid token cannot be
|
||||
pasted together. For example, you cannot concatenate @code{x} with
|
||||
@code{+} in either order. If you try, the preprocessor issues a warning
|
||||
and emits the two tokens as if they had been written next to each other.
|
||||
It is common to find unnecessary uses of @samp{##} in complex macros.
|
||||
If you get this warning, it is likely that you can simply remove the
|
||||
@samp{##}.
|
||||
and emits the two tokens. Whether it puts white space between the
|
||||
tokens is undefined. It is common to find unnecessary uses of @samp{##}
|
||||
in complex macros. If you get this warning, it is likely that you can
|
||||
simply remove the @samp{##}.
|
||||
|
||||
Both the tokens combined by @samp{##} could come from the macro body,
|
||||
but you could just as well write them as one token in the first place.
|
||||
|
|
|
@ -661,12 +661,11 @@ read_scan_file (in_fname, argc, argv)
|
|||
/* from_stage3 */ true, 1);
|
||||
for (;;)
|
||||
{
|
||||
cpp_token t;
|
||||
const cpp_token *t = cpp_get_token (scan_in);
|
||||
|
||||
cpp_get_token (scan_in, &t);
|
||||
if (t.type == CPP_EOF)
|
||||
if (t->type == CPP_EOF)
|
||||
break;
|
||||
else if (cpp_ideq (&t, "_filbuf"))
|
||||
else if (cpp_ideq (t, "_filbuf"))
|
||||
seen_filbuf++;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "scan.h"
|
||||
|
||||
static void skip_to_closing_brace PARAMS ((cpp_reader *));
|
||||
static const cpp_token *get_a_token PARAMS ((cpp_reader *));
|
||||
|
||||
int brace_nesting = 0;
|
||||
|
||||
|
@ -38,6 +39,19 @@ char extern_C_braces[20];
|
|||
prefixed by extern "C". */
|
||||
int current_extern_C = 0;
|
||||
|
||||
/* Get a token but skip padding. */
|
||||
static const cpp_token *
|
||||
get_a_token (pfile)
|
||||
cpp_reader *pfile;
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
const cpp_token *result = cpp_get_token (pfile);
|
||||
if (result->type != CPP_PADDING)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
skip_to_closing_brace (pfile)
|
||||
cpp_reader *pfile;
|
||||
|
@ -45,11 +59,8 @@ skip_to_closing_brace (pfile)
|
|||
int nesting = 1;
|
||||
for (;;)
|
||||
{
|
||||
cpp_token tok;
|
||||
enum cpp_ttype token;
|
||||
enum cpp_ttype token = get_a_token (pfile)->type;
|
||||
|
||||
cpp_get_token (pfile, &tok);
|
||||
token = tok.type;
|
||||
if (token == CPP_EOF)
|
||||
break;
|
||||
if (token == CPP_OPEN_BRACE)
|
||||
|
@ -88,16 +99,17 @@ scan_decls (pfile, argc, argv)
|
|||
char **argv ATTRIBUTE_UNUSED;
|
||||
{
|
||||
int saw_extern, saw_inline;
|
||||
cpp_token token, prev_id;
|
||||
cpp_token prev_id;
|
||||
const cpp_token *token;
|
||||
|
||||
new_statement:
|
||||
cpp_get_token (pfile, &token);
|
||||
token = get_a_token (pfile);
|
||||
|
||||
handle_statement:
|
||||
current_extern_C = 0;
|
||||
saw_extern = 0;
|
||||
saw_inline = 0;
|
||||
if (token.type == CPP_OPEN_BRACE)
|
||||
if (token->type == CPP_OPEN_BRACE)
|
||||
{
|
||||
/* Pop an 'extern "C"' nesting level, if appropriate. */
|
||||
if (extern_C_braces_length
|
||||
|
@ -106,24 +118,24 @@ scan_decls (pfile, argc, argv)
|
|||
brace_nesting--;
|
||||
goto new_statement;
|
||||
}
|
||||
if (token.type == CPP_OPEN_BRACE)
|
||||
if (token->type == CPP_OPEN_BRACE)
|
||||
{
|
||||
brace_nesting++;
|
||||
goto new_statement;
|
||||
}
|
||||
|
||||
if (token.type == CPP_EOF)
|
||||
if (token->type == CPP_EOF)
|
||||
return 0;
|
||||
|
||||
if (token.type == CPP_SEMICOLON)
|
||||
if (token->type == CPP_SEMICOLON)
|
||||
goto new_statement;
|
||||
if (token.type != CPP_NAME)
|
||||
if (token->type != CPP_NAME)
|
||||
goto new_statement;
|
||||
|
||||
prev_id.type = CPP_EOF;
|
||||
for (;;)
|
||||
{
|
||||
switch (token.type)
|
||||
switch (token->type)
|
||||
{
|
||||
default:
|
||||
goto handle_statement;
|
||||
|
@ -138,7 +150,7 @@ scan_decls (pfile, argc, argv)
|
|||
{
|
||||
recognized_extern (&prev_id);
|
||||
}
|
||||
if (token.type == CPP_COMMA)
|
||||
if (token->type == CPP_COMMA)
|
||||
break;
|
||||
/* ... fall through ... */
|
||||
case CPP_OPEN_BRACE: case CPP_CLOSE_BRACE:
|
||||
|
@ -155,27 +167,27 @@ scan_decls (pfile, argc, argv)
|
|||
int have_arg_list = 0;
|
||||
for (;;)
|
||||
{
|
||||
cpp_get_token (pfile, &token);
|
||||
if (token.type == CPP_OPEN_PAREN)
|
||||
token = get_a_token (pfile);
|
||||
if (token->type == CPP_OPEN_PAREN)
|
||||
nesting++;
|
||||
else if (token.type == CPP_CLOSE_PAREN)
|
||||
else if (token->type == CPP_CLOSE_PAREN)
|
||||
{
|
||||
nesting--;
|
||||
if (nesting == 0)
|
||||
break;
|
||||
}
|
||||
else if (token.type == CPP_EOF)
|
||||
else if (token->type == CPP_EOF)
|
||||
break;
|
||||
else if (token.type == CPP_NAME
|
||||
|| token.type == CPP_ELLIPSIS)
|
||||
else if (token->type == CPP_NAME
|
||||
|| token->type == CPP_ELLIPSIS)
|
||||
have_arg_list = 1;
|
||||
}
|
||||
recognized_function (&prev_id, token.line,
|
||||
recognized_function (&prev_id, token->line,
|
||||
(saw_inline ? 'I'
|
||||
: in_extern_C_brace || current_extern_C
|
||||
? 'F' : 'f'), have_arg_list);
|
||||
cpp_get_token (pfile, &token);
|
||||
if (token.type == CPP_OPEN_BRACE)
|
||||
token = get_a_token (pfile);
|
||||
if (token->type == CPP_OPEN_BRACE)
|
||||
{
|
||||
/* skip body of (normally) inline function */
|
||||
skip_to_closing_brace (pfile);
|
||||
|
@ -184,28 +196,28 @@ scan_decls (pfile, argc, argv)
|
|||
|
||||
/* skip a possible __attribute__ or throw expression after the
|
||||
parameter list */
|
||||
while (token.type != CPP_SEMICOLON && token.type != CPP_EOF)
|
||||
cpp_get_token (pfile, &token);
|
||||
while (token->type != CPP_SEMICOLON && token->type != CPP_EOF)
|
||||
token = get_a_token (pfile);
|
||||
goto new_statement;
|
||||
}
|
||||
break;
|
||||
case CPP_NAME:
|
||||
/* "inline" and "extern" are recognized but skipped */
|
||||
if (cpp_ideq (&token, "inline"))
|
||||
if (cpp_ideq (token, "inline"))
|
||||
{
|
||||
saw_inline = 1;
|
||||
}
|
||||
else if (cpp_ideq (&token, "extern"))
|
||||
else if (cpp_ideq (token, "extern"))
|
||||
{
|
||||
saw_extern = 1;
|
||||
cpp_get_token (pfile, &token);
|
||||
if (token.type == CPP_STRING
|
||||
&& token.val.str.len == 1
|
||||
&& token.val.str.text[0] == 'C')
|
||||
token = get_a_token (pfile);
|
||||
if (token->type == CPP_STRING
|
||||
&& token->val.str.len == 1
|
||||
&& token->val.str.text[0] == 'C')
|
||||
{
|
||||
current_extern_C = 1;
|
||||
cpp_get_token (pfile, &token);
|
||||
if (token.type == CPP_OPEN_BRACE)
|
||||
token = get_a_token (pfile);
|
||||
if (token->type == CPP_OPEN_BRACE)
|
||||
{
|
||||
brace_nesting++;
|
||||
extern_C_braces[extern_C_braces_length++]
|
||||
|
@ -218,9 +230,9 @@ scan_decls (pfile, argc, argv)
|
|||
break;
|
||||
}
|
||||
/* This may be the name of a variable or function. */
|
||||
prev_id = token;
|
||||
prev_id = *token;
|
||||
break;
|
||||
}
|
||||
cpp_get_token (pfile, &token);
|
||||
token = get_a_token (pfile);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
2001-09-24 Neil Booth <neil@daikokuya.demon.co.uk>
|
||||
|
||||
* gcc.dg/cpp/macro10.c: New test.
|
||||
* gcc.dg/cpp/strify3.c: New test.
|
||||
* gcc.dg/cpp/spacing1.c: Add tests.
|
||||
* gcc.dg/cpp/19990703-1.c: Remove bogus test.
|
||||
* gcc.dg/cpp/20000625-2.c: Fudge to pass.
|
||||
|
||||
2001-09-24 DJ Delorie <dj@redhat.com>
|
||||
|
||||
* gcc.c-torture/execute/20010924-1.c: New test.
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
/* { dg-do run } */
|
||||
|
||||
/* Test of obscure case in token pasting in the preprocessor.
|
||||
I can't think of any way to make this problem provoke a syntax error.
|
||||
Based on a bug report by Manfred Hollstein. */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define SP1(x, y) SP2(x, y)
|
||||
#define SP2(x, y) SP3(x##y)
|
||||
#define SP3(x) #x
|
||||
#define MZ -0
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
char *x = SP1(0,MZ); /* { dg-warning "valid preprocessing token" "" } */
|
||||
char *y = "0-0"; /* should be the expansion of SP1(0,MZ) */
|
||||
|
||||
if(strcmp(x, y))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
|
@ -8,7 +8,10 @@
|
|||
#define str(x) xstr(x)
|
||||
#define xstr(x) #x
|
||||
|
||||
const char a[] = str(symbol_version(getrlimit, GLIBC_2.0));
|
||||
/* This testcase is bogus, as it testing undefined behaviour. We can
|
||||
get the behaviour GLIBC desires by removing the space before
|
||||
GCLIB_2.0 in this line. */
|
||||
const char a[] = str(symbol_version(getrlimit,GLIBC_2.0));
|
||||
/* { dg-warning "valid preprocessing token" "" { target *-*-* } 11 } */
|
||||
const char b[] = str(getrlimit@GLIBC_2.0);
|
||||
const char c[] = "getrlimit@GLIBC_2.0";
|
||||
|
|
25
gcc/testsuite/gcc.dg/cpp/macro10.c
Normal file
25
gcc/testsuite/gcc.dg/cpp/macro10.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/* Copyright (C) 2001 Free Software Foundation, Inc. */
|
||||
|
||||
/* { dg-do preprocess } */
|
||||
|
||||
/* Source: Neil Booth, 23 Sep 2001.
|
||||
|
||||
A tricky, pathological corner case we used to get wrong. Expansion
|
||||
should go as follows. The asterisk indicates the token has "blue
|
||||
paint" can no longer be macro expanded. We used to lose that
|
||||
information when parsing arguments and dropping to the lexer to get
|
||||
the ')'.
|
||||
|
||||
foo )
|
||||
bar foo* )
|
||||
func (foo* )
|
||||
foo*
|
||||
|
||||
If we try and expand the final foo, we get an "unterminated
|
||||
argument list invoking macro <func>" error. If we do the right
|
||||
thing and leave it as is, no diagnostics are emitted. */
|
||||
|
||||
#define func(x) x
|
||||
#define bar func(
|
||||
#define foo bar foo
|
||||
foo )
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2000 Free Software Foundation, Inc. */
|
||||
/* Copyright (C) 2000, 2001 Free Software Foundation, Inc. */
|
||||
|
||||
/* { dg-do preprocess } */
|
||||
|
||||
|
@ -8,20 +8,24 @@
|
|||
not be a macro invocation. Also, multiple macro invocations spread
|
||||
across many lines.
|
||||
|
||||
Neil Booth, 1 Dec 2000. */
|
||||
Neil Booth, 1 Dec 2000, 23 Sep 2001. */
|
||||
|
||||
#define str(x) #x
|
||||
#define f(x) x
|
||||
#define glue(x, y) x ## y
|
||||
#define EMPTY
|
||||
|
||||
/* The correct output is shown here. Note the spaces, and the way
|
||||
everything after the invocation of f appears on the same line.
|
||||
|
||||
44 ;
|
||||
f
|
||||
bar
|
||||
g "1 2" bam baz
|
||||
|
||||
*/
|
||||
|
||||
glue (EMPTY 4, 4) EMPTY;
|
||||
f
|
||||
bar
|
||||
f (g) str
|
||||
|
@ -33,9 +37,10 @@ f (g) str
|
|||
|
||||
/*
|
||||
{ dg-final { if ![file exists spacing1.i] { return } } }
|
||||
{ dg-final { if \{ [grep spacing1.i " 44 ;"] != "" \} \{ } }
|
||||
{ dg-final { if \{ [grep spacing1.i "f.*bar"] == "" \} \{ } }
|
||||
{ dg-final { if \{ [grep spacing1.i "^bar"] != "" \} \{ } }
|
||||
{ dg-final { if \{ [grep spacing1.i "g \"1 2\" bam baz"] != "" \} \{ } }
|
||||
{ dg-final { return \} \} \} } }
|
||||
{ dg-final { return \} \} \} \} } }
|
||||
{ dg-final { fail "spacing1.c: spacing and new-line preservation" } }
|
||||
*/
|
||||
|
|
29
gcc/testsuite/gcc.dg/cpp/strify3.c
Normal file
29
gcc/testsuite/gcc.dg/cpp/strify3.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* Copyright (C) 2001 Free Software Foundation, Inc. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
/* Tests we stringify without inserting a space. GCC 2.95.x and
|
||||
earlier would insert a bogus space before bar in the string, simply
|
||||
because a space was there in the invocation.
|
||||
|
||||
Neil Booth, 24 Sep 2001. */
|
||||
|
||||
extern int strcmp (const char *, const char *);
|
||||
extern int puts (const char *);
|
||||
extern void abort (void);
|
||||
#define err(str) do { puts(str); abort(); } while (0)
|
||||
|
||||
#define str(x) #x
|
||||
#define xstr(x) str(x)
|
||||
#define glibc_hack(x, y) x@y
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
/* The space before "bar" here is vital. */
|
||||
char a[] = xstr(glibc_hack(foo, bar));
|
||||
|
||||
if (strcmp (a, "foo@bar"))
|
||||
err ("stringification without spaces");
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue