Added conditional statement support for DSC file
[people/mcb30/basetools.git] / Source / Python / Workspace / MetaFileParser.py
index 9869f35..715082d 100644 (file)
@@ -22,6 +22,7 @@ import Common.EdkLogger as EdkLogger
 from CommonDataClass.DataClass import *\r
 from Common.DataType import *\r
 from Common.String import *\r
+from Common.Misc import Blist\r
 \r
 class MetaFileParser(object):\r
     _DataType = {}\r
@@ -47,6 +48,7 @@ class MetaFileParser(object):
         self._SubsectionType = MODEL_UNKNOWN\r
         self._SubsectionName = ''\r
         self._LastItem = -1\r
+        self._Enabled = 0\r
 \r
     def _Store(self, *Args):\r
         return self._Table.Insert(*Args)\r
@@ -276,8 +278,22 @@ class DscParser(MetaFileParser):
         TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper(),\r
         ]\r
 \r
+    _OP_ = {\r
+        "!"     :   lambda a:   not a,\r
+        "!="    :   lambda a,b: a!=b,\r
+        "=="    :   lambda a,b: a==b,\r
+        ">"     :   lambda a,b: a>b,\r
+        "<"     :   lambda a,b: a<b,\r
+        "=>"    :   lambda a,b: a>=b,\r
+        ">="    :   lambda a,b: a>=b,\r
+        "<="    :   lambda a,b: a<=b,\r
+        "=<"    :   lambda a,b: a<=b,\r
+    }\r
+\r
     def __init__(self, FilePath, FileId, FileType, Table, Macros={}, Owner=-1, From=-1):\r
         MetaFileParser.__init__(self, FilePath, FileType, Table, Macros, Owner, From)\r
+        # to store conditional directive evaluation result\r
+        self._Eval = Blist()\r
 \r
     def Start(self):\r
         try:\r
@@ -330,8 +346,8 @@ class DscParser(MetaFileParser):
                 continue\r
 \r
             # \r
-            # Model, Value1, Value2, Value3, Value4, Value5, Arch, Platform, BelongsToFile=-1, \r
-            # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, BelongsToItem=-1, FeatureFlag='', \r
+            # Model, Value1, Value2, Value3, Arch, Platform, BelongsToFile=-1, \r
+            # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, BelongsToItem=-1, \r
             # Enabled=-1\r
             # \r
             for Arch, ModuleType in self._Scope:\r
@@ -348,7 +364,7 @@ class DscParser(MetaFileParser):
                     -1,\r
                     self._LineIndex+1,\r
                     -1,\r
-                    0\r
+                    self._Enabled\r
                     )\r
         self._Done()\r
 \r
@@ -400,10 +416,60 @@ class DscParser(MetaFileParser):
                 Parser.Start()\r
             except:\r
                 EdkLogger.error("DscParser", PARSER_ERROR, File=self._FilePath, Line=self._LineIndex+1,\r
-                                ExtraData="'Failed to parse content in file %s" % IncludedFile)\r
+                                ExtraData="Failed to parse content in file %s" % IncludedFile)\r
             self._SectionName = Parser._SectionName\r
             self._SectionType = Parser._SectionType\r
             self._Scope       = Parser._Scope\r
+        else:\r
+            if DirectiveName in ["!IF", "!IFDEF", "!IFNDEF"]:\r
+                # evaluate the expression\r
+                Result = self._Evaluate(self._ValueList[1])\r
+                if DirectiveName == "!IFNDEF":\r
+                    Result = not Result\r
+                self._Eval.append(Result)\r
+            elif DirectiveName in ["!ELSEIF"]:\r
+                # evaluate the expression\r
+                self._Eval[-1] = (not self._Eval[-1]) & self._Evaluate(self._ValueList[1])\r
+            elif DirectiveName in ["!ELSE"]:\r
+                self._Eval[-1] = not self._Eval[-1]\r
+            elif DirectiveName in ["!ENDIF"]:\r
+                if len(self._Eval) > 0:\r
+                    self._Eval.pop()\r
+                else:\r
+                    EdkLogger.error("DscParser", FORMAT_INVALID, "!if..[!else]..!endif doesn't match",\r
+                                    File=self._FilePath, Line=self._LineIndex+1)\r
+            if self._Eval.Result == False:\r
+                self._Enabled = 0 - len(self._Eval)\r
+            else:\r
+                self._Enabled = len(self._Eval)\r
+\r
+    def _Evaluate(self, Expression):\r
+        TokenList = Expression.split()\r
+        TokenNumber = len(TokenList)\r
+        if TokenNumber == 1:\r
+            return TokenList[0] in self._Macros\r
+        elif TokenNumber == 2:\r
+            Op = TokenList[0]\r
+            if Op not in self._OP_:\r
+                EdkLogger.error('DscParser', FORMAT_INVALID, File=self._FilePath, \r
+                                Line=self._LineIndex+1, ExtraData=Expression)\r
+            if TokenList[1].upper() == 'TRUE':\r
+                Value = True\r
+            else:\r
+                Value = False\r
+            return self._OP_[Op](Value)\r
+        elif TokenNumber == 3:\r
+            Name = TokenList[0]\r
+            if Name not in self._Macros:\r
+                return False\r
+            Value = TokenList[2]\r
+            if Value[0] in ["'", '"']:\r
+                Value = Value[1:-1]\r
+            Op = TokenList[1]\r
+            return self._OP_[Op](self._Macros[Macro], Value)\r
+        else:\r
+            EdkLogger.error('DscParser', FORMAT_INVALID, File=self._FilePath, Line=self._LineIndex+1,\r
+                            ExtraData=Expression)\r
 \r
     def _BuildOptionParser(self):\r
         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r