From dbe1b719f8037dda23279b8bc7d8200578415e15 Mon Sep 17 00:00:00 2001 From: marha Date: Fri, 4 Mar 2011 11:26:33 +0000 Subject: Implement eval sort warning functions (see gnu make manual for description) Solved errors in if and foreach implementations Removed message and reparse function (use info and eval instead) $n can be used to add new line define can be used to specify multi-line macros Solved error in argument expansion in call function --- tools/mhmake/src/bisondata/lalr1.cc | 5 + tools/mhmake/src/build.cpp | 70 ++++++-- tools/mhmake/src/flexlexer.h | 8 +- tools/mhmake/src/functions.cpp | 291 +++++++++++++++++++++++++--------- tools/mhmake/src/mhmake.cpp | 14 +- tools/mhmake/src/mhmakefileparser.cpp | 167 +++++++++---------- tools/mhmake/src/mhmakefileparser.h | 118 +++++++++----- tools/mhmake/src/mhmakelexer.l | 115 +++----------- tools/mhmake/src/mhmakeparser.y | 90 ++++++----- tools/mhmake/src/util.cpp | 48 +++--- tools/mhmake/src/util.h | 44 ++++- 11 files changed, 584 insertions(+), 386 deletions(-) (limited to 'tools') diff --git a/tools/mhmake/src/bisondata/lalr1.cc b/tools/mhmake/src/bisondata/lalr1.cc index 25dd01938..fdc033a1d 100644 --- a/tools/mhmake/src/bisondata/lalr1.cc +++ b/tools/mhmake/src/bisondata/lalr1.cc @@ -153,6 +153,11 @@ b4_user_stype void set_debug_level (debug_level_type l); #endif + position *GetCurPos(void) + { + return &yylocation_stack_[1].begin; + } + private: /// Report a syntax error. /// \param loc where the syntax error is found. diff --git a/tools/mhmake/src/build.cpp b/tools/mhmake/src/build.cpp index 682a98410..5976a8632 100644 --- a/tools/mhmake/src/build.cpp +++ b/tools/mhmake/src/build.cpp @@ -400,14 +400,33 @@ mh_pid_t mhmakefileparser::MakeDirsCommand(const string &Params) const } /*****************************************************************************/ -mh_pid_t mhmakefileparser::EchoCommand(const string &Params) const +static string RemoveQuotes(const string &StrIn) { + char FirstChar=StrIn[0]; + string Ret=StrIn; + if (FirstChar=='"') + { + int Len=Ret.length()-1; + if (Ret[Len]=='"') + Ret=Ret.substr(1,Len-1); + } + else if (FirstChar=='\'') + { + int Len=Ret.length()-1; + if (Ret[Len]=='\'') + Ret=Ret.substr(1,Len-1); + } + return Ret; +} +mh_pid_t mhmakefileparser::EchoCommand(const string &ParamsIn) const +{ + string Params=f_strip(ParamsIn); // Find the first > character size_t Pos=Params.find_first_of('>'); if (Pos==string::npos) { // Just echo it - cout << Params << endl; + cout << RemoveQuotes(Params) << endl; } else { @@ -432,9 +451,7 @@ mh_pid_t mhmakefileparser::EchoCommand(const string &Params) const cerr << "Error opening file "<::iterator pFound=m_CommandCache.find(Command); - string OriCommand=Command; + map::iterator pFound=m_CommandCache.find(CommandIn); + string Command=CommandIn; if (pFound==m_CommandCache.end()) { bool Found=false; @@ -688,11 +723,10 @@ string mhmakefileparser::GetFullCommand(string Command) } else { - static bool s_Py2ExeInstalled=true; /* First check for special internal commands */ - if (OriCommand=="del") + if (CommandIn=="del") { - m_CommandCache[OriCommand]="del"; + m_CommandCache[CommandIn]="del"; return Command; } // Try with different extensions @@ -710,13 +744,23 @@ string mhmakefileparser::GetFullCommand(string Command) Found=true; Command=GetPythonExe()+QuoteFileName(FullCommand); } + else + { + // also search without extension, if found look inside the file if we find an executable to use + FullCommand=SearchCommand(Command); + if (!FullCommand.empty()) + { + Found=true; + Command=GetExecutableFromCommand(FullCommand)+QuoteFileName(FullCommand); + } + } } } if (!Found) { Command=GetComspec()+QuoteFileName(Command); } - m_CommandCache[OriCommand]=Command; + m_CommandCache[CommandIn]=Command; return Command; } return pFound->second; @@ -1374,7 +1418,7 @@ mh_time_t mhmakefileparser::StartBuildTarget(fileinfo* pTarget,bool bCheckTarget mh_time_t TargetDate=pTarget->GetDate(); mh_time_t YoungestDate=TargetDate; - bool MakeTarget=!TargetDate.DoesExist(); + bool MakeTarget=!TargetDate.DoesExist(); // When the target does not exist, always build when a rule is found. This also makes sure the autodepscan will be done in case the target does not exist yet if (!pRule || !pRule->GetCommands().size()) { diff --git a/tools/mhmake/src/flexlexer.h b/tools/mhmake/src/flexlexer.h index 08acef335..33132dc93 100644 --- a/tools/mhmake/src/flexlexer.h +++ b/tools/mhmake/src/flexlexer.h @@ -151,13 +151,13 @@ public: string m_InputFileName; string m_curtoken; mystack m_IncludeStack; - mhmakefileparser *m_pParser; - mhmakefileparser *GetParser() + mhmakefileparser *m_pMakefileParser; + mhmakefileparser *GetParser(void) { - return m_pParser; + return m_pMakefileParser; } public: - string &GetInputFilename() + string &GetInputFilename(void) { return m_InputFileName; } diff --git a/tools/mhmake/src/functions.cpp b/tools/mhmake/src/functions.cpp index 61ae6c1e4..1071d2604 100644 --- a/tools/mhmake/src/functions.cpp +++ b/tools/mhmake/src/functions.cpp @@ -54,12 +54,42 @@ funcdef mhmakefileparser::m_FunctionsDef[]= { ,{"strip" ,&mhmakefileparser::f_strip} ,{"which" ,&mhmakefileparser::f_which} ,{"foreach" ,&mhmakefileparser::f_foreach} + ,{"eval" ,&mhmakefileparser::f_eval} + ,{"sort" ,&mhmakefileparser::f_sort} + ,{"error" ,&mhmakefileparser::f_error} + ,{"info" ,&mhmakefileparser::f_info} + ,{"warning" ,&mhmakefileparser::f_warning} }; map mhmakefileparser::m_Functions; bool mhmakefileparser::m_FunctionsInitialised; +inline const char *NextCharExprItem(const char *pTmp,string &Output,char Char) +{ + const char *pStart=pTmp; + while (*pTmp) + { + char CurChar=*pTmp; + if (CurChar==Char) + break; + pTmp++; + if (CurChar=='$' && *pTmp!='$') + pTmp=SkipMakeExpr(pTmp); + } + + const char *pStop=pTmp; + if (*pTmp) pTmp++; + + while (pStart=Input.size()) return g_EmptyString; size_t Stop=Input.size()-1; - while (strchr(" \t",Input[Stop])) Stop--; + while (strchr(" \t",pInput[Stop])) Stop--; return Input.substr(Start,Stop-Start+1); } @@ -119,8 +150,9 @@ static string filter(const string &FileName, void *pvFilter) return g_EmptyString; } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_filter(const string & Arg, const string *pOriExpr) const +string mhmakefileparser::f_filter(const string & ArgIn) const { + string Arg=ExpandExpression(ArgIn); size_t ipos=Arg.find(','); #ifdef _DEBUG if (ipos==string::npos) { @@ -137,8 +169,9 @@ string mhmakefileparser::f_filter(const string & Arg, const string *pOriExpr) co } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_filterout(const string & Arg, const string *pOriExpr) const +string mhmakefileparser::f_filterout(const string & ArgIn) const { + string Arg=ExpandExpression(ArgIn); size_t ipos=Arg.find(','); #ifdef _DEBUG if (ipos==string::npos) { @@ -175,9 +208,52 @@ string mhmakefileparser::f_filterout(const string & Arg, const string *pOriExpr) return Ret; } +class varstack_t : public vector< pair > +{ + mhmakefileparser *m_pMakefileParser; +public: + varstack_t(mhmakefileparser *pMakefileParser) + : m_pMakefileParser(pMakefileParser) + { + } + void PushArg(int ArgNr, const string &Value) + { + char szVarName[10]; + ::sprintf(szVarName,"%d",ArgNr); + string VarName(szVarName); + string VarVal; + if (m_pMakefileParser->GetVariable(VarName,VarVal)) + vector< pair >::push_back(pair(true, VarVal)); + else + vector< pair >::push_back(pair(false,g_EmptyString)); + m_pMakefileParser->SetVariable(VarName,Value); + } + void RestoreArgs() + { + vector< pair >::iterator It=begin(); + int ArgNr=0; + while (It!=end()) + { + char szVarName[10]; + ::sprintf(szVarName,"%d",ArgNr); + string VarName(szVarName); + if (It->first) + m_pMakefileParser->SetVariable(VarName, It->second); + else + { + m_pMakefileParser->DeleteVariable(VarName); + } + It++; + ArgNr++; + } + } +}; + /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_call(const string & Arg, const string *pOriExpr) const +string mhmakefileparser::f_call(const string & ArgIn) const { + string Arg=ExpandExpression(ArgIn); + varstack_t VarStack((mhmakefileparser*)this); const char *pTmp=Arg.c_str(); bool LastCharIsComma=Arg[Arg.length()-1]==','; @@ -191,6 +267,9 @@ string mhmakefileparser::f_call(const string & Arg, const string *pOriExpr) cons throw string("call to non existing function ")+Func; } #endif + // the 0 argument is the function itself + VarStack.PushArg(0,Func); + Func=pFunc->second; int i=0; while (*pTmp || LastCharIsComma) { @@ -199,23 +278,20 @@ string mhmakefileparser::f_call(const string & Arg, const string *pOriExpr) cons string Repl; pTmp=NextCharItem(pTmp,Repl,','); i++; - char Tmp[10]; - ::sprintf(Tmp,"$(%d)",i); - size_t Len=::strlen(Tmp); - size_t Pos=Func.find(Tmp); - while (Func.npos!=Pos) - { - Func=Func.substr(0,Pos)+Repl+Func.substr(Pos+Len); - Pos=Func.find(Tmp,Pos+Len); - } + VarStack.PushArg(i,Repl); } - return ExpandExpression(Func); + string Ret=ExpandExpression(Func); + + VarStack.RestoreArgs(); + + return Ret; } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_subst(const string & Arg, const string *pOriExpr) const +string mhmakefileparser::f_subst(const string & ArgIn) const { + string Arg=ExpandExpression(ArgIn); const char *pTmp=Arg.c_str(); string FromString; @@ -250,8 +326,9 @@ string mhmakefileparser::f_subst(const string & Arg, const string *pOriExpr) con } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_patsubst(const string & Arg, const string *pOriExpr) const +string mhmakefileparser::f_patsubst(const string & ArgIn) const { + string Arg=ExpandExpression(ArgIn); const char *pTmp=Arg.c_str(); string FromString; @@ -274,8 +351,9 @@ string mhmakefileparser::f_patsubst(const string & Arg, const string *pOriExpr) } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_concat(const string & Arg, const string *pOriExpr) const +string mhmakefileparser::f_concat(const string & ArgIn) const { + string Arg=ExpandExpression(ArgIn); const char *pTmp=Arg.c_str(); string JoinString; @@ -311,24 +389,27 @@ string mhmakefileparser::f_concat(const string & Arg, const string *pOriExpr) co } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_if(const string & Arg, const string *pOriExpr) const +// Make sure to only expand the expression which the condition is true for +string mhmakefileparser::f_if(const string & Arg) const { const char *pTmp=Arg.c_str(); string Cond; - pTmp=NextCharItem(pTmp,Cond,','); + pTmp=NextCharExprItem(pTmp,Cond,','); + Cond=ExpandExpression(Cond); string Ret; if (Cond.empty()) { - pTmp=NextCharItem(pTmp,Ret,','); + pTmp=NextCharExprItem(pTmp,Ret,','); } - NextCharItem(pTmp,Ret,','); - return Ret; + NextCharExprItem(pTmp,Ret,','); + return ExpandExpression(Ret); } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_findstring(const string & Arg, const string *pOriExpr) const +string mhmakefileparser::f_findstring(const string & ArgIn) const { + string Arg=ExpandExpression(ArgIn); const char *pTmp=Arg.c_str(); string find; pTmp=NextCharItem(pTmp,find,','); @@ -342,8 +423,9 @@ string mhmakefileparser::f_findstring(const string & Arg, const string *pOriExpr } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_firstword(const string & Arg, const string *pOriExpr) const +string mhmakefileparser::f_firstword(const string & ArgIn) const { + string Arg=ExpandExpression(ArgIn); string FirstWord; NextItem(Arg.c_str(),FirstWord); return FirstWord; @@ -402,15 +484,15 @@ static string wildcard(const string &Arg, void *pvVar) return Ret; } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_wildcard(const string & Arg, const string *pOriExpr) const +string mhmakefileparser::f_wildcard(const string & Arg) const { - return IterList(Arg, wildcard, (void*)this); + return IterList(ExpandExpression(Arg), wildcard, (void*)this); } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_exist(const string & Arg, const string *pOriExpr) const +string mhmakefileparser::f_exist(const string & Arg) const { - string File=TrimString(Arg); + string File=TrimString(ExpandExpression(Arg)); fileinfo *pFile=GetFileInfo(File,m_MakeDir); if (pFile->Exists()) { @@ -421,8 +503,9 @@ string mhmakefileparser::f_exist(const string & Arg, const string *pOriExpr) con } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_filesindirs(const string & Arg, const string *pOriExpr) const +string mhmakefileparser::f_filesindirs(const string & ArgIn) const { + string Arg=ExpandExpression(ArgIn); const char *pTmp=Arg.c_str(); string strFiles; @@ -476,9 +559,9 @@ string mhmakefileparser::f_filesindirs(const string & Arg, const string *pOriExp } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_fullname(const string & Arg, const string *pOriExpr) const +string mhmakefileparser::f_fullname(const string & Arg) const { - string File=TrimString(Arg); + string File=TrimString(ExpandExpression(Arg)); fileinfo *pFile=GetFileInfo(File,m_MakeDir); return pFile->GetQuotedFullFileName(); } @@ -492,9 +575,9 @@ static string basename(const string &FileName,void*) } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_basename(const string & FileNames, const string *pOriExpr) const +string mhmakefileparser::f_basename(const string & FileNames) const { - return IterList(FileNames,basename); + return IterList(ExpandExpression(FileNames),basename); } /////////////////////////////////////////////////////////////////////////////// @@ -515,9 +598,9 @@ static string notdir(const string &FileName,void*) } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_notdir(const string & FileNames, const string *pOriExpr) const +string mhmakefileparser::f_notdir(const string & FileNames) const { - return IterList(FileNames,notdir); + return IterList(ExpandExpression(FileNames),notdir); } /////////////////////////////////////////////////////////////////////////////// @@ -527,14 +610,15 @@ static string addprefix(const string &FileName,void *pPrefix) } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_addprefix(const string & Arg, const string *pOriExpr) const +string mhmakefileparser::f_addprefix(const string & ArgIn) const { + string Arg=ExpandExpression(ArgIn); const char *pTmp=Arg.c_str(); string PreFix; pTmp=NextCharItem(pTmp,PreFix,','); #ifdef _DEBUG if (g_PrintAdditionalInfo && PreFix.empty()) { - cout << "Warning: empty prefix in expression: " << *pOriExpr << endl; + cout << "Warning: empty prefix in expression: " << ArgIn << endl; } #endif string FileNames; @@ -549,8 +633,9 @@ static string addsuffix(const string &FileName,void *pSuffix) } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_addsuffix(const string & Arg, const string *pOriExpr) const +string mhmakefileparser::f_addsuffix(const string & ArgIn) const { + string Arg=ExpandExpression(ArgIn); const char *pTmp=Arg.c_str(); string SufFix; pTmp=NextCharItem(pTmp,SufFix,','); @@ -566,8 +651,9 @@ string mhmakefileparser::f_addsuffix(const string & Arg, const string *pOriExpr) /////////////////////////////////////////////////////////////////////////////// // Returns the n-th word number -string mhmakefileparser::f_word(const string & Arg, const string *pOriExpr) const +string mhmakefileparser::f_word(const string & ArgIn) const { + string Arg=ExpandExpression(ArgIn); const char *pTmp=Arg.c_str(); string strNum; @@ -599,8 +685,9 @@ string mhmakefileparser::f_word(const string & Arg, const string *pOriExpr) cons /////////////////////////////////////////////////////////////////////////////// // Returns the number of words -string mhmakefileparser::f_words(const string & Arg, const string *pOriExpr) const +string mhmakefileparser::f_words(const string & ArgIn) const { + string Arg=ExpandExpression(ArgIn); const char *pTmp=Arg.c_str(); int NrWords=0; char szNumber[10]; @@ -617,15 +704,16 @@ string mhmakefileparser::f_words(const string & Arg, const string *pOriExpr) con /////////////////////////////////////////////////////////////////////////////// // Search for a command in the enivornment path -string mhmakefileparser::f_which(const string & Arg, const string *pOriExpr) const +string mhmakefileparser::f_which(const string & Arg) const { - return SearchCommand(Arg); + return SearchCommand(ExpandExpression(Arg)); } /////////////////////////////////////////////////////////////////////////////// // Removes leading and trailing space -string mhmakefileparser::f_strip(const string & Arg, const string *pOriExpr) const +string mhmakefileparser::f_strip(const string & ArgIn) const { + string Arg=ExpandExpression(ArgIn); string::const_iterator pFirst=Arg.begin(); string::const_iterator pLast=Arg.end(); while (strchr(" \t\r\n",*pFirst) && pFirst!=pLast) pFirst++; @@ -642,10 +730,13 @@ static string dir(const string &FileName, void *) size_t Pos=FileName.find_last_of(OSPATHSEP); if (Pos==string::npos) { + #ifdef _WIN32 + Pos=FileName.find_last_of('/'); + if (Pos==string::npos) + #endif return g_EmptyString; } - else - { + string Ret=g_EmptyString; Ret+=FileName.substr(0,Pos+1); if (FileName[0]=='"' && FileName.end()[-1]=='"') @@ -653,17 +744,16 @@ static string dir(const string &FileName, void *) return Ret; } -} - /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_dir(const string & FileNames, const string *pOriExpr) const +string mhmakefileparser::f_dir(const string & FileNames) const { - return IterList(FileNames,dir); + return IterList(ExpandExpression(FileNames),dir); } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_shell(const string & Command, const string *pOriExpr) const +string mhmakefileparser::f_shell(const string & CommandIn) const { + string Command=ExpandExpression(CommandIn); string Output; #ifdef _DEBUG @@ -733,9 +823,9 @@ 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 *pOriExpr) const +string mhmakefileparser::f_relpath(const string & FileNames) const { - return IterList(FileNames,relpath,(void*)&m_MakeDir); + return IterList(ExpandExpression(FileNames),relpath,(void*)&m_MakeDir); } /////////////////////////////////////////////////////////////////////////////// @@ -752,9 +842,9 @@ static string makeupper(const string &FileName,void *) } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_toupper(const string & FileNames, const string *pOriExpr) const +string mhmakefileparser::f_toupper(const string & FileNames) const { - return IterList(FileNames,makeupper); + return IterList(ExpandExpression(FileNames),makeupper); } /////////////////////////////////////////////////////////////////////////////// @@ -771,9 +861,9 @@ static string makelower(const string &FileName, void *) } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_tolower(const string & FileNames, const string *pOriExpr) const +string mhmakefileparser::f_tolower(const string & FileNames) const { - return IterList(FileNames,makelower); + return IterList(ExpandExpression(FileNames),makelower); } /////////////////////////////////////////////////////////////////////////////// @@ -792,36 +882,26 @@ static string expandexpr(const string &VarVal, void *pvVar) } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::f_foreach(const string & ExpandedArg, const string *pOriExpr) const +string mhmakefileparser::f_foreach(const string & Arg) const { -#ifdef _DEBUG - if (pOriExpr->substr(0,8)!="foreach ") - throw(string("wrong assumption in foreach expression: ")+*pOriExpr); -#endif - const char *pTmp=ExpandedArg.c_str(); + const char *pTmp=Arg.c_str(); expanedexpr_arg Args; Args.pParser=(mhmakefileparser*)this; - pTmp=NextCharItem(pTmp,Args.Var,','); + pTmp=NextCharExprItem(pTmp,Args.Var,','); + Args.Var=ExpandExpression(Args.Var); if (Args.Var.empty()) - throw(string("Wrong syntax in foreach instruction. Should give the variable a name.")); + throw(string("Wrong syntax in foreach instruction: '")+Arg+"'. Variable may not be empty."); string Items; - pTmp=NextCharItem(pTmp,Items,','); + pTmp=NextCharExprItem(pTmp,Items,','); + Items=ExpandExpression(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); + pTmp=NextCharExprItem(pTmp,Args.Expr,','); /* Save the variable to be able to restore it after the foreach expansion */ string VarVal; @@ -840,3 +920,64 @@ string mhmakefileparser::f_foreach(const string & ExpandedArg, const string *pOr return Ret; } +/////////////////////////////////////////////////////////////////////////////// +string mhmakefileparser::f_eval(const string & Arg) const +{ + ((mhmakefileparser*)this)->ParseString(ExpandExpression(Arg)+"\n"); + return g_EmptyString; +} + +/////////////////////////////////////////////////////////////////////////////// +static string AddToList(const string &String, void *pvList) +{ + vector *pList=(vector*)pvList; + pList->push_back(String); + return g_EmptyString; +} + +string mhmakefileparser::f_sort(const string & Arg) const +{ + string ExpandedArg=ExpandExpression(Arg); + vector List; + IterList(ExpandedArg, AddToList, (void*)&List); + sort(List.begin(),List.end()); + string Prev; + vector::iterator It=List.begin(); + string Ret; + bool First=true; + while (It!=List.end()) + { + string This=*It++; + if (This!=Prev) + { + Prev=This; + if (!First) + Ret+=" "; + else + First=false; + Ret+=This; + } + } + return Ret; +} + +/////////////////////////////////////////////////////////////////////////////// +string mhmakefileparser::f_error(const string & Arg) const +{ + throw(GetFileNameLineNo()+ExpandExpression(Arg)); +} + +/////////////////////////////////////////////////////////////////////////////// +string mhmakefileparser::f_warning(const string & Arg) const +{ + cout << GetFileNameLineNo() << ExpandExpression(Arg) << endl; + return g_EmptyString; +} + +/////////////////////////////////////////////////////////////////////////////// +string mhmakefileparser::f_info(const string & Arg) const +{ + cout << ExpandExpression(Arg) << endl; + return g_EmptyString; +} + diff --git a/tools/mhmake/src/mhmake.cpp b/tools/mhmake/src/mhmake.cpp index ce2e8f7a7..ef515b0b2 100644 --- a/tools/mhmake/src/mhmake.cpp +++ b/tools/mhmake/src/mhmake.cpp @@ -105,9 +105,9 @@ int __CDECL main(int argc, char* argv[]) LOADEDMAKEFILES::iterator LoadMakIt=g_LoadedMakefiles.begin(); while (LoadMakIt!=g_LoadedMakefiles.end()) { - (*LoadMakIt)->m_pParser->BuildIncludedMakefiles(); - (*LoadMakIt)->m_pParser->ParseBuildedIncludeFiles(); - (*LoadMakIt)->m_pParser->CheckEnv(); + (*LoadMakIt)->m_pMakefileParser->BuildIncludedMakefiles(); + (*LoadMakIt)->m_pMakefileParser->ParseBuildedIncludeFiles(); + (*LoadMakIt)->m_pMakefileParser->CheckEnv(); LoadMakIt++; } @@ -121,16 +121,16 @@ int __CDECL main(int argc, char* argv[]) g_Clean=true; } fileinfo *pTarget=GetFileInfo(*It,pFirstMakefile->m_MakeDir); - pFirstMakefile->m_pParser->BuildTarget(pTarget); + pFirstMakefile->m_pMakefileParser->BuildTarget(pTarget); It++; } } else { - fileinfo *pFirstTarget=pFirstMakefile->m_pParser->GetFirstTarget(); + fileinfo *pFirstTarget=pFirstMakefile->m_pMakefileParser->GetFirstTarget(); if (pFirstTarget) { - pFirstMakefile->m_pParser->BuildTarget(pFirstTarget); + pFirstMakefile->m_pMakefileParser->BuildTarget(pFirstTarget); } else cout << "Warning: no targets in makefile. Nothing to be build.\nMHMAKECONF defined?\n"; @@ -139,7 +139,7 @@ int __CDECL main(int argc, char* argv[]) } catch (string Message) { - cerr << "Error occured: " << Message << endl; + cerr << "*** Error -> " << Message << endl; #ifdef _DEBUG if (g_DumpOnError) { diff --git a/tools/mhmake/src/mhmakefileparser.cpp b/tools/mhmake/src/mhmakefileparser.cpp index b198c1ca8..1b1119641 100644 --- a/tools/mhmake/src/mhmakefileparser.cpp +++ b/tools/mhmake/src/mhmakefileparser.cpp @@ -25,8 +25,22 @@ #include "mhmakefileparser.h" #include "rule.h" #include "flexlexer.h" +#include "mhmakeparser.hpp" commandqueue mhmakefileparser::sm_CommandQueue; +stack mhmakefileparser::sm_ParserStack; // Keeps track of the currently active parser + +string mhmakefileparser::GetFileNameLineNo(void) +{ + if (!sm_ParserStack.empty()) + { + yy::mhmakeparser* pParser=sm_ParserStack.top(); + yy::position *pPos=pParser->GetCurPos(); + return pParser->GetInputFilename()+":"+stringify(pPos->line)+" "; + } + else + return g_EmptyString; // Currently not parsing, this is a run-time error after parsing +} /////////////////////////////////////////////////////////////////////////////// int mhmakefileparser::ParseFile(const fileinfo *pFileInfo, const fileinfo *pMakeDir) @@ -45,13 +59,33 @@ int mhmakefileparser::ParseFile(const fileinfo *pFileInfo, const fileinfo *pMake } mhmakeFlexLexer theLexer(&yyin); - m_ptheLexer=&theLexer; + theLexer.m_InputFileName=pFileInfo->GetFullFileName(); - theLexer.m_pParser=this; - int Ret=parse(); + theLexer.m_pMakefileParser=this; + + yy::mhmakeparser Parser(this,&theLexer); + sm_ParserStack.push(&Parser); + int Ret=Parser.parse(); + sm_ParserStack.pop(); return Ret; } +/////////////////////////////////////////////////////////////////////////////// +int mhmakefileparser::ParseString(const string &StringIn) +{ + basic_istringstream yyin(StringIn.c_str()); + + mhmakeFlexLexer theLexer(&yyin); + + theLexer.m_InputFileName=string("eval(")+StringIn+")"; + theLexer.m_pMakefileParser=this; + + yy::mhmakeparser Parser(this,&theLexer); + sm_ParserStack.push(&Parser); + int Ret=Parser.parse(); + sm_ParserStack.pop(); + return Ret; +} /////////////////////////////////////////////////////////////////////////////// bool mhmakefileparser::IsDefined(const string &Var) const @@ -75,33 +109,6 @@ static inline size_t SkipUntilQuote(const string &Expr,size_t i,char Char) return i; } -/////////////////////////////////////////////////////////////////////////////// -static inline size_t SkipMakeExpr(const string &Expr,size_t i) -{ - char Char=Expr[i++]; - char EndChar; - if (Char=='(') - EndChar=')'; - else if (Char=='{') - EndChar='}'; - else - return i; - Char=Expr[i++]; - while (Char!=EndChar) - { - if (Char=='$') - { - i=SkipMakeExpr(Expr,i); - } -#ifdef _DEBUG - if (i>=Expr.length()) - throw(string(1,EndChar)+" not found in "+Expr); -#endif - Char=Expr[i++]; - } - return i; -} - /////////////////////////////////////////////////////////////////////////////// // Splits expression on the Item, but the item may not occur within // a macro or quoted string @@ -160,52 +167,39 @@ bool mhmakefileparser::IsEqual(const string &EqualExpr) const } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::ExpandExpression(const string &Expr) const +inline string mhmakefileparser::ExpandExpression(const string &ExprIn) const { - bool Recurse; - string Ret(Expr); - do + bool Recurse=true; + string Ret(ExprIn); + while (Recurse) { Recurse=false; - Ret=ExpandExpressionRecurse(Ret,Recurse); - } - while (Recurse); - return Ret; -} + string Expr(Ret); + Ret.clear(); -/////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::ExpandExpressionRecurse(const string &Expr, bool &Recurse) const -{ - //((mhmakefileparser*)this)->m_InExpandExpression++; size_t i=0; size_t Length=Expr.size(); - string Ret; string ToAdd; while (ii) { - ToAdd=ExpandMacro(Expr.substr(i,inew-i-1),Recurse); + ToAdd=ExpandMacro(Expr.substr(i,inew-i-1)); i=inew; } else { // This is a single character expression - ToAdd=ExpandMacro(string(1,Expr[i-1]),Recurse); + ToAdd=ExpandMacro(string(1,Expr[i-1])); } + if (ToAdd.find('$')!=string::npos && ToAdd.length()!=1) + { + Recurse=true; } Ret+=ToAdd; } @@ -214,20 +208,25 @@ string mhmakefileparser::ExpandExpressionRecurse(const string &Expr, bool &Recur Ret+=Char; } } - + } return Ret; } /////////////////////////////////////////////////////////////////////////////// -string mhmakefileparser::ExpandMacro(const string &Expr, bool &Recurse) const +string mhmakefileparser::ExpandMacro(const string &Expr) const { - string ExpandedExpr=ExpandExpressionRecurse(Expr,Recurse); - - const char *pTmp=ExpandedExpr.c_str(); + const char *pTmp=Expr.c_str(); /* First remove leading spaces */ while (*pTmp==' ' || *pTmp=='\t') pTmp++; const char *pVar=pTmp; - while (*pTmp && *pTmp!=' ' && *pTmp!='\t' && *pTmp!=':') pTmp++; + while (*pTmp && *pTmp!=' ' && *pTmp!='\t' && *pTmp!=':') + { + if (*pTmp=='$' && pTmp[1]) // We have a macro expansion inside a macro expansion, so recurse Do not consider isolated $ (This was a $$) + { + return ExpandMacro(ExpandExpression(Expr)); + } + pTmp++; + } const char *pVarEnd=pTmp; char Type=*pTmp++; while (*pTmp && (*pTmp==' ' || *pTmp=='\t')) pTmp++; @@ -245,8 +244,8 @@ string mhmakefileparser::ExpandMacro(const string &Expr, bool &Recurse) const const char *pStop=pSrc; while (*pStop!='=') pStop++; const char *pTo=pStop+1; - string SrcStr(pSrc,pStop); - string ToStr(pTo); + string SrcStr(ExpandExpression(string(pSrc,pStop))); + string ToStr(pTo); // Do not expand yet to be able to use % inside a macro #ifdef WIN32 if (IsFileName) { @@ -263,31 +262,20 @@ string mhmakefileparser::ExpandMacro(const string &Expr, bool &Recurse) const } else if (Type==' ' || Type == '\t') { - string Func(pVar,pVarEnd); string Arg(pTmp); - if (Recurse) - { - #ifdef _DEBUG - if (!(Arg.find('%')!=string::npos && Arg.find('$')!=string::npos)) - throw(string("Bug in mhmake: expected a % and $ sign: ")+Arg); - #endif - return string("$(")+ExpandedExpr+")"; // we cannot call the function yet since there is still a $(*%*) macro to resolve. so - // return it a a macro again so it can be resolved when the % is resolved - // remark that the current test is not completely safe because the % could be out of - // the $ macro - } + string Func(pVar,pVarEnd); function_f pFunc=m_Functions[Func]; #ifdef _DEBUG if (pFunc) { - return (this->*pFunc)(Arg, &Expr); + return (this->*pFunc)(Arg); } else { - throw string("Unknown function specified in macro: ")+Func; + throw GetFileNameLineNo() + "Unknown function specified in macro: "+Func; } #else - return (this->*pFunc)(Arg, &Expr); + return (this->*pFunc)(Arg); #endif } else @@ -301,21 +289,15 @@ string mhmakefileparser::ExpandMacro(const string &Expr, bool &Recurse) const } else { - if (ExpandedExpr.find('%')!=string::npos) - { - // we have encountered a *%* macro. This means a previous subst is not yet finished. so return - // it back as a macro so it can be expanded again later when the % is replaced - Recurse=true; - return string("$(")+ExpandedExpr+")"; - } #ifdef _DEBUG - else if (ExpandedExpr.find('$')!=string::npos) - throw(string("Bug in mhmake: wasn't expecting a $ sign in: ")+ExpandedExpr); + if (Expr.find('$')!=string::npos && Expr.length()!=1) + throw(string("Bug in mhmake: wasn't expecting a $ sign in: ")+Expr); #endif + string Ret=ExpandVar(Expr); + if (Ret.length()>1) + return ExpandExpression(Ret); else - { - return ExpandExpression(ExpandVar(ExpandedExpr)); - } + return Ret; } } @@ -348,6 +330,10 @@ string mhmakefileparser::ExpandVar(const string &Var) const return m_RuleThatIsBuild->GetPrerequisits(); case '/': return OSPATHSEPSTR; + case '$': + return Var; + case 'n': + return "\n"; default: break; } @@ -360,9 +346,12 @@ string mhmakefileparser::ExpandVar(const string &Var) const case '@': // return full target file name case '*': // return stem case '^': // return all prerequisits + case '$': // $$ expansion return Var; // To make comparing of rules more accurate case '/': return OSPATHSEPSTR; + case 'n': + return "\n"; default: break; } diff --git a/tools/mhmake/src/mhmakefileparser.h b/tools/mhmake/src/mhmakefileparser.h index 581d243b0..82e783dd0 100644 --- a/tools/mhmake/src/mhmakefileparser.h +++ b/tools/mhmake/src/mhmakefileparser.h @@ -30,7 +30,7 @@ class rule; #include "flexlexer.h" class mhmakefileparser; -typedef string (mhmakefileparser::*function_f)(const string &, const string *) const; +typedef string (mhmakefileparser::*function_f)(const string &) const; struct funcdef { @@ -49,16 +49,17 @@ typedef map autodeps_t; namespace yy { class location; + class mhmakeparser; } class mhmakefileparser : public refbase { + friend class yy::mhmakeparser; + private: static commandqueue sm_CommandQueue; -protected: - mhmakeFlexLexer *m_ptheLexer; + static stack sm_ParserStack; // Keeps track of the currently active parser private: - int m_yyloc; fileinfo *m_RuleThatIsBuild; vector m_ToBeIncludeAfterBuild; vector m_MakefilesToLoad; @@ -185,14 +186,28 @@ public: SetAutoDepsDirty(); /* This is to be sure that all new calculated md5 strings are saved. */ } - void SetVariable(string Var,string Val) + void SetVariable(const string &Var, const string &Val) { m_Variables[Var]=Val; } - void DeleteVariable(string Var) + void DeleteVariable(const string &Var) { m_Variables.erase(Var); } + bool GetVariable(const string &Var, string &Val) + { + map::const_iterator pIt=m_Variables.find(Var); + if (pIt==m_Variables.end()) + { + return false; + } + else + { + Val = pIt->second; + return true; + } + } + void EnableAutoDepRescan(void) { m_ForceAutoDepRescan=true; @@ -237,10 +252,6 @@ public: #endif free(m_pEnv); } - int yylex (YYSTYPE* yylval, yy::location* yylloc) - { - return m_ptheLexer->yylex(yylval,yylloc); - } virtual int parse() { @@ -248,14 +259,14 @@ public: } int ParseFile(const fileinfo *pFileInfo,const fileinfo *pMakeDir=NULL); + int ParseString(const string &StringIn); /* 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 ExpandExpressionRecurse(const string &Expr, bool &Recurse) const; - string ExpandMacro(const string &Expr, bool &Recurse) const; + string ExpandMacro(const string &Expr) const; string ExpandVar(const string &Var) const; void PrintVariables(bool Expand=false) const; @@ -265,33 +276,38 @@ public: static map m_Functions; static bool m_FunctionsInitialised; static void InitFuncs(void); - 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; + 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_foreach(const string & Arg) const; + string f_eval(const string & Arg) const; + string f_sort(const string & Arg) const; + string f_error(const string & Arg) const; + string f_info(const string & Arg) const; + string f_warning(const string & Arg) const; fileinfo* GetFirstTarget() const { @@ -372,7 +388,7 @@ public: bool IgnoreError; return ExecuteCommand(Command, IgnoreError, pOutput); } - string GetFullCommand(string Command); + string GetFullCommand(const string &Command); static void InitBuildTime(); @@ -386,8 +402,30 @@ public: const string &GetPythonExe() const; int SearchPath(const char *szCommand, const char *pExt, size_t Len, char *szFullCommand,char **pFilePart) const; mh_pid_t OsExeCommand(const string &Command, const string &Params, bool IgnoreError, string *pOutput) const; + + static string GetFileNameLineNo(void); }; +class mhmakeparserbase +{ +protected: + mhmakefileparser *m_pMakefile; + mhmakeFlexLexer *m_ptheLexer; +public: + mhmakeparserbase(mhmakefileparser *pMakefile, mhmakeFlexLexer *pLexer) + : m_pMakefile(pMakefile), m_ptheLexer(pLexer) + { + } + int yylex (YYSTYPE* yylval, yy::location* yylloc) + { + return m_ptheLexer->yylex(yylval,yylloc); + } + string &GetInputFilename(void) const + { + return m_ptheLexer->GetInputFilename(); + } + +}; #endif diff --git a/tools/mhmake/src/mhmakelexer.l b/tools/mhmake/src/mhmakelexer.l index f27fec31a..aa396ceaf 100644 --- a/tools/mhmake/src/mhmakelexer.l +++ b/tools/mhmake/src/mhmakelexer.l @@ -95,7 +95,7 @@ static void ReplaceCurlyBraces(string &String) /* -------------- rules section -------------- */ %x INCLUDE IFDEF IF IFNDEF SKIPUNTILELSEORENDIF QUOTE MAKEEXPRES SINGLEQUOTE COMMANDPARSE -%x IFEQ IFNEQ ERRORMACRO MESSAGEMACRO REPARSEMACRO LOAD_MAKEFILE +%x IFEQ IFNEQ LOAD_MAKEFILE %x DEFINE %{ @@ -463,7 +463,7 @@ load_makefile { \r /* skip */ -[^\\\r\n\$]+ | +[^\\\r\n\$#]+ | [\\\$] { m_curtoken += (const char *)yytext; } /*****************************************************************************/ @@ -608,7 +608,7 @@ load_makefile { } /*---------------------------------------------------------------------------*/ -[ \t]*#[^\n]* { +[ \t]*#[^\n]* { PRINTF(("%s %d: -COMMENT: %s\n",m_InputFileName.c_str(),lineno(),yytext)); } @@ -678,7 +678,7 @@ export { return yy::mhmakeparser::token::STRING; } -([a-zA-Z0-9\\\._\~\-\+%\@<&;/\*\|]|\\\ |\\#)+ { +([a-zA-Z0-9\\\._\~\-\+%\@<&;/\*\|\[\]]|\\\ |\\#)+ { PRINTF(("%s %d: STRING: %s\n",m_InputFileName.c_str(),lineno(),yytext)); yylval->theString=(const char *)yytext; return yy::mhmakeparser::token::STRING; @@ -701,6 +701,11 @@ export { m_curtoken+=g_SpaceString; } +\n { + inclineno(); + m_curtoken+=(const char *)yytext; +} + . { m_curtoken+=(const char *)yytext; } @@ -733,33 +738,6 @@ export { m_curtoken=(const char *)yytext; } - /*---------------------------------------------------------------------------*/ -\$[\(\{][ \t]*error[ \t]+ { - m_BraceIndent++; - PRINTF(("%s %d: BEGIN ERROR MACRO $(: %d\n",m_InputFileName.c_str(),lineno(),m_BraceIndent)); - BEGIN(ERRORMACRO); - m_curtoken=g_EmptyString; - return yy::mhmakeparser::token::NEWLINE; // Make sure that the previous lines are matched by the bison parser (so that all variables until here are defined) -} - - /*---------------------------------------------------------------------------*/ -\$[\(\{][ \t]*(message|info)[ \t]+ { - m_BraceIndent++; - PRINTF(("%s %d: BEGIN MESSAGE MACRO $(: %d\n",m_InputFileName.c_str(),lineno(),m_BraceIndent)); - BEGIN(MESSAGEMACRO); - m_curtoken=g_EmptyString; - return yy::mhmakeparser::token::NEWLINE; // Make sure that the previous lines are matched by the bison parser (so that all variables until here are defined) -} - - /*---------------------------------------------------------------------------*/ -\$[\(\{][ \t]*reparse[ \t]+ { - m_BraceIndent++; - PRINTF(("%s %d: BEGIN REPARSE MACRO $(: %d\n",m_InputFileName.c_str(),lineno(),m_BraceIndent)); - BEGIN(REPARSEMACRO); - m_curtoken=g_EmptyString; - return yy::mhmakeparser::token::NEWLINE; -} - /*---------------------------------------------------------------------------*/ \$[<@/$] { PRINTF(("%s %d: DOLLAREXPR: %s\n",m_InputFileName.c_str(),lineno(),yytext)); @@ -833,11 +811,6 @@ export { m_curtoken+='#'; } - /*---------------------------------------------------------------------------*/ -[ \t]*#[^\n]* { - PRINTF(("%s %d: -COMMENT: %s\n",m_InputFileName.c_str(),lineno(),yytext)); -} - /*****************************************************************************/ \" { PRINTF(("%s %d: QUOTEDSTRING: %s\n",m_InputFileName.c_str(),lineno(),yytext)); @@ -874,58 +847,6 @@ export { yymore(); } - /*****************************************************************************/ -[\)\}] { - m_BraceIndent--; - PRINTF(("%s %d: CLOSE BRACE ERROR MACRO ): %d\n",m_InputFileName.c_str(),lineno(),m_BraceIndent)); - if (!m_BraceIndent) - { - PRINTF(("%s %d: ERRORMACRO: %s\n",m_InputFileName.c_str(),lineno(),m_curtoken.c_str())); - throw string("\n-> ")+m_InputFileName.c_str()+"("+stringify(lineno())+") : "+GetParser()->ExpandExpression(m_curtoken); - } else { - m_curtoken+=(const char *)yytext; -} -} - - /*****************************************************************************/ -[\)\}] { - m_BraceIndent--; - PRINTF(("%s %d: CLOSE BRACE MESSAGE MACRO ): %d\n",m_InputFileName.c_str(),lineno(),m_BraceIndent)); - if (!m_BraceIndent) - { - PRINTF(("%s %d: MESSAGEMACRO: %s\n",m_InputFileName.c_str(),lineno(),yytext)); - cerr<ExpandExpression(m_curtoken)<[\)\}] { - m_BraceIndent--; - PRINTF(("%s %d: CLOSE BRACE REPARSE MACRO ): %d\n",m_InputFileName.c_str(),lineno(),m_BraceIndent)); - if (!m_BraceIndent) - { - PRINTF(("%s %d: REPARSEMACRO: %s\n",m_InputFileName.c_str(),lineno(),yytext)); - string Deps=GetParser()->ExpandExpression(m_curtoken); - PRINTF(("%s %d: REPARSEMACRO expanded: %s\n",m_InputFileName.c_str(),lineno(),Deps.c_str())); - string::const_reverse_iterator It=Deps.rbegin()+1; // +1 because we don't want the latest brace - string::const_reverse_iterator ItBeg=Deps.rend(); - while (It!= ItBeg) - { - char Char=*It++; - if (Char==';') Char='\n'; - unput(Char); - } - BEGIN(INITIAL); - } - else - { - m_curtoken+=(const char *)yytext; - } -} - /*****************************************************************************/ [\)\}] { m_BraceIndent--; @@ -945,22 +866,32 @@ export { } /*---------------------------------------------------------------------------*/ -\$[\(\{] { +\$[\(\{] { m_BraceIndent++; PRINTF(("%s %d: MACRO extra $(: %d\n",m_InputFileName.c_str(),lineno(),m_BraceIndent)); m_curtoken+=(const char *)yytext; } /*---------------------------------------------------------------------------*/ -[^$\(\)\{\}\r\n\\]+ | -[\(\$\\\{] { +[\(\{] { + m_BraceIndent++; m_curtoken+=(const char *)yytext; } -[ \t\r]*\\[ \t\r]*\n[ \t\r]* { + + /*---------------------------------------------------------------------------*/ +[^$\(\)\{\}\r\n\\]+ | +[\(\$\\\{] { + m_curtoken+=(const char *)yytext; +} +[ \t\r]*\\[ \t\r]*\n[ \t\r]* { inclineno(); m_curtoken+=g_SpaceString; } +\n { + throw m_InputFileName + "(" + stringify(lineno()) + "): End of line inside macro is not allowed"; +} + <> { throw string("Missing endif or else statement. #else or #endif used?"); } diff --git a/tools/mhmake/src/mhmakeparser.y b/tools/mhmake/src/mhmakeparser.y index 4c54ebd29..847cda48a 100644 --- a/tools/mhmake/src/mhmakeparser.y +++ b/tools/mhmake/src/mhmakeparser.y @@ -23,9 +23,9 @@ %require "2.4.1" %defines %define parser_class_name "mhmakeparser" -%define parser_base_class_name "mhmakefileparser" -%define parser_class_constructor_init ": mhmakefileparser(CommandLineVariables)" -%define parser_class_constructor_param "const map &CommandLineVariables" +%define parser_base_class_name "mhmakeparserbase" +%define parser_class_constructor_init ": mhmakeparserbase(pMakefile,pLexer)" +%define parser_class_constructor_param "mhmakefileparser *pMakefile, mhmakeFlexLexer *pLexer" %error-verbose %code requires { @@ -67,10 +67,10 @@ const char Test[]="dit is een test"; %% file : statements { - if (m_pCurrentItems) + if (m_pMakefile->m_pCurrentItems) { - PRINTF(("Adding rule : %s\n",(*m_pCurrentItems)[0]->GetQuotedFullFileName().c_str())); - AddRule(); + PRINTF(("Adding rule : %s\n",(*m_pMakefile->m_pCurrentItems)[0]->GetQuotedFullFileName().c_str())); + m_pMakefile->AddRule(); } } ; @@ -85,6 +85,9 @@ space : SPACE | statement: NEWLINE | SPACE | + DOLLAREXPR NEWLINE { + m_pMakefile->ExpandExpression($1); + } | includemak | ruledef | phonyrule | @@ -97,46 +100,46 @@ statement: NEWLINE | vpathrule | COMMAND { - if (!m_pCurrentRule) + if (!m_pMakefile->m_pCurrentRule) { - m_pCurrentRule=refptr(new rule(this)); + m_pMakefile->m_pCurrentRule=refptr(new rule(m_pMakefile)); } - m_pCurrentRule->AddCommand($1); + m_pMakefile->m_pCurrentRule->AddCommand($1); PRINTF(("Adding command : %s\n",$1.c_str())); } ; includemak: { - if (m_pCurrentItems) + if (m_pMakefile->m_pCurrentItems) { - PRINTF(("Adding rule : %s\n",(*m_pCurrentItems)[0]->GetQuotedFullFileName().c_str())); - AddRule(); + PRINTF(("Adding rule : %s\n",(*m_pMakefile->m_pCurrentItems)[0]->GetQuotedFullFileName().c_str())); + m_pMakefile->AddRule(); } } INCLUDEMAK ; ruledef: expression_nocolorequal rulecolon maybeemptyexpression { - if (m_pCurrentItems) + if (m_pMakefile->m_pCurrentItems) { - PRINTF(("Adding rule : %s\n",(*m_pCurrentItems)[0]->GetQuotedFullFileName().c_str())); - AddRule(); + PRINTF(("Adding rule : %s\n",(*m_pMakefile->m_pCurrentItems)[0]->GetQuotedFullFileName().c_str())); + m_pMakefile->AddRule(); } - m_pCurrentItems=new fileinfoarray; - m_pCurrentDeps=new fileinfoarray; + m_pMakefile->m_pCurrentItems=new fileinfoarray; + m_pMakefile->m_pCurrentDeps=new fileinfoarray; #ifdef _DEBUG - if (!ExpandExpression($1).size()) + if (!m_pMakefile->ExpandExpression($1).size()) { throw string("Empty left hand side in rule: ") + $1 + " : " + $3; } #endif - SplitToItems(ExpandExpression($1),*m_pCurrentItems); - SplitToItems(ExpandExpression($3),*m_pCurrentDeps); - m_DoubleColonRule= ($2==1) ; + m_pMakefile->SplitToItems(m_pMakefile->ExpandExpression($1),*m_pMakefile->m_pCurrentItems); + m_pMakefile->SplitToItems(m_pMakefile->ExpandExpression($3),*m_pMakefile->m_pCurrentDeps); + m_pMakefile->m_DoubleColonRule= ($2==1) ; PRINTF(("Defining rule %s : %s\n",$1.c_str(),$3.c_str())); - PRINTF((" Expanded to %s : %s\n",ExpandExpression($1).c_str(),ExpandExpression($3).c_str())); + PRINTF((" Expanded to %s : %s\n",m_pMakefile->ExpandExpression($1).c_str(),m_pMakefile->ExpandExpression($3).c_str())); } ; @@ -147,7 +150,7 @@ rulecolon: COLON {$$=0;} | phonyrule: PHONY COLON expression { vector Items; - SplitToItems(ExpandExpression($3),Items); + m_pMakefile->SplitToItems(m_pMakefile->ExpandExpression($3),Items); vector::iterator pIt=Items.begin(); while (pIt!=Items.end()) { @@ -155,7 +158,7 @@ phonyrule: PHONY COLON expression pIt++; } PRINTF(("Defining phony rule : %s\n",$3.c_str())); - PRINTF((" Expanded to : %s\n",ExpandExpression($3).c_str())); + PRINTF((" Expanded to : %s\n",m_pMakefile->ExpandExpression($3).c_str())); } NEWLINE ; @@ -163,20 +166,27 @@ phonyrule: PHONY COLON expression autodepsrule: AUTODEPS COLON expression { vector Items; - SplitToItems(ExpandExpression($3),Items); + m_pMakefile->SplitToItems(m_pMakefile->ExpandExpression($3),Items); vector::iterator pIt=Items.begin(); while (pIt!=Items.end()) { - (*pIt)->SetAutoDepsScan(this); + (*pIt)->SetAutoDepsScan(m_pMakefile); pIt++; } PRINTF(("Defining autodeps rule : %s\n",$3.c_str())); - PRINTF((" Expanded to : %s\n",ExpandExpression($3).c_str())); + PRINTF((" Expanded to : %s\n",m_pMakefile->ExpandExpression($3).c_str())); } NEWLINE ; -exportrule: EXPORT space exportstrings NEWLINE +exportrule: EXPORT space exportstrings NEWLINE | + EXPORT space STRING EQUAL maybeemptyexpression + { + string Val=m_pMakefile->ExpandExpression($5); + m_pMakefile->SetVariable($3,Val); + m_pMakefile->SetExport($3,Val); + PRINTF(("Exporting %s : %s\n",$3.c_str(), Val.c_str())); + } ; exportstrings : exportstring | @@ -185,49 +195,49 @@ exportstrings : exportstring | exportstring : STRING { - SetExport($1,ExpandExpression(ExpandVar($1))); - PRINTF(("Exporting %s : %s\n",$1.c_str(),ExpandExpression(ExpandVar($1)).c_str())); + m_pMakefile->SetExport($1,m_pMakefile->ExpandExpression(m_pMakefile->ExpandVar($1))); + PRINTF(("Exporting %s : %s\n",$1.c_str(),m_pMakefile->ExpandExpression(m_pMakefile->ExpandVar($1)).c_str())); } ; vpathrule: VPATH space nonspaceexpression space expression NEWLINE { - SetvPath(ExpandExpression($3),ExpandExpression($5)); - PRINTF(("Setting vpath %s to %s\n",$3.c_str(),ExpandExpression($5).c_str())); + m_pMakefile->SetvPath(m_pMakefile->ExpandExpression($3),m_pMakefile->ExpandExpression($5)); + PRINTF(("Setting vpath %s to %s\n",$3.c_str(),m_pMakefile->ExpandExpression($5).c_str())); } ; varassignment: VARDEF VARVAL { - m_Variables[f_strip($1,NULL)]=$2; - PRINTF(("Defining variable %s to %s\n",f_strip($1,NULL).c_str(), $2.c_str())); + m_pMakefile->m_Variables[m_pMakefile->f_strip($1)]=$2; + PRINTF(("Defining variable %s to %s\n",m_pMakefile->f_strip($1).c_str(), $2.c_str())); } | STRING EQUAL maybeemptyexpression { - m_Variables[$1]=$3; + m_pMakefile->m_Variables[$1]=$3; PRINTF(("Setting variable %s to %s\n",$1.c_str(), $3.c_str())); } ; imvarassignment: STRING IMEQUAL maybeemptyexpression { - m_Variables[$1]=ExpandExpression($3); - PRINTF(("Setting variable %s to %s\n",$1.c_str(), m_Variables[$1].c_str())); + m_pMakefile->m_Variables[$1]=m_pMakefile->ExpandExpression($3); + PRINTF(("Setting variable %s to %s\n",$1.c_str(), m_pMakefile->m_Variables[$1].c_str())); } ; pvarassignment: STRING PEQUAL maybeemptyexpression { - m_Variables[$1]=ExpandVar($1)+g_SpaceString+$3; + m_pMakefile->m_Variables[$1]=m_pMakefile->ExpandVar($1)+g_SpaceString+$3; PRINTF(("Adding to variable %s: %s\n",$1.c_str(), $3.c_str())); } ; optvarassignment: STRING OPTEQUAL maybeemptyexpression { - if (!IsDefined($1)) + if (!m_pMakefile->IsDefined($1)) { - m_Variables[$1]=$3; + m_pMakefile->m_Variables[$1]=$3; PRINTF(("Setting variable %s to %s\n",$1.c_str(), $3.c_str())); } } diff --git a/tools/mhmake/src/util.cpp b/tools/mhmake/src/util.cpp index 1f531e493..8b7d2b164 100644 --- a/tools/mhmake/src/util.cpp +++ b/tools/mhmake/src/util.cpp @@ -593,7 +593,7 @@ void loadedmakefile::LoadMakefile() cout << "Loading makefile "<GetQuotedFullFileName()<(new yy::mhmakeparser(m_CommandLineVars)); + m_pMakefileParser=refptr(new mhmakefileparser(m_CommandLineVars)); // Add the MAKECMDGOALS environment variable string MakeCmdGoals; @@ -608,7 +608,7 @@ void loadedmakefile::LoadMakefile() MakeCmdGoals+=*TarIt; TarIt++; } - m_pParser->SetVariable("MAKECMDGOALS",MakeCmdGoals); + m_pMakefileParser->SetVariable("MAKECMDGOALS",MakeCmdGoals); string BaseAutoMak; @@ -616,29 +616,29 @@ void loadedmakefile::LoadMakefile() fileinfo *pDepFile; if (sm_Statics.m_MhMakeConf) { - BaseAutoMak=m_pParser->ExpandVar(BASEAUTOMAK); + BaseAutoMak=m_pMakefileParser->ExpandVar(BASEAUTOMAK); if (BaseAutoMak.empty()) { BaseAutoMak="makefile"; - m_pParser->SetVariable(BASEAUTOMAK,BaseAutoMak); + m_pMakefileParser->SetVariable(BASEAUTOMAK,BaseAutoMak); } const fileinfo *pBeforeMakefile=GetFileInfo(BaseAutoMak+".before",sm_Statics.m_MhMakeConf); - int result=m_pParser->ParseFile(pBeforeMakefile,m_MakeDir); + int result=m_pMakefileParser->ParseFile(pBeforeMakefile,m_MakeDir); if (result) { throw string("Error parsing ")+pBeforeMakefile->GetQuotedFullFileName(); } - m_pParser->UpdateDate(pBeforeMakefile->GetDate()); + m_pMakefileParser->UpdateDate(pBeforeMakefile->GetDate()); // Now parse the automaticly generated dependency file, which needs to be in the objdir directory - string ObjDirName=m_pParser->ExpandExpression("$(OBJDIR)"); + string ObjDirName=m_pMakefileParser->ExpandExpression("$(OBJDIR)"); if (!ObjDirName.size()) { throw string("When making use of MHMAKECONF, you have to define OBJDIR in makefile.before"); } pDepFile=GetFileInfo(ObjDirName+OSPATHSEPSTR "." + m_Makefile->GetName()+ ".dep",m_MakeDir); - m_pParser->SetVariable(AUTODEPFILE,pDepFile->GetQuotedFullFileName()); + m_pMakefileParser->SetVariable(AUTODEPFILE,pDepFile->GetQuotedFullFileName()); } else { @@ -663,14 +663,14 @@ void loadedmakefile::LoadMakefile() sprintf(ID,"_%lx",md5_finish32( &ctx)); pDepFile=GetFileInfo(string(".") + m_Makefile->GetName()+ ".dep"+ID,m_MakeDir); - m_pParser->SetVariable(AUTODEPFILE,pDepFile->GetQuotedFullFileName()); + m_pMakefileParser->SetVariable(AUTODEPFILE,pDepFile->GetQuotedFullFileName()); } if (pDepFile->Exists()) - m_pParser->LoadAutoDepsFile(pDepFile); /* Already load this autodep file before parsing of the makefile to avoid needless rebuilds. */ + m_pMakefileParser->LoadAutoDepsFile(pDepFile); /* Already load this autodep file before parsing of the makefile to avoid needless rebuilds. */ - //m_pParser->yydebug=1; - int result=m_pParser->ParseFile(m_Makefile,m_MakeDir); + //m_pMakefileParser->yydebug=1; + int result=m_pMakefileParser->ParseFile(m_Makefile,m_MakeDir); if (result) { throw string("Error parsing ")+m_Makefile->GetQuotedFullFileName(); @@ -678,40 +678,40 @@ void loadedmakefile::LoadMakefile() #ifdef _DEBUG /* Check if the makefile has changed the AUTODEPFILE variable, if so generate a warning that a * rebuild could happen for the rules defined for making included makefiles */ - if (m_pParser->ExpandVar(AUTODEPFILE)!=pDepFile->GetQuotedFullFileName()) + if (m_pMakefileParser->ExpandVar(AUTODEPFILE)!=pDepFile->GetQuotedFullFileName()) { cout << "\n\nWARNING:\n makefile '"<< m_Makefile->GetQuotedFullFileName() <<"' re-defines AUTODEPFILE\n from '"<< pDepFile->GetQuotedFullFileName() <<"'\n to '"<< - m_pParser->ExpandVar(AUTODEPFILE) << "'\n (may cause needless rebuilds when having rules for included makefiles!!!!!)\n\n\n"; + m_pMakefileParser->ExpandVar(AUTODEPFILE) << "'\n (may cause needless rebuilds when having rules for included makefiles!!!!!)\n\n\n"; } if (g_PrintAdditionalInfo) { - if (m_pParser->GetFirstTarget()) - cout<<"First target of "<GetQuotedFullFileName()<<" is "<GetFirstTarget()->GetQuotedFullFileName()<GetFirstTarget()) + cout<<"First target of "<GetQuotedFullFileName()<<" is "<GetFirstTarget()->GetQuotedFullFileName()<GetQuotedFullFileName()<UpdateDate(m_Makefile->GetDate()); + m_pMakefileParser->UpdateDate(m_Makefile->GetDate()); if (sm_Statics.m_MhMakeConf) { fileinfo *pAfterMakefile=GetFileInfo(BaseAutoMak+".after",sm_Statics.m_MhMakeConf); - int result=m_pParser->ParseFile(pAfterMakefile); + int result=m_pMakefileParser->ParseFile(pAfterMakefile); if (result) { throw string("Error parsing ")+pAfterMakefile->GetQuotedFullFileName(); } - m_pParser->UpdateDate(pAfterMakefile->GetDate()); + m_pMakefileParser->UpdateDate(pAfterMakefile->GetDate()); } bool ForceAutoDepRescan=g_ForceAutoDepRescan; if (pDepFile->Exists()) - m_pParser->LoadAutoDepsFile(pDepFile); + m_pMakefileParser->LoadAutoDepsFile(pDepFile); else ForceAutoDepRescan=true; if (ForceAutoDepRescan) - m_pParser->EnableAutoDepRescan(); + m_pMakefileParser->EnableAutoDepRescan(); - vector &MakefilesToLoad=m_pParser->GetMakefilesToLoad(); + vector &MakefilesToLoad=m_pMakefileParser->GetMakefilesToLoad(); vector::iterator It=MakefilesToLoad.begin(); while (It!=MakefilesToLoad.end()) { @@ -739,7 +739,7 @@ void loadedmakefile::LoadMakefile() g_LoadedMakefiles.push_back(pLoadedMakefile); /* If there is a rule to build the makefile, first check if it needs to be rebuild */ - m_pParser->BuildTarget(pLoadedMakefile->m_Makefile); + m_pMakefileParser->BuildTarget(pLoadedMakefile->m_Makefile); pLoadedMakefile->LoadMakefile(); } It++; @@ -780,7 +780,7 @@ void DumpVarsAndRules() cout << "Variables of makefile " << (*LoadMakIt)->m_Makefile->GetQuotedFullFileName() << endl; for (i=0; i<80; i++) cout << "_"; cout << endl; - (*LoadMakIt)->m_pParser->PrintVariables(true); + (*LoadMakIt)->m_pMakefileParser->PrintVariables(true); cout << endl; LoadMakIt++; } diff --git a/tools/mhmake/src/util.h b/tools/mhmake/src/util.h index f789584a1..68cb032d7 100644 --- a/tools/mhmake/src/util.h +++ b/tools/mhmake/src/util.h @@ -50,7 +50,7 @@ #define PLATFORM "linux" #endif -#define MHMAKEVER "2.4.5" +#define MHMAKEVER "3.0.0" class makecommand { @@ -138,6 +138,46 @@ inline const char *NextCharItem(const char *pTmp,string &Output,char Char) return pTmp; } +/////////////////////////////////////////////////////////////////////////////// +inline const char *SkipMakeExpr(const char *pMacro) +{ +#ifdef _DEBUG + const char *pMacroIn=pMacro; +#endif + char Char=*pMacro++; + char EndChar; + if (Char=='(') + EndChar=')'; + else if (Char=='{') + EndChar='}'; + else + return pMacro; + Char=*pMacro++; + while (Char!=EndChar) + { + if (Char=='$') + { + pMacro=SkipMakeExpr(pMacro); + } else if (Char=='(') + { + pMacro=SkipMakeExpr(pMacro-1); + } +#ifdef _DEBUG + if (!*pMacro) + throw(string(1,EndChar)+" not found in "+pMacroIn); +#endif + Char=*pMacro++; + } + return pMacro; +} + +/////////////////////////////////////////////////////////////////////////////// +inline size_t SkipMakeExpr(const string &Expr,size_t i) +{ + const char *pTmp=Expr.c_str(); + return SkipMakeExpr(pTmp+i)-pTmp; +} + /////////////////////////////////////////////////////////////////////////////// string Substitute(const string &ToSubst,const string &SrcStr,const string &ToStr); @@ -170,7 +210,7 @@ struct loadedmakefile : public refbase map m_CommandLineVars; vector m_CommandLineTargets; - refptr m_pParser; + refptr m_pMakefileParser; loadedmakefile(const fileinfo *pDir, vector &Args,const string &Makefile=g_EmptyString); -- cgit v1.2.3