BUG: Re-implemented dependency line parsing to deal with quoted paths and escaped spaces.

This commit is contained in:
Brad King 2005-05-10 11:00:15 -04:00
parent b2f5af917b
commit dd9e2b904c
2 changed files with 68 additions and 44 deletions

View File

@ -18,6 +18,8 @@
#include "cmSystemTools.h"
#include <ctype.h> // isspace
//----------------------------------------------------------------------------
cmDependsC::cmDependsC(const char* dir, const char* targetFile, bool verbose):
cmDepends(dir, targetFile, verbose),
@ -181,54 +183,12 @@ bool cmDependsC::CheckDependencies(std::istream& is)
std::string dependee;
while(cmSystemTools::GetLineFromStream(is, line))
{
// Skip empty lines and comments.
std::string::size_type pos = line.find_first_not_of(" \t\r\n");
if(pos == std::string::npos || line[pos] == '#')
// Parse the dependency line.
if(!this->ParseDependency(line.c_str(), depender, dependee))
{
continue;
}
// Strip leading whitespace.
if(pos > 0)
{
line = line.substr(pos);
}
// Skip lines too short to have a dependency.
if(line.size() < 3)
{
continue;
}
// Find the colon on the line. Skip the first two characters to
// avoid finding the colon in a drive letter on Windows. Ignore
// the line if a colon cannot be found.
if((pos = line.find(':', 2)) == std::string::npos)
{
continue;
}
// Split the line into depender and dependee.
depender = line.substr(0, pos);
dependee = line.substr(pos+1);
// Strip whitespace from the dependee.
if((pos = dependee.find_first_not_of(" \t\r\n")) != std::string::npos &&
pos > 0)
{
dependee = dependee.substr(pos);
}
if((pos = dependee.find_last_not_of(" \t\r\n")) != std::string::npos)
{
dependee = dependee.substr(0, pos+1);
}
// Strip whitespace from the depender.
if((pos = depender.find_last_not_of(" \t\r\n")) != std::string::npos)
{
depender = depender.substr(0, pos+1);
}
// Dependencies must be regenerated if the dependee does not exist
// or if the depender exists and is older than the dependee.
bool regenerate = false;
@ -319,3 +279,62 @@ void cmDependsC::Scan(std::istream& is, const char* directory)
}
}
}
//----------------------------------------------------------------------------
bool cmDependsC::ParseDependency(const char* line, std::string& depender,
std::string& dependee)
{
// Start with empty names.
depender = "";
dependee = "";
// Get the left-hand-side of the dependency.
const char* c = this->ParseFileName(line, depender);
// Skip the ':' separator.
for(;c && *c && isspace(*c);++c);
if(!c || !*c || *c != ':')
{
return false;
}
++c;
// Get the right-hand-side of the dependency.
return this->ParseFileName(c, dependee)?true:false;
}
//----------------------------------------------------------------------------
const char* cmDependsC::ParseFileName(const char* in, std::string& name)
{
// Skip leading whitespace.
const char* c = in;
for(;c && *c && isspace(*c);++c);
// If this is an empty line or a comment line return failure.
if(!c || !*c || *c == '#')
{
return 0;
}
// Parse the possibly quoted file name.
bool quoted = false;
for(;*c && (quoted ||
((*c != ':' || name.size() == 1) && !isspace(*c))); ++c)
{
if(*c == '"')
{
quoted = !quoted;
}
else if(!quoted && *c == '\\' && isspace(*(c+1)))
{
name += *(++c);
}
else
{
name += *c;
}
}
// Return the ending position.
return c;
}

View File

@ -50,6 +50,11 @@ protected:
// Method to scan a single file.
void Scan(std::istream& is, const char* directory);
// Method to parse a single dependency line.
bool ParseDependency(const char* line, std::string& depender,
std::string& dependee);
const char* ParseFileName(const char* in, std::string& name);
// The source file from which to start scanning.
std::string m_SourceFile;