[edk2] [PATCH] BaseTools: Update Expression.py for string comparison and MACRO replace issue

Yonghong Zhu posted 1 patch 6 years, 10 months ago
Failed in applying to current master (apply log)
BaseTools/Source/Python/Common/Expression.py       | 41 ++++++----------------
BaseTools/Source/Python/Workspace/DscBuildData.py  |  2 +-
.../Source/Python/Workspace/MetaFileParser.py      |  1 +
3 files changed, 13 insertions(+), 31 deletions(-)
[edk2] [PATCH] BaseTools: Update Expression.py for string comparison and MACRO replace issue
Posted by Yonghong Zhu 6 years, 10 months ago
From: Yunhua Feng <yunhuax.feng@intel.com>

1. Fix string comparison incorrect issue, we expected "ABC" is greater than
"AAD" since the second char 'B' is greater than 'A'.
2. fix MACRO not replace issue.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Yonghong Zhu <yonghong.zhu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yunhua Feng <yunhuax.feng@intel.com>
---
 BaseTools/Source/Python/Common/Expression.py       | 41 ++++++----------------
 BaseTools/Source/Python/Workspace/DscBuildData.py  |  2 +-
 .../Source/Python/Workspace/MetaFileParser.py      |  1 +
 3 files changed, 13 insertions(+), 31 deletions(-)

diff --git a/BaseTools/Source/Python/Common/Expression.py b/BaseTools/Source/Python/Common/Expression.py
index 6a1103df2c..a19f35d991 100644
--- a/BaseTools/Source/Python/Common/Expression.py
+++ b/BaseTools/Source/Python/Common/Expression.py
@@ -155,23 +155,13 @@ class ValueExpression(object):
 
     @staticmethod
     def Eval(Operator, Oprand1, Oprand2 = None):
         WrnExp = None
 
-        if Operator not in ["in", "not in"] and (type(Oprand1) == type('') or type(Oprand2) == type('')):
-            if type(Oprand1) == type(''):
-                if Oprand1[0] in ['"', "'"] or Oprand1.startswith('L"') or Oprand1.startswith("L'")or Oprand1.startswith('UINT'):
-                    Oprand1, Size = ParseFieldValue(Oprand1)
-                else:
-                    Oprand1,Size = ParseFieldValue('"' + Oprand1 + '"')
-            if type(Oprand2) == type(''):
-                if Oprand2[0] in ['"', "'"] or Oprand2.startswith('L"') or Oprand2.startswith("L'") or Oprand2.startswith('UINT'):
-                    Oprand2, Size = ParseFieldValue(Oprand2)
-                else:
-                    Oprand2, Size = ParseFieldValue('"' + Oprand2 + '"')
-            if type(Oprand1) == type('') or type(Oprand2) == type(''):
-                raise BadExpression(ERR_STRING_EXPR % Operator)
+        if Operator not in ["==", "!=", ">=", "<=", ">", "<", "in", "not in"] and \
+            (type(Oprand1) == type('') or type(Oprand2) == type('')):
+            raise BadExpression(ERR_STRING_EXPR % Operator)
         if Operator in ['in', 'not in']:
             if type(Oprand1) != type(''):
                 Oprand1 = IntToStr(Oprand1)
             if type(Oprand2) != type(''):
                 Oprand2 = IntToStr(Oprand2)
@@ -294,12 +284,10 @@ class ValueExpression(object):
             try:
                 Token = self._GetToken()
             except BadExpression:
                 pass
             if type(Token) == type('') and Token.startswith('{') and Token.endswith('}') and self._Idx >= self._Len:
-                if len(Token) != len(self._Expr.replace(' ', '')):
-                    raise BadExpression
                 return self._Expr
 
             self._Idx = 0
             self._Token = ''
 
@@ -457,19 +445,17 @@ class ValueExpression(object):
             Flag = 0
             for Index in range(len(self._Token)):
                 if self._Token[Index] in ['"']:
                     Flag += 1
             if Flag == 2 and self._Token.endswith('"'):
-                self._Token = ParseFieldValue(self._Token)[0]
                 return True
         if self._Token.startswith("'") or self._Token.startswith("L'"):
             Flag = 0
             for Index in range(len(self._Token)):
                 if self._Token[Index] in ["'"]:
                     Flag += 1
             if Flag == 2 and self._Token.endswith("'"):
-                self._Token = ParseFieldValue(self._Token)[0]
                 return True
         try:
             self._Token = int(self._Token, Radix)
             return True
         except ValueError:
@@ -620,28 +606,20 @@ class ValueExpression(object):
         if Expr.startswith('L"'):
             # Skip L
             self._Idx += 1
             UStr = self.__GetString()
             self._Token = 'L"' + UStr + '"'
-            self._Token, Size = ParseFieldValue(self._Token)
             return self._Token
         elif Expr.startswith("L'"):
             # Skip L
             self._Idx += 1
             UStr = self.__GetString()
             self._Token = "L'" + UStr + "'"
-            self._Token, Size = ParseFieldValue(self._Token)
-            return self._Token
-        elif Expr.startswith('"'):
-            UStr = self.__GetString()
-            self._Token = '"' + UStr + '"'
-            self._Token, Size = ParseFieldValue(self._Token)
             return self._Token
         elif Expr.startswith("'"):
             UStr = self.__GetString()
             self._Token = "'" + UStr + "'"
-            self._Token, Size = ParseFieldValue(self._Token)
             return self._Token
         elif Expr.startswith('UINT'):
             Re = re.compile('(?:UINT8|UINT16|UINT32|UINT64)\((.+)\)')
             try:
                 RetValue = Re.search(Expr).group(1)
@@ -749,11 +727,11 @@ class ValueExpressionEx(ValueExpression):
             elif self.PcdType in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN'] and (PcdValue.startswith("'") or \
                       PcdValue.startswith('"') or PcdValue.startswith("L'") or PcdValue.startswith('L"') or PcdValue.startswith('{')):
                 raise BadExpression
         except WrnExpression, Value:
             PcdValue = Value.result
-        except BadExpression:
+        except BadExpression, Value:
             if self.PcdType in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
                 PcdValue = PcdValue.strip()
                 if type(PcdValue) == type('') and PcdValue.startswith('{') and PcdValue.endswith('}'):
                     PcdValue = PcdValue[1:-1].split(',')
                 if type(PcdValue) == type([]):
@@ -783,14 +761,17 @@ class ValueExpressionEx(ValueExpression):
                         TmpValue = (ItemValue << (Size * 8)) | TmpValue
                         Size = Size + ItemSize
                 else:
                     try:
                         TmpValue, Size = ParseFieldValue(PcdValue)
-                    except BadExpression:
-                        raise BadExpression("Type: %s, Value: %s, format or value error" % (self.PcdType, PcdValue))
+                    except BadExpression, Value:
+                        raise BadExpression("Type: %s, Value: %s, %s" % (self.PcdType, PcdValue, Value))
                 if type(TmpValue) == type(''):
-                    TmpValue = int(TmpValue)
+                    try:
+                        TmpValue = int(TmpValue)
+                    except:
+                        raise  BadExpression(Value)
                 else:
                     PcdValue = '0x%0{}X'.format(Size) % (TmpValue)
                 if TmpValue < 0:
                     raise  BadExpression('Type %s PCD Value is negative' % self.PcdType)
                 if self.PcdType == 'UINT8' and Size > 1:
@@ -896,11 +877,11 @@ class ValueExpressionEx(ValueExpression):
                                 Size += ItemSize
 
                             if Size > 0:
                                 PcdValue = '{' + ValueStr[:-2] + '}'
                     else:
-                        raise  BadExpression("Type: %s, Value: %s, format or value error"%(self.PcdType, PcdValue))
+                        raise  BadExpression("Type: %s, Value: %s, %s"%(self.PcdType, PcdValue, Value))
 
         if PcdValue == 'True':
             PcdValue = '1'
         if PcdValue == 'False':
             PcdValue = '0'
diff --git a/BaseTools/Source/Python/Workspace/DscBuildData.py b/BaseTools/Source/Python/Workspace/DscBuildData.py
index d9165f2ac7..8eef252e30 100644
--- a/BaseTools/Source/Python/Workspace/DscBuildData.py
+++ b/BaseTools/Source/Python/Workspace/DscBuildData.py
@@ -806,11 +806,11 @@ class DscBuildData(PlatformBuildClassObject):
                     continue
                 ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]
                 PkgSet.update(ModuleData.Packages)
 
             self._DecPcds, self._GuidDict = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain,PkgSet)
-
+            self._GuidDict.update(GlobalData.gPlatformPcds)
 
         if (PcdCName, TokenSpaceGuid) not in self._DecPcds:
             EdkLogger.error('build', PARSER_ERROR,
                             "Pcd (%s.%s) defined in DSC is not declared in DEC files. Arch: ['%s']" % (TokenSpaceGuid, PcdCName, self._Arch),
                             File=self.MetaFile, Line=LineNo)
diff --git a/BaseTools/Source/Python/Workspace/MetaFileParser.py b/BaseTools/Source/Python/Workspace/MetaFileParser.py
index 57642de4ee..95ea6fb45a 100644
--- a/BaseTools/Source/Python/Workspace/MetaFileParser.py
+++ b/BaseTools/Source/Python/Workspace/MetaFileParser.py
@@ -1992,10 +1992,11 @@ class DecParser(MetaFileParser):
                                 File=self.MetaFile, Line=self._LineIndex + 1)
 
             PcdValue = ValueList[0]
             if PcdValue:
                 try:
+                    self._GuidDict.update(self._AllPcdDict)
                     ValueList[0] = ValueExpressionEx(ValueList[0], ValueList[1], self._GuidDict)(True)
                 except BadExpression, Value:
                     EdkLogger.error('Parser', FORMAT_INVALID, Value, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
             # check format of default value against the datum type
             IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])
-- 
2.12.2.windows.2

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH] BaseTools: Update Expression.py for string comparison and MACRO replace issue
Posted by Zhu, Yonghong 6 years, 10 months ago
Reviewed-by: Yonghong Zhu <yonghong.zhu@intel.com> 

Best Regards,
Zhu Yonghong


-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Yonghong Zhu
Sent: Thursday, February 08, 2018 10:46 PM
To: edk2-devel@lists.01.org
Cc: Feng, YunhuaX <yunhuax.feng@intel.com>; Gao, Liming <liming.gao@intel.com>
Subject: [edk2] [PATCH] BaseTools: Update Expression.py for string comparison and MACRO replace issue

From: Yunhua Feng <yunhuax.feng@intel.com>

1. Fix string comparison incorrect issue, we expected "ABC" is greater than "AAD" since the second char 'B' is greater than 'A'.
2. fix MACRO not replace issue.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Yonghong Zhu <yonghong.zhu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yunhua Feng <yunhuax.feng@intel.com>
---
 BaseTools/Source/Python/Common/Expression.py       | 41 ++++++----------------
 BaseTools/Source/Python/Workspace/DscBuildData.py  |  2 +-
 .../Source/Python/Workspace/MetaFileParser.py      |  1 +
 3 files changed, 13 insertions(+), 31 deletions(-)

diff --git a/BaseTools/Source/Python/Common/Expression.py b/BaseTools/Source/Python/Common/Expression.py
index 6a1103df2c..a19f35d991 100644
--- a/BaseTools/Source/Python/Common/Expression.py
+++ b/BaseTools/Source/Python/Common/Expression.py
@@ -155,23 +155,13 @@ class ValueExpression(object):
 
     @staticmethod
     def Eval(Operator, Oprand1, Oprand2 = None):
         WrnExp = None
 
-        if Operator not in ["in", "not in"] and (type(Oprand1) == type('') or type(Oprand2) == type('')):
-            if type(Oprand1) == type(''):
-                if Oprand1[0] in ['"', "'"] or Oprand1.startswith('L"') or Oprand1.startswith("L'")or Oprand1.startswith('UINT'):
-                    Oprand1, Size = ParseFieldValue(Oprand1)
-                else:
-                    Oprand1,Size = ParseFieldValue('"' + Oprand1 + '"')
-            if type(Oprand2) == type(''):
-                if Oprand2[0] in ['"', "'"] or Oprand2.startswith('L"') or Oprand2.startswith("L'") or Oprand2.startswith('UINT'):
-                    Oprand2, Size = ParseFieldValue(Oprand2)
-                else:
-                    Oprand2, Size = ParseFieldValue('"' + Oprand2 + '"')
-            if type(Oprand1) == type('') or type(Oprand2) == type(''):
-                raise BadExpression(ERR_STRING_EXPR % Operator)
+        if Operator not in ["==", "!=", ">=", "<=", ">", "<", "in", "not in"] and \
+            (type(Oprand1) == type('') or type(Oprand2) == type('')):
+            raise BadExpression(ERR_STRING_EXPR % Operator)
         if Operator in ['in', 'not in']:
             if type(Oprand1) != type(''):
                 Oprand1 = IntToStr(Oprand1)
             if type(Oprand2) != type(''):
                 Oprand2 = IntToStr(Oprand2) @@ -294,12 +284,10 @@ class ValueExpression(object):
             try:
                 Token = self._GetToken()
             except BadExpression:
                 pass
             if type(Token) == type('') and Token.startswith('{') and Token.endswith('}') and self._Idx >= self._Len:
-                if len(Token) != len(self._Expr.replace(' ', '')):
-                    raise BadExpression
                 return self._Expr
 
             self._Idx = 0
             self._Token = ''
 
@@ -457,19 +445,17 @@ class ValueExpression(object):
             Flag = 0
             for Index in range(len(self._Token)):
                 if self._Token[Index] in ['"']:
                     Flag += 1
             if Flag == 2 and self._Token.endswith('"'):
-                self._Token = ParseFieldValue(self._Token)[0]
                 return True
         if self._Token.startswith("'") or self._Token.startswith("L'"):
             Flag = 0
             for Index in range(len(self._Token)):
                 if self._Token[Index] in ["'"]:
                     Flag += 1
             if Flag == 2 and self._Token.endswith("'"):
-                self._Token = ParseFieldValue(self._Token)[0]
                 return True
         try:
             self._Token = int(self._Token, Radix)
             return True
         except ValueError:
@@ -620,28 +606,20 @@ class ValueExpression(object):
         if Expr.startswith('L"'):
             # Skip L
             self._Idx += 1
             UStr = self.__GetString()
             self._Token = 'L"' + UStr + '"'
-            self._Token, Size = ParseFieldValue(self._Token)
             return self._Token
         elif Expr.startswith("L'"):
             # Skip L
             self._Idx += 1
             UStr = self.__GetString()
             self._Token = "L'" + UStr + "'"
-            self._Token, Size = ParseFieldValue(self._Token)
-            return self._Token
-        elif Expr.startswith('"'):
-            UStr = self.__GetString()
-            self._Token = '"' + UStr + '"'
-            self._Token, Size = ParseFieldValue(self._Token)
             return self._Token
         elif Expr.startswith("'"):
             UStr = self.__GetString()
             self._Token = "'" + UStr + "'"
-            self._Token, Size = ParseFieldValue(self._Token)
             return self._Token
         elif Expr.startswith('UINT'):
             Re = re.compile('(?:UINT8|UINT16|UINT32|UINT64)\((.+)\)')
             try:
                 RetValue = Re.search(Expr).group(1) @@ -749,11 +727,11 @@ class ValueExpressionEx(ValueExpression):
             elif self.PcdType in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN'] and (PcdValue.startswith("'") or \
                       PcdValue.startswith('"') or PcdValue.startswith("L'") or PcdValue.startswith('L"') or PcdValue.startswith('{')):
                 raise BadExpression
         except WrnExpression, Value:
             PcdValue = Value.result
-        except BadExpression:
+        except BadExpression, Value:
             if self.PcdType in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
                 PcdValue = PcdValue.strip()
                 if type(PcdValue) == type('') and PcdValue.startswith('{') and PcdValue.endswith('}'):
                     PcdValue = PcdValue[1:-1].split(',')
                 if type(PcdValue) == type([]):
@@ -783,14 +761,17 @@ class ValueExpressionEx(ValueExpression):
                         TmpValue = (ItemValue << (Size * 8)) | TmpValue
                         Size = Size + ItemSize
                 else:
                     try:
                         TmpValue, Size = ParseFieldValue(PcdValue)
-                    except BadExpression:
-                        raise BadExpression("Type: %s, Value: %s, format or value error" % (self.PcdType, PcdValue))
+                    except BadExpression, Value:
+                        raise BadExpression("Type: %s, Value: %s, %s" % 
+ (self.PcdType, PcdValue, Value))
                 if type(TmpValue) == type(''):
-                    TmpValue = int(TmpValue)
+                    try:
+                        TmpValue = int(TmpValue)
+                    except:
+                        raise  BadExpression(Value)
                 else:
                     PcdValue = '0x%0{}X'.format(Size) % (TmpValue)
                 if TmpValue < 0:
                     raise  BadExpression('Type %s PCD Value is negative' % self.PcdType)
                 if self.PcdType == 'UINT8' and Size > 1:
@@ -896,11 +877,11 @@ class ValueExpressionEx(ValueExpression):
                                 Size += ItemSize
 
                             if Size > 0:
                                 PcdValue = '{' + ValueStr[:-2] + '}'
                     else:
-                        raise  BadExpression("Type: %s, Value: %s, format or value error"%(self.PcdType, PcdValue))
+                        raise  BadExpression("Type: %s, Value: %s, 
+ %s"%(self.PcdType, PcdValue, Value))
 
         if PcdValue == 'True':
             PcdValue = '1'
         if PcdValue == 'False':
             PcdValue = '0'
diff --git a/BaseTools/Source/Python/Workspace/DscBuildData.py b/BaseTools/Source/Python/Workspace/DscBuildData.py
index d9165f2ac7..8eef252e30 100644
--- a/BaseTools/Source/Python/Workspace/DscBuildData.py
+++ b/BaseTools/Source/Python/Workspace/DscBuildData.py
@@ -806,11 +806,11 @@ class DscBuildData(PlatformBuildClassObject):
                     continue
                 ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]
                 PkgSet.update(ModuleData.Packages)
 
             self._DecPcds, self._GuidDict = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain,PkgSet)
-
+            self._GuidDict.update(GlobalData.gPlatformPcds)
 
         if (PcdCName, TokenSpaceGuid) not in self._DecPcds:
             EdkLogger.error('build', PARSER_ERROR,
                             "Pcd (%s.%s) defined in DSC is not declared in DEC files. Arch: ['%s']" % (TokenSpaceGuid, PcdCName, self._Arch),
                             File=self.MetaFile, Line=LineNo) diff --git a/BaseTools/Source/Python/Workspace/MetaFileParser.py b/BaseTools/Source/Python/Workspace/MetaFileParser.py
index 57642de4ee..95ea6fb45a 100644
--- a/BaseTools/Source/Python/Workspace/MetaFileParser.py
+++ b/BaseTools/Source/Python/Workspace/MetaFileParser.py
@@ -1992,10 +1992,11 @@ class DecParser(MetaFileParser):
                                 File=self.MetaFile, Line=self._LineIndex + 1)
 
             PcdValue = ValueList[0]
             if PcdValue:
                 try:
+                    self._GuidDict.update(self._AllPcdDict)
                     ValueList[0] = ValueExpressionEx(ValueList[0], ValueList[1], self._GuidDict)(True)
                 except BadExpression, Value:
                     EdkLogger.error('Parser', FORMAT_INVALID, Value, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
             # check format of default value against the datum type
             IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])
--
2.12.2.windows.2

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel