aboutsummaryrefslogtreecommitdiff
path: root/tools/mhmake/src/rule.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/mhmake/src/rule.cpp')
-rw-r--r--tools/mhmake/src/rule.cpp245
1 files changed, 245 insertions, 0 deletions
diff --git a/tools/mhmake/src/rule.cpp b/tools/mhmake/src/rule.cpp
new file mode 100644
index 000000000..90fee8a91
--- /dev/null
+++ b/tools/mhmake/src/rule.cpp
@@ -0,0 +1,245 @@
+/* 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"
+
+refptr<rule> NullRule;
+
+map< string, vector<pair<string,refptr<rule> > > > IMPLICITRULE::m_ImplicitRules;
+
+makecommand g_MakeCommand; // Order is important since sm_Statics is using g_MakeCommand
+const string g_QuoteString("\""); // Order is important since sm_Statics is using g_QuoteString
+loadedmakefile::loadedmakefile_statics loadedmakefile::sm_Statics;
+
+///////////////////////////////////////////////////////////////////////////////
+static bool FindDep(const string &DepName,vector<pair<string,refptr<rule> > >&ImplicitRule,refptr<rule> &Rule)
+{
+ vector<pair<string,refptr<rule> > >::iterator SecIt=ImplicitRule.begin();
+ while (SecIt!=ImplicitRule.end())
+ {
+ if (SecIt->first==DepName)
+ {
+ #ifdef _DEBUG
+ // Check if the rule has the same commands
+ vector<string> &OldCommands=SecIt->second->GetCommands();
+ vector<string> &NewCommands=Rule->GetCommands();
+
+ bool bCommandsDifferent=OldCommands.size()!=NewCommands.size();
+ if (g_PrintMultipleDefinedRules || bCommandsDifferent)
+ {
+ string ErrorMessage;
+ if (bCommandsDifferent)
+ ErrorMessage += "Implicit Rule '"+ DepName + "' defined twice with different commands\n";
+ else
+ ErrorMessage += "Implicit Rule '"+ DepName + "' defined twice with same commands\n";
+ ErrorMessage += "Command 1: makedir = " + SecIt->second->GetMakefile()->GetMakeDir()->GetQuotedFullFileName()+ "\n";
+
+ vector<string>::const_iterator It;
+ if (bCommandsDifferent)
+ {
+ It=OldCommands.begin();
+ while (It!=OldCommands.end())
+ {
+ ErrorMessage += " " + *It + "\n";
+ }
+ }
+ cerr << "Command 2: makedir = "+ Rule->GetMakefile()->GetMakeDir()->GetQuotedFullFileName()+ "\n";
+ if (bCommandsDifferent)
+ {
+ It=NewCommands.begin();
+ while (It!=NewCommands.end())
+ {
+ ErrorMessage += " " + *It + "\n";
+ }
+ throw ErrorMessage;
+ }
+ else
+ cerr << ErrorMessage << endl;
+ }
+ mhmakeparser *pOldMakefile=SecIt->second->GetMakefile();
+ mhmakeparser *pNewMakefile=Rule->GetMakefile();
+ vector<string>::iterator OldIt=OldCommands.begin();
+ vector<string>::iterator NewIt=NewCommands.begin();
+ while (OldIt!=OldCommands.end())
+ {
+ if (pOldMakefile->ExpandExpression(*OldIt)!=pNewMakefile->ExpandExpression(*NewIt))
+ {
+ string ErrorMessage = string("Implicit Rule '") + DepName + "' defined twice with different commands\n";
+ ErrorMessage += "Command 1: makedir = " + pOldMakefile->GetMakeDir()->GetQuotedFullFileName()+ "\n";
+ ErrorMessage += " " + pOldMakefile->ExpandExpression(*OldIt) + "\n";
+ ErrorMessage += "Command 2: makedir = " + pNewMakefile->GetMakeDir()->GetQuotedFullFileName()+ "\n";
+ ErrorMessage += " " + pNewMakefile->ExpandExpression(*NewIt);
+ throw ErrorMessage;
+ }
+ OldIt++;
+ NewIt++;
+ }
+ #endif
+ return true;
+ }
+ SecIt++;
+ }
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void IMPLICITRULE::AddImplicitRule(const refptr<fileinfo> &Target,const vector< refptr<fileinfo> > &Deps,refptr<rule> Rule)
+{
+ vector<pair<string,refptr<rule> > >& ImplicitRule=m_ImplicitRules[Target->GetFullFileName()];
+ if (Deps.size())
+ {
+ vector< refptr<fileinfo> >::const_iterator DepIt=Deps.begin();
+ while (DepIt!=Deps.end())
+ {
+ const string &DepName=(*DepIt)->GetFullFileName();
+ if (!FindDep(DepName,ImplicitRule,Rule))
+ ImplicitRule.push_back(pair<string,refptr<rule> >(DepName,Rule));
+ DepIt++;
+ }
+ }
+ else
+ {
+ if (!FindDep(g_EmptyString,ImplicitRule,Rule))
+ ImplicitRule.push_back(pair<string,refptr<rule> >(g_EmptyString,Rule));
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void IMPLICITRULE::SearchImplicitRule(const refptr<fileinfo> &Target,vector< pair<refptr<fileinfo>,refptr<rule> > >&Result)
+{
+ string TargetFileName=Target->GetFullFileName();
+
+ map< string, vector<pair<string,refptr<rule> > > >::iterator ImpRegExIt=m_ImplicitRules.begin();
+ while (ImpRegExIt!=m_ImplicitRules.end())
+ {
+ matchres Res;
+
+ if (PercentMatch(TargetFileName,ImpRegExIt->first,&Res))
+ {
+ vector<pair<string,refptr<rule> > >::iterator ResIt=ImpRegExIt->second.begin();
+ while (ResIt!=ImpRegExIt->second.end())
+ {
+#ifdef _DEBUG
+ if (!ResIt->second)
+ {
+ throw string("No rhs for implicit rule : ") + ImpRegExIt->first;
+ }
+#endif
+ ResIt->second->SetStem(Res.m_Stem);
+ if (!ResIt->first.empty())
+ {
+ string Dependent=ReplaceWithStem(ResIt->first,Res.m_Stem);
+ Result.push_back(pair<refptr<fileinfo>,refptr<rule> >(GetFileInfo(Dependent),ResIt->second));
+ }
+ else
+ Result.push_back(pair<refptr<fileinfo>,refptr<rule> >(NullFileInfo,ResIt->second));
+ ResIt++;
+ }
+ }
+ ImpRegExIt++;
+ }
+ return;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool rule::operator != (const rule &Other)
+{
+ if (m_Commands.size()!=Other.m_Commands.size())
+ return true;
+
+ vector<string>::const_iterator It=m_Commands.begin();
+ vector<string>::const_iterator OtherIt=Other.m_Commands.begin();
+ while (It!=m_Commands.end())
+ {
+ if (m_pMakefile->ExpandExpression(*It)!=Other.m_pMakefile->ExpandExpression(*OtherIt))
+ return true;
+ It++;
+ OtherIt++;
+ }
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void rule::SetTargetsIsBuild(uint32 Md5_32)
+{
+ vector< fileinfo* >::iterator It=m_Targets.begin();
+ while (It!=m_Targets.end())
+ {
+ (*It)->SetCommandsMd5_32(Md5_32);
+ (*It)->SetBuild();
+ m_pMakefile->AddTarget(*It);
+ It++;
+ }
+}
+
+
+#ifdef _DEBUG
+///////////////////////////////////////////////////////////////////////////////
+void IMPLICITRULE::PrintImplicitRules()
+{
+ map< string, vector<pair<string,refptr<rule> > > >::iterator ImpRegExIt=m_ImplicitRules.begin();
+ while (ImpRegExIt!=m_ImplicitRules.end())
+ {
+ vector<pair<string,refptr<rule> > >::iterator SecIt=ImpRegExIt->second.begin();
+ cout << ImpRegExIt->first << " :\n";
+ while (SecIt!=ImpRegExIt->second.end())
+ {
+ cout << " : " << SecIt->first <<endl;
+ if (SecIt->second)
+ {
+ SecIt->second->PrintCommands();
+ }
+ else
+ {
+ cout << " No rhs\n";
+ }
+ SecIt++;
+ }
+ ImpRegExIt++;
+ }
+ return;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void rule::PrintCommands(refptr<fileinfo> Target) const
+{
+ if (Target)
+ m_pMakefile->SetRuleThatIsBuild(Target);
+
+ vector<string>::const_iterator pCommandIt=m_Commands.begin();
+ while (pCommandIt!=m_Commands.end())
+ {
+ cout<<g_SpaceString<<*pCommandIt<<endl;
+ if (Target)
+ {
+ cout<<" ("<<m_pMakefile->ExpandExpression(*pCommandIt)<<")\n";
+ }
+ pCommandIt++;
+ }
+}
+
+#endif
+
+