"trigraph ??%c converted to %c",
(int) from_char,
(int) _cpp_trigraph_map[from_char]);
- else
- cpp_warning_with_line (pfile, buffer->lineno, CPP_BUF_COL (buffer) - 2,
- "trigraph ??%c ignored", (int) from_char);
+ else if (buffer->cur != buffer->last_Wtrigraphs)
+ {
+ buffer->last_Wtrigraphs = buffer->cur;
+ cpp_warning_with_line (pfile, buffer->lineno,
+ CPP_BUF_COL (buffer) - 2,
+ "trigraph ??%c ignored", (int) from_char);
+ }
}
return accept;
break;
}
- if (space)
+ if (space && !buffer->pfile->state.lexing_comment)
cpp_warning (buffer->pfile,
"backslash and newline separated by space");
cpp_error (pfile, "attempt to use poisoned \"%s\"", result->name);
/* Constraint 6.10.3.5: __VA_ARGS__ should only appear in the
- replacement list of a variable-arguments macro. */
+ replacement list of a variadic macro. */
if (result == pfile->spec_nodes.n__VA_ARGS__
&& !pfile->state.va_args_ok)
- cpp_pedwarn (pfile, "__VA_ARGS__ can only appear in the expansion of a C99 variable-argument macro");
+ cpp_pedwarn (pfile, "__VA_ARGS__ can only appear in the expansion of a C99 variadic macro");
}
return result;
int leading_period;
{
cpp_buffer *buffer = pfile->buffer;
- cpp_pool *pool = pfile->string_pool;
+ cpp_pool *pool = &pfile->ident_pool;
unsigned char *dest, *limit;
dest = POOL_FRONT (pool);
if (pfile->state.angled_headers)
return 1;
- start = POOL_FRONT (pfile->string_pool);
+ start = POOL_FRONT (&pfile->ident_pool);
/* An odd number of consecutive backslashes represents an escaped
terminator. */
cppchar_t terminator;
{
cpp_buffer *buffer = pfile->buffer;
- cpp_pool *pool = pfile->string_pool;
+ cpp_pool *pool = &pfile->ident_pool;
unsigned char *dest, *limit;
cppchar_t c;
unsigned int nulls = 0;
/* In assembly language, silently terminate string and
character literals at end of line. This is a kludge
around not knowing where comments are. */
- if (CPP_OPTION (pfile, lang_asm) && terminator != '>')
+ if (CPP_OPTION (pfile, lang) == CLK_ASM && terminator != '>')
break;
/* Character constants and header names may not extend over
multiple lines. In Standard C, neither may strings.
Unfortunately, we accept multiline strings as an
- extension. */
- if (terminator != '"')
+ extension, except in #include family directives. */
+ if (terminator != '"' || pfile->state.angled_headers)
{
unterminated (pfile, terminator);
break;
line, which we don't want to save in the comment. */
if (pfile->buffer->read_ahead != EOF)
len--;
- buffer = _cpp_pool_alloc (pfile->string_pool, len);
+ buffer = _cpp_pool_alloc (&pfile->ident_pool, len);
token->type = CPP_COMMENT;
token->val.str.len = len;
cpp_token *result;
{
cppchar_t c;
- cpp_buffer *buffer = pfile->buffer;
+ cpp_buffer *buffer;
const unsigned char *comment_start;
- unsigned char was_skip_newlines = pfile->state.skip_newlines;
- unsigned char newline_in_args = 0;
-
- pfile->state.skip_newlines = 0;
- result->flags = 0;
+ unsigned char bol;
+
+ skip:
+ bol = pfile->state.next_bol;
+ done_directive:
+ buffer = pfile->buffer;
+ pfile->state.next_bol = 0;
+ result->flags = buffer->saved_flags;
+ buffer->saved_flags = 0;
next_char:
pfile->lexer_pos.line = buffer->lineno;
next_char2:
line and _Pragma buffers. */
if (pfile->lexer_pos.col != 0 && !buffer->from_stage3)
cpp_pedwarn (pfile, "no newline at end of file");
- pfile->state.skip_newlines = 1;
+ pfile->state.next_bol = 1;
+ pfile->skipping = 0; /* In case missing #endif. */
result->type = CPP_EOF;
- break;
+ /* Don't do MI optimisation. */
+ return;
case ' ': case '\t': case '\f': case '\v': case '\0':
skip_whitespace (pfile, c);
goto next_char2;
case '\n': case '\r':
- /* Don't let directives spill over to the next line. */
- if (pfile->state.in_directive)
- buffer->read_ahead = c;
- else
+ if (!pfile->state.in_directive)
{
handle_newline (buffer, c);
-
+ bol = 1;
pfile->lexer_pos.output_line = buffer->lineno;
-
- /* Skip newlines in macro arguments (except in directives). */
- if (pfile->state.parsing_args)
- {
- /* Set the whitespace flag. */
- newline_in_args = 1;
- result->flags |= PREV_WHITE;
- goto next_char;
- }
-
- if (was_skip_newlines)
- {
- /* Clear any whitespace flag. */
- result->flags &= ~PREV_WHITE;
- goto next_char;
- }
+ /* This is a new line, so clear any white space flag.
+ Newlines in arguments are white space (6.10.3.10);
+ parse_arg takes care of that. */
+ result->flags &= ~(PREV_WHITE | AVOID_LPASTE);
+ goto next_char;
}
- /* Next we're at BOL, so skip new lines. */
- pfile->state.skip_newlines = 1;
+ /* Don't let directives spill over to the next line. */
+ buffer->read_ahead = c;
+ pfile->state.next_bol = 1;
result->type = CPP_EOF;
- break;
+ /* Don't break; pfile->skipping might be true. */
+ return;
case '?':
case '\\':
&& !CPP_IN_SYSTEM_HEADER (pfile))
break;
- /* We silently allow C++ comments in system headers,
- irrespective of conformance mode, because lots of
- broken systems do that and trying to clean it up in
- fixincludes is a nightmare. */
- if (CPP_OPTION (pfile, c89) && CPP_PEDANTIC (pfile)
+ /* Warn about comments only if pedantically GNUC89, and not
+ in system headers. */
+ if (CPP_OPTION (pfile, lang) == CLK_GNUC89 && CPP_PEDANTIC (pfile)
&& ! buffer->warned_cplusplus_comments)
{
cpp_pedwarn (pfile,
/* Save the comment as a token in its own right. */
save_comment (pfile, result, comment_start);
- break;
+ /* Don't do MI optimisation. */
+ return;
case '<':
if (pfile->state.angled_headers)
break;
case '#':
- if (get_effective_char (buffer) == '#')
- ACCEPT_CHAR (CPP_PASTE);
+ c = buffer->extra_char; /* Can be set by error condition below. */
+ if (c != EOF)
+ {
+ buffer->read_ahead = c;
+ buffer->extra_char = EOF;
+ }
else
+ c = get_effective_char (buffer);
+
+ if (c == '#')
{
- result->type = CPP_HASH;
- do_hash:
- /* CPP_DHASH is the hash introducing a directive. */
- if (was_skip_newlines || newline_in_args)
+ ACCEPT_CHAR (CPP_PASTE);
+ break;
+ }
+
+ result->type = CPP_HASH;
+ do_hash:
+ if (bol)
+ {
+ if (pfile->state.parsing_args)
{
- result->type = CPP_DHASH;
+ /* 6.10.3 paragraph 11: If there are sequences of
+ preprocessing tokens within the list of arguments that
+ would otherwise act as preprocessing directives, the
+ behavior is undefined.
+
+ This implementation will report a hard error, terminate
+ the macro invocation, and proceed to process the
+ directive. */
+ cpp_error (pfile,
+ "directives may not be used inside a macro argument");
+
+ /* Put a '#' in lookahead, return CPP_EOF for parse_arg. */
+ buffer->extra_char = buffer->read_ahead;
+ buffer->read_ahead = '#';
+ pfile->state.next_bol = 1;
+ result->type = CPP_EOF;
+
/* Get whitespace right - newline_in_args sets it. */
if (pfile->lexer_pos.col == 1)
- result->flags &= ~PREV_WHITE;
+ result->flags &= ~(PREV_WHITE | AVOID_LPASTE);
+ }
+ else
+ {
+ /* This is the hash introducing a directive. */
+ if (_cpp_handle_directive (pfile, result->flags & PREV_WHITE))
+ goto done_directive; /* bol still 1. */
+ /* This is in fact an assembler #. */
}
}
break;
random_char:
default:
result->type = CPP_OTHER;
- result->val.aux = c;
+ result->val.c = c;
break;
}
+
+ if (pfile->skipping)
+ goto skip;
+
+ /* If not in a directive, this token invalidates controlling macros. */
+ if (!pfile->state.in_directive)
+ pfile->mi_state = MI_FAILED;
}
/* An upper bound on the number of bytes needed to spell a token,
break;
case SPELL_CHAR:
- *buffer++ = token->val.aux;
+ *buffer++ = token->val.c;
break;
case SPELL_NONE:
const cpp_token *token;
{
unsigned int len = cpp_token_len (token);
- unsigned char *start = _cpp_pool_alloc (&pfile->temp_string_pool, len), *end;
+ unsigned char *start = _cpp_pool_alloc (&pfile->ident_pool, len), *end;
end = cpp_spell_token (pfile, token, start);
end[0] = '\0';
break;
case SPELL_CHAR:
- putc (token->val.aux, fp);
+ putc (token->val.c, fp);
break;
case SPELL_NONE:
case SPELL_OPERATOR:
return 1;
case SPELL_CHAR:
- return a->val.aux == b->val.aux; /* Character. */
+ return a->val.c == b->val.c; /* Character. */
case SPELL_NONE:
- return (a->type != CPP_MACRO_ARG || a->val.aux == b->val.aux);
+ return (a->type != CPP_MACRO_ARG || a->val.arg_no == b->val.arg_no);
case SPELL_IDENT:
return a->val.node == b->val.node;
case SPELL_STRING:
break;
case CPP_OTHER:
- if (CPP_OPTION (pfile, objc) && token1->val.aux == '@')
+ if (CPP_OPTION (pfile, objc) && token1->val.c == '@')
{
if (b == CPP_NAME) return CPP_NAME;
if (b == CPP_STRING) return CPP_OSTRING;
case CPP_OR: return c == '|';
case CPP_COLON: return c == ':' || c == '>';
case CPP_DEREF: return c == '*';
- case CPP_DOT: return c == '.' || c == '%';
+ case CPP_DOT: return c == '.' || c == '%' || b == CPP_NUMBER;
case CPP_HASH: return c == '#' || c == '%'; /* Digraph form. */
case CPP_NAME: return ((b == CPP_NUMBER
&& name_p (pfile, &token2->val.str))
case CPP_NUMBER: return (b == CPP_NUMBER || b == CPP_NAME
|| c == '.' || c == '+' || c == '-');
case CPP_OTHER: return (CPP_OPTION (pfile, objc)
- && token1->val.aux == '@'
+ && token1->val.c == '@'
&& (b == CPP_NAME || b == CPP_STRING));
default: break;
}
{
cpp_token token;
- _cpp_get_token (pfile, &token);
+ cpp_get_token (pfile, &token);
token.flags &= ~PREV_WHITE;
while (token.type != CPP_EOF)
{
cpp_output_token (&token, fp);
- _cpp_get_token (pfile, &token);
+ cpp_get_token (pfile, &token);
}
putc ('\n', fp);