172 lines
4.5 KiB
C
172 lines
4.5 KiB
C
/*=========================================================================
|
|
|
|
Program: KWSys - Kitware System Library
|
|
Module: $RCSfile$
|
|
|
|
Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved.
|
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
PURPOSE. See the above copyright notices for more information.
|
|
|
|
=========================================================================*/
|
|
#include "kwsysPrivate.h"
|
|
#include KWSYS_HEADER(System.h)
|
|
|
|
/* Work-around CMake dependency scanning limitation. This must
|
|
duplicate the above list of headers. */
|
|
#if 0
|
|
# include "System.h.in"
|
|
#endif
|
|
|
|
#include <string.h> /* strlen */
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static int kwsysSystemWindowsShellArgumentNeedsEscape(const char* in)
|
|
{
|
|
/* Scan the string for characters that need escaping. Note that
|
|
single quotes seem to need escaping for some windows shell
|
|
environments (mingw32-make shell for example). Single quotes do
|
|
not actually need backslash escapes but must be in a
|
|
double-quoted argument. */
|
|
const char* c;
|
|
for(c=in; *c; ++c)
|
|
{
|
|
if(*c == ' ' || *c == '\t' || *c == '"' || *c == '\'')
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int kwsysSystem_Windows_ShellArgumentSize(const char* in)
|
|
{
|
|
/* Start with the length of the original argument, plus one for
|
|
either a terminating null or a separating space. */
|
|
int length = (int)strlen(in) + 1;
|
|
|
|
/* String iterator. */
|
|
const char* c;
|
|
|
|
/* Keep track of how many backslashes have been encountered in a row. */
|
|
int backslashes = 0;
|
|
|
|
/* If nothing needs escaping, we do not need any extra length. */
|
|
if(!kwsysSystemWindowsShellArgumentNeedsEscape(in))
|
|
{
|
|
return length;
|
|
}
|
|
|
|
/* Add 2 for double quotes since spaces are present. */
|
|
length += 2;
|
|
|
|
/* Scan the string to find characters that need escaping. */
|
|
for(c=in; *c; ++c)
|
|
{
|
|
if(*c == '\\')
|
|
{
|
|
/* Found a backslash. It may need to be escaped later. */
|
|
++backslashes;
|
|
}
|
|
else if(*c == '"')
|
|
{
|
|
/* Found a double-quote. We need to escape it and all
|
|
immediately preceding backslashes. */
|
|
length += backslashes + 1;
|
|
backslashes = 0;
|
|
}
|
|
else
|
|
{
|
|
/* Found another character. This eliminates the possibility
|
|
that any immediately preceding backslashes will be
|
|
escaped. */
|
|
backslashes = 0;
|
|
}
|
|
}
|
|
|
|
/* We need to escape all ending backslashes. */
|
|
length += backslashes;
|
|
|
|
return length;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
char* kwsysSystem_Windows_ShellArgument(const char* in, char* out)
|
|
{
|
|
/* String iterator. */
|
|
const char* c;
|
|
|
|
/* Keep track of how many backslashes have been encountered in a row. */
|
|
int backslashes = 0;
|
|
|
|
/* If nothing needs escaping, we can pass the argument verbatim. */
|
|
if(!kwsysSystemWindowsShellArgumentNeedsEscape(in))
|
|
{
|
|
/* Just copy the string. */
|
|
for(c=in; *c; ++c)
|
|
{
|
|
*out++ = *c;
|
|
}
|
|
|
|
/* Store a terminating null without incrementing. */
|
|
*out = 0;
|
|
return out;
|
|
}
|
|
|
|
/* Add the opening double-quote for this argument. */
|
|
*out++ = '"';
|
|
|
|
/* Add the characters of the argument, possibly escaping them. */
|
|
for(c=in; *c; ++c)
|
|
{
|
|
if(*c == '\\')
|
|
{
|
|
/* Found a backslash. It may need to be escaped later. */
|
|
++backslashes;
|
|
*out++ = '\\';
|
|
}
|
|
else if(*c == '"')
|
|
{
|
|
/* Add enough backslashes to escape any that preceded the
|
|
double-quote. */
|
|
while(backslashes > 0)
|
|
{
|
|
--backslashes;
|
|
*out++ = '\\';
|
|
}
|
|
|
|
/* Add the backslash to escape the double-quote. */
|
|
*out++ = '\\';
|
|
|
|
/* Add the double-quote itself. */
|
|
*out++ = '"';
|
|
}
|
|
else
|
|
{
|
|
/* We encountered a normal character. This eliminates any
|
|
escaping needed for preceding backslashes. Add the
|
|
character. */
|
|
backslashes = 0;
|
|
*out++ = *c;
|
|
}
|
|
}
|
|
|
|
/* Add enough backslashes to escape any trailing ones. */
|
|
while(backslashes > 0)
|
|
{
|
|
--backslashes;
|
|
*out++ = '\\';
|
|
}
|
|
|
|
/* Add the closing double-quote for this argument. */
|
|
*out++ = '"';
|
|
|
|
/* Store a terminating null without incrementing. */
|
|
*out = 0;
|
|
|
|
return out;
|
|
}
|