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:
Brad King 2003-07-09 17:17:34 -04:00
parent 36880845b6
commit 40c156dead
2 changed files with 69 additions and 16 deletions

View File

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

View File

@ -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':
{ {