summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/cmCommandArgumentParserHelper.cxx63
-rw-r--r--Source/cmCommandArgumentParserHelper.h8
-rw-r--r--Source/cmMakefile.cxx231
3 files changed, 90 insertions, 212 deletions
diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx
index d446e15..cae9256 100644
--- a/Source/cmCommandArgumentParserHelper.cxx
+++ b/Source/cmCommandArgumentParserHelper.cxx
@@ -27,7 +27,7 @@ cmCommandArgumentParserHelper::cmCommandArgumentParserHelper()
{
this->FileLine = -1;
this->FileName = 0;
-
+ this->RemoveEmpty = true;
this->EmptyVariable[0] = 0;
strcpy(this->DCURLYVariable, "${");
strcpy(this->RCURLYVariable, "}");
@@ -38,6 +38,7 @@ cmCommandArgumentParserHelper::cmCommandArgumentParserHelper()
this->NoEscapeMode = false;
this->ReplaceAtSyntax = false;
+ this->AtOnly = false;
}
@@ -70,6 +71,18 @@ char* cmCommandArgumentParserHelper::ExpandSpecialVariable(const char* key,
if ( !key )
{
return this->ExpandVariable(var);
+ }
+ if(this->AtOnly)
+ {
+ std::string ref = "$";
+ ref += key;
+ ref += "{";
+ if(var)
+ {
+ ref += var;
+ }
+ ref += "}";
+ return this->AddString(ref.c_str());
}
if ( strcmp(key, "ENV") == 0 )
{
@@ -92,8 +105,21 @@ char* cmCommandArgumentParserHelper::ExpandSpecialVariable(const char* key,
return 0;
}
-char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
+char* cmCommandArgumentParserHelper::ExpandVariable(const char* var,
+ bool doingAt)
{
+ // if we are in AtOnly mode, and we are not expanding an @ variable
+ // then put back the ${var} unexpanded
+ if(!doingAt && this->AtOnly)
+ {
+ std::string ref = "${";
+ if(var)
+ {
+ ref += var;
+ }
+ ref += "}";
+ return this->AddString(ref.c_str());
+ }
if(!var)
{
return 0;
@@ -109,6 +135,10 @@ char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
return this->AddString(ostr.str().c_str());
}
const char* value = this->Makefile->GetDefinition(var);
+ if(!value && !this->RemoveEmpty)
+ {
+ return 0;
+ }
if (this->EscapeQuotes && value)
{
return this->AddString(cmSystemTools::EscapeQuotes(value).c_str());
@@ -120,15 +150,28 @@ char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var)
{
if(this->ReplaceAtSyntax)
{
- return this->ExpandVariable(var);
- }
- else
- {
- std::string ref = "@";
- ref += var;
- ref += "@";
- return this->AddString(ref.c_str());
+ // try to expand the variable
+ char* ret = this->ExpandVariable(var, true);
+ // if the return was 0 and we want to replace empty strings
+ // then return an empty string
+ if(!ret && this->RemoveEmpty)
+ {
+ return this->AddString(ret);
+ }
+ // if the ret was not 0, then return it
+ if(ret)
+ {
+ return ret;
+ }
}
+ // at this point we want to put it back because of one of these cases:
+ // - this->ReplaceAtSyntax is false
+ // - this->ReplaceAtSyntax is true, but this->RemoveEmpty is false,
+ // and the variable was not defined
+ std::string ref = "@";
+ ref += var;
+ ref += "@";
+ return this->AddString(ref.c_str());
}
char* cmCommandArgumentParserHelper::CombineUnions(char* in1, char* in2)
diff --git a/Source/cmCommandArgumentParserHelper.h b/Source/cmCommandArgumentParserHelper.h
index 7f5078f..d49952a 100644
--- a/Source/cmCommandArgumentParserHelper.h
+++ b/Source/cmCommandArgumentParserHelper.h
@@ -58,7 +58,7 @@ public:
char* CombineUnions(char* in1, char* in2);
char* ExpandSpecialVariable(const char* key, const char* var);
- char* ExpandVariable(const char* var);
+ char* ExpandVariable(const char* var, bool doingAt=false);
char* ExpandVariableForAt(const char* var);
void SetResult(const char* value);
@@ -70,7 +70,9 @@ public:
void SetEscapeQuotes(bool b) { this->EscapeQuotes = b; }
void SetNoEscapeMode(bool b) { this->NoEscapeMode = b; }
void SetReplaceAtSyntax(bool b) { this->ReplaceAtSyntax = b; }
-
+ void SetRemoveEmpty(bool b) { this->RemoveEmpty = b; }
+ void SetAtOnly(bool b) { this->AtOnly = b; }
+
const char* GetError() { return this->ErrorString.c_str(); }
char EmptyVariable[1];
char DCURLYVariable[3];
@@ -104,6 +106,8 @@ private:
std::string ErrorString;
bool NoEscapeMode;
bool ReplaceAtSyntax;
+ bool RemoveEmpty;
+ bool AtOnly;
};
#endif
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index eb16809..60929ef 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -1684,214 +1684,45 @@ const char *cmMakefile::ExpandVariablesInString(std::string& source,
// It also supports the $ENV{VAR} syntax where VAR is looked up in
// the current environment variables.
- bool notParsed = true;
- if ( !atOnly )
- {
- cmCommandArgumentParserHelper parser;
- parser.SetMakefile(this);
- parser.SetLineFile(line, filename);
- parser.SetEscapeQuotes(escapeQuotes);
- parser.SetNoEscapeMode(noEscapes);
- parser.SetReplaceAtSyntax(replaceAt);
- int res = parser.ParseString(source.c_str(), 0);
- if ( res )
- {
- source = parser.GetResult();
- notParsed = false;
- }
- else
- {
- cmOStringStream error;
- error << "Syntax error in cmake code at\n"
- << (filename?filename:"(no filename given)")
- << ":" << line << ":\n"
- << parser.GetError() << ", when parsing string \""
- << source.c_str() << "\"";
- const char* versionValue
- = this->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY");
- int major = 0;
- int minor = 0;
- if ( versionValue )
- {
- sscanf(versionValue, "%d.%d", &major, &minor);
- }
- if ( major < 2 || major == 2 && minor < 1 )
- {
- cmSystemTools::Error(error.str().c_str());
- cmSystemTools::SetFatalErrorOccured();
- return source.c_str();
- }
- else
- {
- cmSystemTools::Message(error.str().c_str());
- }
- }
+ cmCommandArgumentParserHelper parser;
+ parser.SetMakefile(this);
+ parser.SetLineFile(line, filename);
+ parser.SetEscapeQuotes(escapeQuotes);
+ parser.SetNoEscapeMode(noEscapes);
+ parser.SetReplaceAtSyntax(replaceAt);
+ parser.SetRemoveEmpty(removeEmpty);
+ parser.SetAtOnly(atOnly);
+ int res = parser.ParseString(source.c_str(), 0);
+ if ( res )
+ {
+ source = parser.GetResult();
}
-
- if ( notParsed )
+ else
{
-
- // start by look for $ or @ in the string
- std::string::size_type markerPos;
- if(atOnly)
- {
- markerPos = source.find_first_of("@");
- }
- else
+ cmOStringStream error;
+ error << "Syntax error in cmake code at\n"
+ << (filename?filename:"(no filename given)")
+ << ":" << line << ":\n"
+ << parser.GetError() << ", when parsing string \""
+ << source.c_str() << "\"";
+ const char* versionValue
+ = this->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY");
+ int major = 0;
+ int minor = 0;
+ if ( versionValue )
{
- markerPos = source.find_first_of("$@");
+ sscanf(versionValue, "%d.%d", &major, &minor);
}
- // if not found, or found as the last character, then leave quickly as
- // nothing needs to be expanded
- if((markerPos == std::string::npos) || (markerPos >= source.size()-1))
+ if ( major < 2 || major == 2 && minor < 1 )
{
+ cmSystemTools::Error(error.str().c_str());
+ cmSystemTools::SetFatalErrorOccured();
return source.c_str();
}
- // current position
- std::string::size_type currentPos =0; // start at 0
- std::string result; // string with replacements
- // go until the the end of the string
- while((markerPos != std::string::npos) && (markerPos < source.size()-1))
- {
- // grab string from currentPos to the start of the variable
- // and add it to the result
- result += source.substr(currentPos, markerPos - currentPos);
- char endVariableMarker; // what is the end of the variable @ or }
- int markerStartSize = 1; // size of the start marker 1 or 2 or 5
- if(!atOnly && source[markerPos] == '$')
- {
- // ${var} case
- if(source[markerPos+1] == '{')
- {
- endVariableMarker = '}';
- markerStartSize = 2;
- }
- // $ENV{var} case
- else if(markerPos+4 < source.size() &&
- source[markerPos+4] == '{' &&
- !source.substr(markerPos+1, 3).compare("ENV"))
- {
- endVariableMarker = '}';
- markerStartSize = 5;
- }
- else
- {
- // bogus $ with no { so add $ to result and move on
- result += '$'; // add bogus $ back into string
- currentPos = markerPos+1; // move on
- // set end var to space so we can tell bogus
- endVariableMarker = ' ';
- }
- }
- else
- {
- // @VAR case
- endVariableMarker = '@';
- }
- // if it was a valid variable (started with @ or ${ or $ENV{ )
- if(endVariableMarker != ' ')
- {
- markerPos += markerStartSize; // move past marker
- // find the end variable marker starting at the markerPos
- // make sure it is a valid variable between
- std::string::size_type endVariablePos =
- source.find_first_not_of(
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
- markerPos);
- if(endVariablePos != std::string::npos &&
- source[endVariablePos] != endVariableMarker)
- {
- endVariablePos = std::string::npos;
- }
- if(endVariablePos == std::string::npos)
- {
- // no end marker found so add the bogus start
- if(endVariableMarker == '@')
- {
- result += '@';
- }
- else
- {
- result += (markerStartSize == 5 ? "$ENV{" : "${");
- }
- currentPos = markerPos;
- }
- else
- {
- // good variable remove it
- std::string var =
- source.substr(markerPos, endVariablePos - markerPos);
- bool found = false;
- if (markerStartSize == 5) // $ENV{
- {
- char *ptr = getenv(var.c_str());
- if (ptr)
- {
- if (escapeQuotes)
- {
- result += cmSystemTools::EscapeQuotes(ptr);
- }
- else
- {
- result += ptr;
- }
- found = true;
- }
- }
- else
- {
- const char* lookup = this->GetDefinition(var.c_str());
- if(lookup)
- {
- if (escapeQuotes)
- {
- result += cmSystemTools::EscapeQuotes(lookup);
- }
- else
- {
- result += lookup;
- }
- found = true;
- }
- else if(filename && (var == "CMAKE_CURRENT_LIST_FILE"))
- {
- result += filename;
- found = true;
- }
- else if(line >= 0 && (var == "CMAKE_CURRENT_LIST_LINE"))
- {
- cmOStringStream ostr;
- ostr << line;
- result += ostr.str();
- found = true;
- }
- }
- // if found add to result, if not, then it gets blanked
- if (!found)
- {
- // if no definition is found then add the var back
- if(!removeEmpty && endVariableMarker == '@')
- {
- result += "@";
- result += var;
- result += "@";
- }
- }
- // lookup var, and replace it
- currentPos = endVariablePos+1;
- }
- }
- if(atOnly)
- {
- markerPos = source.find_first_of("@", currentPos);
- }
- else
- {
- markerPos = source.find_first_of("$@", currentPos);
- }
+ else
+ {
+ cmSystemTools::Message(error.str().c_str());
}
- result += source.substr(currentPos); // pick up the rest of the string
- source = result;
}
return source.c_str();
}