/* CPP Library - traditional lexical analysis and macro expansion.
- Copyright (C) 2002, 2004, 2005, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2002-2014 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
-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,
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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+along with this program; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
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;
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;
}
do
{
depth++;
- if (context->macro == node && depth > 20)
+ if (context->c.macro == node && depth > 20)
break;
context = context->prev;
}
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;
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);
}
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);
}