Issue ----- This patch covers the following issues: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51259 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64965 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66317
According to: https://gcc.gnu.org/onlinedocs/gcc-5.3.0/cpp/Preprocessor-Output.html#Preprocessor-Output The filename in line markers should never contain any non-printing characters; they are replaced with octal escape sequences. I understand the issues that may arise from the discussion here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66318). Nonetheless, I think, at the very minimum, characters such as the newline and the backspace characters should be escaped - either by an octal-escape-sequence or by the regular escapes (i.e., \n and \b). I noticed that the cpp_quote_string() routine used to convert non-printable characters to octal-escape-sequences prior to https://gcc.gnu.org/viewvc/gcc?view=revision&revision=106463. This patch reimplements this conversion, but with an extra check whether such replacement is desired. This is enabled in the case of __FILE__ and when printing line markers. Testing was done against trunk on x86_64-pc-linux-gnu. Test case 1 ----------- $ gcc -E -x c - #line 1 "\n" __FILE__ Test case 2 ----------- $ gcc -E -x c - #line 1 "\b" gcc/testsuite/ChangeLog ----------------------- 2016-03-20 Daniel Sabogal <dsabo...@ufl.edu> PR preprocessor/64965 PR preprocessor/66317 * gcc.dg/cpp/line9.c: New test. libcpp/ChangeLog ---------------- 2016-03-20 Daniel Sabogal <dsabo...@ufl.edu> PR preprocessor/51259 PR preprocessor/64965 PR preprocessor/66317 * include/cpplib.h (cpp_quote_string): Add boolean parameter. * macro.c (cpp_quote_string): Add parameter to request for non-print characters to be replaced with octal escape sequences. (_cpp_builtin_macro_text): Allow replacement when calling "cpp_quote_string". Adjust the allocated buffer size. (stringify_arg): Disallow replacement when calling "cpp_quote_string". Adjust the allocated buffer size. gcc/c-family/ChangeLog ---------------------- 2016-03-20 Daniel Sabogal <dsabo...@ufl.edu> PR preprocessor/51259 c-ppoutput.c (print_line_1): Allow octal escape sequence replacement when calling "cpp_quote_string". Adjust allocated buffer length. (pp_dir_change): Allow replacement when calling "cpp_quote_string". Patch (trunk) ------------- Index: gcc/c-family/c-ppoutput.c ================================ --- gcc/c-family/c-ppoutput.c (revision 234355) +++ gcc/c-family/c-ppoutput.c (working copy) @@ -408,7 +408,8 @@ ourselves. */ p = cpp_quote_string (to_file_quoted, (const unsigned char *) file_path, - to_file_len); + to_file_len, + true); *p = '\0'; fprintf (stream, "# %u \"%s\"%s", print.src_line == 0 ? 1 : print.src_line, @@ -629,7 +630,10 @@ unsigned char *p; /* cpp_quote_string does not nul-terminate, so we have to do it ourselves. */ - p = cpp_quote_string (to_file_quoted, (const unsigned char *) dir, to_file_len); + p = cpp_quote_string (to_file_quoted, + (const unsigned char *) dir, + to_file_len, + true); *p = '\0'; fprintf (print.outf, "# 1 \"%s//\"\n", to_file_quoted); } Index: libcpp/include/cpplib.h =================================================================== --- libcpp/include/cpplib.h (revision 234355) +++ libcpp/include/cpplib.h (working copy) @@ -1065,7 +1065,7 @@ extern void cpp_scan_nooutput (cpp_reader *); extern int cpp_sys_macro_p (cpp_reader *); extern unsigned char *cpp_quote_string (unsigned char *, const unsigned char *, - unsigned int); + unsigned int, bool); /* In files.c */ extern bool cpp_included (cpp_reader *, const char *); Index: libcpp/macro.c =================================================================== --- libcpp/macro.c (revision 234355) +++ libcpp/macro.c (working copy) @@ -300,10 +300,10 @@ abort (); } len = strlen (name); - buf = _cpp_unaligned_alloc (pfile, len * 2 + 3); + buf = _cpp_unaligned_alloc (pfile, len * 4 + 3); result = buf; *buf = '"'; - buf = cpp_quote_string (buf + 1, (const unsigned char *) name, len); + buf = cpp_quote_string (buf + 1, (const unsigned char *) name, len, true); *buf++ = '"'; *buf = '\0'; } @@ -477,10 +477,11 @@ } /* Copies SRC, of length LEN, to DEST, adding backslashes before all - backslashes and double quotes. DEST must be of sufficient size. + backslashes and double quotes. If OCT is set, all non-print characters will + be converted to an escaped octal. DEST must be of sufficient size. Returns a pointer to the end of the string. */ uchar * -cpp_quote_string (uchar *dest, const uchar *src, unsigned int len) +cpp_quote_string (uchar *dest, const uchar *src, unsigned int len, bool oct) { while (len--) { @@ -487,12 +488,17 @@ uchar c = *src++; if (c == '\\' || c == '"') - { - *dest++ = '\\'; - *dest++ = c; - } + { + *dest++ = '\\'; + *dest++ = c; + } + else if (!oct || ISPRINT (c)) + *dest++ = c; else - *dest++ = c; + { + sprintf((char *) dest, "\\%03o", c); + dest += 4; + } } return dest; @@ -539,7 +545,7 @@ final quote and NUL. */ len = cpp_token_len (token); if (escape_it) - len *= 4; + len *= 2; len += 3; if ((size_t) (BUFF_LIMIT (pfile->u_buff) - dest) < len) @@ -564,7 +570,7 @@ _cpp_buff *buff = _cpp_get_buff (pfile, len); unsigned char *buf = BUFF_FRONT (buff); len = cpp_spell_token (pfile, token, buf, true) - buf; - dest = cpp_quote_string (dest, buf, len); + dest = cpp_quote_string (dest, buf, len, false); _cpp_release_buff (pfile, buff); } else