From c3d55347b14c80f553ab8c487baded1a44acf68c Mon Sep 17 00:00:00 2001 From: marha Date: Mon, 1 Nov 2010 15:42:39 +0000 Subject: Implemented foreach function. wildcard can now have multiple arguments --- tools/mhmake/src/functions.cpp | 130 ++++++++++++++++++++++++++-------- tools/mhmake/src/mhmakefileparser.cpp | 2 +- tools/mhmake/src/mhmakefileparser.h | 59 ++++++++------- tools/mhmake/src/mhmakeparser.y | 4 +- 4 files changed, 136 insertions(+), 59 deletions(-) (limited to 'tools') diff --git a/tools/mhmake/src/functions.cpp b/tools/mhmake/src/functions.cpp index 1602112c3..61ae6c1e4 100644 --- a/tools/mhmake/src/functions.cpp +++ b/tools/mhmake/src/functions.cpp @@ -53,6 +53,7 @@ funcdef mhmakefileparser::m_FunctionsDef[]= { ,{"words" ,&mhmakefileparser::f_words} ,{"strip" ,&mhmakefileparser::f_strip} ,{"which" ,&mhmakefileparser::f_which} + ,{"foreach" ,&mhmakefileparser::f_foreach} }; map mhmakefileparser::m_Functions; @@ -118,7 +119,7 @@ static string filter(const string &FileName, void *pvFilter) return g_EmptyString; } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_filter(const string & Arg) const +string mhmakefileparser::f_filter(const string & Arg, const string *pOriExpr) const { size_t ipos=Arg.find(','); #ifdef _DEBUG @@ -136,7 +137,7 @@ string mhmakefileparser::f_filter(const string & Arg) const } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_filterout(const string & Arg) const +string mhmakefileparser::f_filterout(const string & Arg, const string *pOriExpr) const { size_t ipos=Arg.find(','); #ifdef _DEBUG @@ -175,7 +176,7 @@ string mhmakefileparser::f_filterout(const string & Arg) const } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_call(const string & Arg) const +string mhmakefileparser::f_call(const string & Arg, const string *pOriExpr) const { const char *pTmp=Arg.c_str(); @@ -213,7 +214,7 @@ string mhmakefileparser::f_call(const string & Arg) const } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_subst(const string & Arg) const +string mhmakefileparser::f_subst(const string & Arg, const string *pOriExpr) const { const char *pTmp=Arg.c_str(); @@ -249,7 +250,7 @@ string mhmakefileparser::f_subst(const string & Arg) const } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_patsubst(const string & Arg) const +string mhmakefileparser::f_patsubst(const string & Arg, const string *pOriExpr) const { const char *pTmp=Arg.c_str(); @@ -273,7 +274,7 @@ string mhmakefileparser::f_patsubst(const string & Arg) const } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_concat(const string & Arg) const +string mhmakefileparser::f_concat(const string & Arg, const string *pOriExpr) const { const char *pTmp=Arg.c_str(); @@ -310,7 +311,7 @@ string mhmakefileparser::f_concat(const string & Arg) const } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_if(const string & Arg) const +string mhmakefileparser::f_if(const string & Arg, const string *pOriExpr) const { const char *pTmp=Arg.c_str(); @@ -326,7 +327,7 @@ string mhmakefileparser::f_if(const string & Arg) const } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_findstring(const string & Arg) const +string mhmakefileparser::f_findstring(const string & Arg, const string *pOriExpr) const { const char *pTmp=Arg.c_str(); string find; @@ -341,7 +342,7 @@ string mhmakefileparser::f_findstring(const string & Arg) const } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_firstword(const string & Arg) const +string mhmakefileparser::f_firstword(const string & Arg, const string *pOriExpr) const { string FirstWord; NextItem(Arg.c_str(),FirstWord); @@ -349,9 +350,11 @@ string mhmakefileparser::f_firstword(const string & Arg) const } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_wildcard(const string & Arg) const +static string wildcard(const string &Arg, void *pvVar) { - fileinfo *pFileSpec=GetFileInfo(TrimString(Arg),m_MakeDir); /* Use GetFileInfo to make the relative path absolute */ + mhmakefileparser *pParser=(mhmakefileparser*)pvVar; + + fileinfo *pFileSpec=GetFileInfo(Arg,pParser->GetMakeDir()); /* Use GetFileInfo to make the relative path absolute */ fileinfo *pDir=pFileSpec->GetDir(); #ifdef WIN32 struct _finddata_t FileInfo; @@ -398,9 +401,14 @@ string mhmakefileparser::f_wildcard(const string & Arg) const #endif return Ret; } +/////////////////////////////////////////////////////////////////////////////// +string mhmakefileparser::f_wildcard(const string & Arg, const string *pOriExpr) const +{ + return IterList(Arg, wildcard, (void*)this); +} /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_exist(const string & Arg) const +string mhmakefileparser::f_exist(const string & Arg, const string *pOriExpr) const { string File=TrimString(Arg); fileinfo *pFile=GetFileInfo(File,m_MakeDir); @@ -413,7 +421,7 @@ string mhmakefileparser::f_exist(const string & Arg) const } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_filesindirs(const string & Arg) const +string mhmakefileparser::f_filesindirs(const string & Arg, const string *pOriExpr) const { const char *pTmp=Arg.c_str(); @@ -468,7 +476,7 @@ string mhmakefileparser::f_filesindirs(const string & Arg) const } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_fullname(const string & Arg) const +string mhmakefileparser::f_fullname(const string & Arg, const string *pOriExpr) const { string File=TrimString(Arg); fileinfo *pFile=GetFileInfo(File,m_MakeDir); @@ -484,7 +492,7 @@ static string basename(const string &FileName,void*) } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_basename(const string & FileNames) const +string mhmakefileparser::f_basename(const string & FileNames, const string *pOriExpr) const { return IterList(FileNames,basename); } @@ -507,7 +515,7 @@ static string notdir(const string &FileName,void*) } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_notdir(const string & FileNames) const +string mhmakefileparser::f_notdir(const string & FileNames, const string *pOriExpr) const { return IterList(FileNames,notdir); } @@ -519,14 +527,14 @@ static string addprefix(const string &FileName,void *pPrefix) } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_addprefix(const string & Arg) const +string mhmakefileparser::f_addprefix(const string & Arg, const string *pOriExpr) const { const char *pTmp=Arg.c_str(); string PreFix; pTmp=NextCharItem(pTmp,PreFix,','); #ifdef _DEBUG - if (PreFix.empty()) { - throw ("Wrong number of arguments in function addprefix"); + if (g_PrintAdditionalInfo && PreFix.empty()) { + cout << "Warning: empty prefix in expression: " << *pOriExpr << endl; } #endif string FileNames; @@ -541,7 +549,7 @@ static string addsuffix(const string &FileName,void *pSuffix) } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_addsuffix(const string & Arg) const +string mhmakefileparser::f_addsuffix(const string & Arg, const string *pOriExpr) const { const char *pTmp=Arg.c_str(); string SufFix; @@ -558,7 +566,7 @@ string mhmakefileparser::f_addsuffix(const string & Arg) const /////////////////////////////////////////////////////////////////////////////// // Returns the n-th word number -string mhmakefileparser::f_word(const string & Arg) const +string mhmakefileparser::f_word(const string & Arg, const string *pOriExpr) const { const char *pTmp=Arg.c_str(); @@ -591,7 +599,7 @@ string mhmakefileparser::f_word(const string & Arg) const /////////////////////////////////////////////////////////////////////////////// // Returns the number of words -string mhmakefileparser::f_words(const string & Arg) const +string mhmakefileparser::f_words(const string & Arg, const string *pOriExpr) const { const char *pTmp=Arg.c_str(); int NrWords=0; @@ -609,14 +617,14 @@ string mhmakefileparser::f_words(const string & Arg) const /////////////////////////////////////////////////////////////////////////////// // Search for a command in the enivornment path -string mhmakefileparser::f_which(const string & Arg) const +string mhmakefileparser::f_which(const string & Arg, const string *pOriExpr) const { return SearchCommand(Arg); } /////////////////////////////////////////////////////////////////////////////// // Removes leading and trailing space -string mhmakefileparser::f_strip(const string & Arg) const +string mhmakefileparser::f_strip(const string & Arg, const string *pOriExpr) const { string::const_iterator pFirst=Arg.begin(); string::const_iterator pLast=Arg.end(); @@ -648,13 +656,13 @@ static string dir(const string &FileName, void *) } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_dir(const string & FileNames) const +string mhmakefileparser::f_dir(const string & FileNames, const string *pOriExpr) const { return IterList(FileNames,dir); } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_shell(const string & Command) const +string mhmakefileparser::f_shell(const string & Command, const string *pOriExpr) const { string Output; @@ -725,7 +733,7 @@ static string relpath(const string &FileName,void *pvDir) /////////////////////////////////////////////////////////////////////////////// // Make a path name relative to the current directory -string mhmakefileparser::f_relpath(const string & FileNames) const +string mhmakefileparser::f_relpath(const string & FileNames, const string *pOriExpr) const { return IterList(FileNames,relpath,(void*)&m_MakeDir); } @@ -744,7 +752,7 @@ static string makeupper(const string &FileName,void *) } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_toupper(const string & FileNames) const +string mhmakefileparser::f_toupper(const string & FileNames, const string *pOriExpr) const { return IterList(FileNames,makeupper); } @@ -763,8 +771,72 @@ static string makelower(const string &FileName, void *) } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_tolower(const string & FileNames) const +string mhmakefileparser::f_tolower(const string & FileNames, const string *pOriExpr) const { return IterList(FileNames,makelower); } +/////////////////////////////////////////////////////////////////////////////// +struct expanedexpr_arg +{ + string Var; + mhmakefileparser *pParser; + string Expr; +}; + +static string expandexpr(const string &VarVal, void *pvVar) +{ + expanedexpr_arg *pArg=(expanedexpr_arg*)pvVar; + pArg->pParser->SetVariable(pArg->Var,VarVal); + return pArg->pParser->ExpandExpression(pArg->Expr); +} + +/////////////////////////////////////////////////////////////////////////////// +string mhmakefileparser::f_foreach(const string & ExpandedArg, const string *pOriExpr) const +{ +#ifdef _DEBUG + if (pOriExpr->substr(0,8)!="foreach ") + throw(string("wrong assumption in foreach expression: ")+*pOriExpr); +#endif + const char *pTmp=ExpandedArg.c_str(); + + expanedexpr_arg Args; + Args.pParser=(mhmakefileparser*)this; + pTmp=NextCharItem(pTmp,Args.Var,','); + + if (Args.Var.empty()) + throw(string("Wrong syntax in foreach instruction. Should give the variable a name.")); + + string Items; + pTmp=NextCharItem(pTmp,Items,','); + + if (Items.empty()) + return g_EmptyString; /* No items specified, so nothing needs to be done */ + + /* for the next item we need to use the original expression because we need to re-expand it using Var for each entry + in Items */ + int Pos=pOriExpr->find_first_of(',',0); + if (Pos==string::npos) + throw(string("expected , in ")+*pOriExpr); + Pos=pOriExpr->find_first_of(',',Pos+1); + if (Pos==string::npos) + throw(string("expected two ,'s in ")+*pOriExpr); + Args.Expr=pOriExpr->substr(Pos+1); + + /* Save the variable to be able to restore it after the foreach expansion */ + string VarVal; + map::const_iterator pVal=m_Variables.find(Args.Var); + if (pVal!=m_Variables.end()) + VarVal=pVal->second; + + string Ret=IterList(Items,expandexpr,(void*)&Args); + + /* Restore the variable to it's original value */ + if (pVal!=m_Variables.end()) + Args.pParser->SetVariable(Args.Var,VarVal); + else + Args.pParser->DeleteVariable(Args.Var); + + return Ret; +} + diff --git a/tools/mhmake/src/mhmakefileparser.cpp b/tools/mhmake/src/mhmakefileparser.cpp index a2d4537a0..38c5cd3ac 100644 --- a/tools/mhmake/src/mhmakefileparser.cpp +++ b/tools/mhmake/src/mhmakefileparser.cpp @@ -288,7 +288,7 @@ string mhmakefileparser::ExpandMacro(const string &Expr, bool &Recurse) const #ifdef _DEBUG if (pFunc) { - return (this->*pFunc)(Arg); + return (this->*pFunc)(Arg, &Expr); } else { diff --git a/tools/mhmake/src/mhmakefileparser.h b/tools/mhmake/src/mhmakefileparser.h index 6bdaa911d..f1c9cb280 100644 --- a/tools/mhmake/src/mhmakefileparser.h +++ b/tools/mhmake/src/mhmakefileparser.h @@ -36,7 +36,7 @@ struct TOKENVALUE }; class mhmakefileparser; -typedef string (mhmakefileparser::*function_f)(const string &) const; +typedef string (mhmakefileparser::*function_f)(const string &, const string *) const; struct funcdef { @@ -189,6 +189,10 @@ public: { m_Variables[Var]=Val; } + void DeleteVariable(string Var) + { + m_Variables.erase(Var); + } void EnableAutoDepRescan(void) { m_ForceAutoDepRescan=true; @@ -251,32 +255,33 @@ public: 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; - string f_strip(const string & Arg) const; - string f_which(const string & Arg) const; + string f_filter(const string &, const string *pOriExpr) const; + string f_call(const string &, const string *pOriExpr) const; + string f_if(const string &, const string *pOriExpr) const; + string f_findstring(const string &, const string *pOriExpr) const; + string f_firstword(const string &, const string *pOriExpr) const; + string f_wildcard(const string &, const string *pOriExpr) const; + string f_subst(const string &, const string *pOriExpr) const; + string f_patsubst(const string &, const string *pOriExpr) const; + string f_concat(const string &, const string *pOriExpr) const; + string f_basename(const string & Arg, const string *pOriExpr) const; + string f_notdir(const string & Arg, const string *pOriExpr) const; + string f_dir(const string & Arg, const string *pOriExpr) const; + string f_shell(const string & Arg, const string *pOriExpr) const; + string f_relpath(const string & Arg, const string *pOriExpr) const; + string f_toupper(const string & Arg, const string *pOriExpr) const; + string f_tolower(const string & Arg, const string *pOriExpr) const; + string f_exist(const string & Arg, const string *pOriExpr) const; + string f_filesindirs(const string & Arg, const string *pOriExpr) const; + string f_fullname(const string & Arg, const string *pOriExpr) const; + string f_addprefix(const string & Arg, const string *pOriExpr) const; + string f_addsuffix(const string & Arg, const string *pOriExpr) const; + string f_filterout(const string & Arg, const string *pOriExpr) const; + string f_word(const string & Arg, const string *pOriExpr) const; + string f_words(const string & Arg, const string *pOriExpr) const; + string f_strip(const string & Arg, const string *pOriExpr) const; + string f_which(const string & Arg, const string *pOriExpr) const; + string f_foreach(const string & Arg, const string *pOriExpr) const; fileinfo* GetFirstTarget() const { diff --git a/tools/mhmake/src/mhmakeparser.y b/tools/mhmake/src/mhmakeparser.y index f1ab48606..515caf6e5 100644 --- a/tools/mhmake/src/mhmakeparser.y +++ b/tools/mhmake/src/mhmakeparser.y @@ -184,8 +184,8 @@ vpathrule: VPATH SPACE nonspaceexpression SPACE expression NEWLINE varassignment: VARDEF VARVAL { - m_Variables[f_strip($1)]=$2; - PRINTF(("Defining variable %s to %s\n",f_strip($1).c_str(), $2.c_str())); + m_Variables[f_strip($1,NULL)]=$2; + PRINTF(("Defining variable %s to %s\n",f_strip($1,NULL).c_str(), $2.c_str())); } | STRING EQUAL maybeemptyexpression { -- cgit v1.2.3