mirror of https://github.com/acidanthera/audk.git
907 lines
38 KiB
Python
907 lines
38 KiB
Python
## @file
|
|
# This file is used to define common parsing related functions used in parsing INF/DEC/DSC process
|
|
#
|
|
# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
|
|
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
#
|
|
|
|
##
|
|
# Import Modules
|
|
#
|
|
from __future__ import absolute_import
|
|
from .StringUtils import *
|
|
from CommonDataClass.DataClass import *
|
|
from .DataType import *
|
|
|
|
## ParseDefineMacro
|
|
#
|
|
# Search whole table to find all defined Macro and replaced them with the real values
|
|
#
|
|
def ParseDefineMacro2(Table, RecordSets, GlobalMacro):
|
|
Macros = {}
|
|
#
|
|
# Find all DEFINE macros in section [Header] and its section
|
|
#
|
|
SqlCommand = """select Value1, Value2, BelongsToItem, StartLine, Arch from %s
|
|
where Model = %s
|
|
and Enabled > -1""" % (Table.Table, MODEL_META_DATA_DEFINE)
|
|
RecordSet = Table.Exec(SqlCommand)
|
|
for Record in RecordSet:
|
|
Macros[Record[0]] = Record[1]
|
|
|
|
#
|
|
# Overridden by Global Macros
|
|
#
|
|
Macros.update(GlobalMacro)
|
|
|
|
#
|
|
# Replace the Macros
|
|
#
|
|
for Value in (v for v in RecordSets.values() if v):
|
|
for Item in Value:
|
|
Item[0] = ReplaceMacro(Item[0], Macros)
|
|
|
|
## ParseDefineMacro
|
|
#
|
|
# Search whole table to find all defined Macro and replaced them with the real values
|
|
#
|
|
def ParseDefineMacro(Table, GlobalMacro):
|
|
Macros = {}
|
|
#
|
|
# Find all DEFINE macros
|
|
#
|
|
SqlCommand = """select Value1, Value2, BelongsToItem, StartLine, Arch from %s
|
|
where Model = %s
|
|
and Enabled > -1""" % (Table.Table, MODEL_META_DATA_DEFINE)
|
|
RecordSet = Table.Exec(SqlCommand)
|
|
for Record in RecordSet:
|
|
#***************************************************************************************************************************************************
|
|
# The follow SqlCommand (expr replace) is not supported in Sqlite 3.3.4 which is used in Python 2.5 *
|
|
# Reserved Only *
|
|
# SqlCommand = """update %s set Value1 = replace(Value1, '%s', '%s') *
|
|
# where ID in (select ID from %s *
|
|
# where Model = %s *
|
|
# and Value1 like '%%%s%%' *
|
|
# and StartLine > %s *
|
|
# and Enabled > -1 *
|
|
# and Arch = '%s')""" % \ *
|
|
# (self.TblDsc.Table, Record[0], Record[1], self.TblDsc.Table, Record[2], Record[1], Record[3], Record[4]) *
|
|
#***************************************************************************************************************************************************
|
|
Macros[Record[0]] = Record[1]
|
|
|
|
#
|
|
# Overridden by Global Macros
|
|
#
|
|
Macros.update(GlobalMacro)
|
|
|
|
#
|
|
# Found all defined macro and replaced
|
|
#
|
|
SqlCommand = """select ID, Value1 from %s
|
|
where Model != %s
|
|
and Value1 like '%%$(%%' and Value1 like '%%)%%'
|
|
and Enabled > -1""" % (Table.Table, MODEL_META_DATA_DEFINE)
|
|
FoundRecords = Table.Exec(SqlCommand)
|
|
for FoundRecord in FoundRecords:
|
|
NewValue = ReplaceMacro(FoundRecord[1], Macros)
|
|
SqlCommand = """update %s set Value1 = '%s'
|
|
where ID = %s""" % (Table.Table, ConvertToSqlString2(NewValue), FoundRecord[0])
|
|
Table.Exec(SqlCommand)
|
|
|
|
##QueryDefinesItem
|
|
#
|
|
# Search item of section [Defines] by name, return its values
|
|
#
|
|
# @param Table: The Table to be executed
|
|
# @param Name: The Name of item of section [Defines]
|
|
# @param Arch: The Arch of item of section [Defines]
|
|
#
|
|
# @retval RecordSet: A list of all matched records
|
|
#
|
|
def QueryDefinesItem(Table, Name, Arch, BelongsToFile):
|
|
SqlCommand = """select Value2 from %s
|
|
where Model = %s
|
|
and Value1 = '%s'
|
|
and Arch = '%s'
|
|
and BelongsToFile = %s
|
|
and Enabled > -1""" % (Table.Table, MODEL_META_DATA_HEADER, ConvertToSqlString2(Name), ConvertToSqlString2(Arch), BelongsToFile)
|
|
RecordSet = Table.Exec(SqlCommand)
|
|
if len(RecordSet) < 1:
|
|
SqlCommand = """select Value2 from %s
|
|
where Model = %s
|
|
and Value1 = '%s'
|
|
and Arch = '%s'
|
|
and BelongsToFile = %s
|
|
and Enabled > -1""" % (Table.Table, MODEL_META_DATA_HEADER, ConvertToSqlString2(Name), ConvertToSqlString2(TAB_ARCH_COMMON.upper()), BelongsToFile)
|
|
RecordSet = Table.Exec(SqlCommand)
|
|
if len(RecordSet) == 1:
|
|
if Name == TAB_INF_DEFINES_LIBRARY_CLASS:
|
|
return [RecordSet[0][0]]
|
|
else:
|
|
return GetSplitValueList(RecordSet[0][0])
|
|
elif len(RecordSet) < 1:
|
|
return ['']
|
|
elif len(RecordSet) > 1:
|
|
RetVal = []
|
|
for Record in RecordSet:
|
|
if Name == TAB_INF_DEFINES_LIBRARY_CLASS:
|
|
RetVal.append(Record[0])
|
|
else:
|
|
Items = GetSplitValueList(Record[0])
|
|
for Item in Items:
|
|
RetVal.append(Item)
|
|
return RetVal
|
|
|
|
##QueryDefinesItem
|
|
#
|
|
# Search item of section [Defines] by name, return its values
|
|
#
|
|
# @param Table: The Table to be executed
|
|
# @param Name: The Name of item of section [Defines]
|
|
# @param Arch: The Arch of item of section [Defines]
|
|
#
|
|
# @retval RecordSet: A list of all matched records
|
|
#
|
|
def QueryDefinesItem2(Table, Arch, BelongsToFile):
|
|
SqlCommand = """select Value1, Value2, StartLine from %s
|
|
where Model = %s
|
|
and Arch = '%s'
|
|
and BelongsToFile = %s
|
|
and Enabled > -1""" % (Table.Table, MODEL_META_DATA_HEADER, ConvertToSqlString2(Arch), BelongsToFile)
|
|
RecordSet = Table.Exec(SqlCommand)
|
|
if len(RecordSet) < 1:
|
|
SqlCommand = """select Value1, Value2, StartLine from %s
|
|
where Model = %s
|
|
and Arch = '%s'
|
|
and BelongsToFile = %s
|
|
and Enabled > -1""" % (Table.Table, MODEL_META_DATA_HEADER, ConvertToSqlString2(TAB_ARCH_COMMON), BelongsToFile)
|
|
RecordSet = Table.Exec(SqlCommand)
|
|
|
|
return RecordSet
|
|
|
|
##QueryDscItem
|
|
#
|
|
# Search all dsc item for a specific section
|
|
#
|
|
# @param Table: The Table to be executed
|
|
# @param Model: The type of section
|
|
#
|
|
# @retval RecordSet: A list of all matched records
|
|
#
|
|
def QueryDscItem(Table, Model, BelongsToItem, BelongsToFile):
|
|
SqlCommand = """select Value1, Arch, StartLine, ID, Value2 from %s
|
|
where Model = %s
|
|
and BelongsToItem = %s
|
|
and BelongsToFile = %s
|
|
and Enabled > -1""" % (Table.Table, Model, BelongsToItem, BelongsToFile)
|
|
return Table.Exec(SqlCommand)
|
|
|
|
##QueryDecItem
|
|
#
|
|
# Search all dec item for a specific section
|
|
#
|
|
# @param Table: The Table to be executed
|
|
# @param Model: The type of section
|
|
#
|
|
# @retval RecordSet: A list of all matched records
|
|
#
|
|
def QueryDecItem(Table, Model, BelongsToItem):
|
|
SqlCommand = """select Value1, Arch, StartLine, ID, Value2 from %s
|
|
where Model = %s
|
|
and BelongsToItem = %s
|
|
and Enabled > -1""" % (Table.Table, Model, BelongsToItem)
|
|
return Table.Exec(SqlCommand)
|
|
|
|
##QueryInfItem
|
|
#
|
|
# Search all dec item for a specific section
|
|
#
|
|
# @param Table: The Table to be executed
|
|
# @param Model: The type of section
|
|
#
|
|
# @retval RecordSet: A list of all matched records
|
|
#
|
|
def QueryInfItem(Table, Model, BelongsToItem):
|
|
SqlCommand = """select Value1, Arch, StartLine, ID, Value2 from %s
|
|
where Model = %s
|
|
and BelongsToItem = %s
|
|
and Enabled > -1""" % (Table.Table, Model, BelongsToItem)
|
|
return Table.Exec(SqlCommand)
|
|
|
|
## GetBuildOption
|
|
#
|
|
# Parse a string with format "[<Family>:]<ToolFlag>=Flag"
|
|
# Return (Family, ToolFlag, Flag)
|
|
#
|
|
# @param String: String with BuildOption statement
|
|
# @param File: The file which defines build option, used in error report
|
|
#
|
|
# @retval truple() A truple structure as (Family, ToolChain, Flag)
|
|
#
|
|
def GetBuildOption(String, File, LineNo = -1):
|
|
(Family, ToolChain, Flag) = ('', '', '')
|
|
if String.find(TAB_EQUAL_SPLIT) < 0:
|
|
RaiseParserError(String, 'BuildOptions', File, '[<Family>:]<ToolFlag>=Flag', LineNo)
|
|
else:
|
|
List = GetSplitValueList(String, TAB_EQUAL_SPLIT, MaxSplit = 1)
|
|
if List[0].find(':') > -1:
|
|
Family = List[0][ : List[0].find(':')].strip()
|
|
ToolChain = List[0][List[0].find(':') + 1 : ].strip()
|
|
else:
|
|
ToolChain = List[0].strip()
|
|
Flag = List[1].strip()
|
|
return (Family, ToolChain, Flag)
|
|
|
|
## Get Library Class
|
|
#
|
|
# Get Library of Dsc as <LibraryClassKeyWord>|<LibraryInstance>
|
|
#
|
|
# @param Item: String as <LibraryClassKeyWord>|<LibraryInstance>
|
|
# @param ContainerFile: The file which describes the library class, used for error report
|
|
#
|
|
# @retval (LibraryClassKeyWord, LibraryInstance, [SUP_MODULE_LIST]) Formatted Library Item
|
|
#
|
|
def GetLibraryClass(Item, ContainerFile, WorkspaceDir, LineNo = -1):
|
|
List = GetSplitValueList(Item[0])
|
|
SupMod = SUP_MODULE_LIST_STRING
|
|
if len(List) != 2:
|
|
RaiseParserError(Item[0], 'LibraryClasses', ContainerFile, '<LibraryClassKeyWord>|<LibraryInstance>')
|
|
else:
|
|
CheckFileType(List[1], '.Inf', ContainerFile, 'library class instance', Item[0], LineNo)
|
|
CheckFileExist(WorkspaceDir, List[1], ContainerFile, 'LibraryClasses', Item[0], LineNo)
|
|
if Item[1] != '':
|
|
SupMod = Item[1]
|
|
|
|
return (List[0], List[1], SupMod)
|
|
|
|
## Get Library Class
|
|
#
|
|
# Get Library of Dsc as <LibraryClassKeyWord>[|<LibraryInstance>][|<TokenSpaceGuidCName>.<PcdCName>]
|
|
#
|
|
# @param Item: String as <LibraryClassKeyWord>|<LibraryInstance>
|
|
# @param ContainerFile: The file which describes the library class, used for error report
|
|
#
|
|
# @retval (LibraryClassKeyWord, LibraryInstance, [SUP_MODULE_LIST]) Formatted Library Item
|
|
#
|
|
def GetLibraryClassOfInf(Item, ContainerFile, WorkspaceDir, LineNo = -1):
|
|
ItemList = GetSplitValueList((Item[0] + DataType.TAB_VALUE_SPLIT * 2))
|
|
SupMod = SUP_MODULE_LIST_STRING
|
|
|
|
if len(ItemList) > 5:
|
|
RaiseParserError(Item[0], 'LibraryClasses', ContainerFile, '<LibraryClassKeyWord>[|<LibraryInstance>][|<TokenSpaceGuidCName>.<PcdCName>]')
|
|
else:
|
|
CheckFileType(ItemList[1], '.Inf', ContainerFile, 'LibraryClasses', Item[0], LineNo)
|
|
CheckFileExist(WorkspaceDir, ItemList[1], ContainerFile, 'LibraryClasses', Item[0], LineNo)
|
|
if ItemList[2] != '':
|
|
CheckPcdTokenInfo(ItemList[2], 'LibraryClasses', ContainerFile, LineNo)
|
|
if Item[1] != '':
|
|
SupMod = Item[1]
|
|
|
|
return (ItemList[0], ItemList[1], ItemList[2], SupMod)
|
|
|
|
## CheckPcdTokenInfo
|
|
#
|
|
# Check if PcdTokenInfo is following <TokenSpaceGuidCName>.<PcdCName>
|
|
#
|
|
# @param TokenInfoString: String to be checked
|
|
# @param Section: Used for error report
|
|
# @param File: Used for error report
|
|
#
|
|
# @retval True PcdTokenInfo is in correct format
|
|
#
|
|
def CheckPcdTokenInfo(TokenInfoString, Section, File, LineNo = -1):
|
|
Format = '<TokenSpaceGuidCName>.<PcdCName>'
|
|
if TokenInfoString != '' and TokenInfoString is not None:
|
|
TokenInfoList = GetSplitValueList(TokenInfoString, TAB_SPLIT)
|
|
if len(TokenInfoList) == 2:
|
|
return True
|
|
|
|
RaiseParserError(TokenInfoString, Section, File, Format, LineNo)
|
|
|
|
## Get Pcd
|
|
#
|
|
# Get Pcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<Value>[|<Type>|<MaximumDatumSize>]
|
|
#
|
|
# @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|<Value>[|<Type>|<MaximumDatumSize>]
|
|
# @param ContainerFile: The file which describes the pcd, used for error report
|
|
#
|
|
# @retval (TokenInfo[1], TokenInfo[0], List[1], List[2], List[3], Type)
|
|
#
|
|
def GetPcd(Item, Type, ContainerFile, LineNo = -1):
|
|
TokenGuid, TokenName, Value, MaximumDatumSize, Token = '', '', '', '', ''
|
|
List = GetSplitValueList(Item + TAB_VALUE_SPLIT * 2)
|
|
|
|
if len(List) < 4 or len(List) > 6:
|
|
RaiseParserError(Item, 'Pcds' + Type, ContainerFile, '<PcdTokenSpaceGuidCName>.<TokenCName>|<Value>[|<Type>|<MaximumDatumSize>]', LineNo)
|
|
else:
|
|
Value = List[1]
|
|
MaximumDatumSize = List[2]
|
|
Token = List[3]
|
|
|
|
if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
|
|
(TokenGuid, TokenName) = GetSplitValueList(List[0], TAB_SPLIT)
|
|
|
|
return (TokenName, TokenGuid, Value, MaximumDatumSize, Token, Type)
|
|
|
|
## Get FeatureFlagPcd
|
|
#
|
|
# Get FeatureFlagPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE
|
|
#
|
|
# @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE
|
|
# @param ContainerFile: The file which describes the pcd, used for error report
|
|
#
|
|
# @retval (TokenInfo[1], TokenInfo[0], List[1], Type)
|
|
#
|
|
def GetFeatureFlagPcd(Item, Type, ContainerFile, LineNo = -1):
|
|
TokenGuid, TokenName, Value = '', '', ''
|
|
List = GetSplitValueList(Item)
|
|
if len(List) != 2:
|
|
RaiseParserError(Item, 'Pcds' + Type, ContainerFile, '<PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE', LineNo)
|
|
else:
|
|
Value = List[1]
|
|
if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
|
|
(TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)
|
|
|
|
return (TokenName, TokenGuid, Value, Type)
|
|
|
|
## Get DynamicDefaultPcd
|
|
#
|
|
# Get DynamicDefaultPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<Value>[|<DatumTyp>[|<MaxDatumSize>]]
|
|
#
|
|
# @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE
|
|
# @param ContainerFile: The file which describes the pcd, used for error report
|
|
#
|
|
# @retval (TokenInfo[1], TokenInfo[0], List[1], List[2], List[3], Type)
|
|
#
|
|
def GetDynamicDefaultPcd(Item, Type, ContainerFile, LineNo = -1):
|
|
TokenGuid, TokenName, Value, DatumTyp, MaxDatumSize = '', '', '', '', ''
|
|
List = GetSplitValueList(Item + TAB_VALUE_SPLIT * 2)
|
|
if len(List) < 4 or len(List) > 8:
|
|
RaiseParserError(Item, 'Pcds' + Type, ContainerFile, '<PcdTokenSpaceGuidCName>.<TokenCName>|<Value>[|<DatumTyp>[|<MaxDatumSize>]]', LineNo)
|
|
else:
|
|
Value = List[1]
|
|
DatumTyp = List[2]
|
|
MaxDatumSize = List[3]
|
|
if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
|
|
(TokenGuid, TokenName) = GetSplitValueList(List[0], TAB_SPLIT)
|
|
|
|
return (TokenName, TokenGuid, Value, DatumTyp, MaxDatumSize, Type)
|
|
|
|
## Get DynamicHiiPcd
|
|
#
|
|
# Get DynamicHiiPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<String>|<VariableGuidCName>|<VariableOffset>[|<DefaultValue>[|<MaximumDatumSize>]]
|
|
#
|
|
# @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE
|
|
# @param ContainerFile: The file which describes the pcd, used for error report
|
|
#
|
|
# @retval (TokenInfo[1], TokenInfo[0], List[1], List[2], List[3], List[4], List[5], Type)
|
|
#
|
|
def GetDynamicHiiPcd(Item, Type, ContainerFile, LineNo = -1):
|
|
TokenGuid, TokenName, L1, L2, L3, L4, L5 = '', '', '', '', '', '', ''
|
|
List = GetSplitValueList(Item + TAB_VALUE_SPLIT * 2)
|
|
if len(List) < 6 or len(List) > 8:
|
|
RaiseParserError(Item, 'Pcds' + Type, ContainerFile, '<PcdTokenSpaceGuidCName>.<TokenCName>|<String>|<VariableGuidCName>|<VariableOffset>[|<DefaultValue>[|<MaximumDatumSize>]]', LineNo)
|
|
else:
|
|
L1, L2, L3, L4, L5 = List[1], List[2], List[3], List[4], List[5]
|
|
if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
|
|
(TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)
|
|
|
|
return (TokenName, TokenGuid, L1, L2, L3, L4, L5, Type)
|
|
|
|
## Get DynamicVpdPcd
|
|
#
|
|
# Get DynamicVpdPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<VpdOffset>[|<MaximumDatumSize>]
|
|
#
|
|
# @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE
|
|
# @param ContainerFile: The file which describes the pcd, used for error report
|
|
#
|
|
# @retval (TokenInfo[1], TokenInfo[0], List[1], List[2], Type)
|
|
#
|
|
def GetDynamicVpdPcd(Item, Type, ContainerFile, LineNo = -1):
|
|
TokenGuid, TokenName, L1, L2 = '', '', '', ''
|
|
List = GetSplitValueList(Item + TAB_VALUE_SPLIT)
|
|
if len(List) < 3 or len(List) > 4:
|
|
RaiseParserError(Item, 'Pcds' + Type, ContainerFile, '<PcdTokenSpaceGuidCName>.<TokenCName>|<VpdOffset>[|<MaximumDatumSize>]', LineNo)
|
|
else:
|
|
L1, L2 = List[1], List[2]
|
|
if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
|
|
(TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)
|
|
|
|
return (TokenName, TokenGuid, L1, L2, Type)
|
|
|
|
## GetComponent
|
|
#
|
|
# Parse block of the components defined in dsc file
|
|
# Set KeyValues as [ ['component name', [lib1, lib2, lib3], [bo1, bo2, bo3], [pcd1, pcd2, pcd3]], ...]
|
|
#
|
|
# @param Lines: The content to be parsed
|
|
# @param KeyValues: To store data after parsing
|
|
#
|
|
# @retval True Get component successfully
|
|
#
|
|
def GetComponent(Lines, KeyValues):
|
|
(findBlock, findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, False, False, False, False)
|
|
ListItem = None
|
|
LibraryClassItem = []
|
|
BuildOption = []
|
|
Pcd = []
|
|
|
|
for Line in Lines:
|
|
Line = Line[0]
|
|
|
|
#
|
|
# Ignore !include statement
|
|
#
|
|
if Line.upper().find(TAB_INCLUDE.upper() + ' ') > -1 or Line.upper().find(TAB_DEFINE + ' ') > -1:
|
|
continue
|
|
|
|
if findBlock == False:
|
|
ListItem = Line
|
|
#
|
|
# find '{' at line tail
|
|
#
|
|
if Line.endswith('{'):
|
|
findBlock = True
|
|
ListItem = CleanString(Line.rsplit('{', 1)[0], DataType.TAB_COMMENT_SPLIT)
|
|
|
|
#
|
|
# Parse a block content
|
|
#
|
|
if findBlock:
|
|
if Line.find('<LibraryClasses>') != -1:
|
|
(findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (True, False, False, False, False, False, False)
|
|
continue
|
|
if Line.find('<BuildOptions>') != -1:
|
|
(findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, True, False, False, False, False, False)
|
|
continue
|
|
if Line.find('<PcdsFeatureFlag>') != -1:
|
|
(findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, True, False, False, False, False)
|
|
continue
|
|
if Line.find('<PcdsPatchableInModule>') != -1:
|
|
(findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, True, False, False, False)
|
|
continue
|
|
if Line.find('<PcdsFixedAtBuild>') != -1:
|
|
(findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, True, False, False)
|
|
continue
|
|
if Line.find('<PcdsDynamic>') != -1:
|
|
(findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, False, True, False)
|
|
continue
|
|
if Line.find('<PcdsDynamicEx>') != -1:
|
|
(findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, False, False, True)
|
|
continue
|
|
if Line.endswith('}'):
|
|
#
|
|
# find '}' at line tail
|
|
#
|
|
KeyValues.append([ListItem, LibraryClassItem, BuildOption, Pcd])
|
|
(findBlock, findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, False, False, False, False)
|
|
LibraryClassItem, BuildOption, Pcd = [], [], []
|
|
continue
|
|
|
|
if findBlock:
|
|
if findLibraryClass:
|
|
LibraryClassItem.append(Line)
|
|
elif findBuildOption:
|
|
BuildOption.append(Line)
|
|
elif findPcdsFeatureFlag:
|
|
Pcd.append((DataType.TAB_PCDS_FEATURE_FLAG_NULL, Line))
|
|
elif findPcdsPatchableInModule:
|
|
Pcd.append((DataType.TAB_PCDS_PATCHABLE_IN_MODULE_NULL, Line))
|
|
elif findPcdsFixedAtBuild:
|
|
Pcd.append((DataType.TAB_PCDS_FIXED_AT_BUILD_NULL, Line))
|
|
elif findPcdsDynamic:
|
|
Pcd.append((DataType.TAB_PCDS_DYNAMIC_DEFAULT_NULL, Line))
|
|
elif findPcdsDynamicEx:
|
|
Pcd.append((DataType.TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL, Line))
|
|
else:
|
|
KeyValues.append([ListItem, [], [], []])
|
|
|
|
return True
|
|
|
|
## GetExec
|
|
#
|
|
# Parse a string with format "InfFilename [EXEC = ExecFilename]"
|
|
# Return (InfFilename, ExecFilename)
|
|
#
|
|
# @param String: String with EXEC statement
|
|
#
|
|
# @retval truple() A pair as (InfFilename, ExecFilename)
|
|
#
|
|
def GetExec(String):
|
|
InfFilename = ''
|
|
ExecFilename = ''
|
|
if String.find('EXEC') > -1:
|
|
InfFilename = String[ : String.find('EXEC')].strip()
|
|
ExecFilename = String[String.find('EXEC') + len('EXEC') : ].strip()
|
|
else:
|
|
InfFilename = String.strip()
|
|
|
|
return (InfFilename, ExecFilename)
|
|
|
|
## GetComponents
|
|
#
|
|
# Parse block of the components defined in dsc file
|
|
# Set KeyValues as [ ['component name', [lib1, lib2, lib3], [bo1, bo2, bo3], [pcd1, pcd2, pcd3]], ...]
|
|
#
|
|
# @param Lines: The content to be parsed
|
|
# @param Key: Reserved
|
|
# @param KeyValues: To store data after parsing
|
|
# @param CommentCharacter: Comment char, used to ignore comment content
|
|
#
|
|
# @retval True Get component successfully
|
|
#
|
|
def GetComponents(Lines, Key, KeyValues, CommentCharacter):
|
|
if Lines.find(DataType.TAB_SECTION_END) > -1:
|
|
Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1]
|
|
(findBlock, findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, False, False, False, False)
|
|
ListItem = None
|
|
LibraryClassItem = []
|
|
BuildOption = []
|
|
Pcd = []
|
|
|
|
LineList = Lines.split('\n')
|
|
for Line in LineList:
|
|
Line = CleanString(Line, CommentCharacter)
|
|
if Line is None or Line == '':
|
|
continue
|
|
|
|
if findBlock == False:
|
|
ListItem = Line
|
|
#
|
|
# find '{' at line tail
|
|
#
|
|
if Line.endswith('{'):
|
|
findBlock = True
|
|
ListItem = CleanString(Line.rsplit('{', 1)[0], CommentCharacter)
|
|
|
|
#
|
|
# Parse a block content
|
|
#
|
|
if findBlock:
|
|
if Line.find('<LibraryClasses>') != -1:
|
|
(findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (True, False, False, False, False, False, False)
|
|
continue
|
|
if Line.find('<BuildOptions>') != -1:
|
|
(findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, True, False, False, False, False, False)
|
|
continue
|
|
if Line.find('<PcdsFeatureFlag>') != -1:
|
|
(findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, True, False, False, False, False)
|
|
continue
|
|
if Line.find('<PcdsPatchableInModule>') != -1:
|
|
(findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, True, False, False, False)
|
|
continue
|
|
if Line.find('<PcdsFixedAtBuild>') != -1:
|
|
(findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, True, False, False)
|
|
continue
|
|
if Line.find('<PcdsDynamic>') != -1:
|
|
(findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, False, True, False)
|
|
continue
|
|
if Line.find('<PcdsDynamicEx>') != -1:
|
|
(findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, False, False, True)
|
|
continue
|
|
if Line.endswith('}'):
|
|
#
|
|
# find '}' at line tail
|
|
#
|
|
KeyValues.append([ListItem, LibraryClassItem, BuildOption, Pcd])
|
|
(findBlock, findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, False, False, False, False)
|
|
LibraryClassItem, BuildOption, Pcd = [], [], []
|
|
continue
|
|
|
|
if findBlock:
|
|
if findLibraryClass:
|
|
LibraryClassItem.append(Line)
|
|
elif findBuildOption:
|
|
BuildOption.append(Line)
|
|
elif findPcdsFeatureFlag:
|
|
Pcd.append((DataType.TAB_PCDS_FEATURE_FLAG, Line))
|
|
elif findPcdsPatchableInModule:
|
|
Pcd.append((DataType.TAB_PCDS_PATCHABLE_IN_MODULE, Line))
|
|
elif findPcdsFixedAtBuild:
|
|
Pcd.append((DataType.TAB_PCDS_FIXED_AT_BUILD, Line))
|
|
elif findPcdsDynamic:
|
|
Pcd.append((DataType.TAB_PCDS_DYNAMIC, Line))
|
|
elif findPcdsDynamicEx:
|
|
Pcd.append((DataType.TAB_PCDS_DYNAMIC_EX, Line))
|
|
else:
|
|
KeyValues.append([ListItem, [], [], []])
|
|
|
|
return True
|
|
|
|
## Get Source
|
|
#
|
|
# Get Source of Inf as <Filename>[|<Family>[|<TagName>[|<ToolCode>[|<PcdFeatureFlag>]]]]
|
|
#
|
|
# @param Item: String as <Filename>[|<Family>[|<TagName>[|<ToolCode>[|<PcdFeatureFlag>]]]]
|
|
# @param ContainerFile: The file which describes the library class, used for error report
|
|
#
|
|
# @retval (List[0], List[1], List[2], List[3], List[4])
|
|
#
|
|
def GetSource(Item, ContainerFile, FileRelativePath, LineNo = -1):
|
|
ItemNew = Item + DataType.TAB_VALUE_SPLIT * 4
|
|
List = GetSplitValueList(ItemNew)
|
|
if len(List) < 5 or len(List) > 9:
|
|
RaiseParserError(Item, 'Sources', ContainerFile, '<Filename>[|<Family>[|<TagName>[|<ToolCode>[|<PcdFeatureFlag>]]]]', LineNo)
|
|
List[0] = NormPath(List[0])
|
|
CheckFileExist(FileRelativePath, List[0], ContainerFile, 'Sources', Item, LineNo)
|
|
if List[4] != '':
|
|
CheckPcdTokenInfo(List[4], 'Sources', ContainerFile, LineNo)
|
|
|
|
return (List[0], List[1], List[2], List[3], List[4])
|
|
|
|
## Get Binary
|
|
#
|
|
# Get Binary of Inf as <Filename>[|<Family>[|<TagName>[|<ToolCode>[|<PcdFeatureFlag>]]]]
|
|
#
|
|
# @param Item: String as <Filename>[|<Family>[|<TagName>[|<ToolCode>[|<PcdFeatureFlag>]]]]
|
|
# @param ContainerFile: The file which describes the library class, used for error report
|
|
#
|
|
# @retval (List[0], List[1], List[2], List[3])
|
|
# @retval List
|
|
#
|
|
def GetBinary(Item, ContainerFile, FileRelativePath, LineNo = -1):
|
|
ItemNew = Item + DataType.TAB_VALUE_SPLIT
|
|
List = GetSplitValueList(ItemNew)
|
|
if len(List) != 4 and len(List) != 5:
|
|
RaiseParserError(Item, 'Binaries', ContainerFile, "<FileType>|<Filename>|<Target>[|<TokenSpaceGuidCName>.<PcdCName>]", LineNo)
|
|
else:
|
|
if List[3] != '':
|
|
CheckPcdTokenInfo(List[3], 'Binaries', ContainerFile, LineNo)
|
|
|
|
if len(List) == 4:
|
|
return (List[0], List[1], List[2], List[3])
|
|
elif len(List) == 3:
|
|
return (List[0], List[1], List[2], '')
|
|
elif len(List) == 2:
|
|
return (List[0], List[1], '', '')
|
|
elif len(List) == 1:
|
|
return (List[0], '', '', '')
|
|
|
|
## Get Guids/Protocols/Ppis
|
|
#
|
|
# Get Guids/Protocols/Ppis of Inf as <GuidCName>[|<PcdFeatureFlag>]
|
|
#
|
|
# @param Item: String as <GuidCName>[|<PcdFeatureFlag>]
|
|
# @param Type: Type of parsing string
|
|
# @param ContainerFile: The file which describes the library class, used for error report
|
|
#
|
|
# @retval (List[0], List[1])
|
|
#
|
|
def GetGuidsProtocolsPpisOfInf(Item, Type, ContainerFile, LineNo = -1):
|
|
ItemNew = Item + TAB_VALUE_SPLIT
|
|
List = GetSplitValueList(ItemNew)
|
|
if List[1] != '':
|
|
CheckPcdTokenInfo(List[1], Type, ContainerFile, LineNo)
|
|
|
|
return (List[0], List[1])
|
|
|
|
## Get Guids/Protocols/Ppis
|
|
#
|
|
# Get Guids/Protocols/Ppis of Dec as <GuidCName>=<GuidValue>
|
|
#
|
|
# @param Item: String as <GuidCName>=<GuidValue>
|
|
# @param Type: Type of parsing string
|
|
# @param ContainerFile: The file which describes the library class, used for error report
|
|
#
|
|
# @retval (List[0], List[1])
|
|
#
|
|
def GetGuidsProtocolsPpisOfDec(Item, Type, ContainerFile, LineNo = -1):
|
|
List = GetSplitValueList(Item, DataType.TAB_EQUAL_SPLIT)
|
|
if len(List) != 2:
|
|
RaiseParserError(Item, Type, ContainerFile, '<CName>=<GuidValue>', LineNo)
|
|
|
|
return (List[0], List[1])
|
|
|
|
## GetPackage
|
|
#
|
|
# Get Package of Inf as <PackagePath>[|<PcdFeatureFlag>]
|
|
#
|
|
# @param Item: String as <PackagePath>[|<PcdFeatureFlag>]
|
|
# @param Type: Type of parsing string
|
|
# @param ContainerFile: The file which describes the library class, used for error report
|
|
#
|
|
# @retval (List[0], List[1])
|
|
#
|
|
def GetPackage(Item, ContainerFile, FileRelativePath, LineNo = -1):
|
|
ItemNew = Item + TAB_VALUE_SPLIT
|
|
List = GetSplitValueList(ItemNew)
|
|
CheckFileType(List[0], '.Dec', ContainerFile, 'package', List[0], LineNo)
|
|
CheckFileExist(FileRelativePath, List[0], ContainerFile, 'Packages', List[0], LineNo)
|
|
|
|
if List[1] != '':
|
|
CheckPcdTokenInfo(List[1], 'Packages', ContainerFile, LineNo)
|
|
|
|
return (List[0], List[1])
|
|
|
|
## Get Pcd Values of Inf
|
|
#
|
|
# Get Pcd of Inf as <TokenSpaceGuidCName>.<PcdCName>[|<Value>]
|
|
#
|
|
# @param Item: The string describes pcd
|
|
# @param Type: The type of Pcd
|
|
# @param File: The file which describes the pcd, used for error report
|
|
#
|
|
# @retval (TokenSpcCName, TokenCName, Value, ItemType) Formatted Pcd Item
|
|
#
|
|
def GetPcdOfInf(Item, Type, File, LineNo):
|
|
Format = '<TokenSpaceGuidCName>.<PcdCName>[|<Value>]'
|
|
TokenGuid, TokenName, Value, InfType = '', '', '', ''
|
|
|
|
if Type == TAB_PCDS_FIXED_AT_BUILD:
|
|
InfType = TAB_INF_FIXED_PCD
|
|
elif Type == TAB_PCDS_PATCHABLE_IN_MODULE:
|
|
InfType = TAB_INF_PATCH_PCD
|
|
elif Type == TAB_PCDS_FEATURE_FLAG:
|
|
InfType = TAB_INF_FEATURE_PCD
|
|
elif Type == TAB_PCDS_DYNAMIC_EX:
|
|
InfType = TAB_INF_PCD_EX
|
|
elif Type == TAB_PCDS_DYNAMIC:
|
|
InfType = TAB_INF_PCD
|
|
List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT)
|
|
if len(List) < 2 or len(List) > 3:
|
|
RaiseParserError(Item, InfType, File, Format, LineNo)
|
|
else:
|
|
Value = List[1]
|
|
TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT)
|
|
if len(TokenInfo) != 2:
|
|
RaiseParserError(Item, InfType, File, Format, LineNo)
|
|
else:
|
|
TokenGuid = TokenInfo[0]
|
|
TokenName = TokenInfo[1]
|
|
|
|
return (TokenGuid, TokenName, Value, Type)
|
|
|
|
|
|
## Get Pcd Values of Dec
|
|
#
|
|
# Get Pcd of Dec as <TokenSpcCName>.<TokenCName>|<Value>|<DatumType>|<Token>
|
|
# @retval (TokenSpcCName, TokenCName, Value, DatumType, Token, ItemType) Formatted Pcd Item
|
|
#
|
|
def GetPcdOfDec(Item, Type, File, LineNo = -1):
|
|
Format = '<TokenSpaceGuidCName>.<PcdCName>|<Value>|<DatumType>|<Token>'
|
|
TokenGuid, TokenName, Value, DatumType, Token = '', '', '', '', ''
|
|
List = GetSplitValueList(Item)
|
|
if len(List) != 4:
|
|
RaiseParserError(Item, 'Pcds' + Type, File, Format, LineNo)
|
|
else:
|
|
Value = List[1]
|
|
DatumType = List[2]
|
|
Token = List[3]
|
|
TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT)
|
|
if len(TokenInfo) != 2:
|
|
RaiseParserError(Item, 'Pcds' + Type, File, Format, LineNo)
|
|
else:
|
|
TokenGuid = TokenInfo[0]
|
|
TokenName = TokenInfo[1]
|
|
|
|
return (TokenGuid, TokenName, Value, DatumType, Token, Type)
|
|
|
|
## Parse DEFINE statement
|
|
#
|
|
# Get DEFINE macros
|
|
#
|
|
# 1. Insert a record into TblDec
|
|
# Value1: Macro Name
|
|
# Value2: Macro Value
|
|
#
|
|
def ParseDefine(LineValue, StartLine, Table, FileID, Filename, SectionName, SectionModel, Arch):
|
|
EdkLogger.debug(EdkLogger.DEBUG_2, "DEFINE statement '%s' found in section %s" % (LineValue, SectionName))
|
|
Define = GetSplitValueList(CleanString(LineValue[LineValue.upper().find(DataType.TAB_DEFINE.upper() + ' ') + len(DataType.TAB_DEFINE + ' ') : ]), TAB_EQUAL_SPLIT, 1)
|
|
Table.Insert(MODEL_META_DATA_DEFINE, Define[0], Define[1], '', '', '', Arch, SectionModel, FileID, StartLine, -1, StartLine, -1, 0)
|
|
|
|
## InsertSectionItems
|
|
#
|
|
# Insert item data of a section to a dict
|
|
#
|
|
def InsertSectionItems(Model, CurrentSection, SectionItemList, ArchList, ThirdList, RecordSet):
|
|
# Insert each item data of a section
|
|
for Index in range(0, len(ArchList)):
|
|
Arch = ArchList[Index]
|
|
Third = ThirdList[Index]
|
|
if Arch == '':
|
|
Arch = TAB_ARCH_COMMON
|
|
|
|
Records = RecordSet[Model]
|
|
for SectionItem in SectionItemList:
|
|
BelongsToItem, EndLine, EndColumn = -1, -1, -1
|
|
LineValue, StartLine, EndLine, Comment = SectionItem[0], SectionItem[1], SectionItem[1], SectionItem[2]
|
|
|
|
EdkLogger.debug(4, "Parsing %s ..." %LineValue)
|
|
# And then parse DEFINE statement
|
|
if LineValue.upper().find(DataType.TAB_DEFINE.upper() + ' ') > -1:
|
|
continue
|
|
|
|
# At last parse other sections
|
|
ID = -1
|
|
Records.append([LineValue, Arch, StartLine, ID, Third, Comment])
|
|
|
|
if RecordSet != {}:
|
|
RecordSet[Model] = Records
|
|
|
|
## Insert records to database
|
|
#
|
|
# Insert item data of a section to database
|
|
# @param Table: The Table to be inserted
|
|
# @param FileID: The ID of belonging file
|
|
# @param Filename: The name of belonging file
|
|
# @param CurrentSection: The name of current section
|
|
# @param SectionItemList: A list of items of the section
|
|
# @param ArchList: A list of arches
|
|
# @param ThirdList: A list of third parameters, ModuleType for LibraryClass and SkuId for Dynamic Pcds
|
|
# @param IfDefList: A list of all conditional statements
|
|
# @param RecordSet: A dict of all parsed records
|
|
#
|
|
def InsertSectionItemsIntoDatabase(Table, FileID, Filename, Model, CurrentSection, SectionItemList, ArchList, ThirdList, IfDefList, RecordSet):
|
|
#
|
|
# Insert each item data of a section
|
|
#
|
|
for Index in range(0, len(ArchList)):
|
|
Arch = ArchList[Index]
|
|
Third = ThirdList[Index]
|
|
if Arch == '':
|
|
Arch = TAB_ARCH_COMMON
|
|
|
|
Records = RecordSet[Model]
|
|
for SectionItem in SectionItemList:
|
|
BelongsToItem, EndLine, EndColumn = -1, -1, -1
|
|
LineValue, StartLine, EndLine = SectionItem[0], SectionItem[1], SectionItem[1]
|
|
|
|
EdkLogger.debug(4, "Parsing %s ..." %LineValue)
|
|
#
|
|
# And then parse DEFINE statement
|
|
#
|
|
if LineValue.upper().find(DataType.TAB_DEFINE.upper() + ' ') > -1:
|
|
ParseDefine(LineValue, StartLine, Table, FileID, Filename, CurrentSection, Model, Arch)
|
|
continue
|
|
|
|
#
|
|
# At last parse other sections
|
|
#
|
|
ID = Table.Insert(Model, LineValue, Third, Third, '', '', Arch, -1, FileID, StartLine, -1, StartLine, -1, 0)
|
|
Records.append([LineValue, Arch, StartLine, ID, Third])
|
|
|
|
if RecordSet != {}:
|
|
RecordSet[Model] = Records
|
|
|
|
## GenMetaDatSectionItem
|
|
def GenMetaDatSectionItem(Key, Value, List):
|
|
if Key not in List:
|
|
List[Key] = [Value]
|
|
else:
|
|
List[Key].append(Value)
|
|
|
|
## IsValidWord
|
|
#
|
|
# Check whether the word is valid.
|
|
# <Word> ::= (a-zA-Z0-9_)(a-zA-Z0-9_-){0,} Alphanumeric characters with
|
|
# optional
|
|
# dash "-" and/or underscore "_" characters. No whitespace
|
|
# characters are permitted.
|
|
#
|
|
# @param Word: The word string need to be checked.
|
|
#
|
|
def IsValidWord(Word):
|
|
if not Word:
|
|
return False
|
|
#
|
|
# The first char should be alpha, _ or Digit.
|
|
#
|
|
if not Word[0].isalnum() and \
|
|
not Word[0] == '_' and \
|
|
not Word[0].isdigit():
|
|
return False
|
|
|
|
LastChar = ''
|
|
for Char in Word[1:]:
|
|
if (not Char.isalpha()) and \
|
|
(not Char.isdigit()) and \
|
|
Char != '-' and \
|
|
Char != '_' and \
|
|
Char != '.':
|
|
return False
|
|
if Char == '.' and LastChar == '.':
|
|
return False
|
|
LastChar = Char
|
|
|
|
return True
|