diff options
Diffstat (limited to 'tools/mhmake/src/fileinfo.cpp')
-rw-r--r-- | tools/mhmake/src/fileinfo.cpp | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/tools/mhmake/src/fileinfo.cpp b/tools/mhmake/src/fileinfo.cpp new file mode 100644 index 000000000..b79d51678 --- /dev/null +++ b/tools/mhmake/src/fileinfo.cpp @@ -0,0 +1,382 @@ +/* This file is part of mhmake.
+ *
+ * Copyright (C) 2001-2009 Marc Haesen
+ *
+ * Mhmake is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Mhmake is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mhmake. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* $Rev$ */
+
+#include "stdafx.h"
+
+#include "fileinfo.h"
+#include "rule.h"
+#include "util.h"
+#include "mhmakeparser.h"
+
+const string NullString;
+refptr<fileinfo> NullFileInfo;
+
+#ifdef WIN32
+ZEROTIME g_ZeroTime;
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+string QuoteFileName(const string &Filename)
+{
+ string Ret(Filename);
+#if OSPATHSEP=='\\'
+ /* Put quotes around the string if there are spaces in it */
+ if (Ret.find_first_of(' ')!=string::npos && Ret[0]!='"')
+ {
+ Ret=g_QuoteString+Ret+g_QuoteString;
+ }
+#else
+ int Pos=0;
+ /* Escape the spaces with a backslash */
+ while ((Pos=Ret.find_first_of(' ',Pos))!=string::npos)
+ {
+ Ret=Ret.replace(Pos,1,"\\ ");
+ Pos+=2;
+ }
+#endif
+ return Ret;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+string UnquoteFileName(const string &Filename)
+{
+ int Pos=0;
+ string Name(Filename);
+#if OSPATHSEP=='\\'
+ /* Remove all the quotes from the filename */
+ while ((Pos=Name.find_first_of('"',Pos))!=string::npos)
+ {
+ Name=Name.replace(Pos,1,"");
+ }
+#else
+ /* Remove the escaped spaces */
+ while ((Pos=Name.find_first_of("\\",Pos))!=string::npos)
+ {
+ if (Name[Pos+1]==' ')
+ Name=Name.replace(Pos,2," ");
+ Pos+=1;
+ }
+#endif
+ return Name;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+refptr<fileinfo> fileinfo::GetDir() const
+{
+ return GetAbsFileInfo(m_AbsFileName.substr(0,m_AbsFileName.find_last_of(OSPATHSEP)));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+string fileinfo::GetName() const
+{
+ return m_AbsFileName.substr(m_AbsFileName.find_last_of(OSPATHSEP)+1);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+mh_time_t fileinfo::realGetDate()
+{
+#ifdef WIN32
+ WIN32_FIND_DATA FindData;
+ HANDLE hFind=FindFirstFile(m_AbsFileName.c_str(),&FindData);
+ if (hFind==INVALID_HANDLE_VALUE)
+ {
+ m_Date.SetNotExist();
+ }
+ else
+ {
+ FindClose(hFind);
+ if (FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
+ { // For directories we just take an old time since the lastwritetime is changed each time something
+ // is added to the directory
+ m_Date.SetDir();
+ }
+ else
+ {
+ m_Date=g_ZeroTime.ConvertTime(&FindData.ftLastWriteTime);
+ }
+ }
+#else
+ struct stat Buf;
+ if (-1==stat(m_AbsFileName.c_str(),&Buf))
+ m_Date.SetNotExist();
+ else if (S_ISDIR(Buf.st_mode))
+ m_Date.SetDir();
+ else
+ m_Date=Buf.st_mtime;
+#endif
+ return m_Date;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool fileinfo::IsDir() const
+{
+#ifdef WIN32
+ WIN32_FIND_DATA FindData;
+ HANDLE hFind=FindFirstFile(m_AbsFileName.c_str(),&FindData);
+ if (hFind==INVALID_HANDLE_VALUE)
+ {
+ return false;
+ }
+ else
+ {
+ FindClose(hFind);
+ if (FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+#else
+ struct stat Buf;
+ if (-1==stat(m_AbsFileName.c_str(),&Buf))
+ return false; // File does not exist, so consider this as not a directory
+ else
+ return 0!=S_ISDIR (Buf.st_mode);
+ return true;
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void fileinfo::SetDateToNow()
+{
+#ifdef WIN32
+ FILETIME FileTime;
+ GetSystemTimeAsFileTime(&FileTime);
+ m_Date=g_ZeroTime.ConvertTime(&FileTime);
+#else
+ m_Date=time(NULL);
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+string fileinfo::GetPrerequisits() const
+{
+ // Build a string with all prerequisits, but make sure that every dependency
+ // is only in there once (we do this be building a set in parallel
+ vector< refptr<fileinfo> >::const_iterator DepIt=m_Deps.begin();
+ set< refptr<fileinfo> > Deps;
+ bool first=true;
+ string Ret=g_EmptyString;
+ while (DepIt!=m_Deps.end())
+ {
+ set< refptr<fileinfo> >::iterator pFound=Deps.find(*DepIt);
+ if (pFound==Deps.end())
+ {
+ if (first)
+ {
+ first=false;
+ }
+ else
+ {
+ Ret+=g_SpaceString;
+ }
+ Ret+=(*DepIt)->GetQuotedFullFileName();
+ }
+ Deps.insert(*DepIt);
+ DepIt++;
+ }
+ return Ret;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void fileinfo::AddDeps(vector< refptr<fileinfo> > &Deps)
+{
+ vector< refptr<fileinfo> >::iterator It=Deps.begin();
+ vector< refptr<fileinfo> >::iterator ItEnd=Deps.end();
+ while (It!=ItEnd)
+ {
+ AddDep(*It++);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool fileinfo::IsAutoDepExtention(void) const
+{
+ const char *pName=GetFullFileName().c_str();
+ const char *pExt=strrchr(pName,'.');
+ if (!pExt)
+ return false;
+ pExt++;
+ if (m_pRule)
+ {
+ string ObjExt=m_pRule->GetMakefile()->ExpandVar(OBJEXTVAR);
+ return ((0==strcmp(pExt,ObjExt.c_str()+1)) || (0==strcmp(pExt,"h")));
+ }
+ else
+ return ((0==strcmp(pExt,"obj")) || (0==strcmp(pExt,"doj")) || (0==strcmp(pExt,"o")) || (0==strcmp(pExt,"h")));
+}
+
+#ifdef _DEBUG
+///////////////////////////////////////////////////////////////////////////////
+void fileinfo::DumpErrorMessageDuplicateRule(const refptr<rule>&pRule)
+{
+ cerr << GetQuotedFullFileName() << ": rule is defined multiple times\n";
+ cerr << "First ("<<m_pRule->GetMakefile()->GetMakeDir()->GetQuotedFullFileName()<<") :\n";
+
+ vector<string>::const_iterator It=m_pRule->GetCommands().begin();
+ while (It!=m_pRule->GetCommands().end())
+ {
+ cerr << " " << m_pRule->GetMakefile()->ExpandExpression(*It) << endl;
+ It++;
+ }
+ cerr << "Second ("<<pRule->GetMakefile()->GetMakeDir()->GetQuotedFullFileName()<<") :\n";
+ It=pRule->GetCommands().begin();
+ while (It!=pRule->GetCommands().end())
+ {
+ cerr << " " << pRule->GetMakefile()->ExpandExpression(*It) << endl;
+ It++;
+ }
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+static inline string &NormalizePathName(string &Name)
+{
+ const char *pPtr=Name.c_str();
+ const char *pBeg=pPtr;
+ const char *pLastSlash=NULL;
+ char *pWr=(char*)pBeg;
+ char Char=*pPtr++;
+
+ while (Char)
+ {
+ if (Char=='\\' || Char=='/')
+ {
+ char Char2=pPtr[0];
+ if (Char2=='.')
+ {
+ if (pPtr[1]=='.')
+ {
+ pPtr+=2;
+ while ((pPtr[0]=='\\' || pPtr[0]=='/') && pPtr[1]=='.' && pPtr[2]=='.')
+ {
+ pLastSlash--;
+ while (*pLastSlash!='\\' && *pLastSlash!='/') pLastSlash--;
+ if (pLastSlash<pBeg)
+ pLastSlash=pBeg; // This is a fault in the file name, just put it back at the beginning
+ pPtr+=3;
+ }
+ if (pLastSlash)
+ pWr=(char*)pLastSlash;
+ }
+ else
+ {
+ if (pPtr[1]=='\\' || pPtr[1]=='/')
+ {
+ pPtr++;
+ }
+ else
+ {
+ pLastSlash=pWr;
+ *pWr++ = OSPATHSEP;
+ }
+ }
+ }
+ else if (Char2=='\\' || Char2=='/')
+ {
+ }
+ else
+ {
+ pLastSlash=pWr;
+ *pWr++ = OSPATHSEP;
+ }
+ }
+ else
+ {
+ #ifdef WIN32
+ *pWr++ = tolower(Char);
+ #else
+ *pWr++ = Char;
+ #endif
+ }
+ Char=*pPtr++;
+ }
+ *pWr=0;
+ Name.resize(pWr-pBeg);
+
+ return Name;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+const refptr<fileinfo> &GetFileInfo(const string &NameIn,const refptr<fileinfo> &RelDir)
+{
+ string Name=UnquoteFileName(NameIn);
+ bool DoesExist=true;
+
+ //Only concatenate if szName is not already a full name
+#ifdef WIN32
+ if (!Name.empty() && Name[1]!=':')
+#endif
+ {
+ if (Name[0]!=OSPATHSEP)
+ {
+ Name=RelDir->GetFullFileName()+OSPATHSEPSTR+Name;
+ if (!RelDir->Exists()) /* if the directory does not exist, the file will not exist either */
+ DoesExist=false;
+ }
+ #ifdef WIN32
+ else
+ {
+ /* The filename is absolute but does not contain a driver letter. So add it (only on windows) */
+ Name=RelDir->GetFullFileName().substr(0,2)+Name;
+ }
+ #endif
+ }
+ const refptr<fileinfo> &Ret=GetAbsFileInfo(NormalizePathName(Name));
+ if (!DoesExist)
+ Ret->SetNotExist();
+ return Ret;
+}
+
+#ifdef _DEBUG
+///////////////////////////////////////////////////////////////////////////////
+void PrintFileInfos()
+{
+ set<refptr<fileinfo>,less_refptrfileinfo>::iterator pIt=g_FileInfos.begin();
+ while (pIt!=g_FileInfos.end())
+ {
+ cout<<(*pIt)->GetQuotedFullFileName()<<" :";
+ if ((*pIt)->IsPhony())
+ cout<<" (phony)";
+ vector< refptr<fileinfo> > &Deps=(*pIt)->GetDeps();
+ vector< refptr<fileinfo> >::iterator pDepIt=Deps.begin();
+ while (pDepIt!=Deps.end())
+ {
+ cout<<g_SpaceString<<(*pDepIt)->GetQuotedFullFileName();
+ pDepIt++;
+ }
+ cout<<endl;
+ // Write the commands
+ refptr<rule> pRule=(*pIt)->GetRule();
+ if (pRule)
+ {
+ cout<<g_SpaceString<<"Run in: "<<pRule->GetMakefile()->GetMakeDir()->GetQuotedFullFileName()<<endl;
+ pRule->PrintCommands();
+ }
+ pIt++;
+ }
+
+}
+#endif
+
|