Merge topic 'cmOutputConverter-stringstream'

d645b03e cmOutputConverter: implement Shell__GetArgument using ostringstream
This commit is contained in:
Brad King 2016-06-16 09:46:56 -04:00 committed by CMake Topic Stage
commit a854e1795f
2 changed files with 39 additions and 192 deletions

View File

@ -15,6 +15,7 @@
#include "cmake.h" #include "cmake.h"
#include <assert.h> #include <assert.h>
#include <sstream>
#include <ctype.h> /* isalpha */ #include <ctype.h> /* isalpha */
#include <string.h> /* strlen */ #include <string.h> /* strlen */
@ -328,19 +329,9 @@ std::string cmOutputConverter::EscapeForShell(const std::string& str,
flags |= Shell_Flag_NMake; flags |= Shell_Flag_NMake;
} }
// Compute the buffer size needed. return this->GetState()->UseWindowsShell()
int size = (this->GetState()->UseWindowsShell() ? Shell_GetArgumentForWindows(str.c_str(), flags)
? Shell_GetArgumentSizeForWindows(str.c_str(), flags) : Shell_GetArgumentForUnix(str.c_str(), flags);
: Shell_GetArgumentSizeForUnix(str.c_str(), flags));
// Compute the shell argument itself.
std::vector<char> arg(size);
if (this->GetState()->UseWindowsShell()) {
Shell_GetArgumentForWindows(str.c_str(), &arg[0], flags);
} else {
Shell_GetArgumentForUnix(str.c_str(), &arg[0], flags);
}
return std::string(&arg[0]);
} }
std::string cmOutputConverter::EscapeForCMake(const std::string& str) std::string cmOutputConverter::EscapeForCMake(const std::string& str)
@ -369,18 +360,7 @@ std::string cmOutputConverter::EscapeForCMake(const std::string& str)
std::string cmOutputConverter::EscapeWindowsShellArgument(const char* arg, std::string cmOutputConverter::EscapeWindowsShellArgument(const char* arg,
int shell_flags) int shell_flags)
{ {
char local_buffer[1024]; return Shell_GetArgumentForWindows(arg, shell_flags);
char* buffer = local_buffer;
int size = Shell_GetArgumentSizeForWindows(arg, shell_flags);
if (size > 1024) {
buffer = new char[size];
}
Shell_GetArgumentForWindows(arg, buffer, shell_flags);
std::string result(buffer);
if (buffer != local_buffer) {
delete[] buffer;
}
return result;
} }
cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat( cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat(
@ -586,12 +566,10 @@ int cmOutputConverter::Shell__ArgumentNeedsQuotes(const char* in, int isUnix,
return 0; return 0;
} }
int cmOutputConverter::Shell__GetArgumentSize(const char* in, int isUnix, std::string cmOutputConverter::Shell__GetArgument(const char* in, int isUnix,
int flags) int flags)
{ {
/* Start with the length of the original argument, plus one for std::ostringstream out;
either a terminating null or a separating space. */
int size = (int)strlen(in) + 1;
/* String iterator. */ /* String iterator. */
const char* c; const char* c;
@ -599,116 +577,17 @@ int cmOutputConverter::Shell__GetArgumentSize(const char* in, int isUnix,
/* Keep track of how many backslashes have been encountered in a row. */ /* Keep track of how many backslashes have been encountered in a row. */
int windows_backslashes = 0; int windows_backslashes = 0;
/* Scan the string for characters that require escaping or quoting. */
for (c = in; *c; ++c) {
/* Look for $(MAKEVAR) syntax if requested. */
if (flags & Shell_Flag_AllowMakeVariables) {
/* Skip over the make variable references if any are present. */
c = Shell__SkipMakeVariables(c);
/* Stop if we have reached the end of the string. */
if (!*c) {
break;
}
}
/* Check whether this character needs escaping for the shell. */
if (isUnix) {
/* On Unix a few special characters need escaping even inside a
quoted argument. */
if (*c == '\\' || *c == '"' || *c == '`' || *c == '$') {
/* This character needs a backslash to escape it. */
++size;
}
} else if (flags & Shell_Flag_EchoWindows) {
/* On Windows the built-in command shell echo never needs escaping. */
} else {
/* On Windows only backslashes and double-quotes need escaping. */
if (*c == '\\') {
/* Found a backslash. It may need to be escaped later. */
++windows_backslashes;
} else if (*c == '"') {
/* Found a double-quote. We need to escape it and all
immediately preceding backslashes. */
size += windows_backslashes + 1;
windows_backslashes = 0;
} else {
/* Found another character. This eliminates the possibility
that any immediately preceding backslashes will be
escaped. */
windows_backslashes = 0;
}
}
/* Check whether this character needs escaping for a make tool. */
if (*c == '$') {
if (flags & Shell_Flag_Make) {
/* In Makefiles a dollar is written $$ so we need one extra
character. */
++size;
} else if (flags & Shell_Flag_VSIDE) {
/* In a VS IDE a dollar is written "$" so we need two extra
characters. */
size += 2;
}
} else if (*c == '#') {
if ((flags & Shell_Flag_Make) && (flags & Shell_Flag_WatcomWMake)) {
/* In Watcom WMake makefiles a pound is written $# so we need
one extra character. */
++size;
}
} else if (*c == '%') {
if ((flags & Shell_Flag_VSIDE) ||
((flags & Shell_Flag_Make) &&
((flags & Shell_Flag_MinGWMake) || (flags & Shell_Flag_NMake)))) {
/* In the VS IDE, NMake, or MinGW make a percent is written %%
so we need one extra characters. */
size += 1;
}
} else if (*c == ';') {
if (flags & Shell_Flag_VSIDE) {
/* In a VS IDE a semicolon is written ";" so we need two extra
characters. */
size += 2;
}
}
}
/* Check whether the argument needs surrounding quotes. */
if (Shell__ArgumentNeedsQuotes(in, isUnix, flags)) {
/* Surrounding quotes are needed. Allocate space for them. */
if ((flags & Shell_Flag_WatcomQuote) && (isUnix)) {
size += 2;
}
size += 2;
/* We must escape all ending backslashes when quoting on windows. */
size += windows_backslashes;
}
return size;
}
char* cmOutputConverter::Shell__GetArgument(const char* in, char* out,
int isUnix, int flags)
{
/* String iterator. */
const char* c;
/* Keep track of how many backslashes have been encountered in a row. */
int windows_backslashes = 0;
/* Whether the argument must be quoted. */ /* Whether the argument must be quoted. */
int needQuotes = Shell__ArgumentNeedsQuotes(in, isUnix, flags); int needQuotes = Shell__ArgumentNeedsQuotes(in, isUnix, flags);
if (needQuotes) { if (needQuotes) {
/* Add the opening quote for this argument. */ /* Add the opening quote for this argument. */
if (flags & Shell_Flag_WatcomQuote) { if (flags & Shell_Flag_WatcomQuote) {
if (isUnix) { if (isUnix) {
*out++ = '"'; out << '"';
} }
*out++ = '\''; out << '\'';
} else { } else {
*out++ = '"'; out << '"';
} }
} }
@ -720,7 +599,7 @@ char* cmOutputConverter::Shell__GetArgument(const char* in, char* out,
if (skip != c) { if (skip != c) {
/* Copy to the end of the make variable references. */ /* Copy to the end of the make variable references. */
while (c != skip) { while (c != skip) {
*out++ = *c++; out << *c++;
} }
/* The make variable reference eliminates any escaping needed /* The make variable reference eliminates any escaping needed
@ -740,7 +619,7 @@ char* cmOutputConverter::Shell__GetArgument(const char* in, char* out,
quoted argument. */ quoted argument. */
if (*c == '\\' || *c == '"' || *c == '`' || *c == '$') { if (*c == '\\' || *c == '"' || *c == '`' || *c == '$') {
/* This character needs a backslash to escape it. */ /* This character needs a backslash to escape it. */
*out++ = '\\'; out << '\\';
} }
} else if (flags & Shell_Flag_EchoWindows) { } else if (flags & Shell_Flag_EchoWindows) {
/* On Windows the built-in command shell echo never needs escaping. */ /* On Windows the built-in command shell echo never needs escaping. */
@ -754,11 +633,11 @@ char* cmOutputConverter::Shell__GetArgument(const char* in, char* out,
backslashes. */ backslashes. */
while (windows_backslashes > 0) { while (windows_backslashes > 0) {
--windows_backslashes; --windows_backslashes;
*out++ = '\\'; out << '\\';
} }
/* Add the backslash to escape the double-quote. */ /* Add the backslash to escape the double-quote. */
*out++ = '\\'; out << '\\';
} else { } else {
/* We encountered a normal character. This eliminates any /* We encountered a normal character. This eliminates any
escaping needed for preceding backslashes. */ escaping needed for preceding backslashes. */
@ -771,8 +650,7 @@ char* cmOutputConverter::Shell__GetArgument(const char* in, char* out,
if (flags & Shell_Flag_Make) { if (flags & Shell_Flag_Make) {
/* In Makefiles a dollar is written $$. The make tool will /* In Makefiles a dollar is written $$. The make tool will
replace it with just $ before passing it to the shell. */ replace it with just $ before passing it to the shell. */
*out++ = '$'; out << "$$";
*out++ = '$';
} else if (flags & Shell_Flag_VSIDE) { } else if (flags & Shell_Flag_VSIDE) {
/* In a VS IDE a dollar is written "$". If this is written in /* In a VS IDE a dollar is written "$". If this is written in
an un-quoted argument it starts a quoted segment, inserts an un-quoted argument it starts a quoted segment, inserts
@ -780,34 +658,30 @@ char* cmOutputConverter::Shell__GetArgument(const char* in, char* out,
argument it ends quoting, inserts the $ and restarts argument it ends quoting, inserts the $ and restarts
quoting. Either way the $ is isolated from surrounding quoting. Either way the $ is isolated from surrounding
text to avoid looking like a variable reference. */ text to avoid looking like a variable reference. */
*out++ = '"'; out << "\"$\"";
*out++ = '$';
*out++ = '"';
} else { } else {
/* Otherwise a dollar is written just $. */ /* Otherwise a dollar is written just $. */
*out++ = '$'; out << '$';
} }
} else if (*c == '#') { } else if (*c == '#') {
if ((flags & Shell_Flag_Make) && (flags & Shell_Flag_WatcomWMake)) { if ((flags & Shell_Flag_Make) && (flags & Shell_Flag_WatcomWMake)) {
/* In Watcom WMake makefiles a pound is written $#. The make /* In Watcom WMake makefiles a pound is written $#. The make
tool will replace it with just # before passing it to the tool will replace it with just # before passing it to the
shell. */ shell. */
*out++ = '$'; out << "$#";
*out++ = '#';
} else { } else {
/* Otherwise a pound is written just #. */ /* Otherwise a pound is written just #. */
*out++ = '#'; out << '#';
} }
} else if (*c == '%') { } else if (*c == '%') {
if ((flags & Shell_Flag_VSIDE) || if ((flags & Shell_Flag_VSIDE) ||
((flags & Shell_Flag_Make) && ((flags & Shell_Flag_Make) &&
((flags & Shell_Flag_MinGWMake) || (flags & Shell_Flag_NMake)))) { ((flags & Shell_Flag_MinGWMake) || (flags & Shell_Flag_NMake)))) {
/* In the VS IDE, NMake, or MinGW make a percent is written %%. */ /* In the VS IDE, NMake, or MinGW make a percent is written %%. */
*out++ = '%'; out << "%%";
*out++ = '%';
} else { } else {
/* Otherwise a percent is written just %. */ /* Otherwise a percent is written just %. */
*out++ = '%'; out << '%';
} }
} else if (*c == ';') { } else if (*c == ';') {
if (flags & Shell_Flag_VSIDE) { if (flags & Shell_Flag_VSIDE) {
@ -816,16 +690,14 @@ char* cmOutputConverter::Shell__GetArgument(const char* in, char* out,
inserts the ; and ends the segment. If it is written in a inserts the ; and ends the segment. If it is written in a
quoted argument it ends quoting, inserts the ; and restarts quoted argument it ends quoting, inserts the ; and restarts
quoting. Either way the ; is isolated. */ quoting. Either way the ; is isolated. */
*out++ = '"'; out << "\";\"";
*out++ = ';';
*out++ = '"';
} else { } else {
/* Otherwise a semicolon is written just ;. */ /* Otherwise a semicolon is written just ;. */
*out++ = ';'; out << ';';
} }
} else { } else {
/* Store this character. */ /* Store this character. */
*out++ = *c; out << *c;
} }
} }
@ -833,45 +705,31 @@ char* cmOutputConverter::Shell__GetArgument(const char* in, char* out,
/* Add enough backslashes to escape any trailing ones. */ /* Add enough backslashes to escape any trailing ones. */
while (windows_backslashes > 0) { while (windows_backslashes > 0) {
--windows_backslashes; --windows_backslashes;
*out++ = '\\'; out << '\\';
} }
/* Add the closing quote for this argument. */ /* Add the closing quote for this argument. */
if (flags & Shell_Flag_WatcomQuote) { if (flags & Shell_Flag_WatcomQuote) {
*out++ = '\''; out << '\'';
if (isUnix) { if (isUnix) {
*out++ = '"'; out << '"';
} }
} else { } else {
*out++ = '"'; out << '"';
} }
} }
/* Store a terminating null without incrementing. */ return out.str();
*out = 0;
return out;
} }
char* cmOutputConverter::Shell_GetArgumentForWindows(const char* in, char* out, std::string cmOutputConverter::Shell_GetArgumentForWindows(const char* in,
int flags) int flags)
{ {
return Shell__GetArgument(in, out, 0, flags); return Shell__GetArgument(in, 0, flags);
} }
char* cmOutputConverter::Shell_GetArgumentForUnix(const char* in, char* out, std::string cmOutputConverter::Shell_GetArgumentForUnix(const char* in,
int flags) int flags)
{ {
return Shell__GetArgument(in, out, 1, flags); return Shell__GetArgument(in, 1, flags);
}
int cmOutputConverter::Shell_GetArgumentSizeForWindows(const char* in,
int flags)
{
return Shell__GetArgumentSize(in, 0, flags);
}
int cmOutputConverter::Shell_GetArgumentSizeForUnix(const char* in, int flags)
{
return Shell__GetArgumentSize(in, 1, flags);
} }

View File

@ -126,17 +126,8 @@ public:
* modify the generated quoting and escape sequences to work under * modify the generated quoting and escape sequences to work under
* alternative environments. * alternative environments.
*/ */
static char* Shell_GetArgumentForWindows(const char* in, char* out, static std::string Shell_GetArgumentForWindows(const char* in, int flags);
int flags); static std::string Shell_GetArgumentForUnix(const char* in, int flags);
static char* Shell_GetArgumentForUnix(const char* in, char* out, int flags);
/**
* Compute the size of the buffer required to store the output from
* Shell_GetArgumentForWindows or Shell_GetArgumentForUnix. The flags
* passed must be identical between the two calls.
*/
static int Shell_GetArgumentSizeForWindows(const char* in, int flags);
static int Shell_GetArgumentSizeForUnix(const char* in, int flags);
std::string EscapeForShell(const std::string& str, bool makeVars = false, std::string EscapeForShell(const std::string& str, bool makeVars = false,
bool forEcho = false, bool forEcho = false,
@ -182,9 +173,7 @@ private:
static int Shell__CharIsMakeVariableName(char c); static int Shell__CharIsMakeVariableName(char c);
static const char* Shell__SkipMakeVariables(const char* c); static const char* Shell__SkipMakeVariables(const char* c);
static int Shell__ArgumentNeedsQuotes(const char* in, int isUnix, int flags); static int Shell__ArgumentNeedsQuotes(const char* in, int isUnix, int flags);
static int Shell__GetArgumentSize(const char* in, int isUnix, int flags); static std::string Shell__GetArgument(const char* in, int isUnix, int flags);
static char* Shell__GetArgument(const char* in, char* out, int isUnix,
int flags);
private: private:
cmState::Snapshot StateSnapshot; cmState::Snapshot StateSnapshot;