diff options
author | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-01-07 17:23:40 +0000 |
---|---|---|
committer | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-01-07 17:23:40 +0000 |
commit | 7a1a608c6cb1ff69ef524fcea5612ff8d7c20350 (patch) | |
tree | af95efa577b60bab897bc59c18fc2148c61eb432 /libcpp/traditional.c | |
parent | b041d14713572ad7f62b04ea5c8d2a03b63920eb (diff) | |
download | gcc-7a1a608c6cb1ff69ef524fcea5612ff8d7c20350.tar.gz |
libcpp
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
Diffstat (limited to 'libcpp/traditional.c')
-rw-r--r-- | libcpp/traditional.c | 69 |
1 files changed, 60 insertions, 9 deletions
diff --git a/libcpp/traditional.c b/libcpp/traditional.c index 7ca3cfd9296..6c4dda1a9f3 100644 --- a/libcpp/traditional.c +++ b/libcpp/traditional.c @@ -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); } |