| ## @file | |
| # This file is used to define common parsing related functions used in parsing | |
| # INF/DEC/DSC process | |
| # | |
| # Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR> | |
| # | |
| # This program and the accompanying materials are licensed and made available | |
| # under the terms and conditions of the BSD License which accompanies this | |
| # distribution. The full text of the license may be found at | |
| # http://opensource.org/licenses/bsd-license.php | |
| # | |
| # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| # | |
| ''' | |
| Parsing | |
| ''' | |
| ## | |
| # Import Modules | |
| # | |
| import os.path | |
| import re | |
| from Library.String import RaiseParserError | |
| from Library.String import GetSplitValueList | |
| from Library.String import CheckFileType | |
| from Library.String import CheckFileExist | |
| from Library.String import CleanString | |
| from Library.String import NormPath | |
| from Logger.ToolError import FILE_NOT_FOUND | |
| from Logger.ToolError import FatalError | |
| from Logger.ToolError import FORMAT_INVALID | |
| from Library import DataType | |
| from Library.Misc import GuidStructureStringToGuidString | |
| from Library.Misc import CheckGuidRegFormat | |
| from Logger import StringTable as ST | |
| import Logger.Log as Logger | |
| from Parser.DecParser import Dec | |
| import GlobalData | |
| gPKG_INFO_DICT = {} | |
| ## 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 | |
| # | |
| def GetBuildOption(String, File, LineNo= -1): | |
| (Family, ToolChain, Flag) = ('', '', '') | |
| if String.find(DataType.TAB_EQUAL_SPLIT) < 0: | |
| RaiseParserError(String, 'BuildOptions', File, \ | |
| '[<Family>:]<ToolFlag>=Flag', LineNo) | |
| else: | |
| List = GetSplitValueList(String, DataType.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 | |
| # | |
| def GetLibraryClass(Item, ContainerFile, WorkspaceDir, LineNo= -1): | |
| List = GetSplitValueList(Item[0]) | |
| SupMod = DataType.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 | |
| # | |
| def GetLibraryClassOfInf(Item, ContainerFile, WorkspaceDir, LineNo= -1): | |
| ItemList = GetSplitValueList((Item[0] + DataType.TAB_VALUE_SPLIT * 2)) | |
| SupMod = DataType.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 | |
| # | |
| def CheckPcdTokenInfo(TokenInfoString, Section, File, LineNo= -1): | |
| Format = '<TokenSpaceGuidCName>.<PcdCName>' | |
| if TokenInfoString != '' and TokenInfoString != None: | |
| TokenInfoList = GetSplitValueList(TokenInfoString, DataType.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 | |
| # | |
| def GetPcd(Item, Type, ContainerFile, LineNo= -1): | |
| TokenGuid, TokenName, Value, MaximumDatumSize, Token = '', '', '', '', '' | |
| List = GetSplitValueList(Item + DataType.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], DataType.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 | |
| # | |
| 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 | |
| # | |
| def GetDynamicDefaultPcd(Item, Type, ContainerFile, LineNo= -1): | |
| TokenGuid, TokenName, Value, DatumTyp, MaxDatumSize = '', '', '', '', '' | |
| List = GetSplitValueList(Item + DataType.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], DataType.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 | |
| # | |
| def GetDynamicHiiPcd(Item, Type, ContainerFile, LineNo= -1): | |
| TokenGuid, TokenName, List1, List2, List3, List4, List5 = \ | |
| '', '', '', '', '', '', '' | |
| List = GetSplitValueList(Item + DataType.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: | |
| List1, List2, List3, List4, List5 = \ | |
| 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, List1, List2, List3, List4, List5, 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 | |
| # | |
| def GetDynamicVpdPcd(Item, Type, ContainerFile, LineNo= -1): | |
| TokenGuid, TokenName, List1, List2 = '', '', '', '' | |
| List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT) | |
| if len(List) < 3 or len(List) > 4: | |
| RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \ | |
| '<PcdTokenSpaceGuidCName>.<TokenCName>|<VpdOffset>\ | |
| [|<MaximumDatumSize>]', LineNo) | |
| else: | |
| List1, List2 = List[1], List[2] | |
| if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo): | |
| (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT) | |
| return (TokenName, TokenGuid, List1, List2, 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 | |
| # | |
| 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(DataType.TAB_INCLUDE.upper() + ' ') > -1 or \ | |
| Line.upper().find(DataType.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 | |
| # | |
| 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, 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 == 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 | |
| # | |
| 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 | |
| # | |
| def GetBinary(Item, ContainerFile, LineNo= -1): | |
| ItemNew = Item + DataType.TAB_VALUE_SPLIT | |
| List = GetSplitValueList(ItemNew) | |
| if len(List) < 3 or len(List) > 5: | |
| RaiseParserError(Item, 'Binaries', ContainerFile, \ | |
| "<FileType>|<Filename>[|<Target>\ | |
| [|<TokenSpaceGuidCName>.<PcdCName>]]", LineNo) | |
| if len(List) >= 4: | |
| if List[3] != '': | |
| CheckPcdTokenInfo(List[3], 'Binaries', ContainerFile, LineNo) | |
| return (List[0], List[1], List[2], List[3]) | |
| elif len(List) == 3: | |
| return (List[0], List[1], List[2], '') | |
| ## 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 | |
| # | |
| def GetGuidsProtocolsPpisOfInf(Item): | |
| ItemNew = Item + DataType.TAB_VALUE_SPLIT | |
| List = GetSplitValueList(ItemNew) | |
| 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 | |
| # | |
| 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) | |
| # | |
| #convert C-Format Guid to Register Format | |
| # | |
| if List[1][0] == '{' and List[1][-1] == '}': | |
| RegisterFormatGuid = GuidStructureStringToGuidString(List[1]) | |
| if RegisterFormatGuid == '': | |
| RaiseParserError(Item, Type, ContainerFile, \ | |
| 'CFormat or RegisterFormat', LineNo) | |
| else: | |
| if CheckGuidRegFormat(List[1]): | |
| RegisterFormatGuid = List[1] | |
| else: | |
| RaiseParserError(Item, Type, ContainerFile, \ | |
| 'CFormat or RegisterFormat', LineNo) | |
| return (List[0], RegisterFormatGuid) | |
| ## 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 | |
| # | |
| def GetPackage(Item, ContainerFile, FileRelativePath, LineNo= -1): | |
| ItemNew = Item + DataType.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 | |
| # | |
| def GetPcdOfInf(Item, Type, File, LineNo): | |
| Format = '<TokenSpaceGuidCName>.<PcdCName>[|<Value>]' | |
| TokenGuid, TokenName, Value, InfType = '', '', '', '' | |
| if Type == DataType.TAB_PCDS_FIXED_AT_BUILD: | |
| InfType = DataType.TAB_INF_FIXED_PCD | |
| elif Type == DataType.TAB_PCDS_PATCHABLE_IN_MODULE: | |
| InfType = DataType.TAB_INF_PATCH_PCD | |
| elif Type == DataType.TAB_PCDS_FEATURE_FLAG: | |
| InfType = DataType.TAB_INF_FEATURE_PCD | |
| elif Type == DataType.TAB_PCDS_DYNAMIC_EX: | |
| InfType = DataType.TAB_INF_PCD_EX | |
| elif Type == DataType.TAB_PCDS_DYNAMIC: | |
| InfType = DataType.TAB_INF_PCD | |
| List = GetSplitValueList(Item, DataType.TAB_VALUE_SPLIT, 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] | |
| if len(List) > 1: | |
| Value = List[1] | |
| else: | |
| Value = None | |
| return (TokenGuid, TokenName, Value, InfType) | |
| ## Get Pcd Values of Dec | |
| # | |
| # Get Pcd of Dec as <TokenSpcCName>.<TokenCName>|<Value>|<DatumType>|<Token> | |
| # @param Item: Pcd item | |
| # @param Type: Pcd type | |
| # @param File: Dec file | |
| # @param LineNo: Line number | |
| # | |
| 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 | |
| # | |
| # @param LineValue: A DEFINE line value | |
| # @param StartLine: A DEFINE start line | |
| # @param Table: A table | |
| # @param FileID: File ID | |
| # @param Filename: File name | |
| # @param SectionName: DEFINE section name | |
| # @param SectionModel: DEFINE section model | |
| # @param Arch: DEFINE arch | |
| # | |
| def ParseDefine(LineValue, StartLine, Table, FileID, SectionName, \ | |
| SectionModel, Arch): | |
| Logger.Debug(Logger.DEBUG_2, ST.MSG_DEFINE_STATEMENT_FOUND % (LineValue, \ | |
| SectionName)) | |
| Define = \ | |
| GetSplitValueList(CleanString\ | |
| (LineValue[LineValue.upper().\ | |
| find(DataType.TAB_DEFINE.upper() + ' ') + \ | |
| len(DataType.TAB_DEFINE + ' ') : ]), \ | |
| DataType.TAB_EQUAL_SPLIT, 1) | |
| Table.Insert(DataType.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 | |
| # | |
| # @param Model: A model | |
| # @param CurrentSection: Current section | |
| # @param SectionItemList: Section item list | |
| # @param ArchList: Arch list | |
| # @param ThirdList: Third list | |
| # @param RecordSet: Record set | |
| # | |
| def InsertSectionItems(Model, 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 = DataType.TAB_ARCH_COMMON | |
| Records = RecordSet[Model] | |
| for SectionItem in SectionItemList: | |
| LineValue, StartLine, Comment = SectionItem[0], \ | |
| SectionItem[1], SectionItem[2] | |
| Logger.Debug(4, ST.MSG_PARSING % LineValue) | |
| # | |
| # And then parse DEFINE statement | |
| # | |
| if LineValue.upper().find(DataType.TAB_DEFINE.upper() + ' ') > -1: | |
| continue | |
| # | |
| # At last parse other sections | |
| # | |
| IdNum = -1 | |
| Records.append([LineValue, Arch, StartLine, IdNum, Third, Comment]) | |
| if RecordSet != {}: | |
| RecordSet[Model] = Records | |
| ## GenMetaDatSectionItem | |
| # | |
| # @param Key: A key | |
| # @param Value: A value | |
| # @param List: A list | |
| # | |
| def GenMetaDatSectionItem(Key, Value, List): | |
| if Key not in List: | |
| List[Key] = [Value] | |
| else: | |
| List[Key].append(Value) | |
| ## GetPkgInfoFromDec | |
| # | |
| # get package name, guid, version info from dec files | |
| # | |
| # @param Path: File path | |
| # | |
| def GetPkgInfoFromDec(Path): | |
| PkgName = None | |
| PkgGuid = None | |
| PkgVersion = None | |
| Path = Path.replace('\\', '/') | |
| if not os.path.exists(Path): | |
| Logger.Error("\nUPT", FILE_NOT_FOUND, File=Path) | |
| if Path in gPKG_INFO_DICT: | |
| return gPKG_INFO_DICT[Path] | |
| try: | |
| DecParser = None | |
| if Path not in GlobalData.gPackageDict: | |
| DecParser = Dec(Path) | |
| GlobalData.gPackageDict[Path] = DecParser | |
| else: | |
| DecParser = GlobalData.gPackageDict[Path] | |
| PkgName = DecParser.GetPackageName() | |
| PkgGuid = DecParser.GetPackageGuid() | |
| PkgVersion = DecParser.GetPackageVersion() | |
| gPKG_INFO_DICT[Path] = (PkgName, PkgGuid, PkgVersion) | |
| return PkgName, PkgGuid, PkgVersion | |
| except FatalError: | |
| return None, None, None | |
| ## GetWorkspacePackage | |
| # | |
| # Get a list of workspace package information. | |
| # | |
| def GetWorkspacePackage(): | |
| DecFileList = [] | |
| WorkspaceDir = GlobalData.gWORKSPACE | |
| PackageDir = GlobalData.gPACKAGE_PATH | |
| for PkgRoot in [WorkspaceDir] + PackageDir: | |
| for Root, Dirs, Files in os.walk(PkgRoot): | |
| if 'CVS' in Dirs: | |
| Dirs.remove('CVS') | |
| if '.svn' in Dirs: | |
| Dirs.remove('.svn') | |
| for Dir in Dirs: | |
| if Dir.startswith('.'): | |
| Dirs.remove(Dir) | |
| for FileSp in Files: | |
| if FileSp.startswith('.'): | |
| continue | |
| Ext = os.path.splitext(FileSp)[1] | |
| if Ext.lower() in ['.dec']: | |
| DecFileList.append\ | |
| (os.path.normpath(os.path.join(Root, FileSp))) | |
| # | |
| # abstract package guid, version info from DecFile List | |
| # | |
| PkgList = [] | |
| for DecFile in DecFileList: | |
| (PkgName, PkgGuid, PkgVersion) = GetPkgInfoFromDec(DecFile) | |
| if PkgName and PkgGuid and PkgVersion: | |
| PkgList.append((PkgName, PkgGuid, PkgVersion, DecFile)) | |
| return PkgList | |
| ## GetWorkspaceModule | |
| # | |
| # Get a list of workspace modules. | |
| # | |
| def GetWorkspaceModule(): | |
| InfFileList = [] | |
| WorkspaceDir = GlobalData.gWORKSPACE | |
| for Root, Dirs, Files in os.walk(WorkspaceDir): | |
| if 'CVS' in Dirs: | |
| Dirs.remove('CVS') | |
| if '.svn' in Dirs: | |
| Dirs.remove('.svn') | |
| if 'Build' in Dirs: | |
| Dirs.remove('Build') | |
| for Dir in Dirs: | |
| if Dir.startswith('.'): | |
| Dirs.remove(Dir) | |
| for FileSp in Files: | |
| if FileSp.startswith('.'): | |
| continue | |
| Ext = os.path.splitext(FileSp)[1] | |
| if Ext.lower() in ['.inf']: | |
| InfFileList.append\ | |
| (os.path.normpath(os.path.join(Root, FileSp))) | |
| return InfFileList | |
| ## MacroParser used to parse macro definition | |
| # | |
| # @param Line: The content contain linestring and line number | |
| # @param FileName: The meta-file file name | |
| # @param SectionType: Section for the Line belong to | |
| # @param FileLocalMacros: A list contain Macro defined in [Defines] section. | |
| # | |
| def MacroParser(Line, FileName, SectionType, FileLocalMacros): | |
| MacroDefPattern = re.compile("^(DEFINE)[ \t]+") | |
| LineContent = Line[0] | |
| LineNo = Line[1] | |
| Match = MacroDefPattern.match(LineContent) | |
| if not Match: | |
| # | |
| # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method | |
| # | |
| return None, None | |
| TokenList = GetSplitValueList(LineContent[Match.end(1):], \ | |
| DataType.TAB_EQUAL_SPLIT, 1) | |
| # | |
| # Syntax check | |
| # | |
| if not TokenList[0]: | |
| Logger.Error('Parser', FORMAT_INVALID, ST.ERR_MACRONAME_NOGIVEN, | |
| ExtraData=LineContent, File=FileName, Line=LineNo) | |
| if len(TokenList) < 2: | |
| Logger.Error('Parser', FORMAT_INVALID, ST.ERR_MACROVALUE_NOGIVEN, | |
| ExtraData=LineContent, File=FileName, Line=LineNo) | |
| Name, Value = TokenList | |
| # | |
| # DEFINE defined macros | |
| # | |
| if SectionType == DataType.MODEL_META_DATA_HEADER: | |
| FileLocalMacros[Name] = Value | |
| ReIsValidMacroName = re.compile(r"^[A-Z][A-Z0-9_]*$", re.DOTALL) | |
| if ReIsValidMacroName.match(Name) == None: | |
| Logger.Error('Parser', | |
| FORMAT_INVALID, | |
| ST.ERR_MACRONAME_INVALID % (Name), | |
| ExtraData=LineContent, | |
| File=FileName, | |
| Line=LineNo) | |
| # Validate MACRO Value | |
| # | |
| # <MacroDefinition> ::= [<Comments>]{0,} | |
| # "DEFINE" <MACRO> "=" [{<PATH>} {<VALUE>}] <EOL> | |
| # <Value> ::= {<NumVal>} {<Boolean>} {<AsciiString>} {<GUID>} | |
| # {<CString>} {<UnicodeString>} {<CArray>} | |
| # | |
| # The definition of <NumVal>, <PATH>, <Boolean>, <GUID>, <CString>, | |
| # <UnicodeString>, <CArray> are subset of <AsciiString>. | |
| # | |
| ReIsValidMacroValue = re.compile(r"^[\x20-\x7e]*$", re.DOTALL) | |
| if ReIsValidMacroValue.match(Value) == None: | |
| Logger.Error('Parser', | |
| FORMAT_INVALID, | |
| ST.ERR_MACROVALUE_INVALID % (Value), | |
| ExtraData=LineContent, | |
| File=FileName, | |
| Line=LineNo) | |
| return Name, Value | |
| ## GenSection | |
| # | |
| # generate section contents | |
| # | |
| # @param SectionName: indicate the name of the section, details refer to | |
| # INF, DEC specs | |
| # @param SectionDict: section statement dict, key is SectionAttrs(arch, | |
| # moduletype or platform may exist as needed) list | |
| # seperated by space, | |
| # value is statement | |
| # | |
| def GenSection(SectionName, SectionDict, SplitArch=True, NeedBlankLine=False): | |
| Content = '' | |
| for SectionAttrs in SectionDict: | |
| StatementList = SectionDict[SectionAttrs] | |
| if SectionAttrs and SectionName != 'Defines' and SectionAttrs.strip().upper() != DataType.TAB_ARCH_COMMON: | |
| if SplitArch: | |
| ArchList = GetSplitValueList(SectionAttrs, DataType.TAB_SPACE_SPLIT) | |
| else: | |
| if SectionName != 'UserExtensions': | |
| ArchList = GetSplitValueList(SectionAttrs, DataType.TAB_COMMENT_SPLIT) | |
| else: | |
| ArchList = [SectionAttrs] | |
| for Index in xrange(0, len(ArchList)): | |
| ArchList[Index] = ConvertArchForInstall(ArchList[Index]) | |
| Section = '[' + SectionName + '.' + (', ' + SectionName + '.').join(ArchList) + ']' | |
| else: | |
| Section = '[' + SectionName + ']' | |
| Content += '\n' + Section + '\n' | |
| if StatementList != None: | |
| for Statement in StatementList: | |
| LineList = Statement.split('\n') | |
| NewStatement = "" | |
| for Line in LineList: | |
| # ignore blank comment | |
| if not Line.replace("#", '').strip() and SectionName not in ('Defines', 'Hob', 'Event', 'BootMode'): | |
| continue | |
| # add two space before non-comments line except the comments in Defines section | |
| if Line.strip().startswith('#') and SectionName == 'Defines': | |
| NewStatement += "%s\n" % Line | |
| continue | |
| NewStatement += " %s\n" % Line | |
| if NeedBlankLine: | |
| Content += NewStatement + '\n' | |
| else: | |
| Content += NewStatement | |
| if NeedBlankLine: | |
| Content = Content[:-1] | |
| if not Content.replace('\\n', '').strip(): | |
| return '' | |
| return Content | |
| ## ConvertArchForInstall | |
| # if Arch.upper() is in "IA32", "X64", "IPF", and "EBC", it must be upper case. "common" must be lower case. | |
| # Anything else, the case must be preserved | |
| # | |
| # @param Arch: the arch string that need to be converted, it should be stripped before pass in | |
| # @return: the arch string that get converted | |
| # | |
| def ConvertArchForInstall(Arch): | |
| if Arch.upper() in [DataType.TAB_ARCH_IA32, DataType.TAB_ARCH_X64, | |
| DataType.TAB_ARCH_IPF, DataType.TAB_ARCH_EBC]: | |
| Arch = Arch.upper() | |
| elif Arch.upper() == DataType.TAB_ARCH_COMMON: | |
| Arch = Arch.lower() | |
| return Arch |