BaseTools: Update ValueExpressionEx for flexible PCD

1. Byte  array number should less than 0xFF.
2. Add SplitPcdValueString for PCD split

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>
Reviewed-by: Yonghong Zhu <yonghong.zhu@intel.com>
This commit is contained in:
Feng, YunhuaX 2018-02-23 19:47:30 +08:00 committed by Yonghong Zhu
parent 8bd72d7c05
commit 3be421e987

View File

@ -68,6 +68,44 @@ def SplitString(String):
RetList.append(Item) RetList.append(Item)
return RetList return RetList
def SplitPcdValueString(String):
# There might be escaped comma in GUID() or DEVICE_PATH() or " "
# or ' ' or L' ' or L" "
Str = String
RetList = []
InParenthesis = 0
InSingleQuote = False
InDoubleQuote = False
Item = ''
for i, ch in enumerate(Str):
if ch == '(':
InParenthesis += 1
if ch == ')':
if InParenthesis:
InParenthesis -= 1
else:
raise BadExpression(ERR_STRING_TOKEN % Item)
if ch == '"' and not InSingleQuote:
if String[i-1] != '\\':
InDoubleQuote = not InDoubleQuote
if ch == "'" and not InDoubleQuote:
if String[i-1] != '\\':
InSingleQuote = not InSingleQuote
if ch == ',':
if InParenthesis or InSingleQuote or InDoubleQuote:
Item += String[i]
continue
elif Item:
RetList.append(Item)
Item = ''
continue
Item += String[i]
if InSingleQuote or InDoubleQuote or InParenthesis:
raise BadExpression(ERR_STRING_TOKEN % Item)
if Item:
RetList.append(Item)
return RetList
## ReplaceExprMacro ## ReplaceExprMacro
# #
def ReplaceExprMacro(String, Macros, ExceptionList = None): def ReplaceExprMacro(String, Macros, ExceptionList = None):
@ -733,24 +771,42 @@ class ValueExpressionEx(ValueExpression):
if self.PcdType in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']: if self.PcdType in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
PcdValue = PcdValue.strip() PcdValue = PcdValue.strip()
if type(PcdValue) == type('') and PcdValue.startswith('{') and PcdValue.endswith('}'): if type(PcdValue) == type('') and PcdValue.startswith('{') and PcdValue.endswith('}'):
PcdValue = PcdValue[1:-1].split(',') PcdValue = SplitPcdValueString(PcdValue[1:-1])
if type(PcdValue) == type([]): if type(PcdValue) == type([]):
TmpValue = 0 TmpValue = 0
Size = 0 Size = 0
ValueType = ''
for Item in PcdValue: for Item in PcdValue:
Item = Item.strip()
if Item.startswith('UINT8'): if Item.startswith('UINT8'):
ItemSize = 1 ItemSize = 1
if Item.startswith('UINT16'): ValueType = 'UINT8'
elif Item.startswith('UINT16'):
ItemSize = 2 ItemSize = 2
ValueType = 'UINT16'
elif Item.startswith('UINT32'): elif Item.startswith('UINT32'):
ItemSize = 4 ItemSize = 4
ValueType = 'UINT32'
elif Item.startswith('UINT64'): elif Item.startswith('UINT64'):
ItemSize = 8 ItemSize = 8
ValueType = 'UINT64'
elif Item.startswith('"') or Item.startswith("'") or Item.startswith('L'):
ItemSize = 0
ValueType = 'VOID*'
else: else:
ItemSize = 0 ItemSize = 0
Item = ValueExpressionEx(Item, self.PcdType, self._Symb)(True) ValueType = 'UINT8'
Item = ValueExpressionEx(Item, ValueType, self._Symb)(True)
if ItemSize == 0: if ItemSize == 0:
try:
tmpValue = int(Item, 16) if Item.upper().startswith('0X') else int(Item, 0)
if tmpValue > 255:
raise BadExpression("Byte array number %s should less than 0xFF." % Item)
except BadExpression, Value:
raise BadExpression(Value)
except ValueError:
pass
ItemValue, ItemSize = ParseFieldValue(Item) ItemValue, ItemSize = ParseFieldValue(Item)
else: else:
ItemValue = ParseFieldValue(Item)[0] ItemValue = ParseFieldValue(Item)[0]
@ -794,84 +850,81 @@ class ValueExpressionEx(ValueExpression):
PcdValue = '{' + ', '.join(TmpList) + '}' PcdValue = '{' + ', '.join(TmpList) + '}'
except: except:
if PcdValue.strip().startswith('{'): if PcdValue.strip().startswith('{'):
PcdValue = PcdValue.strip()[1:-1].strip() PcdValueList = SplitPcdValueString(PcdValue.strip()[1:-1])
Size = 0 LabelDict = {}
ValueStr = '' NewPcdValueList = []
TokenSpaceGuidName = '' ReLabel = re.compile('LABEL\((\w+)\)')
if PcdValue.startswith('GUID') and PcdValue.endswith(')'): ReOffset = re.compile('OFFSET_OF\((\w+)\)')
LabelOffset = 0
for Index, Item in enumerate(PcdValueList):
# compute byte offset of every LABEL
Item = Item.strip()
try: try:
TokenSpaceGuidName = re.search('GUID\((\w+)\)', PcdValue).group(1) LabelList = ReLabel.findall(Item)
for Label in LabelList:
if Label not in LabelDict.keys():
LabelDict[Label] = str(LabelOffset)
except: except:
pass pass
if TokenSpaceGuidName and TokenSpaceGuidName in self._Symb: if Item.startswith('UINT8'):
PcdValue = 'GUID(' + self._Symb[TokenSpaceGuidName] + ')' LabelOffset = LabelOffset + 1
elif TokenSpaceGuidName: elif Item.startswith('UINT16'):
raise BadExpression('%s not found in DEC file' % TokenSpaceGuidName) LabelOffset = LabelOffset + 2
elif Item.startswith('UINT32'):
ListItem, Size = ParseFieldValue(PcdValue) LabelOffset = LabelOffset + 4
elif PcdValue.startswith('DEVICE_PATH') and PcdValue.endswith(')'): elif Item.startswith('UINT64'):
ListItem, Size = ParseFieldValue(PcdValue) LabelOffset = LabelOffset + 8
else: else:
ListItem = PcdValue.split(',')
if type(ListItem) == type(0) or type(ListItem) == type(0L):
for Index in range(0, Size):
ValueStr += '0x%02X' % (int(ListItem) & 255)
ListItem >>= 8
ValueStr += ', '
PcdValue = '{' + ValueStr[:-2] + '}'
elif type(ListItem) == type(''):
if ListItem.startswith('{') and ListItem.endswith('}'):
PcdValue = ListItem
else:
LabelDict = {}
ReLabel = re.compile('LABEL\((\w+)\)')
ReOffset = re.compile('OFFSET_OF\((\w+)\)')
LabelOffset = 0
for Index, Item in enumerate(ListItem):
# compute byte offset of every LABEL
Item = Item.strip()
try: try:
LabelList = ReLabel.findall(Item)
for Label in LabelList:
if Label not in LabelDict.keys():
LabelDict[Label] = str(LabelOffset)
Item = ReLabel.sub('', Item)
except:
pass
if Item.startswith('UINT8'):
LabelOffset = LabelOffset + 1
elif Item.startswith('UINT16'):
LabelOffset = LabelOffset + 2
elif Item.startswith('UINT32'):
LabelOffset = LabelOffset + 4
elif Item.startswith('UINT64'):
LabelOffset = LabelOffset + 8
else:
ItemValue, ItemSize = ParseFieldValue(Item) ItemValue, ItemSize = ParseFieldValue(Item)
LabelOffset = LabelOffset + ItemSize LabelOffset = LabelOffset + ItemSize
except:
LabelOffset = LabelOffset + 1
for Index, Item in enumerate(ListItem): for Index, Item in enumerate(PcdValueList):
# for LABEL parse # for LABEL parse
Item = Item.strip() Item = Item.strip()
try:
Item = ReLabel.sub('', Item)
except:
pass
try:
OffsetList = ReOffset.findall(Item)
except:
pass
for Offset in OffsetList:
if Offset in LabelDict.keys():
Re = re.compile('OFFSET_OF\(%s\)' % Offset)
Item = Re.sub(LabelDict[Offset], Item)
else:
raise BadExpression('%s not defined' % Offset)
NewPcdValueList.append(Item)
AllPcdValueList = []
for Item in NewPcdValueList:
Size = 0
ValueStr = ''
TokenSpaceGuidName = ''
if Item.startswith('GUID') and Item.endswith(')'):
try: try:
LabelList = ReLabel.findall(Item) TokenSpaceGuidName = re.search('GUID\((\w+)\)', Item).group(1)
for Label in LabelList:
if Label not in LabelDict.keys():
LabelDict[Label] = str(Index)
Item = ReLabel.sub('', Item)
except: except:
pass pass
try: if TokenSpaceGuidName and TokenSpaceGuidName in self._Symb:
OffsetList = ReOffset.findall(Item) Item = 'GUID(' + self._Symb[TokenSpaceGuidName] + ')'
except: elif TokenSpaceGuidName:
pass raise BadExpression('%s not found in DEC file' % TokenSpaceGuidName)
for Offset in OffsetList: Item, Size = ParseFieldValue(Item)
if Offset in LabelDict.keys(): for Index in range(0, Size):
Re = re.compile('OFFSET_OF\(%s\)'% Offset) ValueStr = '0x%02X' % (int(Item) & 255)
Item = Re.sub(LabelDict[Offset], Item) Item >>= 8
else: AllPcdValueList.append(ValueStr)
raise BadExpression('%s not defined' % Offset) continue
elif Item.startswith('DEVICE_PATH') and Item.endswith(')'):
Item, Size = ParseFieldValue(Item)
AllPcdValueList.append(Item[1:-1])
continue
else:
ValueType = "" ValueType = ""
if Item.startswith('UINT8'): if Item.startswith('UINT8'):
ItemSize = 1 ItemSize = 1
@ -894,16 +947,18 @@ class ValueExpressionEx(ValueExpression):
Item = '0x%x' % TmpValue if type(TmpValue) != type('') else TmpValue Item = '0x%x' % TmpValue if type(TmpValue) != type('') else TmpValue
if ItemSize == 0: if ItemSize == 0:
ItemValue, ItemSize = ParseFieldValue(Item) ItemValue, ItemSize = ParseFieldValue(Item)
if not (Item.startswith('"') or Item.startswith('L') or Item.startswith('{')) and ItemSize > 1:
raise BadExpression("Byte array number %s should less than 0xFF." % Item)
else: else:
ItemValue = ParseFieldValue(Item)[0] ItemValue = ParseFieldValue(Item)[0]
for I in range(0, ItemSize): for I in range(0, ItemSize):
ValueStr += '0x%02X' % (int(ItemValue) & 255) ValueStr = '0x%02X' % (int(ItemValue) & 255)
ItemValue >>= 8 ItemValue >>= 8
ValueStr += ', ' AllPcdValueList.append(ValueStr)
Size += ItemSize Size += ItemSize
if Size > 0: if Size > 0:
PcdValue = '{' + ValueStr[:-2] + '}' PcdValue = '{' + ','.join(AllPcdValueList) + '}'
else: else:
raise BadExpression("Type: %s, Value: %s, %s"%(self.PcdType, PcdValue, Value)) raise BadExpression("Type: %s, Value: %s, %s"%(self.PcdType, PcdValue, Value))