/* 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 . */ /* $Rev$ */ #ifndef __MHMAKEFILE_PARSER__ #define __MHMAKEFILE_PARSER__ #include "fileinfo.h" #include "util.h" class rule; class mhmakelexer; struct TOKENVALUE { string theString; int ival; }; class mhmakefileparser; typedef string (mhmakefileparser::*function_f)(const string &) const; struct funcdef { const char *szFuncName; function_f pFunc; }; class fileinfoarray : public refbase,public vector > { }; class mhmakefileparser : public refbase { private: mhmakelexer *m_ptheLexer; int m_yyloc; refptr m_RuleThatIsBuild; vector m_ToBeIncludeAfterBuild; vector m_MakefilesToLoad; refptr m_AutoDepFileLoaded; int m_InExpandExpression; mh_time_t m_Date; uint32 m_EnvMd5_32; /* Cached Md5_32 value of the userd environment variables */ #ifdef _DEBUG int m_ImplicitSearch; #endif map m_CommandCache; protected: map m_Variables; map m_CommandLineVars; TOKENVALUE m_theTokenValue; refptr m_MakeDir; refptr m_pCurrentRule; refptr m_pCurrentItems; refptr m_pCurrentDeps; refptr m_FirstTarget; fileinfoarray m_IncludedMakefiles; refptr< fileinfoarray > m_pIncludeDirs; string m_IncludeDirs; map< refptr, set< refptr > > m_AutoDeps; set< const fileinfo* , less_fileinfo > m_Targets; // List of targets that are build by this makefile bool m_DoubleColonRule; bool m_AutoDepsDirty; bool m_ForceAutoDepRescan; set m_SkipHeaders; // Headers to skip vector m_PercentHeaders; // Percent specification of headers to skip bool m_SkipHeadersInitialized; // true when previous 2 variables are initialized bool m_RebuildAll; /* true when to rebuild all targets of this makefile */ vector m_Exports; // Array of variables to export. map m_SavedExports; // Original values of the environment are saved here. set m_UsedEnvVars; // Array containing a list of variables that are taken from the environment (This is used for rebuild checking) static const mhmakefileparser *m_spCurEnv; // Identifies which makefiles exports are currently set static mh_time_t m_sBuildTime; public: #ifdef _DEBUG deque< refptr > m_TargetStack; /* Used to detect circular dependencies */ #endif mhmakefileparser(const map &CommandLineVars) : m_CommandLineVars(CommandLineVars) ,m_InExpandExpression(0) ,m_AutoDepsDirty(false) ,m_ForceAutoDepRescan(false) ,m_SkipHeadersInitialized(false) ,m_RebuildAll(false) ,m_EnvMd5_32(0) #ifdef _DEBUG ,m_ImplicitSearch(false) #endif { if (!m_FunctionsInitialised) InitFuncs(); SetVariable("MAKE_VERSION",MHMAKEVER); SetVariable(OBJEXTVAR,OBJEXT); SetVariable(EXEEXTVAR,EXEEXT); } bool CompareEnv() const; uint32 CreateEnvMd5_32() const; string GetFromEnv(const string &Var,bool Cache=true) const; void CreateUSED_ENVVARS(); void SaveEnv(); void RestoreEnv() const; void SetRebuildAll() { m_RebuildAll=true; m_AutoDepsDirty=true; /* This is to be sure that all new calculated md5 strings are saved. */ } void SetVariable(string Var,string Val) { m_Variables[Var]=Val; } void EnableAutoDepRescan(void) { m_ForceAutoDepRescan=true; m_AutoDepsDirty=true; } bool ForceAutoDepRescan(void) { return m_ForceAutoDepRescan; } void SetRuleThatIsBuild(const refptr &Target) { m_RuleThatIsBuild=Target; } void ClearRuleThatIsBuild() { m_RuleThatIsBuild=NULL; } void UpdateAutomaticDependencies(const refptr &Target); const refptr GetIncludeDirs() const; void GetAutoDeps(const refptr &FirstDep,set< refptr > &Autodeps); void SaveAutoDepsFile(); void LoadAutoDepsFile(refptr &DepFile); bool SkipHeaderFile(const string &FileName); void InitEnv() const; virtual ~mhmakefileparser() { SaveAutoDepsFile(); } virtual int yylex(void); virtual void yyerror(char *m); virtual int yyparse()=0; int ParseFile(const refptr &FileInfo,bool SetMakeDir=false); /* Functions to handle variables */ bool IsDefined(const string &Var) const; bool IsEqual(const string &EqualExpr) const; string ExpandExpression(const string &Expr) const; string ExpandMacro(const string &Expr) const; string ExpandVar(const string &Var) const; void PrintVariables(bool Expand=false) const; /* Functions for macro functions */ static funcdef m_FunctionsDef[]; static map m_Functions; static bool m_FunctionsInitialised; static void InitFuncs(void); string f_filter(const string &) const; string f_call(const string &) const; string f_if(const string &) const; string f_findstring(const string &) const; string f_firstword(const string &) const; string f_wildcard(const string &) const; string f_subst(const string &) const; string f_patsubst(const string &) const; string f_concat(const string &) const; string f_basename(const string & Arg) const; string f_notdir(const string & Arg) const; string f_dir(const string & Arg) const; string f_shell(const string & Arg) const; string f_relpath(const string & Arg) const; string f_toupper(const string & Arg) const; string f_tolower(const string & Arg) const; string f_exist(const string & Arg) const; string f_filesindirs(const string & Arg) const; string f_fullname(const string & Arg) const; string f_addprefix(const string & Arg) const; string f_addsuffix(const string & Arg) const; string f_filterout(const string & Arg) const; string f_word(const string & Arg) const; string f_words(const string & Arg) const; const refptr GetFirstTarget() const { return m_FirstTarget; } const refptr GetMakeDir() const { return m_MakeDir; } mh_time_t GetDate(void) const { return m_Date; } void UpdateDate(mh_time_t Date) { if (Date.IsNewer(m_Date)) m_Date=Date; } void AddTarget(const fileinfo* pTarget) { m_Targets.insert(pTarget); } mh_time_t BuildTarget(const refptr &Target, bool bCheckTargetDir=true); /* returns the date of the target after build, especially important for phony rules, since this will be the youngest date of all dependencies */ void BuildDependencies(const refptr &pRule, const refptr &Target, mh_time_t TargetDate, mh_time_t &YoungestDate, bool &MakeTarget); void BuildIncludedMakefiles(); void AddIncludedMakefile(refptr &MakeInfo) { UpdateDate(MakeInfo->GetDate()); m_IncludedMakefiles.push_back(MakeInfo); } fileinfoarray &GetIncludedMakefiles() { return m_IncludedMakefiles; } void IncludeAfterBuild(const string &IncludeFile) { m_ToBeIncludeAfterBuild.push_back(IncludeFile); } void ParseBuildedIncludeFiles(); void AddMakefileToMakefilesToLoad(const string &Makefile) { m_MakefilesToLoad.push_back(Makefile); } vector& GetMakefilesToLoad() { return m_MakefilesToLoad; } void AddRule(); bool ExecuteCommand(string Command,string *pOutput=NULL); string GetFullCommand(string Command); void CreatePythonExe(const string &FullCommand); static void InitBuildTime(); }; void SplitToItems(const string &String,vector< refptr > &Items,refptr Dir=curdir::GetCurDir()); #endif