ENH: add atonly support to cmCommandArgumentParserHelper.cxx and remove old non-yacc parser code from cmMakefile.cxx
This commit is contained in:
parent
0e1ae13f7c
commit
0e95a190bc
|
@ -27,7 +27,7 @@ cmCommandArgumentParserHelper::cmCommandArgumentParserHelper()
|
||||||
{
|
{
|
||||||
this->FileLine = -1;
|
this->FileLine = -1;
|
||||||
this->FileName = 0;
|
this->FileName = 0;
|
||||||
|
this->RemoveEmpty = true;
|
||||||
this->EmptyVariable[0] = 0;
|
this->EmptyVariable[0] = 0;
|
||||||
strcpy(this->DCURLYVariable, "${");
|
strcpy(this->DCURLYVariable, "${");
|
||||||
strcpy(this->RCURLYVariable, "}");
|
strcpy(this->RCURLYVariable, "}");
|
||||||
|
@ -38,6 +38,7 @@ cmCommandArgumentParserHelper::cmCommandArgumentParserHelper()
|
||||||
|
|
||||||
this->NoEscapeMode = false;
|
this->NoEscapeMode = false;
|
||||||
this->ReplaceAtSyntax = false;
|
this->ReplaceAtSyntax = false;
|
||||||
|
this->AtOnly = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,6 +71,18 @@ char* cmCommandArgumentParserHelper::ExpandSpecialVariable(const char* key,
|
||||||
if ( !key )
|
if ( !key )
|
||||||
{
|
{
|
||||||
return this->ExpandVariable(var);
|
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 )
|
if ( strcmp(key, "ENV") == 0 )
|
||||||
{
|
{
|
||||||
|
@ -92,8 +105,21 @@ char* cmCommandArgumentParserHelper::ExpandSpecialVariable(const char* key,
|
||||||
return 0;
|
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)
|
if(!var)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -109,6 +135,10 @@ char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
|
||||||
return this->AddString(ostr.str().c_str());
|
return this->AddString(ostr.str().c_str());
|
||||||
}
|
}
|
||||||
const char* value = this->Makefile->GetDefinition(var);
|
const char* value = this->Makefile->GetDefinition(var);
|
||||||
|
if(!value && !this->RemoveEmpty)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (this->EscapeQuotes && value)
|
if (this->EscapeQuotes && value)
|
||||||
{
|
{
|
||||||
return this->AddString(cmSystemTools::EscapeQuotes(value).c_str());
|
return this->AddString(cmSystemTools::EscapeQuotes(value).c_str());
|
||||||
|
@ -120,15 +150,28 @@ char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var)
|
||||||
{
|
{
|
||||||
if(this->ReplaceAtSyntax)
|
if(this->ReplaceAtSyntax)
|
||||||
{
|
{
|
||||||
return this->ExpandVariable(var);
|
// try to expand the variable
|
||||||
}
|
char* ret = this->ExpandVariable(var, true);
|
||||||
else
|
// if the return was 0 and we want to replace empty strings
|
||||||
{
|
// then return an empty string
|
||||||
std::string ref = "@";
|
if(!ret && this->RemoveEmpty)
|
||||||
ref += var;
|
{
|
||||||
ref += "@";
|
return this->AddString(ret);
|
||||||
return this->AddString(ref.c_str());
|
}
|
||||||
|
// 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)
|
char* cmCommandArgumentParserHelper::CombineUnions(char* in1, char* in2)
|
||||||
|
|
|
@ -58,7 +58,7 @@ public:
|
||||||
char* CombineUnions(char* in1, char* in2);
|
char* CombineUnions(char* in1, char* in2);
|
||||||
|
|
||||||
char* ExpandSpecialVariable(const char* key, const char* var);
|
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);
|
char* ExpandVariableForAt(const char* var);
|
||||||
void SetResult(const char* value);
|
void SetResult(const char* value);
|
||||||
|
|
||||||
|
@ -70,7 +70,9 @@ public:
|
||||||
void SetEscapeQuotes(bool b) { this->EscapeQuotes = b; }
|
void SetEscapeQuotes(bool b) { this->EscapeQuotes = b; }
|
||||||
void SetNoEscapeMode(bool b) { this->NoEscapeMode = b; }
|
void SetNoEscapeMode(bool b) { this->NoEscapeMode = b; }
|
||||||
void SetReplaceAtSyntax(bool b) { this->ReplaceAtSyntax = 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(); }
|
const char* GetError() { return this->ErrorString.c_str(); }
|
||||||
char EmptyVariable[1];
|
char EmptyVariable[1];
|
||||||
char DCURLYVariable[3];
|
char DCURLYVariable[3];
|
||||||
|
@ -104,6 +106,8 @@ private:
|
||||||
std::string ErrorString;
|
std::string ErrorString;
|
||||||
bool NoEscapeMode;
|
bool NoEscapeMode;
|
||||||
bool ReplaceAtSyntax;
|
bool ReplaceAtSyntax;
|
||||||
|
bool RemoveEmpty;
|
||||||
|
bool AtOnly;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1684,214 +1684,45 @@ const char *cmMakefile::ExpandVariablesInString(std::string& source,
|
||||||
// It also supports the $ENV{VAR} syntax where VAR is looked up in
|
// It also supports the $ENV{VAR} syntax where VAR is looked up in
|
||||||
// the current environment variables.
|
// the current environment variables.
|
||||||
|
|
||||||
bool notParsed = true;
|
cmCommandArgumentParserHelper parser;
|
||||||
if ( !atOnly )
|
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 )
|
||||||
{
|
{
|
||||||
cmCommandArgumentParserHelper parser;
|
source = parser.GetResult();
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if ( notParsed )
|
|
||||||
{
|
{
|
||||||
|
cmOStringStream error;
|
||||||
// start by look for $ or @ in the string
|
error << "Syntax error in cmake code at\n"
|
||||||
std::string::size_type markerPos;
|
<< (filename?filename:"(no filename given)")
|
||||||
if(atOnly)
|
<< ":" << 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);
|
||||||
}
|
}
|
||||||
else
|
if ( major < 2 || major == 2 && minor < 1 )
|
||||||
{
|
|
||||||
markerPos = source.find_first_of("$@");
|
|
||||||
}
|
|
||||||
// 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))
|
|
||||||
{
|
{
|
||||||
|
cmSystemTools::Error(error.str().c_str());
|
||||||
|
cmSystemTools::SetFatalErrorOccured();
|
||||||
return source.c_str();
|
return source.c_str();
|
||||||
}
|
}
|
||||||
// current position
|
else
|
||||||
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
|
cmSystemTools::Message(error.str().c_str());
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
result += source.substr(currentPos); // pick up the rest of the string
|
|
||||||
source = result;
|
|
||||||
}
|
}
|
||||||
return source.c_str();
|
return source.c_str();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue