Commit 64aaf407 by Neil Booth Committed by Neil Booth

cppexp.c (parse_charconst): Null does not end character constants.

	* cppexp.c (parse_charconst): Null does not end character
	constants.
	* cppinit.c (ISTABLE): Null character handled as whitespace.
	* cpplex.c (null_warning):  new function.
	(skip_string): Emit warning if nulls encountered.
	(_cpp_skip_hspace): Emit warning if nulls encountered.
	(_cpp_lex_token): Emit warning if nulls encountered.  Drop
	them.
	* cpp.texi: Update.

From-SVN: r33013
parent 62828c00
2000-04-08 Neil Booth <NeilB@earthling.net>
* cppexp.c (parse_charconst): Null does not end character
constants.
* cppinit.c (ISTABLE): Null character handled as whitespace.
* cpplex.c (null_warning): new function.
(skip_string): Emit warning if nulls encountered.
(_cpp_skip_hspace): Emit warning if nulls encountered.
(_cpp_lex_token): Emit warning if nulls encountered. Drop
them.
* cpp.texi: Update.
2000-04-07 Richard Henderson <rth@cygnus.com> 2000-04-07 Richard Henderson <rth@cygnus.com>
* flow.c (loop_depth): Remove. * flow.c (loop_depth): Remove.
......
...@@ -138,6 +138,7 @@ and this may cause problems with other languages. ...@@ -138,6 +138,7 @@ and this may cause problems with other languages.
@node Global Actions, Directives, Top, Top @node Global Actions, Directives, Top, Top
@section Transformations Made Globally @section Transformations Made Globally
@cindex ASCII NUL handling
Most C preprocessor features are inactive unless you give specific directives Most C preprocessor features are inactive unless you give specific directives
to request their use. (Preprocessing directives are lines starting with to request their use. (Preprocessing directives are lines starting with
...@@ -214,6 +215,43 @@ This exception is relevant only if you use the @samp{-trigraphs} ...@@ -214,6 +215,43 @@ This exception is relevant only if you use the @samp{-trigraphs}
option to enable trigraph processing. @xref{Invocation}. option to enable trigraph processing. @xref{Invocation}.
@end itemize @end itemize
The preprocessor handles null characters embedded in the input file
depending upon the context in which the null appears. Note that here we
are referring not to the two-character escape sequence "\0", but to the
single character ASCII NUL.
There are three different contexts in which a null character may
appear:-
@itemize @bullet
@item
Within comments. Here, null characters are silently ignored.
@item
Within a string or character constant. Here the preprocessor emits a
warning, but preserves the null character and passes it through to the
output file.
@item
In any other context, the preprocessor issues a warning, and discards
the null character. In all other respects the preprocessor treats it
like whitespace, combining it with any surrounding whitespace to become
a single whitespace token. Representing the null character by "^@@",
this means that code like
@example
#define X^@@1
@end example
is equivalent to
@example
#define X 1
@end example
and X is defined with replacement text "1".
@end itemize
@node Directives, Header Files, Global Actions, Top @node Directives, Header Files, Global Actions, Top
@section Preprocessing Directives @section Preprocessing Directives
......
...@@ -274,7 +274,7 @@ parse_charconst (pfile, start, end) ...@@ -274,7 +274,7 @@ parse_charconst (pfile, start, end)
while (ptr < end) while (ptr < end)
{ {
c = *ptr++; c = *ptr++;
if (c == '\'' || c == '\0') if (c == '\'')
break; break;
else if (c == '\\') else if (c == '\\')
{ {
......
...@@ -265,7 +265,7 @@ ISTABLE ...@@ -265,7 +265,7 @@ ISTABLE
N('1') N('2') N('3') N('4') N('5') N('6') N('7') N('8') N('9') N('0') N('1') N('2') N('3') N('4') N('5') N('6') N('7') N('8') N('9') N('0')
H(' ') H('\t') H('\v') H('\f') H('\0') H(' ') H('\t') H('\v') H('\f')
S('\n') S('\n')
END END
......
...@@ -45,6 +45,7 @@ static void skip_string PARAMS ((cpp_reader *, int)); ...@@ -45,6 +45,7 @@ static void skip_string PARAMS ((cpp_reader *, int));
static void parse_string PARAMS ((cpp_reader *, int)); static void parse_string PARAMS ((cpp_reader *, int));
static U_CHAR *find_position PARAMS ((U_CHAR *, U_CHAR *, unsigned long *)); static U_CHAR *find_position PARAMS ((U_CHAR *, U_CHAR *, unsigned long *));
static int null_cleanup PARAMS ((cpp_buffer *, cpp_reader *)); static int null_cleanup PARAMS ((cpp_buffer *, cpp_reader *));
static void null_warning PARAMS ((cpp_reader *, unsigned int));
/* Re-allocates PFILE->token_buffer so it will hold at least N more chars. */ /* Re-allocates PFILE->token_buffer so it will hold at least N more chars. */
...@@ -381,23 +382,38 @@ copy_comment (pfile, m) ...@@ -381,23 +382,38 @@ copy_comment (pfile, m)
return ' '; return ' ';
} }
static void
null_warning (pfile, count)
cpp_reader *pfile;
unsigned int count;
{
if (count == 1)
cpp_warning (pfile, "embedded null character ignored");
else
cpp_warning (pfile, "embedded null characters ignored");
}
/* Skip whitespace \-newline and comments. Does not macro-expand. */ /* Skip whitespace \-newline and comments. Does not macro-expand. */
void void
_cpp_skip_hspace (pfile) _cpp_skip_hspace (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
unsigned int null_count = 0;
int c; int c;
while (1) while (1)
{ {
c = GETC(); c = GETC();
if (c == EOF) if (c == EOF)
return; goto out;
else if (is_hspace(c)) else if (is_hspace(c))
{ {
if ((c == '\f' || c == '\v') && CPP_PEDANTIC (pfile)) if ((c == '\f' || c == '\v') && CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile, "%s in preprocessing directive", cpp_pedwarn (pfile, "%s in preprocessing directive",
c == '\f' ? "formfeed" : "vertical tab"); c == '\f' ? "formfeed" : "vertical tab");
else if (c == '\0')
null_count++;
} }
else if (c == '\r') else if (c == '\r')
{ {
...@@ -423,6 +439,9 @@ _cpp_skip_hspace (pfile) ...@@ -423,6 +439,9 @@ _cpp_skip_hspace (pfile)
break; break;
} }
FORWARD(-1); FORWARD(-1);
out:
if (null_count)
null_warning (pfile, null_count);
} }
/* Read and discard the rest of the current line. */ /* Read and discard the rest of the current line. */
...@@ -505,8 +524,9 @@ skip_string (pfile, c) ...@@ -505,8 +524,9 @@ skip_string (pfile, c)
int c; int c;
{ {
long start_line, start_column; long start_line, start_column;
cpp_buf_line_and_col (cpp_file_buffer (pfile), &start_line, &start_column); unsigned int null_count = 0;
cpp_buf_line_and_col (cpp_file_buffer (pfile), &start_line, &start_column);
while (1) while (1)
{ {
int cc = GETC(); int cc = GETC();
...@@ -521,8 +541,12 @@ skip_string (pfile, c) ...@@ -521,8 +541,12 @@ skip_string (pfile, c)
pfile->multiline_string_line, -1, pfile->multiline_string_line, -1,
"possible real start of unterminated constant"); "possible real start of unterminated constant");
pfile->multiline_string_line = 0; pfile->multiline_string_line = 0;
return; goto out;
case '\0':
null_count++;
break;
case '\n': case '\n':
CPP_BUMP_LINE (pfile); CPP_BUMP_LINE (pfile);
/* In Fortran and assembly language, silently terminate /* In Fortran and assembly language, silently terminate
...@@ -533,7 +557,7 @@ skip_string (pfile, c) ...@@ -533,7 +557,7 @@ skip_string (pfile, c)
|| CPP_OPTION (pfile, lang_asm)) || CPP_OPTION (pfile, lang_asm))
{ {
FORWARD(-1); FORWARD(-1);
return; goto out;
} }
/* Character constants may not extend over multiple lines. /* Character constants may not extend over multiple lines.
In Standard C, neither may strings. We accept multiline In Standard C, neither may strings. We accept multiline
...@@ -543,7 +567,7 @@ skip_string (pfile, c) ...@@ -543,7 +567,7 @@ skip_string (pfile, c)
cpp_error_with_line (pfile, start_line, start_column, cpp_error_with_line (pfile, start_line, start_column,
"unterminated character constant"); "unterminated character constant");
FORWARD(-1); FORWARD(-1);
return; goto out;
} }
if (CPP_PEDANTIC (pfile) && pfile->multiline_string_line == 0) if (CPP_PEDANTIC (pfile) && pfile->multiline_string_line == 0)
cpp_pedwarn_with_line (pfile, start_line, start_column, cpp_pedwarn_with_line (pfile, start_line, start_column,
...@@ -570,10 +594,16 @@ skip_string (pfile, c) ...@@ -570,10 +594,16 @@ skip_string (pfile, c)
case '\"': case '\"':
case '\'': case '\'':
if (cc == c) if (cc == c)
return; goto out;
break; break;
} }
} }
out:
if (null_count == 1)
cpp_warning (pfile, "null character in string or character constant");
else if (null_count > 1)
cpp_warning (pfile, "null characters in string or character constant");
} }
/* Parse a string and copy it to the output. */ /* Parse a string and copy it to the output. */
...@@ -976,16 +1006,25 @@ _cpp_lex_token (pfile) ...@@ -976,16 +1006,25 @@ _cpp_lex_token (pfile)
_cpp_parse_name (pfile, c); _cpp_parse_name (pfile, c);
return CPP_MACRO; return CPP_MACRO;
case ' ': case '\t': case '\v': case '\f': case ' ': case '\t': case '\v': case '\f': case '\0':
for (;;) {
{ int null_count = 0;
CPP_PUTC (pfile, c);
c = PEEKC (); for (;;)
if (c == EOF || !is_hspace(c)) {
break; if (c == '\0')
FORWARD(1); null_count++;
} else
return CPP_HSPACE; CPP_PUTC (pfile, c);
c = PEEKC ();
if (c == EOF || !is_hspace(c))
break;
FORWARD(1);
}
if (null_count)
null_warning (pfile, null_count);
return CPP_HSPACE;
}
case '\r': case '\r':
if (CPP_BUFFER (pfile)->has_escapes) if (CPP_BUFFER (pfile)->has_escapes)
......
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