X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=BaseTools%2FSource%2FPython%2FEcc%2FMetaFileWorkspace%2FMetaFileParser.py;h=15765654552378fa7fc9224870130bf4ab2e66de;hb=2e351cbe8e190271b3716284fc1076551d005472;hp=949d067945554cfc60951533056428bf0c0a8235;hpb=1be2ed90a20618d71ddf34b8a07d038da0b36854;p=mirror_edk2.git diff --git a/BaseTools/Source/Python/Ecc/MetaFileWorkspace/MetaFileParser.py b/BaseTools/Source/Python/Ecc/MetaFileWorkspace/MetaFileParser.py index 949d067945..1576565455 100644 --- a/BaseTools/Source/Python/Ecc/MetaFileWorkspace/MetaFileParser.py +++ b/BaseTools/Source/Python/Ecc/MetaFileWorkspace/MetaFileParser.py @@ -1,19 +1,14 @@ ## @file # This file is used to parse meta files # -# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.
-# 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. +# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent # ## # Import Modules # +from __future__ import absolute_import import Common.LongFilePathOs as os import re import time @@ -21,23 +16,25 @@ import copy import Common.EdkLogger as EdkLogger import Common.GlobalData as GlobalData -import EccGlobalData +import Ecc.EccGlobalData as EccGlobalData +import Ecc.EccToolError as EccToolError from CommonDataClass.DataClass import * from Common.DataType import * -from Common.String import * +from Common.StringUtils import * from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData from Common.Expression import * from CommonDataClass.Exceptions import * -from MetaFileTable import MetaFileStorage +from Ecc.MetaFileWorkspace.MetaFileTable import MetaFileStorage from GenFds.FdfParser import FdfParser from Common.LongFilePathSupport import OpenLongFilePath as open +from Common.LongFilePathSupport import CodecOpenLongFilePath ## A decorator used to parse macro definition def ParseMacro(Parser): def MacroParser(self): - Match = gMacroDefPattern.match(self._CurrentLine) + Match = GlobalData.gMacroDefPattern.match(self._CurrentLine) if not Match: # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method Parser(self) @@ -58,7 +55,7 @@ def ParseMacro(Parser): EdkLogger.error('Parser', FORMAT_INVALID, "%s can only be defined via environment variable" % Name, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1) # Only upper case letters, digit and '_' are allowed - if not gMacroNamePattern.match(Name): + if not GlobalData.gMacroNamePattern.match(Name): EdkLogger.error('Parser', FORMAT_INVALID, "The macro name must be in the pattern [A-Z][A-Z0-9_]*", ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1) @@ -66,7 +63,7 @@ def ParseMacro(Parser): self._ItemType = MODEL_META_DATA_DEFINE # DEFINE defined macros if Type == TAB_DSC_DEFINES_DEFINE: - if type(self) == DecParser: + if isinstance(self, DecParser): if MODEL_META_DATA_HEADER in self._SectionType: self._FileLocalMacros[Name] = Value else: @@ -81,7 +78,7 @@ def ParseMacro(Parser): SectionLocalMacros = self._SectionsMacroDict[SectionDictKey] SectionLocalMacros[Name] = Value # EDK_GLOBAL defined macros - elif type(self) != DscParser: + elif not isinstance(self, DscParser): EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used in .dsc file", ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1) elif self._SectionType != MODEL_META_DATA_HEADER: @@ -90,7 +87,7 @@ def ParseMacro(Parser): elif (Name in self._FileLocalMacros) and (self._FileLocalMacros[Name] != Value): EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'", ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1) - + self._ValueList = [Type, Name, Value] return MacroParser @@ -174,6 +171,9 @@ class MetaFileParser(object): self._PostProcessed = False # Different version of meta-file has different way to parse. self._Version = 0 + # UNI object and extra UNI object + self._UniObj = None + self._UniExtraObj = None ## Store the parsed data in table def _Store(self, *Args): @@ -210,7 +210,7 @@ class MetaFileParser(object): # DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)] # def __getitem__(self, DataInfo): - if type(DataInfo) != type(()): + if not isinstance(DataInfo, type(())): DataInfo = (DataInfo,) # Parse the file first, if necessary @@ -223,7 +223,7 @@ class MetaFileParser(object): self.Start() # No specific ARCH or Platform given, use raw data - if self._RawTable and (len(DataInfo) == 1 or DataInfo[1] == None): + if self._RawTable and (len(DataInfo) == 1 or DataInfo[1] is None): return self._RawTable.Query(*DataInfo) # Do post-process if necessary @@ -252,14 +252,22 @@ class MetaFileParser(object): TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT) self._ValueList[0:len(TokenList)] = TokenList # Don't do macro replacement for dsc file at this point - if type(self) != DscParser: + if not isinstance(self, DscParser): Macros = self._Macros self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList] ## Skip unsupported data def _Skip(self): - EdkLogger.warn("Parser", "Unrecognized content", File=self.MetaFile, - Line=self._LineIndex+1, ExtraData=self._CurrentLine); + if self._SectionName == TAB_USER_EXTENSIONS.upper() and self._CurrentLine.upper().endswith('.UNI'): + if EccGlobalData.gConfig.UniCheckHelpInfo == '1' or EccGlobalData.gConfig.UniCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + ExtraUni = self._CurrentLine.strip() + ExtraUniFile = os.path.join(os.path.dirname(self.MetaFile), ExtraUni) + IsModuleUni = self.MetaFile.upper().endswith('.INF') + self._UniExtraObj = UniParser(ExtraUniFile, IsExtraUni=True, IsModuleUni=IsModuleUni) + self._UniExtraObj.Start() + else: + EdkLogger.warn("Parser", "Unrecognized content", File=self.MetaFile, + Line=self._LineIndex + 1, ExtraData=self._CurrentLine); self._ValueList[0:1] = [self._CurrentLine] ## Section header parser @@ -321,15 +329,28 @@ class MetaFileParser(object): self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList] Name, Value = self._ValueList[1], self._ValueList[2] - # Sometimes, we need to make differences between EDK and EDK2 modules + # Sometimes, we need to make differences between EDK and EDK2 modules if Name == 'INF_VERSION': try: self._Version = int(Value, 0) except: EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number", ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1) - - if type(self) == InfParser and self._Version < 0x00010005: + elif Name == 'MODULE_UNI_FILE': + UniFile = os.path.join(os.path.dirname(self.MetaFile), Value) + if os.path.exists(UniFile): + self._UniObj = UniParser(UniFile, IsExtraUni=False, IsModuleUni=True) + self._UniObj.Start() + else: + EdkLogger.error('Parser', FILE_NOT_FOUND, "Module UNI file %s is missing." % Value, + ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1, + RaiseError=False) + elif Name == 'PACKAGE_UNI_FILE': + UniFile = os.path.join(os.path.dirname(self.MetaFile), Value) + if os.path.exists(UniFile): + self._UniObj = UniParser(UniFile, IsExtraUni=False, IsModuleUni=False) + + if isinstance(self, InfParser) and self._Version < 0x00010005: # EDK module allows using defines as macros self._FileLocalMacros[Name] = Value self._Defines[Name] = Value @@ -344,7 +365,7 @@ class MetaFileParser(object): self._ValueList[1] = TokenList2[1] # keys else: self._ValueList[1] = TokenList[0] - if len(TokenList) == 2 and type(self) != DscParser: # value + if len(TokenList) == 2 and not isinstance(self, DscParser): # value self._ValueList[2] = ReplaceMacro(TokenList[1], self._Macros) if self._ValueList[1].count('_') != 4: @@ -364,7 +385,7 @@ class MetaFileParser(object): return Macros - ## Get section Macros that are applicable to current line, which may come from other sections + ## Get section Macros that are applicable to current line, which may come from other sections ## that share the same name while scope is wider def _GetApplicableSectionMacro(self): Macros = {} @@ -433,6 +454,7 @@ class InfParser(MetaFileParser): def Start(self): NmakeLine = '' Content = '' + Usage = '' try: Content = open(str(self.MetaFile), 'r').readlines() except: @@ -446,13 +468,32 @@ class InfParser(MetaFileParser): self.FileID = FileID else: self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_INF) - + # parse the file line by line IsFindBlockComment = False for Index in range(0, len(Content)): + if self._SectionType in [MODEL_EFI_GUID, + MODEL_EFI_PROTOCOL, + MODEL_EFI_PPI, + MODEL_PCD_FIXED_AT_BUILD, + MODEL_PCD_PATCHABLE_IN_MODULE, + MODEL_PCD_FEATURE_FLAG, + MODEL_PCD_DYNAMIC_EX, + MODEL_PCD_DYNAMIC]: + Line = Content[Index].strip() + if Line.startswith(TAB_SPECIAL_COMMENT): + Usage += ' ' + Line[Line.find(TAB_SPECIAL_COMMENT):] + continue + elif Line.startswith(TAB_COMMENT_SPLIT): + continue + elif Line.find(TAB_COMMENT_SPLIT) > 0: + Usage += ' ' + Line[Line.find(TAB_COMMENT_SPLIT):] + Line = Line[:Line.find(TAB_COMMENT_SPLIT)] + else: # skip empty, commented, block commented lines - Line = CleanString(Content[Index], AllowCppStyleComment=True) + Line = CleanString(Content[Index], AllowCppStyleComment=True) + Usage = '' NextLine = '' if Index + 1 < len(Content): NextLine = CleanString(Content[Index + 1]) @@ -515,10 +556,10 @@ class InfParser(MetaFileParser): NmakeLine = '' # section content - self._ValueList = ['','',''] + self._ValueList = ['', '', ''] # parse current line, result will be put in self._ValueList self._SectionParser[self._SectionType](self) - if self._ValueList == None or self._ItemType == MODEL_META_DATA_DEFINE: + if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE: self._ItemType = -1 continue # @@ -526,6 +567,7 @@ class InfParser(MetaFileParser): # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1 # self._ValueList[0] = self._ValueList[0].replace('/', '\\') + Usage = Usage.strip() for Arch, Platform in self._Scope: self._Store(self._SectionType, self._ValueList[0], @@ -539,10 +581,12 @@ class InfParser(MetaFileParser): -1, self._LineIndex+1, -1, - 0 + 0, + Usage ) + Usage = '' if IsFindBlockComment: - EdkLogger.error("Parser", FORMAT_INVALID, "Open block comments (starting with /*) are expected to end with */", + EdkLogger.error("Parser", FORMAT_INVALID, "Open block comments (starting with /*) are expected to end with */", File=self.MetaFile) self._Done() @@ -560,17 +604,6 @@ class InfParser(MetaFileParser): if not Value: continue - if Value.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1: - Value = '$(EDK_SOURCE)' + Value[17:] - if Value.find('$(EFI_SOURCE)') > -1 or Value.find('$(EDK_SOURCE)') > -1: - pass - elif Value.startswith('.'): - pass - elif Value.startswith('$('): - pass - else: - Value = '$(EFI_SOURCE)/' + Value - self._ValueList[Index] = ReplaceMacro(Value, Macros) ## Parse [Sources] section @@ -700,7 +733,6 @@ class DscParser(MetaFileParser): TAB_PCDS_DYNAMIC_EX_HII_NULL.upper() : MODEL_PCD_DYNAMIC_EX_HII, TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_EX_VPD, TAB_COMPONENTS.upper() : MODEL_META_DATA_COMPONENT, - TAB_COMPONENTS_SOURCE_OVERRIDE_PATH.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH, TAB_DSC_DEFINES.upper() : MODEL_META_DATA_HEADER, TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE, TAB_DSC_DEFINES_EDKGLOBAL : MODEL_META_DATA_GLOBAL_DEFINE, @@ -711,6 +743,7 @@ class DscParser(MetaFileParser): TAB_ELSE_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF, TAB_ELSE.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE, TAB_END_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF, + TAB_ERROR.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR, } # Valid names in define section @@ -733,6 +766,10 @@ class DscParser(MetaFileParser): "FIX_LOAD_TOP_MEMORY_ADDRESS" ] + SubSectionDefineKeywords = [ + "FILE_GUID" + ] + SymbolPattern = ValueExpression.SymbolPattern ## Constructor of DscParser @@ -764,7 +801,7 @@ class DscParser(MetaFileParser): # the owner item # self._IdMapping = {-1:-1} - + self.TblFile = EccGlobalData.gDb.TblFile self.FileID = -1 @@ -784,8 +821,8 @@ class DscParser(MetaFileParser): self.FileID = FileID else: self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_DSC) - - + + for Index in range(0, len(Content)): Line = CleanString(Content[Index]) # skip empty line @@ -796,7 +833,7 @@ class DscParser(MetaFileParser): self._LineIndex = Index if self._InSubsection and self._Owner[-1] == -1: self._Owner.append(self._LastItem) - + # section header if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END: self._SectionType = MODEL_META_DATA_SECTION_HEADER @@ -823,7 +860,7 @@ class DscParser(MetaFileParser): self._ValueList = ['', '', ''] self._SectionParser[SectionType](self) - if self._ValueList == None: + if self._ValueList is None: continue # # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1, @@ -866,7 +903,7 @@ class DscParser(MetaFileParser): ## Directive statement parser def _DirectiveParser(self): - self._ValueList = ['','',''] + self._ValueList = ['', '', ''] TokenList = GetSplitValueList(self._CurrentLine, ' ', 1) self._ValueList[0:len(TokenList)] = TokenList @@ -906,7 +943,7 @@ class DscParser(MetaFileParser): elif self._From > 0: EdkLogger.error('Parser', FORMAT_INVALID, "No '!include' allowed in included file", - ExtraData=self._CurrentLine, File=self.MetaFile, + ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1) # @@ -943,7 +980,8 @@ class DscParser(MetaFileParser): if not self._ValueList[2]: EdkLogger.error('Parser', FORMAT_INVALID, "No value specified", ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1) - if not self._ValueList[1] in self.DefineKeywords: + if (not self._ValueList[1] in self.DefineKeywords and + (self._InSubsection and self._ValueList[1] not in self.SubSectionDefineKeywords)): EdkLogger.error('Parser', FORMAT_INVALID, "Unknown keyword found: %s. " "If this is a macro you must " @@ -1027,8 +1065,6 @@ class DscParser(MetaFileParser): self._ValueList[0:len(TokenList)] = TokenList - def _CompponentSourceOverridePathParser(self): - self._ValueList[0] = self._CurrentLine ## [BuildOptions] section parser @ParseMacro @@ -1055,7 +1091,7 @@ class DscParser(MetaFileParser): ## Override parent's method since we'll do all macro replacements in parser def _GetMacros(self): - Macros = dict( [('ARCH','IA32'), ('FAMILY','MSFT'),('TOOL_CHAIN_TAG','VS2008x86'),('TARGET','DEBUG')]) + Macros = dict( [('ARCH', 'IA32'), ('FAMILY', TAB_COMPILER_MSFT), ('TOOL_CHAIN_TAG', 'VS2008x86'), ('TARGET', 'DEBUG')]) Macros.update(self._FileLocalMacros) Macros.update(self._GetApplicableSectionMacro()) Macros.update(GlobalData.gEdkGlobal) @@ -1093,12 +1129,12 @@ class DscParser(MetaFileParser): MODEL_PCD_DYNAMIC_EX_HII : self.__ProcessPcd, MODEL_PCD_DYNAMIC_EX_VPD : self.__ProcessPcd, MODEL_META_DATA_COMPONENT : self.__ProcessComponent, - MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : self.__ProcessSourceOverridePath, MODEL_META_DATA_BUILD_OPTION : self.__ProcessBuildOption, MODEL_UNKNOWN : self._Skip, MODEL_META_DATA_USER_EXTENSION : self._Skip, + MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR : self._Skip, } - + self._RawTable = self._Table self._Table = MetaFileStorage(self._RawTable.Cur, self.MetaFile, MODEL_FILE_DSC, True) self._DirectiveStack = [] @@ -1127,21 +1163,22 @@ class DscParser(MetaFileParser): try: Processer[self._ItemType]() - except EvaluationException, Excpt: - # + except EvaluationException as Excpt: + # # Only catch expression evaluation error here. We need to report # the precise number of line on which the error occurred # - EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt), - File=self._FileWithError, ExtraData=' '.join(self._ValueList), - Line=self._LineIndex+1) - except MacroException, Excpt: + pass +# EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt), +# File=self._FileWithError, ExtraData=' '.join(self._ValueList), +# Line=self._LineIndex+1) + except MacroException as Excpt: EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt), - File=self._FileWithError, ExtraData=' '.join(self._ValueList), + File=self._FileWithError, ExtraData=' '.join(self._ValueList), Line=self._LineIndex+1) - if self._ValueList == None: - continue + if self._ValueList is None: + continue NewOwner = self._IdMapping.get(Owner, -1) self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack)) @@ -1164,11 +1201,11 @@ class DscParser(MetaFileParser): self._IdMapping[Id] = self._LastItem RecordList = self._Table.GetAll() - + self._RawTable.Drop() self._Table.Drop() for Record in RecordList: - EccGlobalData.gDb.TblDsc.Insert(Record[1],Record[2],Record[3],Record[4],Record[5],Record[6],Record[7],Record[8],Record[9],Record[10],Record[11],Record[12],Record[13],Record[14]) + EccGlobalData.gDb.TblDsc.Insert(Record[1], Record[2], Record[3], Record[4], Record[5], Record[6], Record[7], Record[8], Record[9], Record[10], Record[11], Record[12], Record[13], Record[14]) GlobalData.gPlatformDefines.update(self._FileLocalMacros) self._PostProcessed = True self._Content = None @@ -1189,7 +1226,7 @@ class DscParser(MetaFileParser): def __RetrievePcdValue(self): Records = self._RawTable.Query(MODEL_PCD_FEATURE_FLAG, BelongsToItem=-1.0) - for TokenSpaceGuid,PcdName,Value,Dummy2,Dummy3,ID,Line in Records: + for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, ID, Line in Records: Value, DatumType, MaxDatumSize = AnalyzePcdData(Value) # Only use PCD whose value is straitforward (no macro and PCD) if self.SymbolPattern.findall(Value): @@ -1198,20 +1235,20 @@ class DscParser(MetaFileParser): # Don't use PCD with different values. if Name in self._Symbols and self._Symbols[Name] != Value: self._Symbols.pop(Name) - continue + continue self._Symbols[Name] = Value Records = self._RawTable.Query(MODEL_PCD_FIXED_AT_BUILD, BelongsToItem=-1.0) - for TokenSpaceGuid,PcdName,Value,Dummy2,Dummy3,ID,Line in Records: + for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, ID, Line in Records: Value, DatumType, MaxDatumSize = AnalyzePcdData(Value) # Only use PCD whose value is straitforward (no macro and PCD) if self.SymbolPattern.findall(Value): - continue + continue Name = TokenSpaceGuid+'.'+PcdName # Don't use PCD with different values. if Name in self._Symbols and self._Symbols[Name] != Value: self._Symbols.pop(Name) - continue + continue self._Symbols[Name] = Value def __ProcessDefine(self): @@ -1231,13 +1268,13 @@ class DscParser(MetaFileParser): SectionLocalMacros[Name] = Value elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE: GlobalData.gEdkGlobal[Name] = Value - + # # Keyword in [Defines] section can be used as Macros # if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER): self._FileLocalMacros[Name] = Value - + self._ValueList = [Type, Name, Value] def __ProcessDirective(self): @@ -1248,18 +1285,21 @@ class DscParser(MetaFileParser): Macros.update(GlobalData.gGlobalDefines) try: Result = ValueExpression(self._ValueList[1], Macros)() - except SymbolNotFound, Exc: + except SymbolNotFound as Exc: EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1]) Result = False - except WrnExpression, Excpt: - # + except WrnExpression as Excpt: + # # Catch expression evaluation warning here. We need to report # the precise number of line and return the evaluation result # EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt), - File=self._FileWithError, ExtraData=' '.join(self._ValueList), + File=self._FileWithError, ExtraData=' '.join(self._ValueList), Line=self._LineIndex+1) Result = Excpt.result + except BadExpression as Exc: + EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1]) + Result = False if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF, MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF, @@ -1298,21 +1338,12 @@ class DscParser(MetaFileParser): # Allow using system environment variables in path after !include # __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE'] - if "ECP_SOURCE" in GlobalData.gGlobalDefines.keys(): - __IncludeMacros['ECP_SOURCE'] = GlobalData.gGlobalDefines['ECP_SOURCE'] - # - # During GenFds phase call DSC parser, will go into this branch. - # - elif "ECP_SOURCE" in GlobalData.gCommandLineDefines.keys(): - __IncludeMacros['ECP_SOURCE'] = GlobalData.gCommandLineDefines['ECP_SOURCE'] - - __IncludeMacros['EFI_SOURCE'] = GlobalData.gGlobalDefines['EFI_SOURCE'] - __IncludeMacros['EDK_SOURCE'] = GlobalData.gGlobalDefines['EDK_SOURCE'] + # - # Allow using MACROs comes from [Defines] section to keep compatible. + # Allow using MACROs comes from [Defines] section to keep compatible. # __IncludeMacros.update(self._Macros) - + IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True)) # # First search the include file under the same directory as DSC file @@ -1326,14 +1357,14 @@ class DscParser(MetaFileParser): IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace) ErrorCode, ErrorInfo2 = IncludedFile1.Validate() if ErrorCode != 0: - EdkLogger.error('parser', ErrorCode, File=self._FileWithError, + EdkLogger.error('parser', ErrorCode, File=self._FileWithError, Line=self._LineIndex+1, ExtraData=ErrorInfo1 + "\n"+ ErrorInfo2) self._FileWithError = IncludedFile1 IncludedFileTable = MetaFileStorage(self._Table.Cur, IncludedFile1, MODEL_FILE_DSC, True) Owner = self._Content[self._ContentIndex-1][0] - Parser = DscParser(IncludedFile1, self._FileType, IncludedFileTable, + Parser = DscParser(IncludedFile1, self._FileType, IncludedFileTable, Owner=Owner, From=Owner) # set the parser status with current status @@ -1357,7 +1388,7 @@ class DscParser(MetaFileParser): self._Content.pop(self._ContentIndex-1) self._ValueList = None self._ContentIndex -= 1 - + def __ProcessSkuId(self): self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True) for Value in self._ValueList] @@ -1373,32 +1404,29 @@ class DscParser(MetaFileParser): # # PCD value can be an expression # - if len(ValueList) > 1 and ValueList[1] == 'VOID*': - PcdValue = ValueList[0] + if len(ValueList) > 1 and ValueList[1] == TAB_VOID: + PcdValue = ValueList[0] try: ValueList[0] = ValueExpression(PcdValue, self._Macros)(True) - except WrnExpression, Value: - ValueList[0] = Value.result + except WrnExpression as Value: + ValueList[0] = Value.result else: PcdValue = ValueList[-1] try: ValueList[-1] = ValueExpression(PcdValue, self._Macros)(True) - except WrnExpression, Value: + except WrnExpression as Value: ValueList[-1] = Value.result - + if ValueList[-1] == 'True': ValueList[-1] = '1' if ValueList[-1] == 'False': - ValueList[-1] = '0' + ValueList[-1] = '0' self._ValueList[2] = '|'.join(ValueList) def __ProcessComponent(self): self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros) - def __ProcessSourceOverridePath(self): - self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros) - def __ProcessBuildOption(self): self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False) for Value in self._ValueList] @@ -1418,7 +1446,6 @@ class DscParser(MetaFileParser): MODEL_PCD_DYNAMIC_EX_HII : _PcdParser, MODEL_PCD_DYNAMIC_EX_VPD : _PcdParser, MODEL_META_DATA_COMPONENT : _ComponentParser, - MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : _CompponentSourceOverridePathParser, MODEL_META_DATA_BUILD_OPTION : _BuildOptionParser, MODEL_UNKNOWN : MetaFileParser._Skip, MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip, @@ -1488,7 +1515,7 @@ class DecParser(MetaFileParser): self.FileID = FileID else: self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_DEC) - + for Index in range(0, len(Content)): Line, Comment = CleanString2(Content[Index]) self._CurrentLine = Line @@ -1511,9 +1538,9 @@ class DecParser(MetaFileParser): continue # section content - self._ValueList = ['','',''] + self._ValueList = ['', '', ''] self._SectionParser[self._SectionType[0]](self) - if self._ValueList == None or self._ItemType == MODEL_META_DATA_DEFINE: + if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE: self._ItemType = -1 self._Comments = [] continue @@ -1654,9 +1681,10 @@ class DecParser(MetaFileParser): continue else: if GuidValue.startswith('{'): - HexList.append('0x' + str(GuidValue[3:])) + GuidValue = GuidValue.lstrip(' {') + HexList.append('0x' + str(GuidValue[2:])) Index += 1 - self._ValueList[1] = "{ %s, %s, %s, { %s, %s, %s, %s, %s, %s, %s, %s }}" % (HexList[0], HexList[1], HexList[2],HexList[3],HexList[4],HexList[5],HexList[6],HexList[7],HexList[8],HexList[9],HexList[10]) + self._ValueList[1] = "{ %s, %s, %s, { %s, %s, %s, %s, %s, %s, %s, %s }}" % (HexList[0], HexList[1], HexList[2], HexList[3], HexList[4], HexList[5], HexList[6], HexList[7], HexList[8], HexList[9], HexList[10]) else: EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format", ExtraData=self._CurrentLine + \ @@ -1689,19 +1717,19 @@ class DecParser(MetaFileParser): " (.|||)", File=self.MetaFile, Line=self._LineIndex+1) - + ValueRe = re.compile(r'^\s*L?\".*\|.*\"') PtrValue = ValueRe.findall(TokenList[1]) - - # Has VOID* type string, may contain "|" character in the string. + + # Has VOID* type string, may contain "|" character in the string. if len(PtrValue) != 0: ptrValueList = re.sub(ValueRe, '', TokenList[1]) ValueList = GetSplitValueList(ptrValueList) ValueList[0] = PtrValue[0] else: ValueList = GetSplitValueList(TokenList[1]) - - + + # check if there's enough datum information given if len(ValueList) != 3: EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given", @@ -1732,6 +1760,89 @@ class DecParser(MetaFileParser): EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1) + if EccGlobalData.gConfig.UniCheckPCDInfo == '1' or EccGlobalData.gConfig.UniCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': + # check Description, Prompt information + PatternDesc = re.compile('##\s*([\x21-\x7E\s]*)', re.S) + PatternPrompt = re.compile('#\s+@Prompt\s+([\x21-\x7E\s]*)', re.S) + Description = None + Prompt = None + # check @ValidRange, @ValidList and @Expression format valid + ErrorCodeValid = '0x0 <= %s <= 0xFFFFFFFF' + PatternValidRangeIn = '(NOT)?\s*(\d+\s*-\s*\d+|0[xX][a-fA-F0-9]+\s*-\s*0[xX][a-fA-F0-9]+|LT\s*\d+|LT\s*0[xX][a-fA-F0-9]+|GT\s*\d+|GT\s*0[xX][a-fA-F0-9]+|LE\s*\d+|LE\s*0[xX][a-fA-F0-9]+|GE\s*\d+|GE\s*0[xX][a-fA-F0-9]+|XOR\s*\d+|XOR\s*0[xX][a-fA-F0-9]+|EQ\s*\d+|EQ\s*0[xX][a-fA-F0-9]+)' + PatternValidRng = re.compile('^' + '(NOT)?\s*' + PatternValidRangeIn + '$') + for Comment in self._Comments: + Comm = Comment[0].strip() + if not Comm: + continue + if not Description: + Description = PatternDesc.findall(Comm) + if not Prompt: + Prompt = PatternPrompt.findall(Comm) + if Comm[0] == '#': + ValidFormt = Comm.lstrip('#') + ValidFormt = ValidFormt.lstrip() + if ValidFormt[0:11] == '@ValidRange': + ValidFormt = ValidFormt[11:] + ValidFormt = ValidFormt.lstrip() + try: + ErrorCode, Expression = ValidFormt.split('|', 1) + except ValueError: + ErrorCode = '0x0' + Expression = ValidFormt + ErrorCode, Expression = ErrorCode.strip(), Expression.strip() + try: + if not eval(ErrorCodeValid % ErrorCode): + EdkLogger.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0])) + except: + EdkLogger.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0])) + if not PatternValidRng.search(Expression): + EdkLogger.warn('Parser', '@ValidRange Expression(%s) of PCD %s is incorrect format.' % (Expression, TokenList[0])) + if ValidFormt[0:10] == '@ValidList': + ValidFormt = ValidFormt[10:] + ValidFormt = ValidFormt.lstrip() + try: + ErrorCode, Expression = ValidFormt.split('|', 1) + except ValueError: + ErrorCode = '0x0' + Expression = ValidFormt + ErrorCode, Expression = ErrorCode.strip(), Expression.strip() + try: + if not eval(ErrorCodeValid % ErrorCode): + EdkLogger.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0])) + except: + EdkLogger.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0])) + Values = Expression.split(',') + for Value in Values: + Value = Value.strip() + try: + eval(Value) + except: + EdkLogger.warn('Parser', '@ValidList Expression of PCD %s include a invalid value(%s).' % (TokenList[0], Value)) + break + if ValidFormt[0:11] == '@Expression': + ValidFormt = ValidFormt[11:] + ValidFormt = ValidFormt.lstrip() + try: + ErrorCode, Expression = ValidFormt.split('|', 1) + except ValueError: + ErrorCode = '0x0' + Expression = ValidFormt + ErrorCode, Expression = ErrorCode.strip(), Expression.strip() + try: + if not eval(ErrorCodeValid % ErrorCode): + EdkLogger.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0])) + except: + EdkLogger.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0])) + if not Expression: + EdkLogger.warn('Parser', '@Expression Expression of PCD %s is incorrect format.' % TokenList[0]) + if not Description: + EdkLogger.warn('Parser', 'PCD %s Description information is not provided.' % TokenList[0]) + if not Prompt: + EdkLogger.warn('Parser', 'PCD %s Prompt information is not provided.' % TokenList[0]) + # check Description, Prompt localization information + if self._UniObj: + self._UniObj.CheckPcdInfo(TokenList[0]) + if ValueList[0] in ['True', 'true', 'TRUE']: ValueList[0] = '1' elif ValueList[0] in ['False', 'false', 'FALSE']: @@ -1756,29 +1867,18 @@ class DecParser(MetaFileParser): } -## FdfObject -# -# This class defined basic Fdf object which is used by inheriting -# -# @param object: Inherited from object class -# -class FdfObject(object): - def __init__(self): - object.__init__() - ## Fdf # # This class defined the structure used in Fdf object -# -# @param FdfObject: Inherited from FdfObject class +# # @param Filename: Input value for Ffilename of Fdf file, default is None # @param WorkspaceDir: Input value for current workspace directory, default is None # -class Fdf(FdfObject): +class Fdf(object): def __init__(self, Filename = None, IsToDatabase = False, WorkspaceDir = None, Database = None): self.WorkspaceDir = WorkspaceDir self.IsToDatabase = IsToDatabase - + self.Cur = Database.Cur self.TblFile = Database.TblFile self.TblFdf = Database.TblFdf @@ -1788,8 +1888,11 @@ class Fdf(FdfObject): # # Load Fdf file if filename is not None # - if Filename != None: - self.LoadFdfFile(Filename) + if Filename is not None: + try: + self.LoadFdfFile(Filename) + except Exception: + pass # # Insert a FDF file record into database @@ -1802,15 +1905,15 @@ class Fdf(FdfObject): self.FileList[Filename] = FileID return self.FileList[Filename] - - + + ## Load Fdf file # # Load the file if it exists # # @param Filename: Input value for filename of Fdf file # - def LoadFdfFile(self, Filename): + def LoadFdfFile(self, Filename): FileList = [] # # Parse Fdf file @@ -1844,6 +1947,71 @@ class Fdf(FdfObject): BelongsToFile = self.InsertFile(FileName) self.TblFdf.Insert(Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled) +class UniParser(object): + # IsExtraUni defined the UNI file is Module UNI or extra Module UNI + # IsModuleUni defined the UNI file is Module UNI or Package UNI + def __init__(self, FilePath, IsExtraUni=False, IsModuleUni=True): + self.FilePath = FilePath + self.FileName = os.path.basename(FilePath) + self.IsExtraUni = IsExtraUni + self.IsModuleUni = IsModuleUni + self.FileIn = None + self.Missing = [] + self.__read() + + def __read(self): + try: + self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_8').read() + except UnicodeError: + self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_16').read() + except UnicodeError: + self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_16_le').read() + except IOError: + self.FileIn = "" + + def Start(self): + if self.IsModuleUni: + if self.IsExtraUni: + ModuleName = self.CheckKeyValid('STR_PROPERTIES_MODULE_NAME') + self.PrintLog('STR_PROPERTIES_MODULE_NAME', ModuleName) + else: + ModuleAbstract = self.CheckKeyValid('STR_MODULE_ABSTRACT') + self.PrintLog('STR_MODULE_ABSTRACT', ModuleAbstract) + ModuleDescription = self.CheckKeyValid('STR_MODULE_DESCRIPTION') + self.PrintLog('STR_MODULE_DESCRIPTION', ModuleDescription) + else: + if self.IsExtraUni: + PackageName = self.CheckKeyValid('STR_PROPERTIES_PACKAGE_NAME') + self.PrintLog('STR_PROPERTIES_PACKAGE_NAME', PackageName) + else: + PackageAbstract = self.CheckKeyValid('STR_PACKAGE_ABSTRACT') + self.PrintLog('STR_PACKAGE_ABSTRACT', PackageAbstract) + PackageDescription = self.CheckKeyValid('STR_PACKAGE_DESCRIPTION') + self.PrintLog('STR_PACKAGE_DESCRIPTION', PackageDescription) + + def CheckKeyValid(self, Key, Contents=None): + if not Contents: + Contents = self.FileIn + KeyPattern = re.compile('#string\s+%s\s+.*?#language.*?".*?"' % Key, re.S) + if KeyPattern.search(Contents): + return True + return False + + def CheckPcdInfo(self, PcdCName): + PromptKey = 'STR_%s_PROMPT' % PcdCName.replace('.', '_') + PcdPrompt = self.CheckKeyValid(PromptKey) + self.PrintLog(PromptKey, PcdPrompt) + HelpKey = 'STR_%s_HELP' % PcdCName.replace('.', '_') + PcdHelp = self.CheckKeyValid(HelpKey) + self.PrintLog(HelpKey, PcdHelp) + + def PrintLog(self, Key, Value): + if not Value and Key not in self.Missing: + Msg = '%s is missing in the %s file.' % (Key, self.FileName) + EdkLogger.warn('Parser', Msg) + EccGlobalData.gDb.TblReport.Insert(EccToolError.ERROR_GENERAL_CHECK_UNI_HELP_INFO, OtherMsg=Msg, BelongsToTable='File', BelongsToItem=-2) + self.Missing.append(Key) + ## # # This acts like the main() function for the script, unless it is 'import'ed into another