#define TOKEN_NAME(token) (token_spellings[(token)->type].name)
static cppchar_t handle_newline PARAMS ((cpp_reader *, cppchar_t));
-static cppchar_t skip_escaped_newlines PARAMS ((cpp_buffer *, cppchar_t));
-static cppchar_t get_effective_char PARAMS ((cpp_buffer *));
+static cppchar_t skip_escaped_newlines PARAMS ((cpp_reader *, cppchar_t));
+static cppchar_t get_effective_char PARAMS ((cpp_reader *));
static int skip_block_comment PARAMS ((cpp_reader *));
static int skip_line_comment PARAMS ((cpp_reader *));
static void unterminated PARAMS ((cpp_reader *, int));
static int trigraph_ok PARAMS ((cpp_reader *, cppchar_t));
static void save_comment PARAMS ((cpp_reader *, cpp_token *, const U_CHAR *));
-static void lex_percent PARAMS ((cpp_buffer *, cpp_token *));
+static void lex_percent PARAMS ((cpp_reader *, cpp_token *));
static void lex_dot PARAMS ((cpp_reader *, cpp_token *));
static int name_p PARAMS ((cpp_reader *, const cpp_string *));
static int maybe_read_ucs PARAMS ((cpp_reader *, const unsigned char **,
cppchar_t next = EOF;
pfile->line++;
- pfile->pseudo_newlines++;
-
buffer = pfile->buffer;
buffer->col_adjust = 0;
- buffer->lineno++;
buffer->line_base = buffer->cur;
/* Handle CR-LF and LF-CR combinations, get the next character. */
if (CPP_OPTION (pfile, warn_trigraphs) && !pfile->state.lexing_comment)
{
cpp_buffer *buffer = pfile->buffer;
+
if (accept)
- cpp_warning_with_line (pfile, buffer->lineno, CPP_BUF_COL (buffer) - 2,
+ cpp_warning_with_line (pfile, pfile->line, CPP_BUF_COL (buffer) - 2,
"trigraph ??%c converted to %c",
(int) from_char,
(int) _cpp_trigraph_map[from_char]);
else if (buffer->cur != buffer->last_Wtrigraphs)
{
buffer->last_Wtrigraphs = buffer->cur;
- cpp_warning_with_line (pfile, buffer->lineno,
+ cpp_warning_with_line (pfile, pfile->line,
CPP_BUF_COL (buffer) - 2,
"trigraph ??%c ignored", (int) from_char);
}
been placed in buffer->read_ahead. This routine performs
preprocessing stages 1 and 2 of the ISO C standard. */
static cppchar_t
-skip_escaped_newlines (buffer, next)
- cpp_buffer *buffer;
+skip_escaped_newlines (pfile, next)
+ cpp_reader *pfile;
cppchar_t next;
{
+ cpp_buffer *buffer = pfile->buffer;
+
/* Only do this if we apply stages 1 and 2. */
if (!buffer->from_stage3)
{
next1 = *buffer->cur++;
if (!_cpp_trigraph_map[next1]
- || !trigraph_ok (buffer->pfile, next1))
+ || !trigraph_ok (pfile, next1))
{
RESTORE_STATE ();
break;
break;
}
- if (space && !buffer->pfile->state.lexing_comment)
- cpp_warning (buffer->pfile,
- "backslash and newline separated by space");
+ if (space && !pfile->state.lexing_comment)
+ cpp_warning (pfile, "backslash and newline separated by space");
- next = handle_newline (buffer->pfile, next1);
+ next = handle_newline (pfile, next1);
if (next == EOF)
- cpp_pedwarn (buffer->pfile, "backslash-newline at end of file");
+ cpp_pedwarn (pfile, "backslash-newline at end of file");
}
while (next == '\\' || next == '?');
}
an arbitrary string of escaped newlines. The common case of no
trigraphs or escaped newlines falls through quickly. */
static cppchar_t
-get_effective_char (buffer)
- cpp_buffer *buffer;
+get_effective_char (pfile)
+ cpp_reader *pfile;
{
+ cpp_buffer *buffer = pfile->buffer;
cppchar_t next = EOF;
if (buffer->cur < buffer->rlimit)
UCNs, which, depending upon lexer state, we will handle in
the future. */
if (next == '?' || next == '\\')
- next = skip_escaped_newlines (buffer, next);
+ next = skip_escaped_newlines (pfile, next);
}
buffer->read_ahead = next;
/* FIXME: For speed, create a new character class of characters
of interest inside block comments. */
if (c == '?' || c == '\\')
- c = skip_escaped_newlines (buffer, c);
+ c = skip_escaped_newlines (pfile, c);
/* People like decorating comments with '*', so check for '/'
instead for efficiency. */
{
prevc = c, c = *buffer->cur++;
if (c != '/')
- cpp_warning_with_line (pfile, CPP_BUF_LINE (buffer),
- CPP_BUF_COL (buffer),
+ cpp_warning_with_line (pfile, pfile->line,
+ CPP_BUF_COL (buffer) - 2,
"\"/*\" within comment");
}
goto next_char;
cpp_reader *pfile;
{
cpp_buffer *buffer = pfile->buffer;
- unsigned int orig_lineno = buffer->lineno;
+ unsigned int orig_line = pfile->line;
cppchar_t c;
pfile->state.lexing_comment = 1;
c = *buffer->cur++;
if (c == '?' || c == '\\')
- c = skip_escaped_newlines (buffer, c);
+ c = skip_escaped_newlines (pfile, c);
}
while (!is_vspace (c));
pfile->state.lexing_comment = 0;
buffer->read_ahead = c; /* Leave any newline for caller. */
- return orig_lineno != buffer->lineno;
+ return orig_line != pfile->line;
}
/* pfile->buffer->cur is one beyond the \t character. Update
}
}
else if (pfile->state.in_directive && CPP_PEDANTIC (pfile))
- cpp_pedwarn_with_line (pfile, CPP_BUF_LINE (buffer),
+ cpp_pedwarn_with_line (pfile, pfile->line,
CPP_BUF_COL (buffer),
"%s in preprocessing directive",
c == '\f' ? "form feed" : "vertical tab");
/* Potential escaped newline? */
if (c != '?' && c != '\\')
break;
- c = skip_escaped_newlines (buffer, c);
+ c = skip_escaped_newlines (pfile, c);
}
while (is_idchar (c));
/* Potential escaped newline? */
if (c != '?' && c != '\\')
break;
- c = skip_escaped_newlines (buffer, c);
+ c = skip_escaped_newlines (pfile, c);
}
while (is_numchar (c) || c == '.' || VALID_SIGN (c, dest[-1]));
cpp_pool *pool = &pfile->ident_pool;
unsigned char *dest, *limit;
cppchar_t c;
- unsigned int nulls = 0;
+ bool warned_nulls = false, warned_multi = false;
dest = POOL_FRONT (pool);
limit = POOL_LIMIT (pool);
/* Handle trigraphs, escaped newlines etc. */
if (c == '?' || c == '\\')
- c = skip_escaped_newlines (buffer, c);
+ c = skip_escaped_newlines (pfile, c);
if (c == terminator && unescaped_terminator_p (pfile, dest))
{
break;
}
- cpp_pedwarn (pfile, "multi-line string literals are deprecated");
+ if (!warned_multi)
+ {
+ warned_multi = true;
+ cpp_pedwarn (pfile, "multi-line string literals are deprecated");
+ }
+
if (pfile->mlstring_pos.line == 0)
pfile->mlstring_pos = pfile->lexer_pos;
*dest++ = '\n';
goto have_char;
}
- else if (c == '\0')
+ else if (c == '\0' && !warned_nulls)
{
- if (nulls++ == 0)
- cpp_warning (pfile, "null character(s) preserved in literal");
+ warned_nulls = true;
+ cpp_warning (pfile, "null character(s) preserved in literal");
}
*dest++ = c;
/* Subroutine of lex_token to handle '%'. A little tricky, since we
want to avoid stepping back when lexing %:%X. */
static void
-lex_percent (buffer, result)
- cpp_buffer *buffer;
+lex_percent (pfile, result)
+ cpp_reader *pfile;
cpp_token *result;
{
+ cpp_buffer *buffer= pfile->buffer;
cppchar_t c;
result->type = CPP_MOD;
/* Parsing %:%X could leave an extra character. */
if (buffer->extra_char == EOF)
- c = get_effective_char (buffer);
+ c = get_effective_char (pfile);
else
{
c = buffer->read_ahead = buffer->extra_char;
if (c == '=')
ACCEPT_CHAR (CPP_MOD_EQ);
- else if (CPP_OPTION (buffer->pfile, digraphs))
+ else if (CPP_OPTION (pfile, digraphs))
{
if (c == ':')
{
result->flags |= DIGRAPH;
ACCEPT_CHAR (CPP_HASH);
- if (get_effective_char (buffer) == '%')
+ if (get_effective_char (pfile) == '%')
{
- buffer->extra_char = get_effective_char (buffer);
+ buffer->extra_char = get_effective_char (pfile);
if (buffer->extra_char == ':')
{
buffer->extra_char = EOF;
/* Parsing ..X could leave an extra character. */
if (buffer->extra_char == EOF)
- c = get_effective_char (buffer);
+ c = get_effective_char (pfile);
else
{
c = buffer->read_ahead = buffer->extra_char;
result->type = CPP_DOT;
if (c == '.')
{
- buffer->extra_char = get_effective_char (buffer);
+ buffer->extra_char = get_effective_char (pfile);
if (buffer->extra_char == '.')
{
buffer->extra_char = EOF;
cppchar_t c;
cpp_buffer *buffer;
const unsigned char *comment_start;
- unsigned char bol;
+ int bol;
- skip:
- bol = pfile->state.next_bol;
- done_directive:
+ next_token:
buffer = pfile->buffer;
- pfile->state.next_bol = 0;
result->flags = buffer->saved_flags;
buffer->saved_flags = 0;
+ bol = (buffer->cur <= buffer->line_base + 1
+ && pfile->lexer_pos.output_line == pfile->line);
next_char:
- pfile->lexer_pos.line = buffer->lineno;
+ pfile->lexer_pos.line = pfile->line;
result->line = pfile->line;
next_char2:
pfile->lexer_pos.col = CPP_BUF_COLUMN (buffer, buffer->cur);
switch (c)
{
case EOF:
- /* Non-empty files should end in a newline. Checking "bol" too
- prevents multiple warnings when hitting the EOF more than
- once, like in a directive. Don't warn for command line and
- _Pragma buffers. */
- if (pfile->lexer_pos.col != 0 && !bol && !buffer->from_stage3)
- cpp_pedwarn (pfile, "no newline at end of file");
- pfile->state.next_bol = 1;
- pfile->state.skipping = 0; /* In case missing #endif. */
+ /* Non-empty files should end in a newline. Don't warn for
+ command line and _Pragma buffers. */
+ if (pfile->lexer_pos.col != 0)
+ {
+ /* Account for the missing \n, prevent multiple warnings. */
+ pfile->line++;
+ pfile->lexer_pos.col = 0;
+ if (!buffer->from_stage3)
+ cpp_pedwarn (pfile, "no newline at end of file");
+ }
+
+ /* To prevent bogus diagnostics, only pop the buffer when
+ in-progress directives and arguments have been taken care of.
+ Decrement the line to terminate an in-progress directive. */
+ if (pfile->state.in_directive)
+ pfile->lexer_pos.output_line = pfile->line--;
+ else if (! pfile->state.parsing_args)
+ {
+ /* Don't pop the last buffer. */
+ if (buffer->prev)
+ {
+ unsigned char stop = buffer->return_at_eof;
+
+ _cpp_pop_buffer (pfile);
+ if (!stop)
+ goto next_token;
+ }
+ }
result->type = CPP_EOF;
- /* Don't do MI optimisation. */
return;
case ' ': case '\t': case '\f': case '\v': case '\0':
goto next_char2;
case '\n': case '\r':
- if (!pfile->state.in_directive)
+ if (pfile->state.in_directive)
{
- handle_newline (pfile, c);
- if (!pfile->state.parsing_args)
- pfile->pseudo_newlines = 0;
- bol = 1;
- pfile->lexer_pos.output_line = buffer->lineno;
- /* 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;
+ result->type = CPP_EOF;
+ if (pfile->state.parsing_args)
+ buffer->read_ahead = c;
+ else
+ {
+ handle_newline (pfile, c);
+ /* Decrementing pfile->line allows directives to
+ recognise that the newline has been seen, and also
+ means that diagnostics don't point to the next line. */
+ pfile->lexer_pos.output_line = pfile->line--;
+ }
+ return;
}
- /* Don't let directives spill over to the next line. */
- buffer->read_ahead = c;
- pfile->state.next_bol = 1;
- result->type = CPP_EOF;
- /* Don't break; pfile->state.skipping might be true. */
- return;
+ handle_newline (pfile, c);
+ /* 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);
+ bol = 1;
+ if (pfile->state.parsing_args != 2)
+ pfile->lexer_pos.output_line = pfile->line;
+ goto next_char;
case '?':
case '\\':
/* These could start an escaped newline, or '?' a trigraph. Let
skip_escaped_newlines do all the work. */
{
- unsigned int lineno = buffer->lineno;
+ unsigned int line = pfile->line;
- c = skip_escaped_newlines (buffer, c);
- if (lineno != buffer->lineno)
+ c = skip_escaped_newlines (pfile, c);
+ if (line != pfile->line)
/* We had at least one escaped newline of some sort, and the
next character is in buffer->read_ahead. Update the
token's line and column. */
/* A potential block or line comment. */
comment_start = buffer->cur;
result->type = CPP_DIV;
- c = get_effective_char (buffer);
+ c = get_effective_char (pfile);
if (c == '=')
ACCEPT_CHAR (CPP_DIV_EQ);
if (c != '/' && c != '*')
if (c == '*')
{
if (skip_block_comment (pfile))
- cpp_error_with_line (pfile, pfile->lexer_pos.line,
- pfile->lexer_pos.col,
- "unterminated comment");
+ cpp_error (pfile, "unterminated comment");
}
else
{
}
result->type = CPP_LESS;
- c = get_effective_char (buffer);
+ c = get_effective_char (pfile);
if (c == '=')
ACCEPT_CHAR (CPP_LESS_EQ);
else if (c == '<')
{
ACCEPT_CHAR (CPP_LSHIFT);
- if (get_effective_char (buffer) == '=')
+ if (get_effective_char (pfile) == '=')
ACCEPT_CHAR (CPP_LSHIFT_EQ);
}
else if (c == '?' && CPP_OPTION (pfile, cplusplus))
{
ACCEPT_CHAR (CPP_MIN);
- if (get_effective_char (buffer) == '=')
+ if (get_effective_char (pfile) == '=')
ACCEPT_CHAR (CPP_MIN_EQ);
}
else if (c == ':' && CPP_OPTION (pfile, digraphs))
case '>':
result->type = CPP_GREATER;
- c = get_effective_char (buffer);
+ c = get_effective_char (pfile);
if (c == '=')
ACCEPT_CHAR (CPP_GREATER_EQ);
else if (c == '>')
{
ACCEPT_CHAR (CPP_RSHIFT);
- if (get_effective_char (buffer) == '=')
+ if (get_effective_char (pfile) == '=')
ACCEPT_CHAR (CPP_RSHIFT_EQ);
}
else if (c == '?' && CPP_OPTION (pfile, cplusplus))
{
ACCEPT_CHAR (CPP_MAX);
- if (get_effective_char (buffer) == '=')
+ if (get_effective_char (pfile) == '=')
ACCEPT_CHAR (CPP_MAX_EQ);
}
break;
case '%':
- lex_percent (buffer, result);
+ lex_percent (pfile, result);
if (result->type == CPP_HASH)
goto do_hash;
break;
case '+':
result->type = CPP_PLUS;
- c = get_effective_char (buffer);
+ c = get_effective_char (pfile);
if (c == '=')
ACCEPT_CHAR (CPP_PLUS_EQ);
else if (c == '+')
case '-':
result->type = CPP_MINUS;
- c = get_effective_char (buffer);
+ c = get_effective_char (pfile);
if (c == '>')
{
ACCEPT_CHAR (CPP_DEREF);
if (CPP_OPTION (pfile, cplusplus)
- && get_effective_char (buffer) == '*')
+ && get_effective_char (pfile) == '*')
ACCEPT_CHAR (CPP_DEREF_STAR);
}
else if (c == '=')
case '*':
result->type = CPP_MULT;
- if (get_effective_char (buffer) == '=')
+ if (get_effective_char (pfile) == '=')
ACCEPT_CHAR (CPP_MULT_EQ);
break;
case '=':
result->type = CPP_EQ;
- if (get_effective_char (buffer) == '=')
+ if (get_effective_char (pfile) == '=')
ACCEPT_CHAR (CPP_EQ_EQ);
break;
case '!':
result->type = CPP_NOT;
- if (get_effective_char (buffer) == '=')
+ if (get_effective_char (pfile) == '=')
ACCEPT_CHAR (CPP_NOT_EQ);
break;
case '&':
result->type = CPP_AND;
- c = get_effective_char (buffer);
+ c = get_effective_char (pfile);
if (c == '=')
ACCEPT_CHAR (CPP_AND_EQ);
else if (c == '&')
buffer->extra_char = EOF;
}
else
- c = get_effective_char (buffer);
+ c = get_effective_char (pfile);
if (c == '#')
{
macro invocation, and proceed to process the directive. */
if (pfile->state.parsing_args)
{
+ pfile->lexer_pos.output_line = pfile->line;
if (pfile->state.parsing_args == 2)
- 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 | AVOID_LPASTE);
+ {
+ cpp_error (pfile,
+ "directives may not be used inside a macro argument");
+ result->type = CPP_EOF;
+ }
}
- else
+ /* in_directive can be true inside a _Pragma. */
+ else if (!pfile->state.in_directive)
{
- /* This is the hash introducing a directive. */
+ /* This is the hash introducing a directive. If the return
+ value is false, it is an assembler #. */
if (_cpp_handle_directive (pfile, result->flags & PREV_WHITE))
- goto done_directive; /* bol still 1. */
- /* This is in fact an assembler #. */
+ goto next_token;
}
break;
case '|':
result->type = CPP_OR;
- c = get_effective_char (buffer);
+ c = get_effective_char (pfile);
if (c == '=')
ACCEPT_CHAR (CPP_OR_EQ);
else if (c == '|')
case '^':
result->type = CPP_XOR;
- if (get_effective_char (buffer) == '=')
+ if (get_effective_char (pfile) == '=')
ACCEPT_CHAR (CPP_XOR_EQ);
break;
case ':':
result->type = CPP_COLON;
- c = get_effective_char (buffer);
+ c = get_effective_char (pfile);
if (c == ':' && CPP_OPTION (pfile, cplusplus))
ACCEPT_CHAR (CPP_SCOPE);
else if (c == '>' && CPP_OPTION (pfile, digraphs))
}
if (!pfile->state.in_directive && pfile->state.skipping)
- goto skip;
+ goto next_char;
/* If not in a directive, this token invalidates controlling macros. */
if (!pfile->state.in_directive)
if (align & (align - 1))
abort ();
pool->align = align;
- pool->cur = new_chunk (size);
+ pool->first = new_chunk (size);
+ pool->cur = pool->first;
pool->locked = 0;
pool->locks = 0;
if (temp)
_cpp_free_pool (pool)
cpp_pool *pool;
{
- cpp_chunk *chunk = pool->cur, *next;
+ cpp_chunk *chunk = pool->first, *next;
do
{
free (chunk->base);
chunk = next;
}
- while (chunk && chunk != pool->cur);
+ while (chunk && chunk != pool->first);
}
/* Reserve LEN bytes from a memory pool. */