OSDN Git Service

libcpp
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 7 Jan 2008 17:23:40 +0000 (17:23 +0000)
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 7 Jan 2008 17:23:40 +0000 (17:23 +0000)
2008-01-07  Fred Fish  <fnf@specifix.com>
PR preprocessor/30363:
* traditional.c (replace_args_and_push): Add local variable
cxtquote, calculate the replacement text size assuming a
worst case of every input character quoted with backslash,
and properly handle output quoting of quote characters in
actual arguments used in function-like macros.
gcc/testsuite
2008-01-07  Fred Fish  <fnf@specifix.com>
PR preprocessor/30363:
* gcc.dg/cpp/trad/macroargs.c: Add code to test quoting in
macro expansions.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@131379 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/cpp/trad/macroargs.c
libcpp/ChangeLog
libcpp/traditional.c

index ee0d673..6a9f9b5 100644 (file)
@@ -1,3 +1,9 @@
+2008-01-07  Fred Fish  <fnf@specifix.com>
+
+       PR preprocessor/30363:
+       * gcc.dg/cpp/trad/macroargs.c: Add code to test quoting in
+       macro expansions.
+
 2008-01-07  Paul Thomas  <pault@gcc.gnu.org>
 
        PR fortran/34672
index ce28ccc..c5f91d9 100644 (file)
@@ -8,6 +8,17 @@
 
 extern void abort (void);
 
+void testquoting ()
+{
+  const char *str1 = f("a", "\"a\"");
+  const char *str2 = f( \t, " \t");
+
+  if (strcmp (str1, "\"a\"  \"\\\"a\\\"\""))
+    abort ();
+  if (strcmp (str2, " \t  \" \\t\""))
+    abort ();
+}
+
 int main ()
 {
   const char *str1 = f( foo ,bar);
@@ -26,5 +37,7 @@ foo
 , 2"), "1 , 2"))       
     abort ();
 
+  testquoting ();
+
   return 0;
 }
index 335686f..574e054 100644 (file)
@@ -1,3 +1,12 @@
+2008-01-07  Fred Fish  <fnf@specifix.com>
+
+       PR preprocessor/30363:
+       * traditional.c (replace_args_and_push): Add local variable
+       cxtquote, calculate the replacement text size assuming a 
+       worst case of every input character quoted with backslash,
+       and properly handle output quoting of quote characters in
+       actual arguments used in function-like macros.
+
 2008-01-03  Tom Tromey  <tromey@redhat.com>
 
        PR preprocessor/34602.
index 7ca3cfd..6c4dda1 100644 (file)
@@ -1,5 +1,5 @@
 /* CPP Library - traditional lexical analysis and macro expansion.
-   Copyright (C) 2002, 2004, 2005, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
    Contributed by Neil Booth, May 2002
 
 This program is free software; you can redistribute it and/or modify it
@@ -832,8 +832,11 @@ replace_args_and_push (cpp_reader *pfile, struct fun_macro *fmacro)
       uchar *p;
       _cpp_buff *buff;
       size_t len = 0;
+      int cxtquote = 0;
 
-      /* Calculate the length of the argument-replaced text.  */
+      /* Get an estimate of the length of the argument-replaced text.
+        This is a worst case estimate, assuming that every replacement
+        text character needs quoting.  */
       for (exp = macro->exp.text;;)
        {
          struct block *b = (struct block *) exp;
@@ -841,8 +844,8 @@ replace_args_and_push (cpp_reader *pfile, struct fun_macro *fmacro)
          len += b->text_len;
          if (b->arg_index == 0)
            break;
-         len += (fmacro->args[b->arg_index]
-                 - fmacro->args[b->arg_index - 1] - 1);
+         len += 2 * (fmacro->args[b->arg_index]
+                     - fmacro->args[b->arg_index - 1] - 1);
          exp += BLOCK_LEN (b->text_len);
        }
 
@@ -850,21 +853,69 @@ replace_args_and_push (cpp_reader *pfile, struct fun_macro *fmacro)
       buff = _cpp_get_buff (pfile, len + 1);
 
       /* Copy the expansion and replace arguments.  */
+      /* Accumulate actual length, including quoting as necessary */
       p = BUFF_FRONT (buff);
+      len = 0;
       for (exp = macro->exp.text;;)
        {
          struct block *b = (struct block *) exp;
          size_t arglen;
+         int argquote;
+         uchar *base;
+         uchar *in;
 
-         memcpy (p, b->text, b->text_len);
-         p += b->text_len;
+         len += b->text_len;
+         /* Copy the non-argument text literally, keeping
+            track of whether matching quotes have been seen. */
+         for (arglen = b->text_len, in = b->text; arglen > 0; arglen--)
+           {
+             if (*in == '"')
+               cxtquote = ! cxtquote;
+             *p++ = *in++;
+           }
+         /* Done if no more arguments */
          if (b->arg_index == 0)
            break;
          arglen = (fmacro->args[b->arg_index]
                    - fmacro->args[b->arg_index - 1] - 1);
-         memcpy (p, pfile->out.base + fmacro->args[b->arg_index - 1],
-                 arglen);
-         p += arglen;
+         base = pfile->out.base + fmacro->args[b->arg_index - 1];
+         in = base;
+#if 0
+         /* Skip leading whitespace in the text for the argument to
+            be substituted. To be compatible with gcc 2.95, we would
+            also need to trim trailing whitespace. Gcc 2.95 trims
+            leading and trailing whitespace, which may be a bug.  The
+            current gcc testsuite explicitly checks that this leading
+            and trailing whitespace in actual arguments is
+            preserved. */
+         while (arglen > 0 && is_space (*in))
+           {
+             in++;
+             arglen--;
+           }
+#endif
+         for (argquote = 0; arglen > 0; arglen--)
+           {
+             if (cxtquote && *in == '"')
+               {
+                 if (in > base && *(in-1) != '\\')
+                   argquote = ! argquote;
+                 /* Always add backslash before double quote if argument
+                    is expanded in a quoted context */
+                 *p++ = '\\';
+                 len++;
+               }
+             else if (cxtquote && argquote && *in == '\\')
+               {
+                 /* Always add backslash before a backslash in an argument
+                    that is expanded in a quoted context and also in the
+                    range of a quoted context in the argument itself. */
+                 *p++ = '\\';
+                 len++;
+               }
+             *p++ = *in++;
+             len++;
+           }
          exp += BLOCK_LEN (b->text_len);
        }