OSDN Git Service

PR c++/43680
[pf3gnuchains/gcc-fork.git] / libcpp / traditional.c
index 85be487..7ff11bb 100644 (file)
@@ -1,10 +1,11 @@
 /* CPP Library - traditional lexical analysis and macro expansion.
 /* CPP Library - traditional lexical analysis and macro expansion.
-   Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2004, 2005, 2007, 2008, 2009
+   Free Software Foundation, Inc.
    Contributed by Neil Booth, May 2002
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
    Contributed by Neil Booth, May 2002
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
+Free Software Foundation; either version 3, or (at your option) any
 later version.
 
 This program is distributed in the hope that it will be useful,
 later version.
 
 This program is distributed in the hope that it will be useful,
@@ -13,8 +14,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+along with this program; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
 
 #include "config.h"
 #include "system.h"
@@ -60,7 +61,7 @@ struct fun_macro
   size_t offset;
 
   /* The line the macro name appeared on.  */
   size_t offset;
 
   /* The line the macro name appeared on.  */
-  unsigned int line;
+  source_location line;
 
   /* Zero-based index of argument being currently lexed.  */
   unsigned int argc;
 
   /* Zero-based index of argument being currently lexed.  */
   unsigned int argc;
@@ -107,7 +108,7 @@ check_output_buffer (cpp_reader *pfile, size_t n)
       size_t size = pfile->out.cur - pfile->out.base;
       size_t new_size = (size + n) * 3 / 2;
 
       size_t size = pfile->out.cur - pfile->out.base;
       size_t new_size = (size + n) * 3 / 2;
 
-      pfile->out.base = xrealloc (pfile->out.base, new_size);
+      pfile->out.base = XRESIZEVEC (unsigned char, pfile->out.base, new_size);
       pfile->out.limit = pfile->out.base + new_size;
       pfile->out.cur = pfile->out.base + size;
     }
       pfile->out.limit = pfile->out.base + new_size;
       pfile->out.cur = pfile->out.base + size;
     }
@@ -253,8 +254,8 @@ lex_identifier (cpp_reader *pfile, const uchar *cur)
 
   CUR (pfile->context) = cur;
   len = out - pfile->out.cur;
 
   CUR (pfile->context) = cur;
   len = out - pfile->out.cur;
-  result = (cpp_hashnode *) ht_lookup (pfile->hash_table, pfile->out.cur,
-                                      len, HT_ALLOC);
+  result = CPP_HASHNODE (ht_lookup (pfile->hash_table, pfile->out.cur,
+                                   len, HT_ALLOC));
   pfile->out.cur = out;
   return result;
 }
   pfile->out.cur = out;
   return result;
 }
@@ -353,6 +354,11 @@ _cpp_scan_out_logical_line (cpp_reader *pfile, cpp_macro *macro)
   const uchar *start_of_input_line;
 
   fmacro.buff = NULL;
   const uchar *start_of_input_line;
 
   fmacro.buff = NULL;
+  fmacro.args = NULL;
+  fmacro.node = NULL;
+  fmacro.offset = 0;
+  fmacro.line = 0;
+  fmacro.argc = 0;
 
   quote = 0;
   header_ok = pfile->state.angled_headers;
 
   quote = 0;
   header_ok = pfile->state.angled_headers;
@@ -827,8 +833,11 @@ replace_args_and_push (cpp_reader *pfile, struct fun_macro *fmacro)
       uchar *p;
       _cpp_buff *buff;
       size_t len = 0;
       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;
       for (exp = macro->exp.text;;)
        {
          struct block *b = (struct block *) exp;
@@ -836,8 +845,8 @@ replace_args_and_push (cpp_reader *pfile, struct fun_macro *fmacro)
          len += b->text_len;
          if (b->arg_index == 0)
            break;
          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);
        }
 
          exp += BLOCK_LEN (b->text_len);
        }
 
@@ -845,21 +854,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.  */
       buff = _cpp_get_buff (pfile, len + 1);
 
       /* Copy the expansion and replace arguments.  */
+      /* Accumulate actual length, including quoting as necessary */
       p = BUFF_FRONT (buff);
       p = BUFF_FRONT (buff);
+      len = 0;
       for (exp = macro->exp.text;;)
        {
          struct block *b = (struct block *) exp;
          size_t arglen;
       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);
          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);
        }
 
          exp += BLOCK_LEN (b->text_len);
        }
 
@@ -1069,7 +1126,7 @@ bool
 _cpp_expansions_different_trad (const cpp_macro *macro1,
                                const cpp_macro *macro2)
 {
 _cpp_expansions_different_trad (const cpp_macro *macro1,
                                const cpp_macro *macro2)
 {
-  uchar *p1 = xmalloc (macro1->count + macro2->count);
+  uchar *p1 = XNEWVEC (uchar, macro1->count + macro2->count);
   uchar *p2 = p1 + macro1->count;
   uchar quote1 = 0, quote2 = 0;
   bool mismatch;
   uchar *p2 = p1 + macro1->count;
   uchar quote1 = 0, quote2 = 0;
   bool mismatch;