diff options
Diffstat (limited to 'tools/mhmake/src/mhmakefileparser.h')
-rw-r--r-- | tools/mhmake/src/mhmakefileparser.h | 368 |
1 files changed, 368 insertions, 0 deletions
diff --git a/tools/mhmake/src/mhmakefileparser.h b/tools/mhmake/src/mhmakefileparser.h new file mode 100644 index 000000000..1efb37c39 --- /dev/null +++ b/tools/mhmake/src/mhmakefileparser.h @@ -0,0 +1,368 @@ +/* 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$ */
+
+#ifndef __MHMAKEFILE_PARSER__
+#define __MHMAKEFILE_PARSER__
+
+#include "fileinfo.h"
+#include "util.h"
+#include "commandqueue.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<refptr<fileinfo> >
+{
+};
+
+typedef set< refptr<fileinfo> > deps_t;
+class mhmakefileparser : public refbase
+{
+
+private:
+ static commandqueue sm_CommandQueue;
+
+ mhmakelexer *m_ptheLexer;
+ int m_yyloc;
+ refptr<fileinfo> m_RuleThatIsBuild;
+ vector<string> m_ToBeIncludeAfterBuild;
+ vector<string> m_MakefilesToLoad;
+ refptr<fileinfo> 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<string,string> m_CommandCache;
+
+protected:
+ map<string,string> m_Variables;
+ map<string,string> m_CommandLineVars;
+ TOKENVALUE m_theTokenValue;
+ refptr<fileinfo> m_MakeDir;
+ refptr<rule> m_pCurrentRule;
+ refptr<fileinfoarray> m_pCurrentItems;
+ refptr<fileinfoarray> m_pCurrentDeps;
+ refptr<fileinfo> m_FirstTarget;
+ fileinfoarray m_IncludedMakefiles;
+ refptr<fileinfoarray> m_pIncludeDirs;
+ string m_IncludeDirs;
+
+ bool m_DoubleColonRule;
+ bool m_AutoDepsDirty;
+ bool m_ForceAutoDepRescan;
+ set<string> m_SkipHeaders; // Headers to skip
+ vector<string> 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 */
+
+ set<string> m_UsedEnvVars; // Array containing a list of variables that are taken from the environment (This is used for rebuild checking)
+#ifdef WIN32
+ char *m_pEnv; // New environment in case the makefile exports variables
+#else
+ char **m_pEnv; // New environment in case the makefile exports variables
+#endif
+ int m_EnvLen; // Current length of m_pEnv
+
+ map< refptr<fileinfo>, set< refptr<fileinfo> > > m_AutoDeps;
+ set< const fileinfo* , less_fileinfo > m_Targets; // List of targets that are build by this makefile
+
+ static mh_time_t m_sBuildTime;
+private:
+ string ResolveExpression(const string &InExpr,string &Rest) const;
+
+public:
+#ifdef _DEBUG
+ deque< refptr<fileinfo> > m_TargetStack; /* Used to detect circular dependencies */
+#endif
+
+ mhmakefileparser(const map<string,string> &CommandLineVars)
+ : m_CommandLineVars(CommandLineVars)
+ ,m_InExpandExpression(0)
+ ,m_AutoDepsDirty(false)
+ ,m_ForceAutoDepRescan(false)
+ ,m_SkipHeadersInitialized(false)
+ ,m_RebuildAll(false)
+ ,m_EnvMd5_32(0)
+ ,m_pEnv(NULL)
+ #ifdef _DEBUG
+ ,m_ImplicitSearch(0)
+ #endif
+ {
+ if (!m_FunctionsInitialised) InitFuncs();
+ SetVariable("MAKE_VERSION",MHMAKEVER);
+ SetVariable(OBJEXTVAR,OBJEXT);
+ SetVariable(EXEEXTVAR,EXEEXT);
+ }
+
+ /* Needed if you only want to use the searchcommand and execommand functions */
+ mhmakefileparser(const refptr<fileinfo> &pMakeDir) :
+ m_MakeDir(pMakeDir)
+ , m_AutoDepsDirty(false)
+ , m_pEnv(NULL)
+ {}
+
+ static void SetNrParallelBuilds(int NrParallelBuilds)
+ {
+ sm_CommandQueue.SetNrParallelBuilds(NrParallelBuilds);
+ }
+
+ bool CompareEnv() const;
+ uint32 CreateEnvMd5_32() const;
+ string GetFromEnv(const string &Var,bool Cache=true) const;
+ void CreateUSED_ENVVARS();
+
+ void SetExport(const string & Var, const string & Val);
+
+ void CheckEnv(void);
+
+ #ifdef _DEBUG
+ int ImplicitSearch() const
+ {
+ return m_ImplicitSearch;
+ }
+ #endif
+
+ void SetAutoDepsDirty()
+ {
+ m_AutoDepsDirty=true;
+ }
+
+ void ClearAutoDepsDirty()
+ {
+ m_AutoDepsDirty=false;
+ }
+ bool IsAutoDepsDirty() const
+ {
+ return m_AutoDepsDirty;
+ }
+
+ void SetRebuildAll()
+ {
+ m_RebuildAll=true;
+ SetAutoDepsDirty(); /* 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;
+ SetAutoDepsDirty();
+ }
+ bool ForceAutoDepRescan(void)
+ {
+ return m_ForceAutoDepRescan;
+ }
+ void SetRuleThatIsBuild(const refptr<fileinfo> &Target)
+ {
+ m_RuleThatIsBuild=Target;
+ }
+ void ClearRuleThatIsBuild()
+ {
+ m_RuleThatIsBuild=NULL;
+ }
+ void UpdateAutomaticDependencies(const refptr<fileinfo> &Target);
+ void UpdateNoRuleAutomaticDependencies(const refptr<fileinfo> &Target);
+ const refptr<fileinfoarray> GetIncludeDirs() const;
+ void GetAutoDeps(const refptr<fileinfo> &FirstDep,set< refptr<fileinfo> > &Autodeps);
+ void SaveAutoDepsFile();
+ void LoadAutoDepsFile(refptr<fileinfo> &DepFile);
+ bool SkipHeaderFile(const string &FileName);
+ void InitEnv() const;
+
+ virtual ~mhmakefileparser()
+ {
+ SaveAutoDepsFile();
+#ifndef WIN32
+ char **pEnv=m_pEnv;
+ if (pEnv)
+ while (*pEnv) free(*pEnv++);
+#endif
+ free(m_pEnv);
+ }
+ virtual int yylex(void);
+ virtual void yyerror(const char *m);
+ virtual int yyparse()
+ {
+ throw("Please derive if you want to execute yyparse.");
+ }
+
+ int ParseFile(const refptr<fileinfo> &FileInfo,refptr<fileinfo> &pMakeDir=NullFileInfo);
+
+ /* Functions to handle variables */
+ bool IsDefined(const string &Var) const;
+ bool IsEqual(const string &EqualExpr) const;
+ bool IsExprTrue(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<string,function_f> 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;
+ string f_strip(const string & Arg) const;
+ string f_which(const string & Arg) const;
+
+ const refptr<fileinfo> GetFirstTarget() const
+ {
+ return m_FirstTarget;
+ }
+
+ const refptr<fileinfo> 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);
+ }
+ /* Starts building the target,
+ returns 0 when target build is not finished,
+ returns the date of the target when target is build, especially important for phony rules, since this will be the youngest date of all dependencies */
+ mh_time_t StartBuildTarget(const refptr<fileinfo> &Target, bool bCheckTargetDir=true);
+ /* Waits for the target being build, returns the date of the target. Not needed to be cald when StartBuildTarget returned a value different from zero */
+ mh_time_t WaitBuildTarget(const refptr<fileinfo> &Target);
+
+ /* Use the following command when you want to wait for the target is built */
+ mh_time_t BuildTarget(const refptr<fileinfo> &Target, bool bCheckTargetDir=true)
+ {
+ mh_time_t TargetDate=StartBuildTarget(Target,bCheckTargetDir);
+ if (!TargetDate.IsDateValid())
+ return WaitBuildTarget(Target);
+ else
+ return TargetDate;
+ }
+
+ void BuildDependencies(const refptr<rule> &pRule, const refptr<fileinfo> &Target, mh_time_t TargetDate, mh_time_t &YoungestDate, bool &MakeTarget);
+
+ void BuildIncludedMakefiles();
+
+ void AddIncludedMakefile(refptr<fileinfo> &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<string>& GetMakefilesToLoad()
+ {
+ return m_MakefilesToLoad;
+ }
+ void AddRule();
+
+ mh_pid_t ExecuteCommand(string Command, bool &IgnoreError, string *pOutput=NULL);
+ mh_pid_t ExecuteCommand(string Command, string *pOutput=NULL)
+ {
+ bool IgnoreError;
+ return ExecuteCommand(Command, IgnoreError, pOutput);
+ }
+ string GetFullCommand(string Command);
+ void CreatePythonExe(const string &FullCommand);
+
+ static void InitBuildTime();
+
+ void SplitToItems(const string &String, vector< refptr<fileinfo> > &Items) const;
+ mh_pid_t DeleteFiles(const string &Params) const;
+ mh_pid_t CopyFiles(const string &Params) const;
+ mh_pid_t TouchFiles(const string &Params) const;
+ mh_pid_t EchoCommand(const string &Params) const;
+ string SearchCommand(const string &Command, const string &Extension="") const;
+ const string &GetPythonExe() const;
+ int SearchPath(const char *szCommand, const char *pExt, int Len, char *szFullCommand,char **pFilePart) const;
+ mh_pid_t OsExeCommand(const string &Command, const string &Params, bool IgnoreError, string *pOutput) const;
+};
+
+
+#endif
+
|