cmOutputConverter: implement Shell__GetArgument using ostringstream
This removes the need to calculate the resulting string length beforehand.
This commit is contained in:
parent
909d51bece
commit
d645b03e9c
|
@ -15,6 +15,7 @@
|
|||
#include "cmake.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <sstream>
|
||||
|
||||
#include <ctype.h> /* isalpha */
|
||||
#include <string.h> /* strlen */
|
||||
|
@ -328,19 +329,9 @@ std::string cmOutputConverter::EscapeForShell(const std::string& str,
|
|||
flags |= Shell_Flag_NMake;
|
||||
}
|
||||
|
||||
// Compute the buffer size needed.
|
||||
int size = (this->GetState()->UseWindowsShell()
|
||||
? Shell_GetArgumentSizeForWindows(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]);
|
||||
return this->GetState()->UseWindowsShell()
|
||||
? Shell_GetArgumentForWindows(str.c_str(), flags)
|
||||
: Shell_GetArgumentForUnix(str.c_str(), flags);
|
||||
}
|
||||
|
||||
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,
|
||||
int shell_flags)
|
||||
{
|
||||
char local_buffer[1024];
|
||||
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;
|
||||
return Shell_GetArgumentForWindows(arg, shell_flags);
|
||||
}
|
||||
|
||||
cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat(
|
||||
|
@ -586,12 +566,10 @@ int cmOutputConverter::Shell__ArgumentNeedsQuotes(const char* in, int isUnix,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int cmOutputConverter::Shell__GetArgumentSize(const char* in, int isUnix,
|
||||
int flags)
|
||||
std::string cmOutputConverter::Shell__GetArgument(const char* in, int isUnix,
|
||||
int flags)
|
||||
{
|
||||
/* Start with the length of the original argument, plus one for
|
||||
either a terminating null or a separating space. */
|
||||
int size = (int)strlen(in) + 1;
|
||||
std::ostringstream out;
|
||||
|
||||
/* String iterator. */
|
||||
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. */
|
||||
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. */
|
||||
int needQuotes = Shell__ArgumentNeedsQuotes(in, isUnix, flags);
|
||||
if (needQuotes) {
|
||||
/* Add the opening quote for this argument. */
|
||||
if (flags & Shell_Flag_WatcomQuote) {
|
||||
if (isUnix) {
|
||||
*out++ = '"';
|
||||
out << '"';
|
||||
}
|
||||
*out++ = '\'';
|
||||
out << '\'';
|
||||
} else {
|
||||
*out++ = '"';
|
||||
out << '"';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -720,7 +599,7 @@ char* cmOutputConverter::Shell__GetArgument(const char* in, char* out,
|
|||
if (skip != c) {
|
||||
/* Copy to the end of the make variable references. */
|
||||
while (c != skip) {
|
||||
*out++ = *c++;
|
||||
out << *c++;
|
||||
}
|
||||
|
||||
/* The make variable reference eliminates any escaping needed
|
||||
|
@ -740,7 +619,7 @@ char* cmOutputConverter::Shell__GetArgument(const char* in, char* out,
|
|||
quoted argument. */
|
||||
if (*c == '\\' || *c == '"' || *c == '`' || *c == '$') {
|
||||
/* This character needs a backslash to escape it. */
|
||||
*out++ = '\\';
|
||||
out << '\\';
|
||||
}
|
||||
} else if (flags & Shell_Flag_EchoWindows) {
|
||||
/* 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. */
|
||||
while (windows_backslashes > 0) {
|
||||
--windows_backslashes;
|
||||
*out++ = '\\';
|
||||
out << '\\';
|
||||
}
|
||||
|
||||
/* Add the backslash to escape the double-quote. */
|
||||
*out++ = '\\';
|
||||
out << '\\';
|
||||
} else {
|
||||
/* We encountered a normal character. This eliminates any
|
||||
escaping needed for preceding backslashes. */
|
||||
|
@ -771,8 +650,7 @@ char* cmOutputConverter::Shell__GetArgument(const char* in, char* out,
|
|||
if (flags & Shell_Flag_Make) {
|
||||
/* In Makefiles a dollar is written $$. The make tool will
|
||||
replace it with just $ before passing it to the shell. */
|
||||
*out++ = '$';
|
||||
*out++ = '$';
|
||||
out << "$$";
|
||||
} else if (flags & Shell_Flag_VSIDE) {
|
||||
/* In a VS IDE a dollar is written "$". If this is written in
|
||||
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
|
||||
quoting. Either way the $ is isolated from surrounding
|
||||
text to avoid looking like a variable reference. */
|
||||
*out++ = '"';
|
||||
*out++ = '$';
|
||||
*out++ = '"';
|
||||
out << "\"$\"";
|
||||
} else {
|
||||
/* Otherwise a dollar is written just $. */
|
||||
*out++ = '$';
|
||||
out << '$';
|
||||
}
|
||||
} else if (*c == '#') {
|
||||
if ((flags & Shell_Flag_Make) && (flags & Shell_Flag_WatcomWMake)) {
|
||||
/* In Watcom WMake makefiles a pound is written $#. The make
|
||||
tool will replace it with just # before passing it to the
|
||||
shell. */
|
||||
*out++ = '$';
|
||||
*out++ = '#';
|
||||
out << "$#";
|
||||
} else {
|
||||
/* Otherwise a pound is written just #. */
|
||||
*out++ = '#';
|
||||
out << '#';
|
||||
}
|
||||
} 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 %%. */
|
||||
*out++ = '%';
|
||||
*out++ = '%';
|
||||
out << "%%";
|
||||
} else {
|
||||
/* Otherwise a percent is written just %. */
|
||||
*out++ = '%';
|
||||
out << '%';
|
||||
}
|
||||
} else if (*c == ';') {
|
||||
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
|
||||
quoted argument it ends quoting, inserts the ; and restarts
|
||||
quoting. Either way the ; is isolated. */
|
||||
*out++ = '"';
|
||||
*out++ = ';';
|
||||
*out++ = '"';
|
||||
out << "\";\"";
|
||||
} else {
|
||||
/* Otherwise a semicolon is written just ;. */
|
||||
*out++ = ';';
|
||||
out << ';';
|
||||
}
|
||||
} else {
|
||||
/* 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. */
|
||||
while (windows_backslashes > 0) {
|
||||
--windows_backslashes;
|
||||
*out++ = '\\';
|
||||
out << '\\';
|
||||
}
|
||||
|
||||
/* Add the closing quote for this argument. */
|
||||
if (flags & Shell_Flag_WatcomQuote) {
|
||||
*out++ = '\'';
|
||||
out << '\'';
|
||||
if (isUnix) {
|
||||
*out++ = '"';
|
||||
out << '"';
|
||||
}
|
||||
} else {
|
||||
*out++ = '"';
|
||||
out << '"';
|
||||
}
|
||||
}
|
||||
|
||||
/* Store a terminating null without incrementing. */
|
||||
*out = 0;
|
||||
|
||||
return out;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
char* cmOutputConverter::Shell_GetArgumentForWindows(const char* in, char* out,
|
||||
int flags)
|
||||
std::string cmOutputConverter::Shell_GetArgumentForWindows(const char* in,
|
||||
int flags)
|
||||
{
|
||||
return Shell__GetArgument(in, out, 0, flags);
|
||||
return Shell__GetArgument(in, 0, flags);
|
||||
}
|
||||
|
||||
char* cmOutputConverter::Shell_GetArgumentForUnix(const char* in, char* out,
|
||||
int flags)
|
||||
std::string cmOutputConverter::Shell_GetArgumentForUnix(const char* in,
|
||||
int flags)
|
||||
{
|
||||
return Shell__GetArgument(in, out, 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);
|
||||
return Shell__GetArgument(in, 1, flags);
|
||||
}
|
||||
|
|
|
@ -126,17 +126,8 @@ public:
|
|||
* modify the generated quoting and escape sequences to work under
|
||||
* alternative environments.
|
||||
*/
|
||||
static char* Shell_GetArgumentForWindows(const char* in, char* out,
|
||||
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);
|
||||
static std::string Shell_GetArgumentForWindows(const char* in, int flags);
|
||||
static std::string Shell_GetArgumentForUnix(const char* in, int flags);
|
||||
|
||||
std::string EscapeForShell(const std::string& str, bool makeVars = false,
|
||||
bool forEcho = false,
|
||||
|
@ -182,9 +173,7 @@ private:
|
|||
static int Shell__CharIsMakeVariableName(char c);
|
||||
static const char* Shell__SkipMakeVariables(const char* c);
|
||||
static int Shell__ArgumentNeedsQuotes(const char* in, int isUnix, int flags);
|
||||
static int Shell__GetArgumentSize(const char* in, int isUnix, int flags);
|
||||
static char* Shell__GetArgument(const char* in, char* out, int isUnix,
|
||||
int flags);
|
||||
static std::string Shell__GetArgument(const char* in, int isUnix, int flags);
|
||||
|
||||
private:
|
||||
cmState::Snapshot StateSnapshot;
|
||||
|
|
Loading…
Reference in New Issue