From a1c59d04b8d5ce972c34bd1e5abd941b55655029 Mon Sep 17 00:00:00 2001
From: marha <marha@users.sourceforge.net>
Date: Wed, 1 Sep 2010 15:05:15 +0000
Subject: Make it possible to use more complicated expressions in if statements

---
 tools/mhmake/src/flexskel.cc          |   3 -
 tools/mhmake/src/mhmakefileparser.cpp | 136 ++++++++++++++++++++++++++++++++++
 tools/mhmake/src/mhmakefileparser.h   |   3 +
 tools/mhmake/src/mhmakelexer.l        |  38 +++++++---
 tools/mhmake/src/util.h               |   2 +-
 5 files changed, 169 insertions(+), 13 deletions(-)

(limited to 'tools/mhmake/src')

diff --git a/tools/mhmake/src/flexskel.cc b/tools/mhmake/src/flexskel.cc
index 43c395dba..a08f23fd3 100644
--- a/tools/mhmake/src/flexskel.cc
+++ b/tools/mhmake/src/flexskel.cc
@@ -806,9 +806,6 @@ void YY_@_CLASS::yyunput( YY_@_CHAR c, YY_@_CHAR *yy_bp )
         YY_FATAL_ERROR( "flex scanner push-back overflow" );
   }
 
-  if ( yy_cp > yy_bp && yy_cp[-1] == '\n' )
-    yy_cp[-2] = '\n';
-
   *--yy_cp = c;
 
     /* note: the formal parameter *must* be called "yy_bp" for this
diff --git a/tools/mhmake/src/mhmakefileparser.cpp b/tools/mhmake/src/mhmakefileparser.cpp
index 35d379cd0..e87f46887 100644
--- a/tools/mhmake/src/mhmakefileparser.cpp
+++ b/tools/mhmake/src/mhmakefileparser.cpp
@@ -100,6 +100,10 @@ static inline size_t SkipMakeExpr(const string &Expr,size_t i)
     {
       i=SkipMakeExpr(Expr,i);
     }
+#ifdef _DEBUG
+    if (i>=Expr.length())
+      throw(string(") not found in ")+Expr);
+#endif
     Char=Expr[i++];
   }
   return i;
@@ -1181,3 +1185,135 @@ void mhmakefileparser::CreateUSED_ENVVARS()
   m_Variables[USED_ENVVARS]=Val;
 }
 
+static string s_TrueString("1");
+static string s_FalseString("0");
+
+static string AndExpression(const string &First, const string &Second)
+{
+  if (First.empty() || First==s_FalseString)
+  {
+    return g_EmptyString;
+  }
+  else
+  {
+    return Second.empty() || Second==s_FalseString ? g_EmptyString : s_TrueString;
+  }
+}
+
+static string OrExpression(const string &First, const string &Second)
+{
+  if (First.empty() || First==s_FalseString)
+  {
+    return Second.empty() || Second==s_FalseString ? g_EmptyString : s_TrueString;
+  }
+  else
+  {
+    return s_TrueString;
+  }
+}
+
+string mhmakefileparser::ResolveExpression(const string &InExpr,string &Rest) const
+{
+  unsigned i=0;
+  string Ret;
+  string Expr=InExpr;
+
+  Rest=g_EmptyString;
+
+  while (i<Expr.length())
+  {
+    while (strchr(" \t\r",Expr[i])) i++;
+    switch (Expr[i])
+    {
+    case '!':
+      if (Expr[i+1]!='=')
+      {
+        Ret=ResolveExpression(Expr.substr(i+1),Expr);
+        Ret = Ret.empty() || Ret==s_FalseString ? s_TrueString : g_EmptyString;
+        i=0;
+      }
+      else
+      {
+        Ret = Ret!=ResolveExpression(Expr.substr(i+2),Expr) ? s_TrueString : g_EmptyString;
+        i=0;
+      }
+      break;
+    case '&':
+      if (Expr[i+1]!='&')
+      {
+        Ret+=Expr[i++];
+      }
+      else
+      {
+        Ret=AndExpression(Ret,ResolveExpression(Expr.substr(i+2),Expr));
+        i=0;
+      }
+      break;
+    case '|':
+      if (Expr[i+1]!='|')
+      {
+        Ret+=Expr[i++];
+      }
+      else
+      {
+        Ret=OrExpression(Ret,ResolveExpression(Expr.substr(i+2),Expr));
+        i=0;
+      }
+      break;
+    case '(':
+      if (Ret=="defined")
+      {
+        Ret=IsDefined(ResolveExpression(Expr.substr(i+1),Expr)) ? s_TrueString : g_EmptyString;
+      }
+      else
+      {
+        Ret+=ResolveExpression(Expr.substr(i+1),Expr);
+      }
+      i=0;
+      break;
+    case ')':
+      Rest=Expr.substr(i+1);
+      return Ret;
+      break;
+    case '"':
+      {
+        i++;
+        while (i<Expr.length())
+        {
+          char Char=Expr[i++];
+          if (Char=='"')
+            break;
+          Ret+=Char;
+        }
+      }
+      break;
+    case '=':
+      if (Expr[i+1]!='=')
+      {
+        Ret+=Expr[i++];
+      }
+      else
+      {
+        Ret = Ret==ResolveExpression(Expr.substr(i+2),Expr) ? s_TrueString : g_EmptyString;
+        i=0;
+      }
+      break;
+    default:
+      Ret+=Expr[i++];
+      break;
+    }
+  }
+  return Ret;
+}
+///////////////////////////////////////////////////////////////////////////////
+bool mhmakefileparser::IsExprTrue(const string &EqualExpr) const
+{
+  string Expr=ExpandExpression(EqualExpr);
+  string Rest;
+  Expr=ResolveExpression(Expr,Rest);
+  if (Expr.empty() || Expr==s_FalseString)
+    return false;
+  else
+    return true;
+}
+
diff --git a/tools/mhmake/src/mhmakefileparser.h b/tools/mhmake/src/mhmakefileparser.h
index 048435f34..73d3979dc 100644
--- a/tools/mhmake/src/mhmakefileparser.h
+++ b/tools/mhmake/src/mhmakefileparser.h
@@ -103,6 +103,8 @@ protected:
   set< const fileinfo* , less_fileinfo > m_Targets; // List of targets that are build by this makefile
 
   static mh_time_t m_sBuildTime;
+private:
+  string mhmakefileparser::ResolveExpression(const string &InExpr,string &Rest) const;
 
 public:
 #ifdef _DEBUG
@@ -228,6 +230,7 @@ public:
   /* 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;
diff --git a/tools/mhmake/src/mhmakelexer.l b/tools/mhmake/src/mhmakelexer.l
index d64d7cc5c..59aaad0ca 100644
--- a/tools/mhmake/src/mhmakelexer.l
+++ b/tools/mhmake/src/mhmakelexer.l
@@ -337,11 +337,13 @@ load_makefile {
 ^[ \t]*if[ \t]*\\[ \t\r]*\n[ \t]* {
   BEGIN(IF);
   m_Line++;
+  m_curtoken=g_EmptyString;
   return mhmakeparser::NEWLINE;
 }
 
 ^[ \t]*if[ \t]+ {
   BEGIN(IF);
+  m_curtoken=g_EmptyString;
   return mhmakeparser::NEWLINE;
 }
 
@@ -417,12 +419,12 @@ load_makefile {
   }
 }
 
-<IFEQ,IFNEQ>[ \t]*\\[ \t\r]*\n[ \t]* { m_Line++; m_curtoken += g_SpaceString;}
+<IF,IFEQ,IFNEQ>[ \t]*\\[ \t\r]*\n[ \t]* { m_Line++; m_curtoken += g_SpaceString;}
 
-<IFEQ,IFNEQ>\r    /* skip */
+<IF,IFEQ,IFNEQ>\r    /* skip */
 
-<IFEQ,IFNEQ>[^\\\r\n]+ |
-<IFEQ,IFNEQ>\\                        { m_curtoken += (const char *)yytext; }
+<IF,IFEQ,IFNEQ>[^\\\r\n]+ |
+<IF,IFEQ,IFNEQ>\\                        { m_curtoken += (const char *)yytext; }
 
  /*****************************************************************************/
 <IFNEQ>\n {
@@ -442,10 +444,8 @@ load_makefile {
 }
 
  /*****************************************************************************/
-<IF,IFDEF,IFNDEF>[ \t\r]*  /* skip */
-
- /*---------------------------------------------------------------------------*/
-<IF>[a-zA-Z0-9_]+ {
+<IF>[ \t\r]*[a-zA-Z0-9_]+[ \t\r]*\n {
+  unput( '\n' );
   m_IndentStack.push(0);
   string Val=GetParser()->ExpandVar((const char *)yytext);
   if (Val.empty() || Val=="0")
@@ -461,6 +461,26 @@ load_makefile {
   }
 }
 
+ /*---------------------------------------------------------------------------*/
+<IF>\n {
+  unput( yytext[0] );
+  m_IndentStack.push(0);
+  if (GetParser()->IsExprTrue(m_curtoken))
+  {
+    PRINTF(("%s %d: Not Skipping ifeq %s: depth %d\n",m_InputFileName.c_str(),m_Line,m_curtoken.c_str(),m_IndentStack.size()));
+    BEGIN(INITIAL);
+  }
+  else
+  {
+    PRINTF(("%s %d: Skipping ifeq %s: depth %d\n",m_InputFileName.c_str(),m_Line,m_curtoken.c_str(),m_IndentStack.size()));
+    m_IndentSkip=m_IndentStack.size();
+    BEGIN(SKIPUNTILELSEORENDIF);
+  }
+}
+
+ /*****************************************************************************/
+<IFDEF,IFNDEF>[ \t\r]*  /* skip */
+
  /*---------------------------------------------------------------------------*/
 <IFDEF>[a-zA-Z0-9_]+ {
   m_IndentStack.push(0);
@@ -523,7 +543,7 @@ load_makefile {
 }
 
  /*---------------------------------------------------------------------------*/
-<SKIPUNTILELSEORENDIF>\n[ ]*if(def|ndef|eq|neq) {
+<SKIPUNTILELSEORENDIF>\n[ ]*if(def|ndef|eq|neq)? {
   m_Line++;
   m_IndentStack.push(0);
   PRINTF(("%s %d: %s: depth %d\n",m_InputFileName.c_str(),m_Line,yytext+1,m_IndentStack.size()));
diff --git a/tools/mhmake/src/util.h b/tools/mhmake/src/util.h
index ef874eb96..62efbd245 100644
--- a/tools/mhmake/src/util.h
+++ b/tools/mhmake/src/util.h
@@ -50,7 +50,7 @@
 #define PLATFORM     "linux"
 #endif
 
-#define MHMAKEVER    "2.1.0"
+#define MHMAKEVER    "2.2.0"
 
 class makecommand
 {
-- 
cgit v1.2.3