summaryrefslogtreecommitdiffstats
path: root/Source/cmMakeDepend.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmMakeDepend.cxx')
-rw-r--r--Source/cmMakeDepend.cxx268
1 files changed, 268 insertions, 0 deletions
diff --git a/Source/cmMakeDepend.cxx b/Source/cmMakeDepend.cxx
new file mode 100644
index 0000000..4738373
--- /dev/null
+++ b/Source/cmMakeDepend.cxx
@@ -0,0 +1,268 @@
+#ifdef _MSC_VER
+#pragma warning ( disable : 4786 )
+#endif
+#include "cmMakeDepend.h"
+#include <fstream>
+#include <iostream>
+#include <algorithm>
+#include <functional>
+
+
+void cmMakeDepend::SetIncludeRegularExpression(const char* prefix)
+{
+ m_IncludeFileRegularExpression.compile(prefix);
+}
+
+cmMakeDepend::cmMakeDepend()
+{
+ m_Verbose = false;
+ m_IncludeFileRegularExpression.compile("^itk|^vtk|^vnl|^vcl|^f2c");
+}
+
+cmMakeDepend::~cmMakeDepend()
+{
+ for(DependArray::iterator i = m_DependInformation.begin();
+ i != m_DependInformation.end(); ++i)
+ {
+ delete *i;
+ }
+ m_DependInformation.clear();
+}
+
+
+// Set the makefile that depends will be made from.
+// The pointer is kept so the cmClassFile array can
+// be updated with the depend information.
+
+void cmMakeDepend::SetMakefile(cmMakefile* makefile)
+{
+ m_Makefile = makefile;
+ int index = 0;
+ std::vector<cmClassFile>::iterator i = makefile->m_Classes.begin();
+ while(i != makefile->m_Classes.end())
+ {
+ if(!(*i).m_HeaderFileOnly)
+ {
+ cmDependInformation* info = new cmDependInformation;
+ info->m_FullPath = this->FullPath((*i).m_FullPath.c_str());
+ this->AddFileToSearchPath(info->m_FullPath.c_str());
+ info->m_IncludeName = (*i).m_FullPath;
+ m_DependInformation.push_back(info);
+ info->m_ClassFileIndex = index;
+
+ }
+ ++i;
+ index++;
+ }
+}
+
+
+// Compute the depends.
+void cmMakeDepend::DoDepends()
+{
+ // The size of the m_DependInformation will change as
+ // Depend is called so do not use an iterater but rather
+ // depend on the size of the array.
+ int j = 0;
+ while(j != m_DependInformation.size())
+ {
+ cmDependInformation* info = m_DependInformation[j];
+ // compute the depend information for the info object
+ // this may add more objects to the m_DependInformation
+ // array
+ this->Depend(info);
+ ++j;
+ }
+ // Now update the depend information for each cmClassFile
+ // in the cmMakefile m_Makefile
+ for(DependArray::iterator i = m_DependInformation.begin();
+ i != m_DependInformation.end(); ++i)
+ {
+ cmDependInformation* info = *i;
+ // Remove duplicate depends
+ info->RemoveDuplicateIndices();
+ std::vector<cmClassFile>::iterator j = m_Makefile->m_Classes.begin();
+ // find the class
+ if(info->m_ClassFileIndex != -1)
+ {
+ cmClassFile& cfile = m_Makefile->m_Classes[info->m_ClassFileIndex];
+ for( std::vector<int>::iterator indx = info->m_Indices.begin();
+ indx != info->m_Indices.end(); ++indx)
+ {
+ cfile.m_Depends.push_back(m_DependInformation[*indx]->m_FullPath);
+ }
+ }
+ }
+}
+
+// This function actually reads the file
+// and scans it for #include directives
+void cmMakeDepend::Depend(cmDependInformation* info)
+{
+ const char* path = info->m_FullPath.c_str();
+ if(!path)
+ {
+ std::cerr << "no full path for object" << std::endl;
+ return;
+ }
+
+ std::ifstream fin(path);
+ if(!fin)
+ {
+ std::cerr << "error can not open " << info->m_FullPath << std::endl;
+ return;
+ }
+ char line[255];
+ while(!fin.eof() && !fin.fail())
+ {
+ fin.getline(line, 255);
+ if(!strncmp(line, "#include", 8))
+ {
+ // if it is an include line then create a string class
+ std::string currentline = line;
+ size_t qstart = currentline.find('\"', 8);
+ size_t qend;
+ // if a quote is not found look for a <
+ if(qstart == std::string::npos)
+ {
+ qstart = currentline.find('<', 8);
+ // if a < is not found then move on
+ if(qstart == std::string::npos)
+ {
+ std::cerr << "unknown include directive " << currentline
+ << std::endl;
+ continue;
+ }
+ else
+ {
+ qend = currentline.find('>', qstart+1);
+ }
+ }
+ else
+ {
+ qend = currentline.find('\"', qstart+1);
+ }
+ // extract the file being included
+ std::string includeFile = currentline.substr(qstart+1, qend - qstart-1);
+ // see if the include matches the regular expression
+ if(!m_IncludeFileRegularExpression.find(includeFile))
+ {
+ if(m_Verbose)
+ {
+ std::cerr << "skipping " << includeFile << " for file " << path << std::endl;
+ }
+ continue;
+ }
+ // find the index of the include file in the
+ // m_DependInformation array, if it is not
+ // there then FindInformation will create it
+ int index = this->FindInformation(includeFile.c_str());
+ // add the index to the depends of the current
+ // depend info object
+ info->m_Indices.push_back(index);
+ // Get the depend information object for the include file
+ cmDependInformation* dependInfo = m_DependInformation[index];
+ // if the depends are not known for an include file, then compute them
+ // recursively
+ if(!dependInfo->m_DependDone)
+ {
+ // stop the recursion here
+ dependInfo->m_DependDone = true;
+ this->Depend(dependInfo);
+ }
+ // add the depends of the included file to the includer
+ info->MergeInfo(dependInfo);
+ }
+ }
+ info->m_DependDone = true;
+}
+
+
+// Find the cmDependInformation array index of the
+// given include file. Create a new cmDependInformation
+// object if one is not found
+int cmMakeDepend::FindInformation(const char* fname)
+{
+ int i = 0;
+
+ while(i < m_DependInformation.size())
+ {
+ if(m_DependInformation[i]->m_IncludeName == fname)
+ {
+ return i;
+ }
+ ++i;
+ }
+ cmDependInformation* newinfo = new cmDependInformation;
+ newinfo->m_FullPath = this->FullPath(fname);
+ this->AddFileToSearchPath(newinfo->m_FullPath.c_str());
+ newinfo->m_IncludeName = fname;
+ m_DependInformation.push_back(newinfo);
+ return m_DependInformation.size()-1;
+}
+
+// remove duplicate indices from the depend information
+void cmDependInformation::RemoveDuplicateIndices()
+{
+ std::sort(m_Indices.begin(), m_Indices.end(), std::less<int>());
+ std::vector<int>::iterator new_end =
+ std::unique(m_Indices.begin(), m_Indices.end());
+ m_Indices.erase(new_end, m_Indices.end());
+}
+
+// add the depend information from info to this
+void cmDependInformation::MergeInfo(cmDependInformation* info)
+{
+ std::vector<int>::iterator i = info->m_Indices.begin();
+ for(; i!= info->m_Indices.end(); ++i)
+ {
+ m_Indices.push_back(*i);
+ }
+}
+
+// find the full path to fname by searching the m_IncludeDirectories array
+std::string cmMakeDepend::FullPath(const char* fname)
+{
+ for(std::vector<std::string>::iterator i = m_IncludeDirectories.begin();
+ i != m_IncludeDirectories.end(); ++i)
+ {
+ if(cmFileExists(fname))
+ {
+ return std::string(fname);
+ }
+ std::string path = *i;
+ path = path + "/";
+ path = path + fname;
+ if(cmFileExists(path.c_str()))
+ {
+ return path;
+ }
+ }
+ std::cerr << "File not found " << fname << std::endl;
+ return std::string(fname);
+}
+
+// Add a directory to the search path
+void cmMakeDepend::AddSearchPath(const char* path)
+{
+ m_IncludeDirectories.push_back(path);
+}
+
+// Add a directory to the search path
+void cmMakeDepend::AddFileToSearchPath(const char* file)
+{
+ std::string filepath = file;
+ std::string::size_type pos = filepath.rfind('/');
+ if(pos != std::string::npos)
+ {
+ std::string path = filepath.substr(0, pos);
+ if(std::find(m_IncludeDirectories.begin(), m_IncludeDirectories.end(), path)
+ == m_IncludeDirectories.end())
+ {
+ m_IncludeDirectories.push_back(path);
+ return;
+ }
+ }
+}
+
+