BaseTools/Expression: Use 2nd passes on PCD values
authorKinney, Michael D <michael.d.kinney@intel.com>
Wed, 21 Feb 2018 04:08:32 +0000 (20:08 -0800)
committerYonghong Zhu <yonghong.zhu@intel.com>
Sun, 25 Feb 2018 08:03:14 +0000 (16:03 +0800)
Use 2 passes when evaluating PCD values to discover
all the LABEL() operators and compute the byte offset
of each LABEL().  The 2nd pass then has the information
to replace the OFFSET_OF() operator with the computed
byte offset.  The 2 passes allows OFFSET_OF() to be used
before a LABEL() is declared.

fixes:https://bugzilla.tianocore.org/show_bug.cgi?id=880
Cc: Liming Gao <liming.gao@intel.com>
Cc: Yonghong Zhu <yonghong.zhu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
Reviewed-by: Yonghong Zhu <yonghong.zhu@intel.com>
BaseTools/Source/Python/Common/Expression.py

index 74d1b08..28320d7 100644 (file)
@@ -827,6 +827,30 @@ class ValueExpressionEx(ValueExpression):
                             LabelDict = {}\r
                             ReLabel = re.compile('LABEL\((\w+)\)')\r
                             ReOffset = re.compile('OFFSET_OF\((\w+)\)')\r
+                            LabelOffset = 0\r
+                            for Index, Item in enumerate(ListItem):\r
+                                # compute byte offset of every LABEL\r
+                                Item = Item.strip()\r
+                                try:\r
+                                    LabelList = ReLabel.findall(Item)\r
+                                    for Label in LabelList:\r
+                                        if Label not in LabelDict.keys():\r
+                                            LabelDict[Label] = str(LabelOffset)\r
+                                    Item = ReLabel.sub('', Item)\r
+                                except:\r
+                                    pass\r
+                                if Item.startswith('UINT8'):\r
+                                    LabelOffset = LabelOffset + 1\r
+                                elif Item.startswith('UINT16'):\r
+                                    LabelOffset = LabelOffset + 2\r
+                                elif Item.startswith('UINT32'):\r
+                                    LabelOffset = LabelOffset + 4\r
+                                elif Item.startswith('UINT64'):\r
+                                    LabelOffset = LabelOffset + 8\r
+                                else:\r
+                                    ItemValue, ItemSize = ParseFieldValue(Item)\r
+                                    LabelOffset = LabelOffset + ItemSize\r
+\r
                             for Index, Item in enumerate(ListItem):\r
                                 # for LABEL parse\r
                                 Item = Item.strip()\r
@@ -847,7 +871,7 @@ class ValueExpressionEx(ValueExpression):
                                         Re = re.compile('OFFSET_OF\(%s\)'% Offset)\r
                                         Item = Re.sub(LabelDict[Offset], Item)\r
                                     else:\r
-                                        raise BadExpression('%s not defined before use' % Offset)\r
+                                        raise BadExpression('%s not defined' % Offset)\r
                                 ValueType = ""\r
                                 if Item.startswith('UINT8'):\r
                                     ItemSize = 1\r