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

Reply via email to