diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index 6a64b6af1..6e359a55c 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -18,6 +18,8 @@ #include "cmSystemTools.h" +#include // 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; +} diff --git a/Source/cmDependsC.h b/Source/cmDependsC.h index 8cc88420c..0a0bc36fa 100644 --- a/Source/cmDependsC.h +++ b/Source/cmDependsC.h @@ -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;