Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions BaseTools/Source/Python/Common/Expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,33 @@
_ReOffset = re.compile(r'OFFSET_OF\((\w+)\)')
PcdPattern = re.compile(r'^[_a-zA-Z][0-9A-Za-z_]*\.[_a-zA-Z][0-9A-Za-z_]*$')

## Fast path for the simple byte array
#
# Simple byte array refers to PCD data in the form of {0x01, 0x02, 0x03}
# - Enclosed in {}.
# - One or more comma-separated elements.
# - Each element is 0x followed by one or two hexadecimal digits.
# - Only spaces or tabs surround elements.
# - Used only for top-level VOID* real-value evaluation.
#
# Return the stripped original value when valid. Otherwise None.
def _NormalizeSimpleByteArray(Value):
Value = Value.strip()
if not Value.startswith('{') or not Value.endswith('}'):
return None

Items = Value[1:-1].split(',')
if not Items:
return None

for Item in Items:
Item = Item.strip(' \t')
if len(Item) < 3 or len(Item) > 4 or Item[:2].lower() != '0x' or \
not all(Char in string.hexdigits for Char in Item[2:]):
return None

return Value

## SplitString
# Split string to list according double quote
# For example: abc"de\"f"ghi"jkl"mn will be: ['abc', '"de\"f"', 'ghi', '"jkl"', 'mn']
Expand Down Expand Up @@ -821,6 +848,10 @@ def __init__(self, PcdValue, PcdType, SymbolTable={}):

def __call__(self, RealValue=False, Depth=0):
PcdValue = self.PcdValue
if RealValue and Depth == 0 and self.PcdType == TAB_VOID and "{CODE(" not in PcdValue:
SimpleByteArray = _NormalizeSimpleByteArray(PcdValue)
if SimpleByteArray is not None:
return SimpleByteArray
if "{CODE(" not in PcdValue:
try:
PcdValue = ValueExpression.__call__(self, RealValue, Depth)
Expand Down
46 changes: 40 additions & 6 deletions BaseTools/Tests/TestRegularExpression.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,53 @@
# SPDX-License-Identifier: BSD-2-Clause-Patent

import unittest
from Common.DataType import TAB_VOID
from Common.Expression import ValueExpression, ValueExpressionEx
from Common.Misc import RemoveCComments
from Workspace.BuildClassObject import ArrayIndex


class TestValueExpressionEx(unittest.TestCase):
def test_simple_byte_array_matches_legacy_parser(self):
value = ' { 0X01, 0xaB, 0xff } '

self.assertEqual(ValueExpression(value)(True), ValueExpressionEx(value, TAB_VOID)(True))

def test_nested_simple_byte_array_uses_legacy_parser(self):
value = '{ 0X01, 0x02 }'

self.assertEqual(ValueExpression(value)(True, 1), ValueExpressionEx(value, TAB_VOID)(True, 1))

def test_multiline_byte_array_uses_legacy_parser(self):
value = '{0x01,\n0x02}'

self.assertEqual('{0x01, 0x02}', ValueExpressionEx(value, TAB_VOID)(True))

def test_non_dsc_whitespace_uses_legacy_parser(self):
value = '{0x01,\v0x02}'

self.assertEqual('{0x01, 0x02}', ValueExpressionEx(value, TAB_VOID)(True))

def test_structured_array_uses_legacy_parser(self):
value = '{UINT16(0x1234), 0x56}'

self.assertEqual('{0x34, 0x12, 0x56}', ValueExpressionEx(value, TAB_VOID)(True))

def test_trailing_comma_uses_legacy_parser(self):
value = '{0x01,}'

self.assertEqual('{0x01}', ValueExpressionEx(value, TAB_VOID)(True))

class TestRe(unittest.TestCase):
def test_ccomments(self):
TestStr1 = """ {0x01,0x02} """
self.assertEquals(TestStr1, RemoveCComments(TestStr1))
self.assertEqual(TestStr1, RemoveCComments(TestStr1))

TestStr2 = """ L'TestString' """
self.assertEquals(TestStr2, RemoveCComments(TestStr2))
self.assertEqual(TestStr2, RemoveCComments(TestStr2))

TestStr3 = """ 'TestString' """
self.assertEquals(TestStr3, RemoveCComments(TestStr3))
self.assertEqual(TestStr3, RemoveCComments(TestStr3))

TestStr4 = """
{CODE({
Expand All @@ -35,14 +69,14 @@ def test_ccomments(self):
{0x01, {0x02, 0x03, 0x04 }},
})
}"""
self.assertEquals(Expect_TestStr4, RemoveCComments(TestStr4).strip())
self.assertEqual(Expect_TestStr4, RemoveCComments(TestStr4).strip())

def Test_ArrayIndex(self):
TestStr1 = """[1]"""
self.assertEquals(['[1]'], ArrayIndex.findall(TestStr1))
self.assertEqual(['[1]'], ArrayIndex.findall(TestStr1))

TestStr2 = """[1][2][0x1][0x01][]"""
self.assertEquals(['[1]','[2]','[0x1]','[0x01]','[]'], ArrayIndex.findall(TestStr2))
self.assertEqual(['[1]','[2]','[0x1]','[0x01]','[]'], ArrayIndex.findall(TestStr2))

if __name__ == '__main__':
unittest.main()
Loading