BUG: Re-implemented dependency line parsing to deal with quoted paths and escaped spaces.
This commit is contained in:
parent
b2f5af917b
commit
dd9e2b904c
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
#include "cmSystemTools.h"
|
#include "cmSystemTools.h"
|
||||||
|
|
||||||
|
#include <ctype.h> // isspace
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
cmDependsC::cmDependsC(const char* dir, const char* targetFile, bool verbose):
|
cmDependsC::cmDependsC(const char* dir, const char* targetFile, bool verbose):
|
||||||
cmDepends(dir, targetFile, verbose),
|
cmDepends(dir, targetFile, verbose),
|
||||||
|
@ -181,54 +183,12 @@ bool cmDependsC::CheckDependencies(std::istream& is)
|
||||||
std::string dependee;
|
std::string dependee;
|
||||||
while(cmSystemTools::GetLineFromStream(is, line))
|
while(cmSystemTools::GetLineFromStream(is, line))
|
||||||
{
|
{
|
||||||
// Skip empty lines and comments.
|
// Parse the dependency line.
|
||||||
std::string::size_type pos = line.find_first_not_of(" \t\r\n");
|
if(!this->ParseDependency(line.c_str(), depender, dependee))
|
||||||
if(pos == std::string::npos || line[pos] == '#')
|
|
||||||
{
|
{
|
||||||
continue;
|
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
|
// Dependencies must be regenerated if the dependee does not exist
|
||||||
// or if the depender exists and is older than the dependee.
|
// or if the depender exists and is older than the dependee.
|
||||||
bool regenerate = false;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -50,6 +50,11 @@ protected:
|
||||||
// Method to scan a single file.
|
// Method to scan a single file.
|
||||||
void Scan(std::istream& is, const char* directory);
|
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.
|
// The source file from which to start scanning.
|
||||||
std::string m_SourceFile;
|
std::string m_SourceFile;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue