Separate Xcode flag escaping code from defines
Generalize the core Xcode generator preprocessor flag escaping code to be useful for escaping all flags.
This commit is contained in:
parent
8ab2548d6c
commit
76eb733f3a
|
@ -3126,48 +3126,89 @@ void cmGlobalXCodeGenerator::AppendDefines(BuildObjectListOrString& defs,
|
|||
std::vector<std::string> defines;
|
||||
cmSystemTools::ExpandListArgument(defines_list, defines);
|
||||
|
||||
// Store the definitions in the string.
|
||||
this->AppendDefines(defs, defines, dflag);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmGlobalXCodeGenerator::AppendDefines(BuildObjectListOrString& defs,
|
||||
std::vector<std::string> const& defines,
|
||||
bool dflag)
|
||||
{
|
||||
// GCC_PREPROCESSOR_DEFINITIONS is a space-separated list of definitions.
|
||||
// We escape everything as follows:
|
||||
// - Place each definition in single quotes ''
|
||||
std::string def;
|
||||
for(std::vector<std::string>::const_iterator di = defines.begin();
|
||||
di != defines.end(); ++di)
|
||||
{
|
||||
// Start with -D if requested.
|
||||
def = dflag? "-D": "";
|
||||
def += *di;
|
||||
|
||||
// Append the flag with needed escapes.
|
||||
std::string tmp;
|
||||
this->AppendFlag(tmp, def);
|
||||
defs.Add(tmp.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmGlobalXCodeGenerator::AppendFlag(std::string& flags,
|
||||
std::string const& flag)
|
||||
{
|
||||
// Short-circuit for an empty flag.
|
||||
if(flag.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Separate from previous flags.
|
||||
if(!flags.empty())
|
||||
{
|
||||
flags += " ";
|
||||
}
|
||||
|
||||
// Check if the flag needs quoting.
|
||||
bool quoteFlag =
|
||||
flag.find_first_of("`~!@#$%^&*()+={}[]|:;\"'<>,.? ") != flag.npos;
|
||||
|
||||
// We escape a flag as follows:
|
||||
// - Place each flag in single quotes ''
|
||||
// - Escape a single quote as \\'
|
||||
// - Escape a backslash as \\\\ since it itself is an escape
|
||||
// Note that in the code below we need one more level of escapes for
|
||||
// C string syntax in this source file.
|
||||
for(std::vector<std::string>::const_iterator di = defines.begin();
|
||||
di != defines.end(); ++di)
|
||||
{
|
||||
std::string def;
|
||||
//
|
||||
// The final level of escaping is done when the string is stored
|
||||
// into the project file by cmXCodeObject::PrintString.
|
||||
|
||||
if(quoteFlag)
|
||||
{
|
||||
// Open single quote.
|
||||
def += "'";
|
||||
|
||||
// Add -D flag if requested.
|
||||
if(dflag)
|
||||
{
|
||||
def += "-D";
|
||||
flags += "'";
|
||||
}
|
||||
|
||||
// Escaped definition string.
|
||||
for(const char* c = di->c_str(); *c; ++c)
|
||||
// Flag value with escaped quotes and backslashes.
|
||||
for(const char* c = flag.c_str(); *c; ++c)
|
||||
{
|
||||
if(*c == '\'')
|
||||
{
|
||||
def += "\\\\'";
|
||||
flags += "\\\\'";
|
||||
}
|
||||
else if(*c == '\\')
|
||||
{
|
||||
def += "\\\\\\\\";
|
||||
flags += "\\\\\\\\";
|
||||
}
|
||||
else
|
||||
{
|
||||
def += *c;
|
||||
flags += *c;
|
||||
}
|
||||
}
|
||||
|
||||
if(quoteFlag)
|
||||
{
|
||||
// Close single quote.
|
||||
def += "'";
|
||||
|
||||
defs.Add(def.c_str());
|
||||
flags += "'";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -183,6 +183,10 @@ private:
|
|||
|
||||
void AppendDefines(BuildObjectListOrString& defs, const char* defines_list,
|
||||
bool dflag = false);
|
||||
void AppendDefines(BuildObjectListOrString& defs,
|
||||
std::vector<std::string> const& defines,
|
||||
bool dflag = false);
|
||||
void AppendFlag(std::string& flags, std::string const& flag);
|
||||
|
||||
protected:
|
||||
virtual const char* GetInstallTargetName() { return "install"; }
|
||||
|
|
Loading…
Reference in New Issue