From d0acc87a41d9aa25fe87eb096efa62afacd1f865 Mon Sep 17 00:00:00 2001 From: lgao4 Date: Wed, 7 Dec 2011 06:19:28 +0000 Subject: Sync BaseTool trunk (version r2460) into EDKII BaseTools. The change mainly includes: 1. Support use expression as DSC file PCD value. 2. Update FDF parser to fix bug to get complete macro value. 3. Fix bug to replace SET statement macro and evaluate SET statement PCD value in FDF file. 4. Fix a bug for MACRO defined in conditional block cannot be processed correctly Signed-off-by: lgao4 Reviewed-by: gikidy git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12827 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Source/Python/Workspace/MetaFileParser.py | 169 ++++++++++++++++----- 1 file changed, 127 insertions(+), 42 deletions(-) (limited to 'BaseTools/Source/Python/Workspace/MetaFileParser.py') diff --git a/BaseTools/Source/Python/Workspace/MetaFileParser.py b/BaseTools/Source/Python/Workspace/MetaFileParser.py index d907b11ba1..e26b558de0 100644 --- a/BaseTools/Source/Python/Workspace/MetaFileParser.py +++ b/BaseTools/Source/Python/Workspace/MetaFileParser.py @@ -59,17 +59,29 @@ def ParseMacro(Parser): 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) - self._ItemType = self.DataType[Type] + Value = ReplaceMacro(Value, self._Macros) + if Type in self.DataType: + self._ItemType = self.DataType[Type] + else: + self._ItemType = MODEL_META_DATA_DEFINE # DEFINE defined macros - if self._ItemType == MODEL_META_DATA_DEFINE: - if self._SectionType == MODEL_META_DATA_HEADER: - self._FileLocalMacros[Name] = Value + if Type == TAB_DSC_DEFINES_DEFINE: + # + # First judge whether this DEFINE is in conditional directive statements or not. + # + if type(self) == DscParser and self._InDirective > -1: + pass else: - SectionDictKey = self._SectionType, self._Scope[0][0], self._Scope[0][1] - if SectionDictKey not in self._SectionsMacroDict: - self._SectionsMacroDict[SectionDictKey] = {} - SectionLocalMacros = self._SectionsMacroDict[SectionDictKey] - SectionLocalMacros[Name] = Value + if type(self) == DecParser: + if MODEL_META_DATA_HEADER in self._SectionType: + self._FileLocalMacros[Name] = Value + else: + self._ConstructSectionMacroDict(Name, Value) + elif self._SectionType == MODEL_META_DATA_HEADER: + self._FileLocalMacros[Name] = Value + else: + self._ConstructSectionMacroDict(Name, Value) + # EDK_GLOBAL defined macros elif type(self) != DscParser: EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used in .dsc file", @@ -310,6 +322,7 @@ class MetaFileParser(object): EdkLogger.error('Parser', FORMAT_INVALID, "No value specified", ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1) + 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 if Name == 'INF_VERSION': @@ -319,7 +332,6 @@ class MetaFileParser(object): EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number", ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1) - Value = ReplaceMacro(Value, self._Macros) if type(self) == InfParser and self._Version < 0x00010005: # EDK module allows using defines as macros self._FileLocalMacros[Name] = Value @@ -354,15 +366,59 @@ class MetaFileParser(object): Macros.update(self._GetApplicableSectionMacro()) return Macros + ## Construct section Macro dict + def _ConstructSectionMacroDict(self, Name, Value): + ScopeKey = [(Scope[0], Scope[1]) for Scope in self._Scope] + ScopeKey = tuple(ScopeKey) + SectionDictKey = self._SectionType, ScopeKey + # + # DecParser SectionType is a list, will contain more than one item only in Pcd Section + # As Pcd section macro usage is not alllowed, so here it is safe + # + if type(self) == DecParser: + SectionDictKey = self._SectionType[0], ScopeKey + if SectionDictKey not in self._SectionsMacroDict: + self._SectionsMacroDict[SectionDictKey] = {} + SectionLocalMacros = self._SectionsMacroDict[SectionDictKey] + SectionLocalMacros[Name] = Value ## 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 = {} - for SectionType, Scope1, Scope2 in self._SectionsMacroDict: - if (SectionType == self._SectionType) and (Scope1 == self._Scope[0][0] or Scope1 == "COMMON") and (Scope2 == self._Scope[0][1] or Scope2 == "COMMON"): - Macros.update(self._SectionsMacroDict[(SectionType, Scope1, Scope2)]) + ComComMacroDict = {} + ComSpeMacroDict = {} + SpeSpeMacroDict = {} + + ActiveSectionType = self._SectionType + if type(self) == DecParser: + ActiveSectionType = self._SectionType[0] + + for (SectionType, Scope) in self._SectionsMacroDict: + if SectionType != ActiveSectionType: + continue + + for ActiveScope in self._Scope: + Scope0, Scope1 = ActiveScope[0], ActiveScope[1] + if(Scope0, Scope1) not in Scope: + break + else: + SpeSpeMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)]) + + for ActiveScope in self._Scope: + Scope0, Scope1 = ActiveScope[0], ActiveScope[1] + if(Scope0, Scope1) not in Scope and (Scope0, "COMMON") not in Scope and ("COMMON", Scope1) not in Scope: + break + else: + ComSpeMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)]) + + if ("COMMON", "COMMON") in Scope: + ComComMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)]) + + Macros.update(ComComMacroDict) + Macros.update(ComSpeMacroDict) + Macros.update(SpeSpeMacroDict) return Macros @@ -499,7 +555,8 @@ class InfParser(MetaFileParser): self._ValueList = ['','',''] # parse current line, result will be put in self._ValueList self._SectionParser[self._SectionType](self) - if self._ValueList == None: + if self._ValueList == None or self._ItemType == MODEL_META_DATA_DEFINE: + self._ItemType = -1 continue # # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1, @@ -733,7 +790,12 @@ class DscParser(MetaFileParser): self._DirectiveStack = [] self._DirectiveEvalStack = [] self._Enabled = 1 - + + # + # Specify whether current line is in uncertain condition + # + self._InDirective = -1 + # Final valid replacable symbols self._Symbols = {} # @@ -838,6 +900,13 @@ class DscParser(MetaFileParser): if DirectiveName not in self.DataType: EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName, File=self.MetaFile, Line=self._LineIndex+1) + + if DirectiveName in ['!IF', '!IFDEF', '!IFNDEF']: + self._InDirective += 1 + + if DirectiveName in ['!ENDIF']: + self._InDirective -= 1 + if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '': EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression", File=self.MetaFile, Line=self._LineIndex+1, @@ -923,6 +992,7 @@ class DscParser(MetaFileParser): self._ValueList[0:len(TokenList)] = TokenList ## Parse Edk style of library modules + @ParseMacro def _LibraryInstanceParser(self): self._ValueList[0] = self._CurrentLine @@ -1146,27 +1216,13 @@ class DscParser(MetaFileParser): Records = self._RawTable.Query(MODEL_PCD_FEATURE_FLAG, BelongsToItem=-1.0) 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 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 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: Value, DatumType, MaxDatumSize = AnalyzePcdData(Value) - # Only use PCD whose value is straitforward (no macro and PCD) - if self.SymbolPattern.findall(Value): - 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 + Name = TokenSpaceGuid + '.' + PcdName self._Symbols[Name] = Value def __ProcessDefine(self): @@ -1179,11 +1235,7 @@ class DscParser(MetaFileParser): if self._SectionType == MODEL_META_DATA_HEADER: self._FileLocalMacros[Name] = Value else: - SectionDictKey = self._SectionType, self._Scope[0][0], self._Scope[0][1] - if SectionDictKey not in self._SectionsMacroDict: - self._SectionsMacroDict[SectionDictKey] = {} - SectionLocalMacros = self._SectionsMacroDict[SectionDictKey] - SectionLocalMacros[Name] = Value + self._ConstructSectionMacroDict(Name, Value) elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE: GlobalData.gEdkGlobal[Name] = Value @@ -1234,8 +1286,9 @@ class DscParser(MetaFileParser): self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1] self._DirectiveEvalStack.append(bool(Result)) elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE: - self._DirectiveStack[-1] = self._ItemType + self._DirectiveStack.append(self._ItemType) self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1] + self._DirectiveEvalStack.append(True) elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF: # Back to the nearest !if/!ifdef/!ifndef while self._DirectiveStack: @@ -1243,7 +1296,6 @@ class DscParser(MetaFileParser): Directive = self._DirectiveStack.pop() if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF, MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF, - MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE, MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]: break elif self._ItemType == MODEL_META_DATA_INCLUDE: @@ -1324,13 +1376,43 @@ class DscParser(MetaFileParser): self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True) def __ProcessPcd(self): + PcdValue = None ValueList = GetSplitValueList(self._ValueList[2]) + # + # PCD value can be an expression + # if len(ValueList) > 1 and ValueList[1] == 'VOID*': - PcdValue = ValueList[0] - ValueList[0] = ReplaceMacro(PcdValue, self._Macros) + PcdValue = ValueList[0] + try: + ValueList[0] = ValueExpression(PcdValue, self._Macros)(True) + except WrnExpression, Value: + ValueList[0] = Value.result else: - PcdValue = ValueList[-1] - ValueList[-1] = ReplaceMacro(PcdValue, self._Macros) + # + # Int*/Boolean VPD PCD + # TokenSpace | PcdCName | Offset | [Value] + # + # VOID* VPD PCD + # TokenSpace | PcdCName | Offset | [Size] | [Value] + # + if self._ItemType == MODEL_PCD_DYNAMIC_VPD: + if len(ValueList) >= 4: + PcdValue = ValueList[-1] + else: + PcdValue = ValueList[-1] + # + # For the VPD PCD, there may not have PcdValue data in DSC file + # + if PcdValue: + try: + ValueList[-1] = ValueExpression(PcdValue, self._Macros)(True) + except WrnExpression, Value: + ValueList[-1] = Value.result + + if ValueList[-1] == 'True': + ValueList[-1] = '1' + if ValueList[-1] == 'False': + ValueList[-1] = '0' self._ValueList[2] = '|'.join(ValueList) @@ -1380,6 +1462,7 @@ class DecParser(MetaFileParser): # DEC file supported data types (one type per section) DataType = { TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER, + TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE, TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE, TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS, TAB_GUIDS.upper() : MODEL_EFI_GUID, @@ -1441,7 +1524,8 @@ class DecParser(MetaFileParser): # section content self._ValueList = ['','',''] self._SectionParser[self._SectionType[0]](self) - if self._ValueList == None: + if self._ValueList == None or self._ItemType == MODEL_META_DATA_DEFINE: + self._ItemType = -1 self._Comments = [] continue @@ -1482,6 +1566,7 @@ class DecParser(MetaFileParser): self._Comments = [] self._Done() + ## Section header parser # # The section header is always in following format: -- cgit v1.2.3