]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/Common/Expression.py
Sync BaseTool trunk (version r2460) into EDKII BaseTools. The change mainly includes:
[mirror_edk2.git] / BaseTools / Source / Python / Common / Expression.py
index e2889a8dd30e7e3ca9c1b80b74b1254e943b42df..8b112d50b39b0627b6e09b271902de2c0ed5a007 100644 (file)
@@ -14,7 +14,6 @@
 #\r
 from Common.GlobalData import *\r
 from CommonDataClass.Exceptions import BadExpression\r
-from CommonDataClass.Exceptions import SymbolNotFound\r
 from CommonDataClass.Exceptions import WrnExpression\r
 from Misc import GuidStringToGuidStructureString\r
 \r
@@ -36,6 +35,7 @@ ERR_RELCMP_STR_OTHERS   = 'Operator taking Operand of string type and Boolean/Nu
 ERR_STRING_CMP          = 'Unicode string and general string cannot be compared: [%s %s %s]'\r
 ERR_ARRAY_TOKEN         = 'Bad C array or C format GUID token: [%s].'\r
 ERR_ARRAY_ELE           = 'This must be HEX value for NList or Array: [%s].'\r
+ERR_EMPTY_EXPR          = 'Empty expression is not allowed.'\r
 \r
 ## SplitString\r
 #  Split string to list according double quote\r
@@ -133,7 +133,7 @@ class ValueExpression(object):
     @staticmethod\r
     def Eval(Operator, Oprand1, Oprand2 = None):\r
         WrnExp = None\r
-        \r
+\r
         if Operator not in ["==", "!=", ">=", "<=", ">", "<", "in", "not in"] and \\r
             (type(Oprand1) == type('') or type(Oprand2) == type('')):\r
             raise BadExpression(ERR_STRING_EXPR % Operator)\r
@@ -166,13 +166,13 @@ class ValueExpression(object):
                     raise WrnExp\r
                 else:\r
                     raise BadExpression(ERR_RELCMP_STR_OTHERS % Operator)\r
-            elif TypeDict[type(Oprand1)] != TypeDict[type(Oprand2)]: \r
+            elif TypeDict[type(Oprand1)] != TypeDict[type(Oprand2)]:\r
                 if Operator in ["==", "!=", ">=", "<=", ">", "<"] and set((TypeDict[type(Oprand1)], TypeDict[type(Oprand2)])) == set((TypeDict[type(True)], TypeDict[type(0)])):\r
                     # comparison between number and boolean is allowed\r
                     pass\r
-                elif Operator in ['&', '|', '^', "&&", "||"] and set((TypeDict[type(Oprand1)], TypeDict[type(Oprand2)])) == set((TypeDict[type(True)], TypeDict[type(0)])):\r
+                elif Operator in ['&', '|', '^', "and", "or"] and set((TypeDict[type(Oprand1)], TypeDict[type(Oprand2)])) == set((TypeDict[type(True)], TypeDict[type(0)])):\r
                     # bitwise and logical operation between number and boolean is allowed\r
-                    pass                \r
+                    pass\r
                 else:\r
                     raise BadExpression(ERR_EXPR_TYPE)\r
             if type(Oprand1) == type('') and type(Oprand2) == type(''):\r
@@ -198,7 +198,7 @@ class ValueExpression(object):
                 Val = True\r
             else:\r
                 Val = False\r
-        \r
+\r
         if WrnExp:\r
             WrnExp.result = Val\r
             raise WrnExp\r
@@ -216,8 +216,7 @@ class ValueExpression(object):
                                   ['TARGET', 'TOOL_CHAIN_TAG', 'ARCH'])\r
 \r
         if not self._Expr.strip():\r
-            self._NoProcess = True\r
-            return\r
+            raise BadExpression(ERR_EMPTY_EXPR)\r
 \r
         #\r
         # The symbol table including PCD and macro mapping\r
@@ -227,25 +226,64 @@ class ValueExpression(object):
         self._Idx = 0\r
         self._Len = len(self._Expr)\r
         self._Token = ''\r
+        self._WarnExcept = None\r
 \r
         # Literal token without any conversion\r
         self._LiteralToken = ''\r
 \r
     # Public entry for this class\r
-    def __call__(self):\r
+    #   @param RealValue: False: only evaluate if the expression is true or false, used for conditional expression\r
+    #                     True : return the evaluated str(value), used for PCD value\r
+    #\r
+    #   @return: True or False if RealValue is False\r
+    #            Evaluated value of string format if RealValue is True\r
+    #\r
+    def __call__(self, RealValue=False):\r
         if self._NoProcess:\r
             return self._Expr\r
 \r
+        self._Expr = self._Expr.strip()\r
+        if RealValue:\r
+            self._Token = self._Expr\r
+            if self.__IsNumberToken():\r
+                return self._Expr\r
+\r
+            Token = self._GetToken()\r
+            if type(Token) == type('') and Token.startswith('{') and Token.endswith('}') and self._Idx >= self._Len:\r
+                return self._Expr\r
+\r
+            self._Idx = 0\r
+            self._Token = ''\r
+\r
         Val = self._OrExpr()\r
-        if type(Val) == type('') and Val == 'L""':\r
-            Val = ''\r
+        RealVal = Val\r
+        if type(Val) == type(''):\r
+            if Val == 'L""':\r
+                Val = False\r
+            elif not Val:\r
+                Val = False\r
+                RealVal = '""'\r
+            elif not Val.startswith('L"') and not Val.startswith('{'):\r
+                Val = True\r
+                RealVal = '"' + RealVal + '"'\r
 \r
         # The expression has been parsed, but the end of expression is not reached\r
         # It means the rest does not comply EBNF of <Expression>\r
         if self._Idx != self._Len:\r
             raise BadExpression(ERR_SNYTAX % self._Expr[self._Idx:])\r
 \r
-        return Val\r
+        if RealValue:\r
+            RetVal = str(RealVal)\r
+        elif Val:\r
+            RetVal = True\r
+        else:\r
+            RetVal = False\r
+\r
+        if self._WarnExcept:\r
+            self._WarnExcept.result = RetVal\r
+            raise self._WarnExcept\r
+        else:\r
+            return RetVal\r
 \r
     # Template function to parse binary operators which have same precedence\r
     # Expr [Operator Expr]*\r
@@ -253,7 +291,11 @@ class ValueExpression(object):
         Val = EvalFunc()\r
         while self._IsOperator(OpLst):\r
             Op = self._Token\r
-            Val = self.Eval(Op, Val, EvalFunc())\r
+            try:\r
+                Val = self.Eval(Op, Val, EvalFunc())\r
+            except WrnExpression, Warn:\r
+                self._WarnExcept = Warn\r
+                Val = Warn.result\r
         return Val\r
 \r
     # A [|| B]*\r
@@ -285,7 +327,11 @@ class ValueExpression(object):
                 if not self._IsOperator(["IN", "in"]):\r
                     raise BadExpression(ERR_REL_NOT_IN)\r
                 Op += ' ' + self._Token\r
-            Val = self.Eval(Op, Val, self._RelExpr())\r
+            try:\r
+                Val = self.Eval(Op, Val, self._RelExpr())\r
+            except WrnExpression, Warn:\r
+                self._WarnExcept = Warn\r
+                Val = Warn.result\r
         return Val\r
 \r
     # A [ > B]*\r
@@ -300,7 +346,11 @@ class ValueExpression(object):
     def _UnaryExpr(self):\r
         if self._IsOperator(["!", "NOT", "not"]):\r
             Val = self._UnaryExpr()\r
-            return self.Eval('not', Val)\r
+            try:\r
+                return self.Eval('not', Val)\r
+            except WrnExpression, Warn:\r
+                self._WarnExcept = Warn\r
+                return Warn.result\r
         return self._IdenExpr()\r
 \r
     # Parse identifier or encapsulated expression\r
@@ -407,8 +457,8 @@ class ValueExpression(object):
         # PCD token\r
         if self.PcdPattern.match(self._Token):\r
             if self._Token not in self._Symb:\r
-                raise SymbolNotFound(ERR_PCD_RESOLVE % self._Token)\r
-            self._Token = ValueExpression(self._Symb[self._Token], self._Symb)()\r
+                raise BadExpression(ERR_PCD_RESOLVE % self._Token)\r
+            self._Token = ValueExpression(self._Symb[self._Token], self._Symb)(True)\r
             if type(self._Token) != type(''):\r
                 self._LiteralToken = hex(self._Token)\r
                 return\r
@@ -459,7 +509,7 @@ class ValueExpression(object):
             if not Token:\r
                 self._LiteralToken = '0x0'\r
             else:\r
-                self._LiteralToken = '0x' + Token\r
+                self._LiteralToken = '0x' + Token.lower()\r
             return True\r
         return False\r
 \r
@@ -488,7 +538,7 @@ class ValueExpression(object):
             if Match and not Expr[Match.end():Match.end()+1].isalnum() \\r
                 and Expr[Match.end():Match.end()+1] != '_':\r
                 self._Idx += Match.end()\r
-                self._Token = ValueExpression(GuidStringToGuidStructureString(Expr[0:Match.end()]))()\r
+                self._Token = ValueExpression(GuidStringToGuidStructureString(Expr[0:Match.end()]))(True)\r
                 return self._Token\r
             elif self.__IsIdChar(Ch):\r
                 return self.__GetIdToken()\r
@@ -526,7 +576,7 @@ class ValueExpression(object):
         OpToken = ''\r
         for Ch in Expr:\r
             if Ch in self.NonLetterOpLst:\r
-                if '!' == Ch and OpToken in ['!=', '!']:\r
+                if '!' == Ch and OpToken:\r
                     break\r
                 self._Idx += 1\r
                 OpToken += Ch\r
@@ -551,5 +601,15 @@ class ValueExpression(object):
 \r
 if __name__ == '__main__':\r
     pass\r
-\r
-\r
+    while True:\r
+        input = raw_input('Input expr: ')\r
+        if input in 'qQ':\r
+            break\r
+        try:\r
+            print ValueExpression(input)(True)\r
+            print ValueExpression(input)(False)\r
+        except WrnExpression, Ex:\r
+            print Ex.result\r
+            print str(Ex)\r
+        except Exception, Ex:\r
+            print str(Ex)\r