ENH: Added support for # characters inside quoted arguments and for escaping # in a non-quoted argument. Improved parsing speed by not compiling regular expressions on blank lines.
This commit is contained in:
parent
36880845b6
commit
40c156dead
@ -146,15 +146,59 @@ void cmListFileCache::FlushCache(const char* path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void RemoveComments(std::string& line)
|
//----------------------------------------------------------------------------
|
||||||
|
inline bool cmListFileCachePreprocessLine(std::string& line)
|
||||||
{
|
{
|
||||||
std::string::size_type pos = line.find("#");
|
// Keep track of whether characters are inside a quoted argument.
|
||||||
if (pos != std::string::npos )
|
bool quoted = false;
|
||||||
|
|
||||||
|
// Keep track of whether the line is blank.
|
||||||
|
bool blank = true;
|
||||||
|
|
||||||
|
// Loop over every character in the line.
|
||||||
|
std::string::iterator c;
|
||||||
|
for(c = line.begin(); c != line.end(); ++c)
|
||||||
{
|
{
|
||||||
line.erase(pos);
|
if((*c == '\\') && (c < line.end()-1))
|
||||||
|
{
|
||||||
|
// A backslash escapes any character, so skip the next
|
||||||
|
// character.
|
||||||
|
++c;
|
||||||
|
|
||||||
|
// We have encountered a non-whitespace character.
|
||||||
|
blank = false;
|
||||||
|
}
|
||||||
|
else if(*c == '"')
|
||||||
|
{
|
||||||
|
// A double-quote either starts or ends a quoted argument.
|
||||||
|
quoted = !quoted;
|
||||||
|
|
||||||
|
// We have encountered a non-whitespace character.
|
||||||
|
blank = false;
|
||||||
|
}
|
||||||
|
else if(*c == '#' && !quoted)
|
||||||
|
{
|
||||||
|
// A pound character outside a double-quoted argument marks the
|
||||||
|
// rest of the line as a comment. Skip it.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if((*c != ' ') && (*c != '\t') && (*c != '\r'))
|
||||||
|
{
|
||||||
|
// We have encountered a non-whitespace character.
|
||||||
|
blank = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Erase from the comment character to the end of the line. If no
|
||||||
|
// comment was present, both iterators are end() iterators and this
|
||||||
|
// does nothing.
|
||||||
|
line.erase(c, line.end());
|
||||||
|
|
||||||
|
// Return true if there is anything useful on this line.
|
||||||
|
return !blank;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
bool cmListFileCache::ParseFunction(std::ifstream& fin,
|
bool cmListFileCache::ParseFunction(std::ifstream& fin,
|
||||||
cmListFileFunction& function,
|
cmListFileFunction& function,
|
||||||
const char* filename,
|
const char* filename,
|
||||||
@ -173,20 +217,23 @@ bool cmListFileCache::ParseFunction(std::ifstream& fin,
|
|||||||
}
|
}
|
||||||
if(cmSystemTools::GetLineFromStream(fin, inbuffer) )
|
if(cmSystemTools::GetLineFromStream(fin, inbuffer) )
|
||||||
{
|
{
|
||||||
|
// Count this line in line numbering.
|
||||||
++line;
|
++line;
|
||||||
RemoveComments(inbuffer);
|
|
||||||
cmsys::RegularExpression blankLine("^[ \t\r]*$");
|
// Preprocess the line to remove comments. Only use it if there
|
||||||
|
// is non-whitespace.
|
||||||
|
if(!cmListFileCachePreprocessLine(inbuffer))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regular expressions to match portions of a command invocation.
|
||||||
cmsys::RegularExpression oneLiner("^[ \t]*([A-Za-z_0-9]*)[ \t]*\\((.*)\\)[ \t\r]*$");
|
cmsys::RegularExpression oneLiner("^[ \t]*([A-Za-z_0-9]*)[ \t]*\\((.*)\\)[ \t\r]*$");
|
||||||
cmsys::RegularExpression multiLine("^[ \t]*([A-Za-z_0-9]*)[ \t]*\\((.*)$");
|
cmsys::RegularExpression multiLine("^[ \t]*([A-Za-z_0-9]*)[ \t]*\\((.*)$");
|
||||||
cmsys::RegularExpression lastLine("^(.*)\\)[ \t\r]*$");
|
cmsys::RegularExpression lastLine("^(.*)\\)[ \t\r]*$");
|
||||||
|
|
||||||
// check for blank line or comment
|
|
||||||
if(blankLine.find(inbuffer.c_str()) )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// look for a oneline fun(arg arg2)
|
// look for a oneline fun(arg arg2)
|
||||||
else if(oneLiner.find(inbuffer.c_str()))
|
if(oneLiner.find(inbuffer.c_str()))
|
||||||
{
|
{
|
||||||
// the arguments are the second match
|
// the arguments are the second match
|
||||||
std::string args = oneLiner.match(2);
|
std::string args = oneLiner.match(2);
|
||||||
@ -210,11 +257,16 @@ bool cmListFileCache::ParseFunction(std::ifstream& fin,
|
|||||||
// read lines until the end paren is found
|
// read lines until the end paren is found
|
||||||
if(cmSystemTools::GetLineFromStream(fin, inbuffer) )
|
if(cmSystemTools::GetLineFromStream(fin, inbuffer) )
|
||||||
{
|
{
|
||||||
|
// Count this line in line numbering.
|
||||||
++line;
|
++line;
|
||||||
RemoveComments(inbuffer);
|
|
||||||
// Check for comment lines and ignore them.
|
// Preprocess the line to remove comments. Only use it if there
|
||||||
if(blankLine.find(inbuffer.c_str()))
|
// is non-whitespace.
|
||||||
{ continue; }
|
if(!cmListFileCachePreprocessLine(inbuffer))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Is this the last line?
|
// Is this the last line?
|
||||||
if(lastLine.find(inbuffer.c_str()))
|
if(lastLine.find(inbuffer.c_str()))
|
||||||
{
|
{
|
||||||
|
@ -164,6 +164,7 @@ std::string cmSystemTools::RemoveEscapes(const char* s)
|
|||||||
case 't': result.insert(result.end(), '\t'); break;
|
case 't': result.insert(result.end(), '\t'); break;
|
||||||
case 'n': result.insert(result.end(), '\n'); break;
|
case 'n': result.insert(result.end(), '\n'); break;
|
||||||
case 'r': result.insert(result.end(), '\r'); break;
|
case 'r': result.insert(result.end(), '\r'); break;
|
||||||
|
case '#': result.insert(result.end(), '#'); break;
|
||||||
case '0': result.insert(result.end(), '\0'); break;
|
case '0': result.insert(result.end(), '\0'); break;
|
||||||
case '\0':
|
case '\0':
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user