Commit 3fdc651f by Zack Weinberg Committed by Dave Brolley

cppfiles.c (read_and_prescan): Map backslash-newline to '\r' (which cannot…

cppfiles.c (read_and_prescan): Map backslash-newline to '\r' (which cannot otherwise appear in the processed...

1999-03-16 16:06 -0500  Zack Weinberg  <zack@rabi.columbia.edu>
	* cppfiles.c (read_and_prescan): Map backslash-newline to '\r'
	(which cannot otherwise appear in the processed buffer) and
	move it out of tokens that it appears in the middle of.
	Improve performance.
	(find_position): New function.
	* cpplib.c: \r (one character) indicates backslash
	newline, not \\\n (two characters).  It cannot appear in the
	middle of a token.  Call CPP_BUMP_LINE (pfile) whenever
	parsing moves past \n or \r.  Increment pfile->lineno whenever
	a \n is placed into token_buffer.  Only one mark can exist at
	a time, and CPP_BUMP_LINE must not be used while it is
	active.  It is automatically cleared by cpp_pop_buffer and
	parse_goto_mark.  \r is not in is_hor_space or is_space.
	(NEWLINE_FIX, NEWLINE_FIX1, adjust_position,
	update_position, count_newlines, parse_move_mark): Removed.
	(parse_string, copy_comment): New functions.
	(parse_name): Returns void.
	(parse_set_mark, parse_clear_mark, parse_goto_mark): Take only
	one argument, a cpp_reader *.  Change for new marking scheme.
	(skip_comment): Handle CHILL line comments too.  Second
	argument is now first character of comment marker; all callers
	changed.  Issue error for unterminated block comment here.
	(cpp_skip_hspace): Recognize CHILL comments.
	(copy_rest_of_line): Likewise.  Call skip_comment and
	parse_string directly, don't go through cpp_get_token.  Emit
	"/**/" for block comments if -traditional (create_definition
	needs this).
	(do_define): Don't play with put_out_comments.
	(cpp_push_buffer): Initialize ->mark to -1.
	(cpp_buf_line_and_col): Just read out the values in the buffer
	structure.
	(output_line_command): Use cpp_buf_line_and_col.  Fix
	formatting.  Remove stale code.
	(cpp_get_token): Break out string parsing code to
	parse_string.  Use skip_comment for CHILL comments too.  Use
	copy_comment for put_out_comments instead of dinking with
	marks.  Remove stale code.  Don't call output_line_command
	unless it's necessary.
	* cpplib.h (parse_marker): Removed.
	(struct cpp_buffer): line_base is now a unsigned char *; add
	`mark' [long], remove `marks' [struct parse_marker *].
	(parse_set_mark, parse_clear_mark, parse_goto_mark): Update
	prototypes.
	(CPP_BUMP_LINE, CPP_BUMP_BUFFER_LINE): New macros.
	* cppinit.c (is_hor_space, is_space): '\r' is not considered
	whitespace.
	* cppexp.c (cpp_parse_expression): Use cpp_skip_hspace, not
	SKIP_WHITE_SPACE.
	* cpphash.c (macarg): Disable line commands while expanding.

From-SVN: r25802
parent d888cbc4
1999-03-16 16:06 -0500 Zack Weinberg <zack@rabi.columbia.edu>
* cppfiles.c (read_and_prescan): Map backslash-newline to '\r'
(which cannot otherwise appear in the processed buffer) and
move it out of tokens that it appears in the middle of.
Improve performance.
(find_position): New function.
* cpplib.c: \r (one character) indicates backslash
newline, not \\\n (two characters). It cannot appear in the
middle of a token. Call CPP_BUMP_LINE (pfile) whenever
parsing moves past \n or \r. Increment pfile->lineno whenever
a \n is placed into token_buffer. Only one mark can exist at
a time, and CPP_BUMP_LINE must not be used while it is
active. It is automatically cleared by cpp_pop_buffer and
parse_goto_mark. \r is not in is_hor_space or is_space.
(NEWLINE_FIX, NEWLINE_FIX1, adjust_position,
update_position, count_newlines, parse_move_mark): Removed.
(parse_string, copy_comment): New functions.
(parse_name): Returns void.
(parse_set_mark, parse_clear_mark, parse_goto_mark): Take only
one argument, a cpp_reader *. Change for new marking scheme.
(skip_comment): Handle CHILL line comments too. Second
argument is now first character of comment marker; all callers
changed. Issue error for unterminated block comment here.
(cpp_skip_hspace): Recognize CHILL comments.
(copy_rest_of_line): Likewise. Call skip_comment and
parse_string directly, don't go through cpp_get_token. Emit
"/**/" for block comments if -traditional (create_definition
needs this).
(do_define): Don't play with put_out_comments.
(cpp_push_buffer): Initialize ->mark to -1.
(cpp_buf_line_and_col): Just read out the values in the buffer
structure.
(output_line_command): Use cpp_buf_line_and_col. Fix
formatting. Remove stale code.
(cpp_get_token): Break out string parsing code to
parse_string. Use skip_comment for CHILL comments too. Use
copy_comment for put_out_comments instead of dinking with
marks. Remove stale code. Don't call output_line_command
unless it's necessary.
* cpplib.h (parse_marker): Removed.
(struct cpp_buffer): line_base is now a unsigned char *; add
`mark' [long], remove `marks' [struct parse_marker *].
(parse_set_mark, parse_clear_mark, parse_goto_mark): Update
prototypes.
(CPP_BUMP_LINE, CPP_BUMP_BUFFER_LINE): New macros.
* cppinit.c (is_hor_space, is_space): '\r' is not considered
whitespace.
* cppexp.c (cpp_parse_expression): Use cpp_skip_hspace, not
SKIP_WHITE_SPACE.
* cpphash.c (macarg): Disable line commands while expanding.
Tue Mar 16 11:30:19 1999 Gavin Romig-Koch <gavin@cygnus.com> Tue Mar 16 11:30:19 1999 Gavin Romig-Koch <gavin@cygnus.com>
* c-lex.c (yylex) : Remove warning for integer literals being * c-lex.c (yylex) : Remove warning for integer literals being
......
...@@ -101,8 +101,6 @@ static HOST_WIDEST_INT right_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT, int, ...@@ -101,8 +101,6 @@ static HOST_WIDEST_INT right_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT, int,
#define SKIP_OPERAND 8 #define SKIP_OPERAND 8
/*#define UNSIGNEDP 16*/ /*#define UNSIGNEDP 16*/
#define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
struct operation { struct operation {
short op; short op;
char rprio; /* Priority of op (relative to it right operand). */ char rprio; /* Priority of op (relative to it right operand). */
...@@ -444,12 +442,12 @@ cpp_lex (pfile, skip_evaluation) ...@@ -444,12 +442,12 @@ cpp_lex (pfile, skip_evaluation)
cpp_buffer *ip = CPP_BUFFER (pfile); cpp_buffer *ip = CPP_BUFFER (pfile);
U_CHAR *tok; U_CHAR *tok;
SKIP_WHITE_SPACE (ip->cur); cpp_skip_hspace (pfile);
if (*ip->cur == '(') if (*ip->cur == '(')
{ {
paren++; paren++;
ip->cur++; /* Skip over the paren */ ip->cur++; /* Skip over the paren */
SKIP_WHITE_SPACE (ip->cur); cpp_skip_hspace (pfile);
} }
if (!is_idstart[*ip->cur]) if (!is_idstart[*ip->cur])
...@@ -460,7 +458,7 @@ cpp_lex (pfile, skip_evaluation) ...@@ -460,7 +458,7 @@ cpp_lex (pfile, skip_evaluation)
while (is_idchar[*ip->cur]) while (is_idchar[*ip->cur])
++ip->cur; ++ip->cur;
len = ip->cur - tok; len = ip->cur - tok;
SKIP_WHITE_SPACE (ip->cur); cpp_skip_hspace (pfile);
if (paren) if (paren)
{ {
if (*ip->cur != ')') if (*ip->cur != ')')
......
...@@ -757,15 +757,51 @@ actual_directory (pfile, fname) ...@@ -757,15 +757,51 @@ actual_directory (pfile, fname)
return x; return x;
} }
/* Read the entire contents of file DESC into buffer BUF, convert end-of-line /* Almost but not quite the same as adjust_position in cpplib.c.
markers to canonical form, and convert trigraphs if enabled. Also, make Used only by read_and_prescan. */
sure there is a newline at the end of the file. LEN is how much room we static void
have to start with (this can be expanded if necessary). find_position (start, limit, linep, colp)
Returns -1 on failure, or the actual length of the data to be scanned. U_CHAR *start;
U_CHAR *limit;
long *linep;
long *colp;
{
long line = *linep, col = 0;
while (start < limit)
{
U_CHAR ch = *start++;
if (ch == '\n' || ch == '\r')
line++, col = 1;
else
col++;
}
*linep = line, *colp = col;
}
N.B. This function has been rearranged to out-of-line the uncommon cases /* Read the entire contents of file DESC into buffer BUF. LEN is how
as much as possible; this is important to prevent it from being a much memory to allocate initially; more will be allocated if
performance bottleneck. */ necessary. Convert end-of-line markers (\n, \r, \r\n, \n\r) to
canonical form (\n). If enabled, convert and/or warn about
trigraphs. Convert backslash-newline to a one-character escape
(\r) and remove it from "embarrassing" places (i.e. the middle of a
token). If there is no newline at the end of the file, add one and
warn. Returns -1 on failure, or the actual length of the data to
be scanned.
This function does a lot of work, and can be a serious performance
bottleneck. It has been tuned heavily; make sure you understand it
before hacking. The common case - no trigraphs, Unix style line
breaks, backslash-newline set off by whitespace, newline at EOF -
has been optimized at the expense of the others. The performance
penalty for DOS style line breaks (\r\n) is about 15%.
Warnings lose particularly heavily since we have to determine the
line number, which involves scanning from the beginning of the file
or from the last warning. The penalty for the absence of a newline
at the end of reload1.c is about 60%. (reload1.c is 329k.)
If your file has more than one kind of end-of-line marker, you
will get messed-up line numbering. */
static long static long
read_and_prescan (pfile, fp, desc, len) read_and_prescan (pfile, fp, desc, len)
...@@ -774,29 +810,47 @@ read_and_prescan (pfile, fp, desc, len) ...@@ -774,29 +810,47 @@ read_and_prescan (pfile, fp, desc, len)
int desc; int desc;
size_t len; size_t len;
{ {
U_CHAR *buf = (U_CHAR *) xmalloc (len); U_CHAR *buf = xmalloc (len);
U_CHAR *ip, *op, *line_base; U_CHAR *ip, *op, *line_base;
U_CHAR *ibase; U_CHAR *ibase;
unsigned int line; unsigned int line, deferred_newlines;
int count; int count;
size_t offset; size_t offset;
/* 4096 bytes of buffer proper, 2 to detect running off the end without /* PIPE_BUF bytes of buffer proper, 2 to detect running off the end
address arithmetic all the time, and 2 for pushback in the case there's without address arithmetic all the time, and 2 for pushback in
a potential trigraph or end-of-line digraph at the end of a block. */ the case there's a potential trigraph or end-of-line digraph at
#define INTERMED_BUFFER_SIZE 4096 the end of a block. */
U_CHAR intermed[INTERMED_BUFFER_SIZE + 2 + 2]; U_CHAR intermed[PIPE_BUF + 2 + 2];
/* Table of characters that can't be handled in the inner loop.
Keep these contiguous to optimize the performance of the code generated
for the switch that uses them. */
#define SPECCASE_EMPTY 0
#define SPECCASE_NUL 1
#define SPECCASE_CR 2
#define SPECCASE_BACKSLASH 3
#define SPECCASE_QUESTION 4
U_CHAR speccase[256];
offset = 0; offset = 0;
op = buf; op = buf;
line_base = buf; line_base = buf;
line = 1; line = 1;
ibase = intermed + 2; ibase = intermed + 2;
deferred_newlines = 0;
memset (speccase, SPECCASE_EMPTY, sizeof (speccase));
speccase['\0'] = SPECCASE_NUL;
speccase['\r'] = SPECCASE_CR;
speccase['\\'] = SPECCASE_BACKSLASH;
if (CPP_OPTIONS (pfile)->trigraphs || CPP_OPTIONS (pfile)->warn_trigraphs)
speccase['?'] = SPECCASE_QUESTION;
for (;;) for (;;)
{ {
read_next: read_next:
count = read (desc, intermed + 2, INTERMED_BUFFER_SIZE); count = read (desc, intermed + 2, PIPE_BUF);
if (count < 0) if (count < 0)
goto error; goto error;
else if (count == 0) else if (count == 0)
...@@ -827,48 +881,102 @@ read_and_prescan (pfile, fp, desc, len) ...@@ -827,48 +881,102 @@ read_and_prescan (pfile, fp, desc, len)
for (;;) for (;;)
{ {
unsigned int c; unsigned int span = 0;
c = *ip++;
switch (c) /* Deal with \-newline in the middle of a token. */
if (deferred_newlines)
{ {
/* The default case is at the top so gcc will realize while (speccase[ip[span]] == SPECCASE_EMPTY
it's the common case, and leave c in a register. && ip[span] != '\n'
Also, cache utilization is a little better this way. */ && ip[span] != '\t'
default: && ip[span] != ' ')
*op++ = c; span++;
break; memcpy (op, ip, span);
op += span;
ip += span;
if (*ip == '\n' || *ip == '\t'
|| *ip == ' ' || *ip == ' ')
while (deferred_newlines)
deferred_newlines--, *op++ = '\r';
span = 0;
}
/* Copy as much as we can without special treatment. */
while (speccase[ip[span]] == SPECCASE_EMPTY) span++;
memcpy (op, ip, span);
op += span;
ip += span;
case '\0': switch (speccase[*ip++])
{
case SPECCASE_NUL: /* \0 */
ibase[-1] = op[-1];
goto read_next; goto read_next;
case '\r':
if (*ip == '\n') ip++; case SPECCASE_CR: /* \r */
if (*ip == '\n')
ip++;
else if (*ip == '\0') else if (*ip == '\0')
{ {
--ibase; --ibase;
intermed[1] = '\r'; intermed[1] = '\r';
goto read_next; goto read_next;
} }
else if (ip[-2] == '\n')
continue;
*op++ = '\n'; *op++ = '\n';
line++;
line_base = op;
break; break;
case '\n': case SPECCASE_BACKSLASH: /* \ */
backslash:
{
/* If we're at the end of the intermediate buffer,
we have to shift the backslash down to the start
and come back next pass. */
if (*ip == '\0')
{
--ibase;
intermed[1] = '\\';
goto read_next;
}
else if (*ip == '\n')
{
ip++;
if (*ip == '\r') ip++; if (*ip == '\r') ip++;
if (*ip == '\n' || *ip == '\t' || *ip == ' ')
*op++ = '\r';
else if (op[-1] == '\t' || op[-1] == ' '
|| op[-1] == '\r' || op[-1] == '\n')
*op++ = '\r';
else
deferred_newlines++;
line++;
line_base = op;
}
else if (*ip == '\r')
{
ip++;
if (*ip == '\n') ip++;
else if (*ip == '\0') else if (*ip == '\0')
{ {
--ibase; ibase -= 2;
intermed[1] = '\n'; intermed[0] = '\\';
intermed[1] = '\r';
goto read_next; goto read_next;
} }
*op++ = '\n'; else if (*ip == '\r' || *ip == '\t' || *ip == ' ')
*op++ = '\r';
else
deferred_newlines++;
line++; line++;
line_base = op; line_base = op;
}
else
*op++ = '\\';
}
break; break;
case '?': case SPECCASE_QUESTION: /* ? */
if (CPP_OPTIONS (pfile)->trigraphs
|| CPP_OPTIONS (pfile)->warn_trigraphs)
{ {
unsigned int d; unsigned int d;
/* If we're at the end of the intermediate buffer, /* If we're at the end of the intermediate buffer,
...@@ -900,10 +1008,20 @@ read_and_prescan (pfile, fp, desc, len) ...@@ -900,10 +1008,20 @@ read_and_prescan (pfile, fp, desc, len)
} }
if (CPP_OPTIONS (pfile)->warn_trigraphs) if (CPP_OPTIONS (pfile)->warn_trigraphs)
cpp_warning_with_line (pfile, line, op-line_base, {
long col;
find_position (line_base, op, &line, &col);
line_base = op - col;
cpp_warning_with_line (pfile, line, col,
"trigraph ??%c encountered", d); "trigraph ??%c encountered", d);
}
if (CPP_OPTIONS (pfile)->trigraphs) if (CPP_OPTIONS (pfile)->trigraphs)
{
if (trigraph_table[d] == '\\')
goto backslash;
else
*op++ = trigraph_table[d]; *op++ = trigraph_table[d];
}
else else
{ {
*op++ = '?'; *op++ = '?';
...@@ -912,8 +1030,6 @@ read_and_prescan (pfile, fp, desc, len) ...@@ -912,8 +1030,6 @@ read_and_prescan (pfile, fp, desc, len)
} }
ip += 2; ip += 2;
} }
else
*op++ = c;
} }
} }
} }
...@@ -922,47 +1038,48 @@ read_and_prescan (pfile, fp, desc, len) ...@@ -922,47 +1038,48 @@ read_and_prescan (pfile, fp, desc, len)
return 0; return 0;
/* Deal with pushed-back chars at true EOF. /* Deal with pushed-back chars at true EOF.
If two chars were pushed back, they must both be ?'s. This may be any of: ?? ? \ \r \n \\r \\n.
If one was, it might be ?, \r, or \n, and \r needs to \r must become \n, \\r or \\n must become \r.
become \n.
We know we have space already. */ We know we have space already. */
if (ibase == intermed) if (ibase == intermed)
{ {
if (*ibase == '?')
{
*op++ = '?'; *op++ = '?';
*op++ = '?'; *op++ = '?';
} }
else
*op++ = '\r';
}
else if (ibase == intermed + 1) else if (ibase == intermed + 1)
{ {
if (*ibase == '?') if (*ibase == '\r')
*op++ = '?';
else
*op++ = '\n'; *op++ = '\n';
else
*op++ = *ibase;
} }
if (op[-1] != '\n' || op[-2] == '\\') if (op[-1] != '\n')
{ {
if (CPP_PEDANTIC (pfile)) long col;
cpp_pedwarn_with_line (pfile, line, op - line_base, find_position (line_base, op, &line, &col);
"no newline at end of file"); cpp_warning_with_line (pfile, line, col, "no newline at end of file\n");
if (offset + 2 > len) if (offset + 1 > len)
{ {
len += 2; len += 1;
if (offset + 2 > len) if (offset + 1 > len)
goto too_big; goto too_big;
buf = (U_CHAR *) xrealloc (buf, len); buf = (U_CHAR *) xrealloc (buf, len);
op = buf + offset; op = buf + offset;
} }
if (op[-1] == '\\')
*op++ = '\n';
*op++ = '\n'; *op++ = '\n';
} }
fp->buf = fp->buf = ((len - offset < 20) ? buf : (U_CHAR *)xrealloc (buf, op - buf));
(U_CHAR *) ((len - offset < 20) ? (PTR) buf : xrealloc (buf, op - buf));
return op - buf; return op - buf;
too_big: too_big:
cpp_error (pfile, "file is too large"); cpp_error (pfile, "file is too large (>%lu bytes)\n", (unsigned long)offset);
free (buf); free (buf);
return -1; return -1;
......
...@@ -787,6 +787,7 @@ macarg (pfile, rest_args) ...@@ -787,6 +787,7 @@ macarg (pfile, rest_args)
/* Try to parse as much of the argument as exists at this /* Try to parse as much of the argument as exists at this
input stack level. */ input stack level. */
pfile->no_macro_expand++; pfile->no_macro_expand++;
CPP_OPTIONS (pfile)->no_line_commands++;
for (;;) for (;;)
{ {
token = cpp_get_token (pfile); token = cpp_get_token (pfile);
...@@ -824,6 +825,7 @@ macarg (pfile, rest_args) ...@@ -824,6 +825,7 @@ macarg (pfile, rest_args)
done: done:
CPP_OPTIONS (pfile)->put_out_comments = save_put_out_comments; CPP_OPTIONS (pfile)->put_out_comments = save_put_out_comments;
CPP_OPTIONS (pfile)->no_line_commands--;
pfile->no_macro_expand--; pfile->no_macro_expand--;
return token; return token;
......
...@@ -255,15 +255,16 @@ U_CHAR is_idstart[256] = ...@@ -255,15 +255,16 @@ U_CHAR is_idstart[256] =
['_'] = 1, ['_'] = 1,
}; };
/* Table to tell if a character is horizontal space. */ /* Table to tell if a character is horizontal space.
\r is magical, so it is not in here. */
U_CHAR is_hor_space[256] = U_CHAR is_hor_space[256] =
{ {
[' '] = 1, ['\t'] = 1, ['\v'] = 1, ['\f'] = 1, ['\r'] = 1 [' '] = 1, ['\t'] = 1, ['\v'] = 1, ['\f'] = 1,
}; };
/* table to tell if a character is horizontal or vertical space. */ /* table to tell if a character is horizontal or vertical space. */
U_CHAR is_space[256] = U_CHAR is_space[256] =
{ {
[' '] = 1, ['\t'] = 1, ['\v'] = 1, ['\f'] = 1, ['\r'] = 1, ['\n'] = 1, [' '] = 1, ['\t'] = 1, ['\v'] = 1, ['\f'] = 1, ['\n'] = 1,
}; };
/* Table to handle trigraph conversion, which occurs before all other /* Table to handle trigraph conversion, which occurs before all other
processing, everywhere in the file. (This is necessary since one processing, everywhere in the file. (This is necessary since one
...@@ -362,14 +363,12 @@ initialize_char_syntax (dollar_in_ident) ...@@ -362,14 +363,12 @@ initialize_char_syntax (dollar_in_ident)
is_hor_space['\t'] = 1; is_hor_space['\t'] = 1;
is_hor_space['\v'] = 1; is_hor_space['\v'] = 1;
is_hor_space['\f'] = 1; is_hor_space['\f'] = 1;
is_hor_space['\r'] = 1;
is_space[' '] = 1; is_space[' '] = 1;
is_space['\t'] = 1; is_space['\t'] = 1;
is_space['\v'] = 1; is_space['\v'] = 1;
is_space['\f'] = 1; is_space['\f'] = 1;
is_space['\n'] = 1; is_space['\n'] = 1;
is_space['\r'] = 1;
/* trigraph conversion */ /* trigraph conversion */
trigraph_table['='] = '#'; trigraph_table[')'] = ']'; trigraph_table['='] = '#'; trigraph_table[')'] = ']';
......
...@@ -36,21 +36,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ ...@@ -36,21 +36,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
(Note that it is false while we're expanding macro *arguments*.) */ (Note that it is false while we're expanding macro *arguments*.) */
#define CPP_IS_MACRO_BUFFER(PBUF) ((PBUF)->data != NULL) #define CPP_IS_MACRO_BUFFER(PBUF) ((PBUF)->data != NULL)
/* Move all backslash-newline pairs out of embarrassing places.
Exchange all such pairs following BP
with any potentially-embarrassing characters that follow them.
Potentially-embarrassing characters are / and *
(because a backslash-newline inside a comment delimiter
would cause it not to be recognized). */
#define NEWLINE_FIX \
do {while (PEEKC() == '\\' && PEEKN(1) == '\n') FORWARD(2); } while(0)
/* Same, but assume we've already read the potential '\\' into C. */
#define NEWLINE_FIX1(C) do { \
while ((C) == '\\' && PEEKC() == '\n') { FORWARD(1); (C) = GETC(); }\
} while(0)
/* Forward declarations. */ /* Forward declarations. */
static char *my_strerror PROTO ((int)); static char *my_strerror PROTO ((int));
...@@ -60,7 +45,10 @@ static HOST_WIDEST_INT eval_if_expression PROTO ((cpp_reader *)); ...@@ -60,7 +45,10 @@ static HOST_WIDEST_INT eval_if_expression PROTO ((cpp_reader *));
static void conditional_skip PROTO ((cpp_reader *, int, static void conditional_skip PROTO ((cpp_reader *, int,
enum node_type, U_CHAR *)); enum node_type, U_CHAR *));
static void skip_if_group PROTO ((cpp_reader *)); static void skip_if_group PROTO ((cpp_reader *));
static int parse_name PARAMS ((cpp_reader *, int));
static void parse_name PARAMS ((cpp_reader *, int));
static void parse_string PARAMS ((cpp_reader *, int));
static int parse_assertion PARAMS ((cpp_reader *));
/* External declarations. */ /* External declarations. */
...@@ -245,106 +233,188 @@ null_cleanup (pbuf, pfile) ...@@ -245,106 +233,188 @@ null_cleanup (pbuf, pfile)
return 0; return 0;
} }
/* Assuming we have read '/'. /* Skip a comment - C, C++, or Chill style. M is the first character
If this is the start of a comment (followed by '*' or '/'), of the comment marker. If this really is a comment, skip to its
skip to the end of the comment, and return ' '. end and return ' '. If we hit end-of-file before end-of-comment,
Return EOF if we reached the end of file before the end of the comment. return EOF. If this is not a comment, return M (which will be
If not the start of a comment, return '/'. */ '/' or '-'). */
static int static int
skip_comment (pfile, linep) skip_comment (pfile, m)
cpp_reader *pfile; cpp_reader *pfile;
long *linep; int m;
{ {
int c = 0; if (m == '/' && PEEKC() == '*')
while (PEEKC() == '\\' && PEEKN(1) == '\n')
{
if (linep)
(*linep)++;
FORWARD(2);
}
if (PEEKC() == '*')
{ {
int c, prev_c = -1;
long line, col;
FORWARD(1); FORWARD(1);
cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
for (;;) for (;;)
{ {
int prev_c = c;
c = GETC (); c = GETC ();
if (c == EOF) if (c == EOF)
return EOF;
while (c == '\\' && PEEKC() == '\n')
{ {
if (linep) cpp_error_with_line (pfile, line, col, "unterminated comment");
(*linep)++; return EOF;
FORWARD(1), c = GETC();
} }
if (prev_c == '*' && c == '/') else if (c == '\n' || c == '\r')
CPP_BUMP_LINE (pfile);
else if (c == '/' && prev_c == '*')
return ' '; return ' ';
if (c == '\n' && linep) else if (c == '*' && prev_c == '/'
(*linep)++; && CPP_OPTIONS (pfile)->warn_comments)
cpp_warning (pfile, "`/*' within comment");
prev_c = c;
} }
} }
else if (PEEKC() == '/' && CPP_OPTIONS (pfile)->cplusplus_comments) else if ((m == '/' && PEEKC() == '/'
&& CPP_OPTIONS (pfile)->cplusplus_comments)
|| (m == '-' && PEEKC() == '-'
&& CPP_OPTIONS (pfile)->chill))
{ {
FORWARD(1); FORWARD(1);
for (;;) for (;;)
{ {
c = GETC (); int c = GETC ();
if (c == EOF) if (c == EOF)
return ' '; /* Allow // to be terminated by EOF. */ return ' '; /* Allow // to be terminated by EOF. */
while (c == '\\' && PEEKC() == '\n') if (c == '\n')
{
/* Don't consider final '\n' to be part of comment. */
FORWARD(-1);
return ' ';
}
else if (c == '\r')
CPP_BUMP_LINE (pfile);
}
}
else
return m;
}
/* Identical to skip_comment except that it copies the comment into the
token_buffer. This is used if put_out_comments. */
static int
copy_comment (pfile, m)
cpp_reader *pfile;
int m;
{
if (m == '/' && PEEKC() == '*')
{ {
int c, prev_c = -1;
long line, col;
CPP_PUTC (pfile, '/');
CPP_PUTC (pfile, '*');
FORWARD(1); FORWARD(1);
c = GETC(); cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
if (linep) for (;;)
(*linep)++; {
c = GETC ();
if (c == EOF)
{
cpp_error_with_line (pfile, line, col, "unterminated comment");
/* We must pretend this was a legitimate comment, so that the
output in token_buffer is not passed back tagged CPP_POP. */
return ' ';
} }
else if (c == '\r')
{
CPP_BUMP_LINE (pfile);
continue;
}
CPP_PUTC (pfile, c);
if (c == '\n') if (c == '\n')
{ {
pfile->lineno++;
CPP_BUMP_LINE (pfile);
}
else if (c == '/' && prev_c == '*')
return ' ';
else if (c == '*' && prev_c == '/'
&& CPP_OPTIONS (pfile)->warn_comments)
cpp_warning (pfile, "`/*' within comment");
prev_c = c;
}
}
else if ((m == '/' && PEEKC() == '/'
&& CPP_OPTIONS (pfile)->cplusplus_comments)
|| (m == '-' && PEEKC() == '-'
&& CPP_OPTIONS (pfile)->chill))
{
CPP_PUTC (pfile, m);
CPP_PUTC (pfile, m);
FORWARD(1);
for (;;)
{
int c = GETC ();
if (c == EOF)
return ' '; /* Allow line comments to be terminated by EOF. */
else if (c == '\n')
{
/* Don't consider final '\n' to be part of comment. */ /* Don't consider final '\n' to be part of comment. */
FORWARD(-1); FORWARD(-1);
return ' '; return ' ';
} }
else if (c == '\r')
CPP_BUMP_LINE (pfile);
CPP_PUTC (pfile, c);
} }
} }
else else
return '/'; return m;
} }
/* Skip whitespace \-newline and comments. Does not macro-expand. */ /* Skip whitespace \-newline and comments. Does not macro-expand. */
void void
cpp_skip_hspace (pfile) cpp_skip_hspace (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
int c;
while (1) while (1)
{ {
int c = PEEKC(); c = GETC();
if (c == EOF) if (c == EOF)
return; /* FIXME */ return;
if (is_hor_space[c]) else if (is_hor_space[c])
{ {
if ((c == '\f' || c == '\v') && CPP_PEDANTIC (pfile)) if ((c == '\f' || c == '\v') && CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile, "%s in preprocessing directive", cpp_pedwarn (pfile, "%s in preprocessing directive",
c == '\f' ? "formfeed" : "vertical tab"); c == '\f' ? "formfeed" : "vertical tab");
FORWARD(1);
} }
else if (c == '/') else if (c == '\r')
{
CPP_BUFFER (pfile)->lineno++;
}
else if (c == '/' || c == '-')
{
c = skip_comment (pfile, c);
if (c == EOF)
return;
else if (c != ' ')
{ {
FORWARD (1);
c = skip_comment (pfile, NULL);
if (c == '/')
FORWARD(-1); FORWARD(-1);
if (c == EOF || c == '/')
return; return;
} }
else if (c == '\\' && PEEKN(1) == '\n') {
FORWARD(2);
} }
else if (c == '@' && CPP_BUFFER (pfile)->has_escapes else if (c == '@' && CPP_BUFFER (pfile)->has_escapes
&& is_hor_space[PEEKN(1)]) && PEEKC() == ' ')
FORWARD(2); {
else return; FORWARD(1);
}
else
{
FORWARD(-1);
return;
}
} }
} }
...@@ -355,30 +425,36 @@ static void ...@@ -355,30 +425,36 @@ static void
copy_rest_of_line (pfile) copy_rest_of_line (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
struct cpp_options *opts = CPP_OPTIONS (pfile);
for (;;) for (;;)
{ {
int c = GETC(); int c = GETC();
int nextc;
switch (c) switch (c)
{ {
case '\n':
FORWARD(-1);
case EOF: case EOF:
goto end_directive; CPP_NUL_TERMINATE (pfile);
case '\\': return;
if (PEEKC() == '\n')
{ case '\r':
FORWARD (1); CPP_BUFFER (pfile)->lineno++;
continue; continue;
}
case '\'': case '\'':
case '\"': case '\"':
goto scan_directive_token; parse_string (pfile, c);
break; continue;
case '/': case '/':
nextc = PEEKC(); if (PEEKC() == '*' && CPP_TRADITIONAL (pfile))
if (nextc == '*' || (opts->cplusplus_comments && nextc == '/')) {
goto scan_directive_token; CPP_PUTS (pfile, "/**/", 4);
skip_comment (pfile, c);
continue;
}
/* else fall through */
case '-':
c = skip_comment (pfile, c);
break; break;
case '\f': case '\f':
case '\v': case '\v':
if (CPP_PEDANTIC (pfile)) if (CPP_PEDANTIC (pfile))
...@@ -386,20 +462,15 @@ copy_rest_of_line (pfile) ...@@ -386,20 +462,15 @@ copy_rest_of_line (pfile)
c == '\f' ? "formfeed" : "vertical tab"); c == '\f' ? "formfeed" : "vertical tab");
break; break;
case '\n':
FORWARD(-1);
goto end_directive;
scan_directive_token:
FORWARD(-1);
cpp_get_token (pfile);
continue;
} }
CPP_PUTC (pfile, c); CPP_PUTC (pfile, c);
} }
end_directive: ;
CPP_NUL_TERMINATE (pfile);
} }
/* FIXME: It is almost definitely a performance win to make this do
the scan itself. >75% of calls to copy_r_o_l are from here or
skip_if_group, which means the common case is to copy stuff into the
token_buffer only to discard it. */
void void
skip_rest_of_line (pfile) skip_rest_of_line (pfile)
cpp_reader *pfile; cpp_reader *pfile;
...@@ -415,7 +486,8 @@ skip_rest_of_line (pfile) ...@@ -415,7 +486,8 @@ skip_rest_of_line (pfile)
static int static int
handle_directive (pfile) handle_directive (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ int c; {
int c;
register struct directive *kt; register struct directive *kt;
int ident_length; int ident_length;
U_CHAR *ident; U_CHAR *ident;
...@@ -590,16 +662,11 @@ do_define (pfile, keyword) ...@@ -590,16 +662,11 @@ do_define (pfile, keyword)
int hashcode; int hashcode;
MACRODEF mdef; MACRODEF mdef;
HASHNODE *hp; HASHNODE *hp;
int save_put_out_comments;
long here; long here;
U_CHAR *macro, *buf, *end; U_CHAR *macro, *buf, *end;
here = CPP_WRITTEN (pfile); here = CPP_WRITTEN (pfile);
save_put_out_comments = CPP_OPTIONS (pfile)->put_out_comments;
CPP_OPTIONS (pfile)->put_out_comments = CPP_TRADITIONAL (pfile);
copy_rest_of_line (pfile); copy_rest_of_line (pfile);
CPP_OPTIONS (pfile)->put_out_comments = save_put_out_comments;
/* Copy out the line so we can pop the token buffer. */ /* Copy out the line so we can pop the token buffer. */
buf = pfile->token_buffer + here; buf = pfile->token_buffer + here;
...@@ -696,6 +763,7 @@ cpp_push_buffer (pfile, buffer, length) ...@@ -696,6 +763,7 @@ cpp_push_buffer (pfile, buffer, length)
new->buf = new->cur = buffer; new->buf = new->cur = buffer;
new->alimit = new->rlimit = buffer + length; new->alimit = new->rlimit = buffer + length;
new->prev = buf; new->prev = buf;
new->mark = -1;
CPP_BUFFER (pfile) = new; CPP_BUFFER (pfile) = new;
return new; return new;
...@@ -781,58 +849,21 @@ cpp_expand_to_buffer (pfile, buf, length) ...@@ -781,58 +849,21 @@ cpp_expand_to_buffer (pfile, buf, length)
CPP_NUL_TERMINATE (pfile); CPP_NUL_TERMINATE (pfile);
} }
static void
adjust_position (buf, limit, linep, colp)
U_CHAR *buf;
U_CHAR *limit;
long *linep;
long *colp;
{
while (buf < limit)
{
U_CHAR ch = *buf++;
if (ch == '\n')
(*linep)++, (*colp) = 1;
else
(*colp)++;
}
}
/* Move line_base forward, updating lineno and colno. */
static void
update_position (pbuf)
register cpp_buffer *pbuf;
{
unsigned char *old_pos = pbuf->buf + pbuf->line_base;
unsigned char *new_pos = pbuf->cur;
register struct parse_marker *mark;
for (mark = pbuf->marks; mark != NULL; mark = mark->next)
{
if (pbuf->buf + mark->position < new_pos)
new_pos = pbuf->buf + mark->position;
}
pbuf->line_base += new_pos - old_pos;
adjust_position (old_pos, new_pos, &pbuf->lineno, &pbuf->colno);
}
void void
cpp_buf_line_and_col (pbuf, linep, colp) cpp_buf_line_and_col (pbuf, linep, colp)
register cpp_buffer *pbuf; register cpp_buffer *pbuf;
long *linep, *colp; long *linep, *colp;
{ {
long dummy;
if (colp == NULL)
colp = &dummy;
if (pbuf) if (pbuf)
{ {
*linep = pbuf->lineno; *linep = pbuf->lineno;
*colp = pbuf->colno; if (colp)
adjust_position (pbuf->buf + pbuf->line_base, pbuf->cur, linep, colp); *colp = pbuf->cur - pbuf->line_base;
} }
else else
{ {
*linep = 0; *linep = 0;
if (colp)
*colp = 0; *colp = 0;
} }
} }
...@@ -851,21 +882,6 @@ cpp_file_buffer (pfile) ...@@ -851,21 +882,6 @@ cpp_file_buffer (pfile)
return NULL; return NULL;
} }
static long
count_newlines (buf, limit)
register U_CHAR *buf;
register U_CHAR *limit;
{
register long count = 0;
while (buf < limit)
{
U_CHAR ch = *buf++;
if (ch == '\n')
count++;
}
return count;
}
/* /*
* write out a #line command, for instance, after an #include file. * write out a #line command, for instance, after an #include file.
* If CONDITIONAL is nonzero, we can omit the #line if it would * If CONDITIONAL is nonzero, we can omit the #line if it would
...@@ -886,28 +902,24 @@ output_line_command (pfile, conditional, file_change) ...@@ -886,28 +902,24 @@ output_line_command (pfile, conditional, file_change)
if (ip->fname == NULL) if (ip->fname == NULL)
return; return;
update_position (ip);
if (CPP_OPTIONS (pfile)->no_line_commands if (CPP_OPTIONS (pfile)->no_line_commands
|| CPP_OPTIONS (pfile)->no_output) || CPP_OPTIONS (pfile)->no_output)
return; return;
line = CPP_BUFFER (pfile)->lineno; cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
col = CPP_BUFFER (pfile)->colno;
adjust_position (CPP_LINE_BASE (ip), ip->cur, &line, &col);
if (CPP_OPTIONS (pfile)->no_line_commands)
return;
if (conditional) { if (conditional)
{
if (line == pfile->lineno) if (line == pfile->lineno)
return; return;
/* If the inherited line number is a little too small, /* If the inherited line number is a little too small,
output some newlines instead of a #line command. */ output some newlines instead of a #line command. */
if (line > pfile->lineno && line < pfile->lineno + 8) { if (line > pfile->lineno && line < pfile->lineno + 8)
{
CPP_RESERVE (pfile, 20); CPP_RESERVE (pfile, 20);
while (line > pfile->lineno) { while (line > pfile->lineno)
{
CPP_PUTC_Q (pfile, '\n'); CPP_PUTC_Q (pfile, '\n');
pfile->lineno++; pfile->lineno++;
} }
...@@ -915,41 +927,28 @@ output_line_command (pfile, conditional, file_change) ...@@ -915,41 +927,28 @@ output_line_command (pfile, conditional, file_change)
} }
} }
#if 0
/* Don't output a line number of 0 if we can help it. */
if (ip->lineno == 0 && ip->bufp - ip->buf < ip->length
&& *ip->bufp == '\n') {
ip->lineno++;
ip->bufp++;
}
#endif
CPP_RESERVE (pfile, 4 * strlen (ip->nominal_fname) + 50); CPP_RESERVE (pfile, 4 * strlen (ip->nominal_fname) + 50);
{ CPP_PUTS_Q (pfile, "# ", 2);
#ifdef OUTPUT_LINE_COMMANDS
static char sharp_line[] = "#line ";
#else
static char sharp_line[] = "# ";
#endif
CPP_PUTS_Q (pfile, sharp_line, sizeof(sharp_line)-1);
}
sprintf ((char *) CPP_PWRITTEN (pfile), "%ld ", line); sprintf ((char *) CPP_PWRITTEN (pfile), "%ld ", line);
CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile))); CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
quote_string (pfile, ip->nominal_fname); quote_string (pfile, ip->nominal_fname);
if (file_change != same_file) { if (file_change != same_file)
{
CPP_PUTC_Q (pfile, ' '); CPP_PUTC_Q (pfile, ' ');
CPP_PUTC_Q (pfile, file_change == enter_file ? '1' : '2'); CPP_PUTC_Q (pfile, file_change == enter_file ? '1' : '2');
} }
/* Tell cc1 if following text comes from a system header file. */ /* Tell cc1 if following text comes from a system header file. */
if (ip->system_header_p) { if (ip->system_header_p)
{
CPP_PUTC_Q (pfile, ' '); CPP_PUTC_Q (pfile, ' ');
CPP_PUTC_Q (pfile, '3'); CPP_PUTC_Q (pfile, '3');
} }
#ifndef NO_IMPLICIT_EXTERN_C #ifndef NO_IMPLICIT_EXTERN_C
/* Tell cc1plus if following text should be treated as C. */ /* Tell cc1plus if following text should be treated as C. */
if (ip->system_header_p == 2 && CPP_OPTIONS (pfile)->cplusplus) { if (ip->system_header_p == 2 && CPP_OPTIONS (pfile)->cplusplus)
{
CPP_PUTC_Q (pfile, ' '); CPP_PUTC_Q (pfile, ' ');
CPP_PUTC_Q (pfile, '4'); CPP_PUTC_Q (pfile, '4');
} }
...@@ -1886,6 +1885,7 @@ skip_if_group (pfile) ...@@ -1886,6 +1885,7 @@ skip_if_group (pfile)
{ {
if (CPP_OPTIONS (pfile)->output_conditionals) if (CPP_OPTIONS (pfile)->output_conditionals)
CPP_PUTC (pfile, c); CPP_PUTC (pfile, c);
CPP_BUMP_LINE (pfile);
continue; continue;
} }
else if (c == '#') else if (c == '#')
...@@ -1915,7 +1915,11 @@ skip_if_group (pfile) ...@@ -1915,7 +1915,11 @@ skip_if_group (pfile)
{ {
/* \n */ /* \n */
if (CPP_OPTIONS (pfile)->output_conditionals) if (CPP_OPTIONS (pfile)->output_conditionals)
{
CPP_PUTC (pfile, c); CPP_PUTC (pfile, c);
pfile->lineno++;
}
CPP_BUMP_LINE (pfile);
} }
} }
...@@ -1998,10 +2002,9 @@ do_endif (pfile, keyword) ...@@ -1998,10 +2002,9 @@ do_endif (pfile, keyword)
{ {
/* This #endif matched a #ifndef at the start of the file. /* This #endif matched a #ifndef at the start of the file.
See if it is at the end of the file. */ See if it is at the end of the file. */
struct parse_marker start_mark;
int c; int c;
parse_set_mark (&start_mark, pfile); parse_set_mark (pfile);
for (;;) for (;;)
{ {
...@@ -2010,8 +2013,7 @@ do_endif (pfile, keyword) ...@@ -2010,8 +2013,7 @@ do_endif (pfile, keyword)
if (c != '\n') if (c != '\n')
break; break;
} }
parse_goto_mark (&start_mark, pfile); parse_goto_mark (pfile);
parse_clear_mark (&start_mark);
if (c == EOF) if (c == EOF)
{ {
...@@ -2057,8 +2059,6 @@ cpp_get_token (pfile) ...@@ -2057,8 +2059,6 @@ cpp_get_token (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
register int c, c2, c3; register int c, c2, c3;
long old_written;
long start_line, start_column;
enum cpp_token token; enum cpp_token token;
struct cpp_options *opts = CPP_OPTIONS (pfile); struct cpp_options *opts = CPP_OPTIONS (pfile);
...@@ -2099,68 +2099,27 @@ cpp_get_token (pfile) ...@@ -2099,68 +2099,27 @@ cpp_get_token (pfile)
{ {
switch (c) switch (c)
{ {
long newlines;
struct parse_marker start_mark;
case '/': case '/':
if (PEEKC () == '=') if (PEEKC () == '=')
goto op2; goto op2;
comment:
if (opts->put_out_comments) if (opts->put_out_comments)
parse_set_mark (&start_mark, pfile); c = copy_comment (pfile, c);
newlines = 0; else
cpp_buf_line_and_col (cpp_file_buffer (pfile), c = skip_comment (pfile, c);
&start_line, &start_column);
c = skip_comment (pfile, &newlines);
if (opts->put_out_comments && (c == '/' || c == EOF))
parse_clear_mark (&start_mark);
if (c == '/')
goto randomchar;
if (c == EOF) if (c == EOF)
{
cpp_error_with_line (pfile, start_line, start_column,
"unterminated comment");
goto handle_eof; goto handle_eof;
} else if (c != ' ')
c = '/'; /* Initial letter of comment. */ goto randomchar;
return_comment:
/* Comments are equivalent to spaces. /* Comments are equivalent to spaces.
For -traditional, a comment is equivalent to nothing. */ For -traditional, a comment is equivalent to nothing. */
if (opts->put_out_comments) if (opts->traditional || opts->put_out_comments)
{
cpp_buffer *pbuf = CPP_BUFFER (pfile);
U_CHAR *start = pbuf->buf + start_mark.position;
int len = pbuf->cur - start;
CPP_RESERVE(pfile, 1 + len);
CPP_PUTC_Q (pfile, c);
CPP_PUTS_Q (pfile, start, len);
pfile->lineno += newlines;
parse_clear_mark (&start_mark);
return CPP_COMMENT; return CPP_COMMENT;
}
else if (CPP_TRADITIONAL (pfile))
{
return CPP_COMMENT;
}
else else
{ {
#if 0 CPP_PUTC (pfile, c);
/* This may not work if cpp_get_token is called recursively,
since many places look for horizontal space. */
if (newlines)
{
/* Copy the newlines into the output buffer, in order to
avoid the pain of a #line every time a multiline comment
is seen. */
CPP_RESERVE(pfile, newlines);
while (--newlines >= 0)
{
CPP_PUTC_Q (pfile, '\n');
pfile->lineno++;
}
return CPP_VSPACE;
}
#endif
CPP_RESERVE(pfile, 1);
CPP_PUTC_Q (pfile, ' ');
return CPP_HSPACE; return CPP_HSPACE;
} }
#if 0 #if 0
...@@ -2218,91 +2177,7 @@ cpp_get_token (pfile) ...@@ -2218,91 +2177,7 @@ cpp_get_token (pfile)
case '\"': case '\"':
case '\'': case '\'':
string: string:
/* A single quoted string is treated like a double -- some parse_string (pfile, c);
programs (e.g., troff) are perverse this way */
cpp_buf_line_and_col (cpp_file_buffer (pfile),
&start_line, &start_column);
old_written = CPP_WRITTEN (pfile);
CPP_PUTC (pfile, c);
while (1)
{
int cc = GETC();
if (cc == EOF)
{
if (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
{
/* try harder: this string crosses a macro expansion
boundary. This can happen naturally if -traditional.
Otherwise, only -D can make a macro with an unmatched
quote. */
cpp_pop_buffer (pfile);
continue;
}
if (!CPP_TRADITIONAL (pfile))
{
cpp_error_with_line (pfile, start_line, start_column,
"unterminated string or character constant");
if (pfile->multiline_string_line != start_line
&& pfile->multiline_string_line != 0)
cpp_error_with_line (pfile,
pfile->multiline_string_line, -1,
"possible real start of unterminated constant");
pfile->multiline_string_line = 0;
}
break;
}
CPP_PUTC (pfile, cc);
switch (cc)
{
case '\n':
/* Traditionally, end of line ends a string constant with
no error. So exit the loop and record the new line. */
if (CPP_TRADITIONAL (pfile))
goto while2end;
if (c == '\'')
{
cpp_error_with_line (pfile, start_line, start_column,
"unterminated character constant");
goto while2end;
}
if (CPP_PEDANTIC (pfile)
&& pfile->multiline_string_line == 0)
{
cpp_pedwarn_with_line (pfile, start_line, start_column,
"string constant runs past end of line");
}
if (pfile->multiline_string_line == 0)
pfile->multiline_string_line = start_line;
break;
case '\\':
cc = GETC();
if (cc == '\n')
{
/* Backslash newline is replaced by nothing at all. */
CPP_ADJUST_WRITTEN (pfile, -1);
pfile->lineno++;
}
else
{
/* ANSI stupidly requires that in \\ the second \
is *not* prevented from combining with a newline. */
NEWLINE_FIX1(cc);
if (cc != EOF)
CPP_PUTC (pfile, cc);
}
break;
case '\"':
case '\'':
if (cc == c)
goto while2end;
break;
}
}
while2end:
pfile->lineno += count_newlines (pfile->token_buffer + old_written,
CPP_PWRITTEN (pfile));
pfile->only_seen_white = 0; pfile->only_seen_white = 0;
return c == '\'' ? CPP_CHAR : CPP_STRING; return c == '\'' ? CPP_CHAR : CPP_STRING;
...@@ -2319,7 +2194,6 @@ cpp_get_token (pfile) ...@@ -2319,7 +2194,6 @@ cpp_get_token (pfile)
case '&': case '&':
case '+': case '+':
case '|': case '|':
NEWLINE_FIX;
c2 = PEEKC (); c2 = PEEKC ();
if (c2 == c || c2 == '=') if (c2 == c || c2 == '=')
goto op2; goto op2;
...@@ -2330,35 +2204,14 @@ cpp_get_token (pfile) ...@@ -2330,35 +2204,14 @@ cpp_get_token (pfile)
case '%': case '%':
case '=': case '=':
case '^': case '^':
NEWLINE_FIX;
if (PEEKC () == '=') if (PEEKC () == '=')
goto op2; goto op2;
goto randomchar; goto randomchar;
case '-': case '-':
NEWLINE_FIX;
c2 = PEEKC (); c2 = PEEKC ();
if (c2 == '-' && opts->chill) if (c2 == '-' && opts->chill)
{ goto comment; /* Chill style comment */
/* Chill style comment */
if (opts->put_out_comments)
parse_set_mark (&start_mark, pfile);
FORWARD(1); /* Skip second '-'. */
for (;;)
{
c = GETC ();
if (c == EOF)
break;
if (c == '\n')
{
/* Don't consider final '\n' to be part of comment. */
FORWARD(-1);
break;
}
}
c = '-';
goto return_comment;
}
if (c2 == '-' || c2 == '=' || c2 == '>') if (c2 == '-' || c2 == '=' || c2 == '>')
goto op2; goto op2;
goto randomchar; goto randomchar;
...@@ -2372,19 +2225,23 @@ cpp_get_token (pfile) ...@@ -2372,19 +2225,23 @@ cpp_get_token (pfile)
if (c == '>') if (c == '>')
break; break;
c = GETC (); c = GETC ();
NEWLINE_FIX1 (c);
if (c == '\n' || c == EOF) if (c == '\n' || c == EOF)
{ {
cpp_error (pfile, cpp_error (pfile,
"missing '>' in `#include <FILENAME>'"); "missing '>' in `#include <FILENAME>'");
break; break;
} }
else if (c == '\r')
{
/* Backslash newline is replaced by nothing. */
CPP_ADJUST_WRITTEN (pfile, -1);
CPP_BUMP_LINE (pfile);
}
} }
return CPP_STRING; return CPP_STRING;
} }
/* else fall through */ /* else fall through */
case '>': case '>':
NEWLINE_FIX;
c2 = PEEKC (); c2 = PEEKC ();
if (c2 == '=') if (c2 == '=')
goto op2; goto op2;
...@@ -2394,7 +2251,6 @@ cpp_get_token (pfile) ...@@ -2394,7 +2251,6 @@ cpp_get_token (pfile)
CPP_RESERVE (pfile, 4); CPP_RESERVE (pfile, 4);
CPP_PUTC (pfile, c); CPP_PUTC (pfile, c);
CPP_PUTC (pfile, c2); CPP_PUTC (pfile, c2);
NEWLINE_FIX;
c3 = PEEKC (); c3 = PEEKC ();
if (c3 == '=') if (c3 == '=')
CPP_PUTC_Q (pfile, GETC ()); CPP_PUTC_Q (pfile, GETC ());
...@@ -2413,7 +2269,7 @@ cpp_get_token (pfile) ...@@ -2413,7 +2269,7 @@ cpp_get_token (pfile)
parse_name (pfile, GETC ()); parse_name (pfile, GETC ());
return CPP_NAME; return CPP_NAME;
} }
else if (is_space [c]) else if (c == ' ')
{ {
CPP_RESERVE (pfile, 2); CPP_RESERVE (pfile, 2);
if (pfile->output_escapes) if (pfile->output_escapes)
...@@ -2430,7 +2286,6 @@ cpp_get_token (pfile) ...@@ -2430,7 +2286,6 @@ cpp_get_token (pfile)
goto randomchar; goto randomchar;
case '.': case '.':
NEWLINE_FIX;
c2 = PEEKC (); c2 = PEEKC ();
if (ISDIGIT(c2)) if (ISDIGIT(c2))
{ {
...@@ -2439,7 +2294,6 @@ cpp_get_token (pfile) ...@@ -2439,7 +2294,6 @@ cpp_get_token (pfile)
c = GETC (); c = GETC ();
goto number; goto number;
} }
/* FIXME - misses the case "..\\\n." */
if (c2 == '.' && PEEKN(1) == '.') if (c2 == '.' && PEEKN(1) == '.')
{ {
CPP_RESERVE(pfile, 4); CPP_RESERVE(pfile, 4);
...@@ -2456,7 +2310,6 @@ cpp_get_token (pfile) ...@@ -2456,7 +2310,6 @@ cpp_get_token (pfile)
op2: op2:
token = CPP_OTHER; token = CPP_OTHER;
pfile->only_seen_white = 0; pfile->only_seen_white = 0;
op2any:
CPP_RESERVE(pfile, 3); CPP_RESERVE(pfile, 3);
CPP_PUTC_Q (pfile, c); CPP_PUTC_Q (pfile, c);
CPP_PUTC_Q (pfile, GETC ()); CPP_PUTC_Q (pfile, GETC ());
...@@ -2464,7 +2317,6 @@ cpp_get_token (pfile) ...@@ -2464,7 +2317,6 @@ cpp_get_token (pfile)
return token; return token;
case 'L': case 'L':
NEWLINE_FIX;
c2 = PEEKC (); c2 = PEEKC ();
if ((c2 == '\'' || c2 == '\"') && !CPP_TRADITIONAL (pfile)) if ((c2 == '\'' || c2 == '\"') && !CPP_TRADITIONAL (pfile))
{ {
...@@ -2482,7 +2334,6 @@ cpp_get_token (pfile) ...@@ -2482,7 +2334,6 @@ cpp_get_token (pfile)
{ {
CPP_RESERVE (pfile, 2); CPP_RESERVE (pfile, 2);
CPP_PUTC_Q (pfile, c); CPP_PUTC_Q (pfile, c);
NEWLINE_FIX;
c = PEEKC (); c = PEEKC ();
if (c == EOF) if (c == EOF)
break; break;
...@@ -2512,14 +2363,7 @@ cpp_get_token (pfile) ...@@ -2512,14 +2363,7 @@ cpp_get_token (pfile)
if (c == EOF) if (c == EOF)
goto chill_number_eof; goto chill_number_eof;
if (!is_idchar[c]) if (!is_idchar[c])
{
if (c == '\\' && PEEKC() == '\n')
{
FORWARD(2);
continue;
}
break; break;
}
CPP_PUTC (pfile, c); CPP_PUTC (pfile, c);
} }
if (c == '\'') if (c == '\'')
...@@ -2584,10 +2428,9 @@ cpp_get_token (pfile) ...@@ -2584,10 +2428,9 @@ cpp_get_token (pfile)
decide this is not a macro call and leave things that way. */ decide this is not a macro call and leave things that way. */
if (hp->type == T_MACRO && hp->value.defn->nargs >= 0) if (hp->type == T_MACRO && hp->value.defn->nargs >= 0)
{ {
struct parse_marker macro_mark;
int is_macro_call, macbuf_whitespace = 0; int is_macro_call, macbuf_whitespace = 0;
parse_set_mark (&macro_mark, pfile); parse_set_mark (pfile);
for (;;) for (;;)
{ {
cpp_skip_hspace (pfile); cpp_skip_hspace (pfile);
...@@ -2603,14 +2446,15 @@ cpp_get_token (pfile) ...@@ -2603,14 +2446,15 @@ cpp_get_token (pfile)
{ {
if (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile))) if (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
{ {
if (macro_mark.position != if (CPP_BUFFER (pfile)->mark !=
(CPP_BUFFER (pfile)->cur (CPP_BUFFER (pfile)->cur
- CPP_BUFFER (pfile)->buf)) - CPP_BUFFER (pfile)->buf))
macbuf_whitespace = 1; macbuf_whitespace = 1;
parse_clear_mark (&macro_mark); /* The mark goes away automatically when
the buffer is popped. */
cpp_pop_buffer (pfile); cpp_pop_buffer (pfile);
parse_set_mark (&macro_mark, pfile); parse_set_mark (pfile);
} }
else else
break; break;
...@@ -2618,11 +2462,12 @@ cpp_get_token (pfile) ...@@ -2618,11 +2462,12 @@ cpp_get_token (pfile)
} }
if (!is_macro_call) if (!is_macro_call)
{ {
parse_goto_mark (&macro_mark, pfile); parse_goto_mark (pfile);
if (macbuf_whitespace) if (macbuf_whitespace)
CPP_PUTC (pfile, ' '); CPP_PUTC (pfile, ' ');
} }
parse_clear_mark (&macro_mark); else
parse_clear_mark (pfile);
if (!is_macro_call) if (!is_macro_call)
return CPP_NAME; return CPP_NAME;
} }
...@@ -2634,7 +2479,7 @@ cpp_get_token (pfile) ...@@ -2634,7 +2479,7 @@ cpp_get_token (pfile)
} }
goto get_next; goto get_next;
case ' ': case '\t': case '\v': case '\r': case ' ': case '\t': case '\v':
for (;;) for (;;)
{ {
CPP_PUTC (pfile, c); CPP_PUTC (pfile, c);
...@@ -2646,17 +2491,20 @@ cpp_get_token (pfile) ...@@ -2646,17 +2491,20 @@ cpp_get_token (pfile)
return CPP_HSPACE; return CPP_HSPACE;
case '\\': case '\\':
c2 = PEEKC ();
if (c2 != '\n')
goto randomchar; goto randomchar;
token = CPP_HSPACE;
goto op2any; case '\r':
/* Backslash newline is ignored. */
CPP_BUMP_LINE (pfile);
goto get_next;
case '\n': case '\n':
CPP_PUTC (pfile, c); CPP_PUTC (pfile, c);
if (pfile->only_seen_white == 0) if (pfile->only_seen_white == 0)
pfile->only_seen_white = 1; pfile->only_seen_white = 1;
CPP_BUMP_LINE (pfile);
pfile->lineno++; pfile->lineno++;
if (CPP_BUFFER (pfile)->lineno != pfile->lineno)
output_line_command (pfile, 1, same_file); output_line_command (pfile, 1, same_file);
return CPP_VSPACE; return CPP_VSPACE;
...@@ -2697,19 +2545,15 @@ cpp_get_non_space_token (pfile) ...@@ -2697,19 +2545,15 @@ cpp_get_non_space_token (pfile)
/* Parse an identifier starting with C. */ /* Parse an identifier starting with C. */
static int static void
parse_name (pfile, c) parse_name (pfile, c)
cpp_reader *pfile; int c; cpp_reader *pfile;
int c;
{ {
for (;;) for (;;)
{ {
if (! is_idchar[c]) if (! is_idchar[c])
{ {
if (c == '\\' && PEEKC() == '\n')
{
FORWARD(2);
continue;
}
FORWARD (-1); FORWARD (-1);
break; break;
} }
...@@ -2724,7 +2568,95 @@ parse_name (pfile, c) ...@@ -2724,7 +2568,95 @@ parse_name (pfile, c)
break; break;
} }
CPP_NUL_TERMINATE_Q (pfile); CPP_NUL_TERMINATE_Q (pfile);
return 1; return;
}
/* Parse a string starting with C. A single quoted string is treated
like a double -- some programs (e.g., troff) are perverse this way.
(However, a single quoted string is not allowed to extend over
multiple lines. */
static void
parse_string (pfile, c)
cpp_reader *pfile;
int c;
{
long start_line, start_column;
cpp_buf_line_and_col (cpp_file_buffer (pfile), &start_line, &start_column);
CPP_PUTC (pfile, c);
while (1)
{
int cc = GETC();
if (cc == EOF)
{
if (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
{
/* try harder: this string crosses a macro expansion
boundary. This can happen naturally if -traditional.
Otherwise, only -D can make a macro with an unmatched
quote. */
cpp_pop_buffer (pfile);
continue;
}
if (!CPP_TRADITIONAL (pfile))
{
cpp_error_with_line (pfile, start_line, start_column,
"unterminated string or character constant");
if (pfile->multiline_string_line != start_line
&& pfile->multiline_string_line != 0)
cpp_error_with_line (pfile,
pfile->multiline_string_line, -1,
"possible real start of unterminated constant");
pfile->multiline_string_line = 0;
}
break;
}
CPP_PUTC (pfile, cc);
switch (cc)
{
case '\n':
CPP_BUMP_LINE (pfile);
pfile->lineno++;
/* Traditionally, end of line ends a string constant with
no error. */
if (CPP_TRADITIONAL (pfile))
return;
/* Character constants may not extend over multiple lines. */
if (c == '\'')
{
cpp_error_with_line (pfile, start_line, start_column,
"unterminated character constant");
return;
}
if (CPP_PEDANTIC (pfile) && pfile->multiline_string_line == 0)
{
cpp_pedwarn_with_line (pfile, start_line, start_column,
"string constant runs past end of line");
}
if (pfile->multiline_string_line == 0)
pfile->multiline_string_line = start_line;
break;
case '\r':
/* Backslash newline is replaced by nothing at all. */
CPP_ADJUST_WRITTEN (pfile, -1);
CPP_BUMP_LINE (pfile);
break;
case '\\':
cc = GETC();
if (cc != EOF)
CPP_PUTC (pfile, cc);
break;
case '\"':
case '\'':
if (cc == c)
return;
break;
}
}
} }
/* Read an assertion into the token buffer, converting to /* Read an assertion into the token buffer, converting to
...@@ -2752,7 +2684,7 @@ parse_assertion (pfile) ...@@ -2752,7 +2684,7 @@ parse_assertion (pfile)
c = PEEKC(); c = PEEKC();
if (c != '(') if (c != '(')
{ {
if (is_hor_space[c]) if (is_hor_space[c] || c == '\r')
cpp_skip_hspace (pfile); cpp_skip_hspace (pfile);
c = PEEKC(); c = PEEKC();
} }
...@@ -2772,17 +2704,17 @@ parse_assertion (pfile) ...@@ -2772,17 +2704,17 @@ parse_assertion (pfile)
dropwhite = 1; dropwhite = 1;
} }
} }
else if (c == '\\' && PEEKC() == '\n')
FORWARD(1);
else if (c == '\n' || c == EOF) else if (c == '\n' || c == EOF)
{ {
if (c == '\n') FORWARD(-1); if (c == '\n') FORWARD(-1);
cpp_error (pfile, "un-terminated assertion answer"); cpp_error (pfile, "un-terminated assertion answer");
return 0; return 0;
} }
else if (c == '\r')
CPP_BUMP_LINE (pfile);
else else
{ {
CPP_PUTC(pfile, c); CPP_PUTC (pfile, c);
dropwhite = 0; dropwhite = 0;
} }
} }
...@@ -2795,9 +2727,9 @@ parse_assertion (pfile) ...@@ -2795,9 +2727,9 @@ parse_assertion (pfile)
return 0; return 0;
} }
else else
CPP_PUTC(pfile, ')'); CPP_PUTC (pfile, ')');
CPP_NUL_TERMINATE(pfile); CPP_NUL_TERMINATE (pfile);
return 2; return 2;
} }
...@@ -2971,61 +2903,49 @@ cpp_read_check_assertion (pfile) ...@@ -2971,61 +2903,49 @@ cpp_read_check_assertion (pfile)
return result; return result;
} }
/* Initialize PMARK to remember the current position of PFILE. */ /* Remember the current position of PFILE. */
void void
parse_set_mark (pmark, pfile) parse_set_mark (pfile)
struct parse_marker *pmark;
cpp_reader *pfile; cpp_reader *pfile;
{ {
cpp_buffer *pbuf = CPP_BUFFER (pfile); cpp_buffer *ip = CPP_BUFFER (pfile);
pmark->next = pbuf->marks; if (ip->mark != -1)
pbuf->marks = pmark; cpp_fatal (pfile,
pmark->buf = pbuf; "cpp internal error: ip->mark != -1 in parse_set_mark");
pmark->position = pbuf->cur - pbuf->buf;
}
/* Cleanup PMARK - we no longer need it. */
void ip->mark = ip->cur - ip->buf;
parse_clear_mark (pmark)
struct parse_marker *pmark;
{
struct parse_marker **pp = &pmark->buf->marks;
for (; ; pp = &(*pp)->next) {
if (*pp == NULL) abort ();
if (*pp == pmark) break;
}
*pp = pmark->next;
} }
/* Backup the current position of PFILE to that saved in PMARK. */ /* Clear the current mark - we no longer need it. */
void void
parse_goto_mark (pmark, pfile) parse_clear_mark (pfile)
struct parse_marker *pmark;
cpp_reader *pfile; cpp_reader *pfile;
{ {
cpp_buffer *pbuf = CPP_BUFFER (pfile); cpp_buffer *ip = CPP_BUFFER (pfile);
if (pbuf != pmark->buf) if (ip->mark == -1)
cpp_fatal (pfile, "internal error %s", "parse_goto_mark"); cpp_fatal (pfile,
pbuf->cur = pbuf->buf + pmark->position; "cpp internal error: ip->mark == -1 in parse_clear_mark");
ip->mark = -1;
} }
/* Reset PMARK to point to the current position of PFILE. (Same /* Backup the current position of PFILE to that saved in its mark,
as parse_clear_mark (PMARK), parse_set_mark (PMARK, PFILE) but faster. */ and clear the mark. */
void void
parse_move_mark (pmark, pfile) parse_goto_mark (pfile)
struct parse_marker *pmark;
cpp_reader *pfile; cpp_reader *pfile;
{ {
cpp_buffer *pbuf = CPP_BUFFER (pfile); cpp_buffer *ip = CPP_BUFFER (pfile);
if (pbuf != pmark->buf) if (ip->mark == -1)
cpp_fatal (pfile, "internal error %s", "parse_move_mark"); cpp_fatal (pfile,
pmark->position = pbuf->cur - pbuf->buf; "cpp internal error: ip->mark == -1 in parse_goto_mark");
}
ip->cur = ip->buf + ip->mark;
ip->mark = -1;
}
void void
cpp_print_file_and_line (pfile) cpp_print_file_and_line (pfile)
......
...@@ -72,19 +72,9 @@ enum cpp_token { ...@@ -72,19 +72,9 @@ enum cpp_token {
typedef enum cpp_token (*parse_underflow_t) PARAMS((cpp_reader *)); typedef enum cpp_token (*parse_underflow_t) PARAMS((cpp_reader *));
typedef int (*parse_cleanup_t) PARAMS((cpp_buffer *, cpp_reader *)); typedef int (*parse_cleanup_t) PARAMS((cpp_buffer *, cpp_reader *));
/* A parse_marker indicates a previous position, extern void parse_set_mark PARAMS ((cpp_reader *));
which we can backtrack to. */ extern void parse_clear_mark PARAMS ((cpp_reader *));
extern void parse_goto_mark PARAMS ((cpp_reader *));
struct parse_marker {
cpp_buffer *buf;
struct parse_marker *next;
int position;
};
extern void parse_set_mark PARAMS ((struct parse_marker *, cpp_reader *));
extern void parse_clear_mark PARAMS ((struct parse_marker *));
extern void parse_goto_mark PARAMS((struct parse_marker *, cpp_reader *));
extern void parse_move_mark PARAMS((struct parse_marker *, cpp_reader *));
extern int cpp_handle_option PARAMS ((cpp_reader *, int, char **)); extern int cpp_handle_option PARAMS ((cpp_reader *, int, char **));
extern int cpp_handle_options PARAMS ((cpp_reader *, int, char **)); extern int cpp_handle_options PARAMS ((cpp_reader *, int, char **));
...@@ -95,15 +85,13 @@ extern enum cpp_token cpp_get_non_space_token PARAMS ((cpp_reader *)); ...@@ -95,15 +85,13 @@ extern enum cpp_token cpp_get_non_space_token PARAMS ((cpp_reader *));
/* This frees resources used by PFILE. */ /* This frees resources used by PFILE. */
extern void cpp_cleanup PARAMS ((cpp_reader *PFILE)); extern void cpp_cleanup PARAMS ((cpp_reader *PFILE));
/* If we have a huge buffer, may need to cache more recent counts */
#define CPP_LINE_BASE(BUF) ((BUF)->buf + (BUF)->line_base)
struct cpp_buffer struct cpp_buffer
{ {
unsigned char *cur; /* current position */ unsigned char *cur; /* current position */
unsigned char *rlimit; /* end of valid data */ unsigned char *rlimit; /* end of valid data */
unsigned char *buf; /* entire buffer */ unsigned char *buf; /* entire buffer */
unsigned char *alimit; /* end of allocated buffer */ unsigned char *alimit; /* end of allocated buffer */
unsigned char *line_base; /* start of current line */
struct cpp_buffer *prev; struct cpp_buffer *prev;
...@@ -120,13 +108,13 @@ struct cpp_buffer ...@@ -120,13 +108,13 @@ struct cpp_buffer
to record control macros. */ to record control macros. */
struct include_hash *ihash; struct include_hash *ihash;
long line_base;
long lineno; /* Line number at CPP_LINE_BASE. */ long lineno; /* Line number at CPP_LINE_BASE. */
long colno; /* Column number at CPP_LINE_BASE. */ long colno; /* Column number at CPP_LINE_BASE. */
long mark; /* Saved position for lengthy backtrack. */
parse_underflow_t underflow; parse_underflow_t underflow;
parse_cleanup_t cleanup; parse_cleanup_t cleanup;
void *data; void *data;
struct parse_marker *marks;
/* Value of if_stack at start of this file. /* Value of if_stack at start of this file.
Used to prohibit unmatched #endif (etc) in an include file. */ Used to prohibit unmatched #endif (etc) in an include file. */
struct if_stack *if_stack; struct if_stack *if_stack;
...@@ -289,8 +277,12 @@ struct cpp_reader ...@@ -289,8 +277,12 @@ struct cpp_reader
#define CPP_ADJUST_WRITTEN(PFILE,DELTA) ((PFILE)->limit += (DELTA)) #define CPP_ADJUST_WRITTEN(PFILE,DELTA) ((PFILE)->limit += (DELTA))
#define CPP_SET_WRITTEN(PFILE,N) ((PFILE)->limit = (PFILE)->token_buffer + (N)) #define CPP_SET_WRITTEN(PFILE,N) ((PFILE)->limit = (PFILE)->token_buffer + (N))
#define CPP_OPTIONS(PFILE) ((PFILE)->opts) /* Advance the current line by one. */
#define CPP_BUMP_BUFFER_LINE(PBUF) ((PBUF)->lineno++,\
(PBUF)->line_base = (PBUF)->cur)
#define CPP_BUMP_LINE(PFILE) CPP_BUMP_BUFFER_LINE(CPP_BUFFER(PFILE))
#define CPP_OPTIONS(PFILE) ((PFILE)->opts)
#define CPP_BUFFER(PFILE) ((PFILE)->buffer) #define CPP_BUFFER(PFILE) ((PFILE)->buffer)
#define CPP_PREV_BUFFER(BUFFER) ((BUFFER)->prev) #define CPP_PREV_BUFFER(BUFFER) ((BUFFER)->prev)
/* The bottom of the buffer stack. */ /* The bottom of the buffer stack. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment