/* This file is part of mhmake. * * Copyright (C) 2001-2010 marha@sourceforge.net * * 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 . */ /* $Rev$ */ #include "stdafx.h" #include "fileinfo.h" #include "rule.h" #include "util.h" #include "mhmakefileparser.h" refptr NullRule; set IMPLICITRULE::m_ImplicitRuleRecurseDetStack; vector 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(fileinfo *pTarget, implicitruledep_t *pImplicitRule,refptr &Rule) { implicitruledep_t::iterator SecIt=pImplicitRule->begin(); while (SecIt!=pImplicitRule->end()) { if (SecIt->first.empty()) { #ifdef _DEBUG // Check if the rule has the same commands vector &OldCommands=SecIt->second->GetCommands(); vector &NewCommands=Rule->GetCommands(); bool bCommandsDifferent=OldCommands.size()!=NewCommands.size(); if (g_PrintMultipleDefinedRules || bCommandsDifferent) { string ErrorMessage; if (bCommandsDifferent) ErrorMessage += "Implicit Rule '"+ pTarget->GetFullFileName() + "' defined twice with different commands\n"; else ErrorMessage += "Implicit Rule '"+ pTarget->GetFullFileName() + "' defined twice with same commands\n"; ErrorMessage += "Command 1: makedir = " + SecIt->second->GetMakefile()->GetMakeDir()->GetQuotedFullFileName()+ "\n"; vector::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; } mhmakefileparser *pOldMakefile=SecIt->second->GetMakefile(); mhmakefileparser *pNewMakefile=Rule->GetMakefile(); vector::iterator OldIt=OldCommands.begin(); vector::iterator NewIt=NewCommands.begin(); while (OldIt!=OldCommands.end()) { if (pOldMakefile->ExpandExpression(*OldIt)!=pNewMakefile->ExpandExpression(*NewIt)) { string ErrorMessage = string("Implicit Rule '") + pTarget->GetFullFileName() + "' 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(fileinfo *pTarget,const vector &Deps,refptr Rule) { if (!Rule) { #ifdef _DEBUG if (g_PrintAdditionalInfo) cout << "No commands defined for implicit rule " << pTarget->GetFullFileName()<::iterator RuleIt=m_ImplicitRules.begin(); while (RuleIt!=m_ImplicitRules.end()) { if (pTarget==RuleIt->first) { pImplicitRule=&(RuleIt->second); } RuleIt++; } if (!pImplicitRule) { // Add a new entry m_ImplicitRules.push_back(implicitrule_t(pTarget,implicitruledep_t())); pImplicitRule=&((m_ImplicitRules.end()-1)->second); } if (Deps.size()) { #ifdef _DEBUG vector::const_iterator DepIt=Deps.begin(); while (DepIt!=Deps.end()) { if (*DepIt==pTarget) throw(string("Implicit rule : ")+pTarget->GetFullFileName()+" is directly dependent on itself. This is not allowed."); DepIt++; } #endif pImplicitRule->push_back(pair,refptr >(Deps,Rule)); } else { if (!FindDep(pTarget,pImplicitRule,Rule)) pImplicitRule->push_back(pair, refptr >(vector(), Rule)); } } /////////////////////////////////////////////////////////////////////////////// void IMPLICITRULE::SearchImplicitRule(const fileinfo *pTarget, implicitruledep_t &Result) { string TargetFileName=pTarget->GetFullFileName(); vector::iterator ImpRegExIt=m_ImplicitRules.begin(); while (ImpRegExIt!=m_ImplicitRules.end()) { matchres Res; if (PercentMatch(TargetFileName,ImpRegExIt->first->GetFullFileName(),&Res)) { implicitruledep_t::iterator ResIt=ImpRegExIt->second.begin(); while (ResIt!=ImpRegExIt->second.end()) { #ifdef _DEBUG if (!ResIt->second) { throw string("No commands for implicit rule : ") + ImpRegExIt->first->GetFullFileName(); } #endif ResIt->second->SetStem(Res.m_Stem); vector Deps; const fileinfo *pMakeDir=ResIt->second->GetMakefile()->GetMakeDir(); vector::iterator It=ResIt->first.begin(); while (It!=ResIt->first.end()) { string Dependent=ReplaceWithStem((*It)->GetFullFileName(),Res.m_Stem); #ifdef _DEBUG if (Dependent.length()>MAX_PATH) { /* File name is getting too long, this is most probable an infinit loop */ throw(string("Filename too long in implicit rule search: ")+Dependent+"\nProbably some infinit loop in the implicit rules search.\n"); } #endif Deps.push_back(GetFileInfo(Dependent,pMakeDir)); It++; } Result.push_back(pair,refptr >(Deps, ResIt->second)); ResIt++; } } ImpRegExIt++; } return; } /////////////////////////////////////////////////////////////////////////////// bool rule::operator != (const rule &Other) { if (m_Commands.size()!=Other.m_Commands.size()) return true; vector::const_iterator It=m_Commands.begin(); vector::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++; } } /////////////////////////////////////////////////////////////////////////////// void rule::SetTargetsIsBuilding(const fileinfo *pSrc) { vector< fileinfo* >::iterator It=m_Targets.begin(); while (It!=m_Targets.end()) { if ((*It)!=pSrc) (*It)->SetBuilding(false); It++; } } #ifdef _DEBUG /////////////////////////////////////////////////////////////////////////////// void IMPLICITRULE::PrintImplicitRules() { vector::iterator ImpRegExIt=m_ImplicitRules.begin(); while (ImpRegExIt!=m_ImplicitRules.end()) { implicitruledep_t::iterator SecIt=ImpRegExIt->second.begin(); cout << ImpRegExIt->first->GetFullFileName() << " :\n"; while (SecIt!=ImpRegExIt->second.end()) { cout << " :"; vector::iterator DepIt=SecIt->first.begin(); while (DepIt!=SecIt->first.end()) { cout << " " << (*DepIt)->GetQuotedFullFileName() <second) { SecIt->second->PrintCommands(); } else { cout << " No rhs\n"; } SecIt++; } ImpRegExIt++; } return; } /////////////////////////////////////////////////////////////////////////////// void rule::PrintCommands(fileinfo *pTarget) const { if (pTarget) m_pMakefile->SetRuleThatIsBuild(pTarget); vector::const_iterator pCommandIt=m_Commands.begin(); while (pCommandIt!=m_Commands.end()) { cout<ExpandExpression(*pCommandIt)<<")\n"; } pCommandIt++; } } #endif