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("#");
|
||||
if (pos != std::string::npos )
|
||||
// Keep track of whether characters are inside a quoted argument.
|
||||
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,
|
||||
cmListFileFunction& function,
|
||||
const char* filename,
|
||||
|
@ -173,20 +217,23 @@ bool cmListFileCache::ParseFunction(std::ifstream& fin,
|
|||
}
|
||||
if(cmSystemTools::GetLineFromStream(fin, inbuffer) )
|
||||
{
|
||||
// Count this line in line numbering.
|
||||
++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 multiLine("^[ \t]*([A-Za-z_0-9]*)[ \t]*\\((.*)$");
|
||||
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)
|
||||
else if(oneLiner.find(inbuffer.c_str()))
|
||||
if(oneLiner.find(inbuffer.c_str()))
|
||||
{
|
||||
// the arguments are the second match
|
||||
std::string args = oneLiner.match(2);
|
||||
|
@ -210,11 +257,16 @@ bool cmListFileCache::ParseFunction(std::ifstream& fin,
|
|||
// read lines until the end paren is found
|
||||
if(cmSystemTools::GetLineFromStream(fin, inbuffer) )
|
||||
{
|
||||
// Count this line in line numbering.
|
||||
++line;
|
||||
RemoveComments(inbuffer);
|
||||
// Check for comment lines and ignore them.
|
||||
if(blankLine.find(inbuffer.c_str()))
|
||||
{ continue; }
|
||||
|
||||
// Preprocess the line to remove comments. Only use it if there
|
||||
// is non-whitespace.
|
||||
if(!cmListFileCachePreprocessLine(inbuffer))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Is this the last line?
|
||||
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 'n': result.insert(result.end(), '\n'); 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':
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue