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/mhmakefileparser.cpp | 167 ++++++++++++++++------------------ 1 file changed, 78 insertions(+), 89 deletions(-) (limited to 'tools/mhmake/src/mhmakefileparser.cpp') 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; } -- cgit v1.2.3