aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorZack Weinberg <zack@rabi.columbia.edu>1999-03-16 13:10:15 +0000
committerDave Brolley <brolley@gcc.gnu.org>1999-03-16 08:10:15 -0500
commit3fdc651fed8f150778148b0409c0d2852f8b571a (patch)
treeaca71f4d74eba9693f38e9c8c1736e1b2c31167f /gcc
parentd888cbc4929b8825f434502d245c5ad93509502a (diff)
downloadgcc-3fdc651fed8f150778148b0409c0d2852f8b571a.zip
gcc-3fdc651fed8f150778148b0409c0d2852f8b571a.tar.gz
gcc-3fdc651fed8f150778148b0409c0d2852f8b571a.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog55
-rw-r--r--gcc/cppexp.c8
-rw-r--r--gcc/cppfiles.c325
-rw-r--r--gcc/cpphash.c2
-rw-r--r--gcc/cppinit.c9
-rw-r--r--gcc/cpplib.c820
-rw-r--r--gcc/cpplib.h30
7 files changed, 666 insertions, 583 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 398ab23..f697c1c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,58 @@
+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
diff --git a/gcc/cppexp.c b/gcc/cppexp.c
index 8b59630..eaec468 100644
--- a/gcc/cppexp.c
+++ b/gcc/cppexp.c
@@ -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 != ')')
diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c
index ef78ee3..7828569 100644
--- a/gcc/cppfiles.c
+++ b/gcc/cppfiles.c
@@ -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;
diff --git a/gcc/cpphash.c b/gcc/cpphash.c
index 0f95d8a..ff63bd8 100644
--- a/gcc/cpphash.c
+++ b/gcc/cpphash.c
@@ -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;
diff --git a/gcc/cppinit.c b/gcc/cppinit.c
index c393308..08bbff4 100644
--- a/gcc/cppinit.c
+++ b/gcc/cppinit.c
@@ -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[')'] = ']';
diff --git a/gcc/cpplib.c b/gcc/cpplib.c
index c55eafa..8cbe548 100644
--- a/gcc/cpplib.c
+++ b/gcc/cpplib.c
@@ -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;
diff --git a/gcc/cpplib.h b/gcc/cpplib.h
index e2bb414..9af3b4b 100644
--- a/gcc/cpplib.h
+++ b/gcc/cpplib.h
@@ -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. */