ENH: add atonly support to cmCommandArgumentParserHelper.cxx and remove old non-yacc parser code from cmMakefile.cxx

This commit is contained in:
Bill Hoffman 2007-02-09 13:44:37 -05:00
parent 0e1ae13f7c
commit 0e95a190bc
3 changed files with 88 additions and 210 deletions

View File

@ -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)

View File

@ -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

View File

@ -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();
} }