]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/Common/Expression.py
BaseTools: Enhance BaseTools supports FixedAtBuild usage in VFR file
[mirror_edk2.git] / BaseTools / Source / Python / Common / Expression.py
index 8b112d50b39b0627b6e09b271902de2c0ed5a007..7b3030c5fa08f9d1f219dbd83f3a81e338afd5d4 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 # This file is used to parse and evaluate expression in directive or PCD value.\r
 #\r
-# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR>\r
 # This program and the accompanying materials\r
 # are licensed and made available under the terms and conditions of the BSD License\r
 # which accompanies this distribution.    The full text of the license may be found at\r
@@ -36,6 +36,7 @@ ERR_STRING_CMP          = 'Unicode string and general string cannot be compared:
 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
+ERR_IN_OPERAND          = 'Macro after IN operator can only be: $(FAMILY), $(ARCH), $(TOOL_CHAIN_TAG) and $(TARGET).'\r
 \r
 ## SplitString\r
 #  Split string to list according double quote\r
@@ -75,6 +76,10 @@ def ReplaceExprMacro(String, Macros, ExceptionList = None):
             InQuote = True\r
         MacroStartPos = String.find('$(')\r
         if MacroStartPos < 0:\r
+            for Pcd in gPlatformPcds.keys():\r
+                if Pcd in String:\r
+                    if Pcd not in gConditionalPcds:\r
+                        gConditionalPcds.append(Pcd)\r
             continue\r
         RetStr = ''\r
         while MacroStartPos >= 0:\r
@@ -88,22 +93,29 @@ def ReplaceExprMacro(String, Macros, ExceptionList = None):
                 # If an undefined macro name appears in the constant-expression of\r
                 # !if or !elif, it is replaced by the integer constant 0.\r
                 RetStr += '0'\r
-            elif not InQuote and ExceptionList and Macro in ExceptionList:\r
+            elif not InQuote:\r
+                Tklst = RetStr.split()\r
+                if Tklst and Tklst[-1] in ['IN', 'in'] and ExceptionList and Macro not in ExceptionList:\r
+                    raise BadExpression(ERR_IN_OPERAND)\r
                 # Make sure the macro in exception list is encapsulated by double quote\r
                 # For example: DEFINE ARCH = IA32 X64\r
                 # $(ARCH) is replaced with "IA32 X64"\r
-                RetStr += '"' + Macros[Macro] + '"'\r
-            else:\r
-                if Macros[Macro].strip() != "":\r
+                if ExceptionList and Macro in ExceptionList:\r
+                    RetStr += '"' + Macros[Macro] + '"'\r
+                elif Macros[Macro].strip():\r
                     RetStr += Macros[Macro]\r
                 else:\r
                     RetStr += '""'\r
+            else:\r
+                RetStr += Macros[Macro]\r
             RetStr += String[MacroEndPos+1:]\r
             String = RetStr\r
             MacroStartPos = String.find('$(')\r
         StrList[i] = RetStr\r
     return ''.join(StrList)\r
 \r
+SupportedInMacroList = ['TARGET', 'TOOL_CHAIN_TAG', 'ARCH', 'FAMILY']\r
+\r
 class ValueExpression(object):\r
     # Logical operator mapping\r
     LogicalOperators = {\r
@@ -213,7 +225,7 @@ class ValueExpression(object):
 \r
         self._Expr = ReplaceExprMacro(Expression.strip(),\r
                                   SymbolTable,\r
-                                  ['TARGET', 'TOOL_CHAIN_TAG', 'ARCH'])\r
+                                  SupportedInMacroList)\r
 \r
         if not self._Expr.strip():\r
             raise BadExpression(ERR_EMPTY_EXPR)\r
@@ -238,19 +250,24 @@ class ValueExpression(object):
     #   @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
+    def __call__(self, RealValue=False, Depth=0):\r
         if self._NoProcess:\r
             return self._Expr\r
 \r
+        self._Depth = Depth\r
+\r
         self._Expr = self._Expr.strip()\r
-        if RealValue:\r
+        if RealValue and Depth == 0:\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
+            try:\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
+            except BadExpression:\r
+                pass\r
 \r
             self._Idx = 0\r
             self._Token = ''\r
@@ -457,8 +474,10 @@ class ValueExpression(object):
         # PCD token\r
         if self.PcdPattern.match(self._Token):\r
             if self._Token not in self._Symb:\r
-                raise BadExpression(ERR_PCD_RESOLVE % self._Token)\r
-            self._Token = ValueExpression(self._Symb[self._Token], self._Symb)(True)\r
+                Ex = BadExpression(ERR_PCD_RESOLVE % self._Token)\r
+                Ex.Pcd = self._Token\r
+                raise Ex\r
+            self._Token = ValueExpression(self._Symb[self._Token], self._Symb)(True, self._Depth+1)\r
             if type(self._Token) != type(''):\r
                 self._LiteralToken = hex(self._Token)\r
                 return\r
@@ -538,7 +557,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()]))(True)\r
+                self._Token = ValueExpression(GuidStringToGuidStructureString(Expr[0:Match.end()]))(True, self._Depth+1)\r
                 return self._Token\r
             elif self.__IsIdChar(Ch):\r
                 return self.__GetIdToken()\r