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>
* 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,
#define SKIP_OPERAND 8
/*#define UNSIGNEDP 16*/
#define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
struct operation {
short op;
char rprio; /* Priority of op (relative to it right operand). */
......@@ -444,12 +442,12 @@ cpp_lex (pfile, skip_evaluation)
cpp_buffer *ip = CPP_BUFFER (pfile);
U_CHAR *tok;
SKIP_WHITE_SPACE (ip->cur);
cpp_skip_hspace (pfile);
if (*ip->cur == '(')
{
paren++;
ip->cur++; /* Skip over the paren */
SKIP_WHITE_SPACE (ip->cur);
cpp_skip_hspace (pfile);
}
if (!is_idstart[*ip->cur])
......@@ -460,7 +458,7 @@ cpp_lex (pfile, skip_evaluation)
while (is_idchar[*ip->cur])
++ip->cur;
len = ip->cur - tok;
SKIP_WHITE_SPACE (ip->cur);
cpp_skip_hspace (pfile);
if (paren)
{
if (*ip->cur != ')')
......
......@@ -757,15 +757,51 @@ actual_directory (pfile, fname)
return x;
}
/* Read the entire contents of file DESC into buffer BUF, convert end-of-line
markers to canonical form, and convert trigraphs if enabled. Also, make
sure there is a newline at the end of the file. LEN is how much room we
have to start with (this can be expanded if necessary).
Returns -1 on failure, or the actual length of the data to be scanned.
/* Almost but not quite the same as adjust_position in cpplib.c.
Used only by read_and_prescan. */
static void
find_position (start, limit, linep, colp)
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
as much as possible; this is important to prevent it from being a
performance bottleneck. */
/* Read the entire contents of file DESC into buffer BUF. LEN is how
much memory to allocate initially; more will be allocated if
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
read_and_prescan (pfile, fp, desc, len)
......@@ -774,29 +810,47 @@ read_and_prescan (pfile, fp, desc, len)
int desc;
size_t len;
{
U_CHAR *buf = (U_CHAR *) xmalloc (len);
U_CHAR *buf = xmalloc (len);
U_CHAR *ip, *op, *line_base;
U_CHAR *ibase;
unsigned int line;
unsigned int line, deferred_newlines;
int count;
size_t offset;
/* 4096 bytes of buffer proper, 2 to detect running off the end without
address arithmetic all the time, and 2 for pushback in the case there's
a potential trigraph or end-of-line digraph at the end of a block. */
#define INTERMED_BUFFER_SIZE 4096
U_CHAR intermed[INTERMED_BUFFER_SIZE + 2 + 2];
/* PIPE_BUF bytes of buffer proper, 2 to detect running off the end
without address arithmetic all the time, and 2 for pushback in
the case there's a potential trigraph or end-of-line digraph at
the end of a block. */
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;
op = buf;
line_base = buf;
line = 1;
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 (;;)
{
read_next:
count = read (desc, intermed + 2, INTERMED_BUFFER_SIZE);
count = read (desc, intermed + 2, PIPE_BUF);
if (count < 0)
goto error;
else if (count == 0)
......@@ -806,16 +860,16 @@ read_and_prescan (pfile, fp, desc, len)
ip = ibase;
ibase = intermed + 2;
ibase[count] = ibase[count+1] = '\0';
if (offset > len)
{
size_t delta_op;
size_t delta_line_base;
len *= 2;
if (offset > len)
/* len overflowed.
This could happen if the file is larger than half the
maximum address space of the machine. */
/* len overflowed.
This could happen if the file is larger than half the
maximum address space of the machine. */
goto too_big;
delta_op = op - buf;
......@@ -827,93 +881,155 @@ read_and_prescan (pfile, fp, desc, len)
for (;;)
{
unsigned int c;
c = *ip++;
switch (c)
unsigned int span = 0;
/* Deal with \-newline in the middle of a token. */
if (deferred_newlines)
{
/* The default case is at the top so gcc will realize
it's the common case, and leave c in a register.
Also, cache utilization is a little better this way. */
default:
*op++ = c;
break;
case '\0':
while (speccase[ip[span]] == SPECCASE_EMPTY
&& ip[span] != '\n'
&& ip[span] != '\t'
&& ip[span] != ' ')
span++;
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;
switch (speccase[*ip++])
{
case SPECCASE_NUL: /* \0 */
ibase[-1] = op[-1];
goto read_next;
case '\r':
if (*ip == '\n') ip++;
case SPECCASE_CR: /* \r */
if (*ip == '\n')
ip++;
else if (*ip == '\0')
{
--ibase;
intermed[1] = '\r';
goto read_next;
}
else if (ip[-2] == '\n')
continue;
*op++ = '\n';
line++;
line_base = op;
break;
case '\n':
if (*ip == '\r') ip++;
else if (*ip == '\0')
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] = '\n';
intermed[1] = '\\';
goto read_next;
}
*op++ = '\n';
line++;
line_base = op;
break;
case '?':
if (CPP_OPTIONS (pfile)->trigraphs
|| CPP_OPTIONS (pfile)->warn_trigraphs)
else if (*ip == '\n')
{
unsigned int d;
/* If we're at the end of the intermediate buffer,
we have to shift the ?'s down to the start and
come back next pass. */
d = ip[0];
if (d == '\0')
{
--ibase;
intermed[1] = '?';
goto read_next;
}
if (d != '?')
{
*op++ = '?';
break;
}
d = ip[1];
if (d == '\0')
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')
{
ibase -= 2;
intermed[0] = intermed[1] = '?';
intermed[0] = '\\';
intermed[1] = '\r';
goto read_next;
}
if (!trigraph_table[d])
{
*op++ = '?';
break;
}
if (CPP_OPTIONS (pfile)->warn_trigraphs)
cpp_warning_with_line (pfile, line, op-line_base,
"trigraph ??%c encountered", d);
if (CPP_OPTIONS (pfile)->trigraphs)
*op++ = trigraph_table[d];
else if (*ip == '\r' || *ip == '\t' || *ip == ' ')
*op++ = '\r';
else
{
*op++ = '?';
*op++ = '?';
*op++ = d;
}
ip += 2;
deferred_newlines++;
line++;
line_base = op;
}
else
*op++ = c;
*op++ = '\\';
}
break;
case SPECCASE_QUESTION: /* ? */
{
unsigned int d;
/* If we're at the end of the intermediate buffer,
we have to shift the ?'s down to the start and
come back next pass. */
d = ip[0];
if (d == '\0')
{
--ibase;
intermed[1] = '?';
goto read_next;
}
if (d != '?')
{
*op++ = '?';
break;
}
d = ip[1];
if (d == '\0')
{
ibase -= 2;
intermed[0] = intermed[1] = '?';
goto read_next;
}
if (!trigraph_table[d])
{
*op++ = '?';
break;
}
if (CPP_OPTIONS (pfile)->warn_trigraphs)
{
long col;
find_position (line_base, op, &line, &col);
line_base = op - col;
cpp_warning_with_line (pfile, line, col,
"trigraph ??%c encountered", d);
}
if (CPP_OPTIONS (pfile)->trigraphs)
{
if (trigraph_table[d] == '\\')
goto backslash;
else
*op++ = trigraph_table[d];
}
else
{
*op++ = '?';
*op++ = '?';
*op++ = d;
}
ip += 2;
}
}
}
}
......@@ -922,47 +1038,48 @@ read_and_prescan (pfile, fp, desc, len)
return 0;
/* Deal with pushed-back chars at true EOF.
If two chars were pushed back, they must both be ?'s.
If one was, it might be ?, \r, or \n, and \r needs to
become \n.
This may be any of: ?? ? \ \r \n \\r \\n.
\r must become \n, \\r or \\n must become \r.
We know we have space already. */
if (ibase == intermed)
{
*op++ = '?';
*op++ = '?';
if (*ibase == '?')
{
*op++ = '?';
*op++ = '?';
}
else
*op++ = '\r';
}
else if (ibase == intermed + 1)
{
if (*ibase == '?')
*op++ = '?';
else
if (*ibase == '\r')
*op++ = '\n';
else
*op++ = *ibase;
}
if (op[-1] != '\n' || op[-2] == '\\')
if (op[-1] != '\n')
{
if (CPP_PEDANTIC (pfile))
cpp_pedwarn_with_line (pfile, line, op - line_base,
"no newline at end of file");
if (offset + 2 > len)
long col;
find_position (line_base, op, &line, &col);
cpp_warning_with_line (pfile, line, col, "no newline at end of file\n");
if (offset + 1 > len)
{
len += 2;
if (offset + 2 > len)
len += 1;
if (offset + 1 > len)
goto too_big;
buf = (U_CHAR *) xrealloc (buf, len);
op = buf + offset;
}
if (op[-1] == '\\')
*op++ = '\n';
*op++ = '\n';
}
fp->buf =
(U_CHAR *) ((len - offset < 20) ? (PTR) buf : xrealloc (buf, op - buf));
fp->buf = ((len - offset < 20) ? buf : (U_CHAR *)xrealloc (buf, op - buf));
return op - buf;
too_big:
cpp_error (pfile, "file is too large");
cpp_error (pfile, "file is too large (>%lu bytes)\n", (unsigned long)offset);
free (buf);
return -1;
......
......@@ -787,6 +787,7 @@ macarg (pfile, rest_args)
/* Try to parse as much of the argument as exists at this
input stack level. */
pfile->no_macro_expand++;
CPP_OPTIONS (pfile)->no_line_commands++;
for (;;)
{
token = cpp_get_token (pfile);
......@@ -824,6 +825,7 @@ macarg (pfile, rest_args)
done:
CPP_OPTIONS (pfile)->put_out_comments = save_put_out_comments;
CPP_OPTIONS (pfile)->no_line_commands--;
pfile->no_macro_expand--;
return token;
......
......@@ -255,15 +255,16 @@ U_CHAR is_idstart[256] =
['_'] = 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] =
{
[' '] = 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. */
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
processing, everywhere in the file. (This is necessary since one
......@@ -362,14 +363,12 @@ initialize_char_syntax (dollar_in_ident)
is_hor_space['\t'] = 1;
is_hor_space['\v'] = 1;
is_hor_space['\f'] = 1;
is_hor_space['\r'] = 1;
is_space[' '] = 1;
is_space['\t'] = 1;
is_space['\v'] = 1;
is_space['\f'] = 1;
is_space['\n'] = 1;
is_space['\r'] = 1;
/* trigraph conversion */
trigraph_table['='] = '#'; trigraph_table[')'] = ']';
......
......@@ -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*.) */
#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. */
static char *my_strerror PROTO ((int));
......@@ -60,7 +45,10 @@ static HOST_WIDEST_INT eval_if_expression PROTO ((cpp_reader *));
static void conditional_skip PROTO ((cpp_reader *, int,
enum node_type, U_CHAR *));
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. */
......@@ -245,71 +233,144 @@ null_cleanup (pbuf, pfile)
return 0;
}
/* Assuming we have read '/'.
If this is the start of a comment (followed by '*' or '/'),
skip to the end of the comment, and return ' '.
Return EOF if we reached the end of file before the end of the comment.
If not the start of a comment, return '/'. */
/* Skip a comment - C, C++, or Chill style. M is the first character
of the comment marker. If this really is a comment, skip to its
end and return ' '. If we hit end-of-file before end-of-comment,
return EOF. If this is not a comment, return M (which will be
'/' or '-'). */
static int
skip_comment (pfile, linep)
skip_comment (pfile, m)
cpp_reader *pfile;
long *linep;
int m;
{
int c = 0;
while (PEEKC() == '\\' && PEEKN(1) == '\n')
{
if (linep)
(*linep)++;
FORWARD(2);
}
if (PEEKC() == '*')
if (m == '/' && PEEKC() == '*')
{
int c, prev_c = -1;
long line, col;
FORWARD(1);
cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
for (;;)
{
int prev_c = c;
c = GETC ();
if (c == EOF)
return EOF;
while (c == '\\' && PEEKC() == '\n')
{
if (linep)
(*linep)++;
FORWARD(1), c = GETC();
cpp_error_with_line (pfile, line, col, "unterminated comment");
return EOF;
}
if (prev_c == '*' && c == '/')
else if (c == '\n' || c == '\r')
CPP_BUMP_LINE (pfile);
else if (c == '/' && prev_c == '*')
return ' ';
if (c == '\n' && linep)
(*linep)++;
else if (c == '*' && prev_c == '/'
&& 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);
for (;;)
{
c = GETC ();
int c = GETC ();
if (c == 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);
cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
for (;;)
{
c = GETC ();
if (c == EOF)
{
FORWARD(1);
c = GETC();
if (linep)
(*linep)++;
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')
{
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. */
FORWARD(-1);
return ' ';
}
else if (c == '\r')
CPP_BUMP_LINE (pfile);
CPP_PUTC (pfile, c);
}
}
else
return '/';
}
return m;
}
/* Skip whitespace \-newline and comments. Does not macro-expand. */
......@@ -317,34 +378,43 @@ void
cpp_skip_hspace (pfile)
cpp_reader *pfile;
{
int c;
while (1)
{
int c = PEEKC();
c = GETC();
if (c == EOF)
return; /* FIXME */
if (is_hor_space[c])
return;
else if (is_hor_space[c])
{
if ((c == '\f' || c == '\v') && CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile, "%s in preprocessing directive",
c == '\f' ? "formfeed" : "vertical tab");
FORWARD(1);
}
else if (c == '/')
else if (c == '\r')
{
FORWARD (1);
c = skip_comment (pfile, NULL);
if (c == '/')
FORWARD(-1);
if (c == EOF || c == '/')
CPP_BUFFER (pfile)->lineno++;
}
else if (c == '/' || c == '-')
{
c = skip_comment (pfile, c);
if (c == EOF)
return;
else if (c != ' ')
{
FORWARD(-1);
return;
}
}
else if (c == '\\' && PEEKN(1) == '\n') {
FORWARD(2);
}
else if (c == '@' && CPP_BUFFER (pfile)->has_escapes
&& is_hor_space[PEEKN(1)])
FORWARD(2);
else return;
&& PEEKC() == ' ')
{
FORWARD(1);
}
else
{
FORWARD(-1);
return;
}
}
}
......@@ -355,30 +425,36 @@ static void
copy_rest_of_line (pfile)
cpp_reader *pfile;
{
struct cpp_options *opts = CPP_OPTIONS (pfile);
for (;;)
{
int c = GETC();
int nextc;
switch (c)
{
case '\n':
FORWARD(-1);
case EOF:
goto end_directive;
case '\\':
if (PEEKC() == '\n')
{
FORWARD (1);
continue;
}
CPP_NUL_TERMINATE (pfile);
return;
case '\r':
CPP_BUFFER (pfile)->lineno++;
continue;
case '\'':
case '\"':
goto scan_directive_token;
break;
parse_string (pfile, c);
continue;
case '/':
nextc = PEEKC();
if (nextc == '*' || (opts->cplusplus_comments && nextc == '/'))
goto scan_directive_token;
if (PEEKC() == '*' && CPP_TRADITIONAL (pfile))
{
CPP_PUTS (pfile, "/**/", 4);
skip_comment (pfile, c);
continue;
}
/* else fall through */
case '-':
c = skip_comment (pfile, c);
break;
case '\f':
case '\v':
if (CPP_PEDANTIC (pfile))
......@@ -386,20 +462,15 @@ copy_rest_of_line (pfile)
c == '\f' ? "formfeed" : "vertical tab");
break;
case '\n':
FORWARD(-1);
goto end_directive;
scan_directive_token:
FORWARD(-1);
cpp_get_token (pfile);
continue;
}
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
skip_rest_of_line (pfile)
cpp_reader *pfile;
......@@ -415,7 +486,8 @@ skip_rest_of_line (pfile)
static int
handle_directive (pfile)
cpp_reader *pfile;
{ int c;
{
int c;
register struct directive *kt;
int ident_length;
U_CHAR *ident;
......@@ -590,16 +662,11 @@ do_define (pfile, keyword)
int hashcode;
MACRODEF mdef;
HASHNODE *hp;
int save_put_out_comments;
long here;
U_CHAR *macro, *buf, *end;
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);
CPP_OPTIONS (pfile)->put_out_comments = save_put_out_comments;
/* Copy out the line so we can pop the token buffer. */
buf = pfile->token_buffer + here;
......@@ -696,6 +763,7 @@ cpp_push_buffer (pfile, buffer, length)
new->buf = new->cur = buffer;
new->alimit = new->rlimit = buffer + length;
new->prev = buf;
new->mark = -1;
CPP_BUFFER (pfile) = new;
return new;
......@@ -781,59 +849,22 @@ cpp_expand_to_buffer (pfile, buf, length)
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
cpp_buf_line_and_col (pbuf, linep, colp)
register cpp_buffer *pbuf;
long *linep, *colp;
{
long dummy;
if (colp == NULL)
colp = &dummy;
if (pbuf)
{
*linep = pbuf->lineno;
*colp = pbuf->colno;
adjust_position (pbuf->buf + pbuf->line_base, pbuf->cur, linep, colp);
if (colp)
*colp = pbuf->cur - pbuf->line_base;
}
else
{
*linep = 0;
*colp = 0;
if (colp)
*colp = 0;
}
}
......@@ -851,21 +882,6 @@ cpp_file_buffer (pfile)
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.
* If CONDITIONAL is nonzero, we can omit the #line if it would
......@@ -886,73 +902,56 @@ output_line_command (pfile, conditional, file_change)
if (ip->fname == NULL)
return;
update_position (ip);
if (CPP_OPTIONS (pfile)->no_line_commands
|| CPP_OPTIONS (pfile)->no_output)
return;
line = CPP_BUFFER (pfile)->lineno;
col = CPP_BUFFER (pfile)->colno;
adjust_position (CPP_LINE_BASE (ip), ip->cur, &line, &col);
cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
if (CPP_OPTIONS (pfile)->no_line_commands)
return;
if (conditional)
{
if (line == pfile->lineno)
return;
if (conditional) {
if (line == pfile->lineno)
return;
/* If the inherited line number is a little too small,
output some newlines instead of a #line command. */
if (line > pfile->lineno && line < pfile->lineno + 8) {
CPP_RESERVE (pfile, 20);
while (line > pfile->lineno) {
CPP_PUTC_Q (pfile, '\n');
pfile->lineno++;
}
return;
/* If the inherited line number is a little too small,
output some newlines instead of a #line command. */
if (line > pfile->lineno && line < pfile->lineno + 8)
{
CPP_RESERVE (pfile, 20);
while (line > pfile->lineno)
{
CPP_PUTC_Q (pfile, '\n');
pfile->lineno++;
}
return;
}
}
}
#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);
{
#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);
}
CPP_PUTS_Q (pfile, "# ", 2);
sprintf ((char *) CPP_PWRITTEN (pfile), "%ld ", line);
CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
quote_string (pfile, ip->nominal_fname);
if (file_change != same_file) {
CPP_PUTC_Q (pfile, ' ');
CPP_PUTC_Q (pfile, file_change == enter_file ? '1' : '2');
}
if (file_change != same_file)
{
CPP_PUTC_Q (pfile, ' ');
CPP_PUTC_Q (pfile, file_change == enter_file ? '1' : '2');
}
/* Tell cc1 if following text comes from a system header file. */
if (ip->system_header_p) {
CPP_PUTC_Q (pfile, ' ');
CPP_PUTC_Q (pfile, '3');
}
if (ip->system_header_p)
{
CPP_PUTC_Q (pfile, ' ');
CPP_PUTC_Q (pfile, '3');
}
#ifndef NO_IMPLICIT_EXTERN_C
/* Tell cc1plus if following text should be treated as C. */
if (ip->system_header_p == 2 && CPP_OPTIONS (pfile)->cplusplus) {
CPP_PUTC_Q (pfile, ' ');
CPP_PUTC_Q (pfile, '4');
}
if (ip->system_header_p == 2 && CPP_OPTIONS (pfile)->cplusplus)
{
CPP_PUTC_Q (pfile, ' ');
CPP_PUTC_Q (pfile, '4');
}
#endif
CPP_PUTC_Q (pfile, '\n');
pfile->lineno = line;
......@@ -1886,6 +1885,7 @@ skip_if_group (pfile)
{
if (CPP_OPTIONS (pfile)->output_conditionals)
CPP_PUTC (pfile, c);
CPP_BUMP_LINE (pfile);
continue;
}
else if (c == '#')
......@@ -1915,7 +1915,11 @@ skip_if_group (pfile)
{
/* \n */
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)
{
/* This #endif matched a #ifndef at the start of the file.
See if it is at the end of the file. */
struct parse_marker start_mark;
int c;
parse_set_mark (&start_mark, pfile);
parse_set_mark (pfile);
for (;;)
{
......@@ -2010,8 +2013,7 @@ do_endif (pfile, keyword)
if (c != '\n')
break;
}
parse_goto_mark (&start_mark, pfile);
parse_clear_mark (&start_mark);
parse_goto_mark (pfile);
if (c == EOF)
{
......@@ -2057,8 +2059,6 @@ cpp_get_token (pfile)
cpp_reader *pfile;
{
register int c, c2, c3;
long old_written;
long start_line, start_column;
enum cpp_token token;
struct cpp_options *opts = CPP_OPTIONS (pfile);
......@@ -2099,68 +2099,27 @@ cpp_get_token (pfile)
{
switch (c)
{
long newlines;
struct parse_marker start_mark;
case '/':
if (PEEKC () == '=')
goto op2;
comment:
if (opts->put_out_comments)
parse_set_mark (&start_mark, pfile);
newlines = 0;
cpp_buf_line_and_col (cpp_file_buffer (pfile),
&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;
c = copy_comment (pfile, c);
else
c = skip_comment (pfile, c);
if (c == EOF)
{
cpp_error_with_line (pfile, start_line, start_column,
"unterminated comment");
goto handle_eof;
}
c = '/'; /* Initial letter of comment. */
return_comment:
goto handle_eof;
else if (c != ' ')
goto randomchar;
/* Comments are equivalent to spaces.
For -traditional, a comment is equivalent to nothing. */
if (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;
}
else if (CPP_TRADITIONAL (pfile))
{
return CPP_COMMENT;
}
if (opts->traditional || opts->put_out_comments)
return CPP_COMMENT;
else
{
#if 0
/* 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, ' ');
CPP_PUTC (pfile, c);
return CPP_HSPACE;
}
#if 0
......@@ -2218,91 +2177,7 @@ cpp_get_token (pfile)
case '\"':
case '\'':
string:
/* A single quoted string is treated like a double -- some
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));
parse_string (pfile, c);
pfile->only_seen_white = 0;
return c == '\'' ? CPP_CHAR : CPP_STRING;
......@@ -2319,7 +2194,6 @@ cpp_get_token (pfile)
case '&':
case '+':
case '|':
NEWLINE_FIX;
c2 = PEEKC ();
if (c2 == c || c2 == '=')
goto op2;
......@@ -2330,35 +2204,14 @@ cpp_get_token (pfile)
case '%':
case '=':
case '^':
NEWLINE_FIX;
if (PEEKC () == '=')
goto op2;
goto randomchar;
case '-':
NEWLINE_FIX;
c2 = PEEKC ();
if (c2 == '-' && opts->chill)
{
/* 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;
}
goto comment; /* Chill style comment */
if (c2 == '-' || c2 == '=' || c2 == '>')
goto op2;
goto randomchar;
......@@ -2372,19 +2225,23 @@ cpp_get_token (pfile)
if (c == '>')
break;
c = GETC ();
NEWLINE_FIX1 (c);
if (c == '\n' || c == EOF)
{
cpp_error (pfile,
"missing '>' in `#include <FILENAME>'");
break;
}
else if (c == '\r')
{
/* Backslash newline is replaced by nothing. */
CPP_ADJUST_WRITTEN (pfile, -1);
CPP_BUMP_LINE (pfile);
}
}
return CPP_STRING;
}
/* else fall through */
case '>':
NEWLINE_FIX;
c2 = PEEKC ();
if (c2 == '=')
goto op2;
......@@ -2394,7 +2251,6 @@ cpp_get_token (pfile)
CPP_RESERVE (pfile, 4);
CPP_PUTC (pfile, c);
CPP_PUTC (pfile, c2);
NEWLINE_FIX;
c3 = PEEKC ();
if (c3 == '=')
CPP_PUTC_Q (pfile, GETC ());
......@@ -2413,7 +2269,7 @@ cpp_get_token (pfile)
parse_name (pfile, GETC ());
return CPP_NAME;
}
else if (is_space [c])
else if (c == ' ')
{
CPP_RESERVE (pfile, 2);
if (pfile->output_escapes)
......@@ -2430,7 +2286,6 @@ cpp_get_token (pfile)
goto randomchar;
case '.':
NEWLINE_FIX;
c2 = PEEKC ();
if (ISDIGIT(c2))
{
......@@ -2439,7 +2294,6 @@ cpp_get_token (pfile)
c = GETC ();
goto number;
}
/* FIXME - misses the case "..\\\n." */
if (c2 == '.' && PEEKN(1) == '.')
{
CPP_RESERVE(pfile, 4);
......@@ -2456,7 +2310,6 @@ cpp_get_token (pfile)
op2:
token = CPP_OTHER;
pfile->only_seen_white = 0;
op2any:
CPP_RESERVE(pfile, 3);
CPP_PUTC_Q (pfile, c);
CPP_PUTC_Q (pfile, GETC ());
......@@ -2464,7 +2317,6 @@ cpp_get_token (pfile)
return token;
case 'L':
NEWLINE_FIX;
c2 = PEEKC ();
if ((c2 == '\'' || c2 == '\"') && !CPP_TRADITIONAL (pfile))
{
......@@ -2482,7 +2334,6 @@ cpp_get_token (pfile)
{
CPP_RESERVE (pfile, 2);
CPP_PUTC_Q (pfile, c);
NEWLINE_FIX;
c = PEEKC ();
if (c == EOF)
break;
......@@ -2512,14 +2363,7 @@ cpp_get_token (pfile)
if (c == EOF)
goto chill_number_eof;
if (!is_idchar[c])
{
if (c == '\\' && PEEKC() == '\n')
{
FORWARD(2);
continue;
}
break;
}
break;
CPP_PUTC (pfile, c);
}
if (c == '\'')
......@@ -2584,10 +2428,9 @@ cpp_get_token (pfile)
decide this is not a macro call and leave things that way. */
if (hp->type == T_MACRO && hp->value.defn->nargs >= 0)
{
struct parse_marker macro_mark;
int is_macro_call, macbuf_whitespace = 0;
parse_set_mark (&macro_mark, pfile);
parse_set_mark (pfile);
for (;;)
{
cpp_skip_hspace (pfile);
......@@ -2603,14 +2446,15 @@ cpp_get_token (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)->buf))
macbuf_whitespace = 1;
parse_clear_mark (&macro_mark);
/* The mark goes away automatically when
the buffer is popped. */
cpp_pop_buffer (pfile);
parse_set_mark (&macro_mark, pfile);
parse_set_mark (pfile);
}
else
break;
......@@ -2618,11 +2462,12 @@ cpp_get_token (pfile)
}
if (!is_macro_call)
{
parse_goto_mark (&macro_mark, pfile);
parse_goto_mark (pfile);
if (macbuf_whitespace)
CPP_PUTC (pfile, ' ');
}
parse_clear_mark (&macro_mark);
else
parse_clear_mark (pfile);
if (!is_macro_call)
return CPP_NAME;
}
......@@ -2634,7 +2479,7 @@ cpp_get_token (pfile)
}
goto get_next;
case ' ': case '\t': case '\v': case '\r':
case ' ': case '\t': case '\v':
for (;;)
{
CPP_PUTC (pfile, c);
......@@ -2646,18 +2491,21 @@ cpp_get_token (pfile)
return CPP_HSPACE;
case '\\':
c2 = PEEKC ();
if (c2 != '\n')
goto randomchar;
token = CPP_HSPACE;
goto op2any;
goto randomchar;
case '\r':
/* Backslash newline is ignored. */
CPP_BUMP_LINE (pfile);
goto get_next;
case '\n':
CPP_PUTC (pfile, c);
if (pfile->only_seen_white == 0)
pfile->only_seen_white = 1;
CPP_BUMP_LINE (pfile);
pfile->lineno++;
output_line_command (pfile, 1, same_file);
if (CPP_BUFFER (pfile)->lineno != pfile->lineno)
output_line_command (pfile, 1, same_file);
return CPP_VSPACE;
case '(': token = CPP_LPAREN; goto char1;
......@@ -2697,19 +2545,15 @@ cpp_get_non_space_token (pfile)
/* Parse an identifier starting with C. */
static int
static void
parse_name (pfile, c)
cpp_reader *pfile; int c;
cpp_reader *pfile;
int c;
{
for (;;)
{
if (! is_idchar[c])
{
if (c == '\\' && PEEKC() == '\n')
{
FORWARD(2);
continue;
}
FORWARD (-1);
break;
}
......@@ -2724,7 +2568,95 @@ parse_name (pfile, c)
break;
}
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
......@@ -2752,7 +2684,7 @@ parse_assertion (pfile)
c = PEEKC();
if (c != '(')
{
if (is_hor_space[c])
if (is_hor_space[c] || c == '\r')
cpp_skip_hspace (pfile);
c = PEEKC();
}
......@@ -2772,17 +2704,17 @@ parse_assertion (pfile)
dropwhite = 1;
}
}
else if (c == '\\' && PEEKC() == '\n')
FORWARD(1);
else if (c == '\n' || c == EOF)
{
if (c == '\n') FORWARD(-1);
cpp_error (pfile, "un-terminated assertion answer");
return 0;
}
else if (c == '\r')
CPP_BUMP_LINE (pfile);
else
{
CPP_PUTC(pfile, c);
CPP_PUTC (pfile, c);
dropwhite = 0;
}
}
......@@ -2795,9 +2727,9 @@ parse_assertion (pfile)
return 0;
}
else
CPP_PUTC(pfile, ')');
CPP_PUTC (pfile, ')');
CPP_NUL_TERMINATE(pfile);
CPP_NUL_TERMINATE (pfile);
return 2;
}
......@@ -2971,62 +2903,50 @@ cpp_read_check_assertion (pfile)
return result;
}
/* Initialize PMARK to remember the current position of PFILE. */
/* Remember the current position of PFILE. */
void
parse_set_mark (pmark, pfile)
struct parse_marker *pmark;
parse_set_mark (pfile)
cpp_reader *pfile;
{
cpp_buffer *pbuf = CPP_BUFFER (pfile);
pmark->next = pbuf->marks;
pbuf->marks = pmark;
pmark->buf = pbuf;
pmark->position = pbuf->cur - pbuf->buf;
}
/* Cleanup PMARK - we no longer need it. */
cpp_buffer *ip = CPP_BUFFER (pfile);
if (ip->mark != -1)
cpp_fatal (pfile,
"cpp internal error: ip->mark != -1 in parse_set_mark");
void
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;
ip->mark = ip->cur - ip->buf;
}
/* Backup the current position of PFILE to that saved in PMARK. */
/* Clear the current mark - we no longer need it. */
void
parse_goto_mark (pmark, pfile)
struct parse_marker *pmark;
parse_clear_mark (pfile)
cpp_reader *pfile;
{
cpp_buffer *pbuf = CPP_BUFFER (pfile);
if (pbuf != pmark->buf)
cpp_fatal (pfile, "internal error %s", "parse_goto_mark");
pbuf->cur = pbuf->buf + pmark->position;
cpp_buffer *ip = CPP_BUFFER (pfile);
if (ip->mark == -1)
cpp_fatal (pfile,
"cpp internal error: ip->mark == -1 in parse_clear_mark");
ip->mark = -1;
}
/* Reset PMARK to point to the current position of PFILE. (Same
as parse_clear_mark (PMARK), parse_set_mark (PMARK, PFILE) but faster. */
/* Backup the current position of PFILE to that saved in its mark,
and clear the mark. */
void
parse_move_mark (pmark, pfile)
struct parse_marker *pmark;
parse_goto_mark (pfile)
cpp_reader *pfile;
{
cpp_buffer *pbuf = CPP_BUFFER (pfile);
if (pbuf != pmark->buf)
cpp_fatal (pfile, "internal error %s", "parse_move_mark");
pmark->position = pbuf->cur - pbuf->buf;
cpp_buffer *ip = CPP_BUFFER (pfile);
if (ip->mark == -1)
cpp_fatal (pfile,
"cpp internal error: ip->mark == -1 in parse_goto_mark");
ip->cur = ip->buf + ip->mark;
ip->mark = -1;
}
void
cpp_print_file_and_line (pfile)
cpp_reader *pfile;
......
......@@ -72,19 +72,9 @@ enum cpp_token {
typedef enum cpp_token (*parse_underflow_t) PARAMS((cpp_reader *));
typedef int (*parse_cleanup_t) PARAMS((cpp_buffer *, cpp_reader *));
/* A parse_marker indicates a previous position,
which we can backtrack to. */
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 void parse_set_mark PARAMS ((cpp_reader *));
extern void parse_clear_mark PARAMS ((cpp_reader *));
extern void parse_goto_mark PARAMS ((cpp_reader *));
extern int cpp_handle_option 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 *));
/* This frees resources used by 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
{
unsigned char *cur; /* current position */
unsigned char *rlimit; /* end of valid data */
unsigned char *buf; /* entire buffer */
unsigned char *alimit; /* end of allocated buffer */
unsigned char *line_base; /* start of current line */
struct cpp_buffer *prev;
......@@ -120,13 +108,13 @@ struct cpp_buffer
to record control macros. */
struct include_hash *ihash;
long line_base;
long lineno; /* Line 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_cleanup_t cleanup;
void *data;
struct parse_marker *marks;
/* Value of if_stack at start of this file.
Used to prohibit unmatched #endif (etc) in an include file. */
struct if_stack *if_stack;
......@@ -289,8 +277,12 @@ struct cpp_reader
#define CPP_ADJUST_WRITTEN(PFILE,DELTA) ((PFILE)->limit += (DELTA))
#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_PREV_BUFFER(BUFFER) ((BUFFER)->prev)
/* 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