https://bugzilla.tianocore.org/show_bug.cgi?id=1373 Replace BSD 2-Clause License with BSD+Patent License. This change is based on the following emails: https://lists.01.org/pipermail/edk2-devel/2019-February/036260.html https://lists.01.org/pipermail/edk2-devel/2018-October/030385.html RFCs with detailed process for the license change: V3: https://lists.01.org/pipermail/edk2-devel/2019-March/038116.html V2: https://lists.01.org/pipermail/edk2-devel/2019-March/037669.html V1: https://lists.01.org/pipermail/edk2-devel/2019-March/037500.html Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Bob Feng <bob.c.feng@intel.com>
		
			
				
	
	
		
			1092 lines
		
	
	
		
			43 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			1092 lines
		
	
	
		
			43 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| ## @file
 | |
| # This file is used to parse DEC file. It will consumed by DecParser
 | |
| #
 | |
| # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
 | |
| #
 | |
| # SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| '''
 | |
| DecParser
 | |
| '''
 | |
| ## Import modules
 | |
| #
 | |
| import Logger.Log as Logger
 | |
| from Logger.ToolError import FILE_PARSE_FAILURE
 | |
| from Logger.ToolError import FILE_OPEN_FAILURE
 | |
| from Logger import StringTable as ST
 | |
| from Logger.ToolError import FORMAT_INVALID
 | |
| 
 | |
| import Library.DataType as DT
 | |
| from Library.ParserValidate import IsValidToken
 | |
| from Library.ParserValidate import IsValidPath
 | |
| from Library.ParserValidate import IsValidCFormatGuid
 | |
| from Library.ParserValidate import IsValidIdString
 | |
| from Library.ParserValidate import IsValidUserId
 | |
| from Library.ParserValidate import IsValidArch
 | |
| from Library.ParserValidate import IsValidWord
 | |
| from Library.ParserValidate import IsValidDecVersionVal
 | |
| from Parser.DecParserMisc import TOOL_NAME
 | |
| from Parser.DecParserMisc import CleanString
 | |
| from Parser.DecParserMisc import IsValidPcdDatum
 | |
| from Parser.DecParserMisc import ParserHelper
 | |
| from Parser.DecParserMisc import StripRoot
 | |
| from Parser.DecParserMisc import VERSION_PATTERN
 | |
| from Parser.DecParserMisc import CVAR_PATTERN
 | |
| from Parser.DecParserMisc import PCD_TOKEN_PATTERN
 | |
| from Parser.DecParserMisc import MACRO_PATTERN
 | |
| from Parser.DecParserMisc import FileContent
 | |
| from Object.Parser.DecObject import _DecComments
 | |
| from Object.Parser.DecObject import DecDefineObject
 | |
| from Object.Parser.DecObject import DecDefineItemObject
 | |
| from Object.Parser.DecObject import DecIncludeObject
 | |
| from Object.Parser.DecObject import DecIncludeItemObject
 | |
| from Object.Parser.DecObject import DecLibraryclassObject
 | |
| from Object.Parser.DecObject import DecLibraryclassItemObject
 | |
| from Object.Parser.DecObject import DecGuidObject
 | |
| from Object.Parser.DecObject import DecPpiObject
 | |
| from Object.Parser.DecObject import DecProtocolObject
 | |
| from Object.Parser.DecObject import DecGuidItemObject
 | |
| from Object.Parser.DecObject import DecUserExtensionObject
 | |
| from Object.Parser.DecObject import DecUserExtensionItemObject
 | |
| from Object.Parser.DecObject import DecPcdObject
 | |
| from Object.Parser.DecObject import DecPcdItemObject
 | |
| from Library.Misc import GuidStructureStringToGuidString
 | |
| from Library.Misc import CheckGuidRegFormat
 | |
| from Library.StringUtils import ReplaceMacro
 | |
| from Library.StringUtils import GetSplitValueList
 | |
| from Library.StringUtils import gMACRO_PATTERN
 | |
| from Library.StringUtils import ConvertSpecialChar
 | |
| from Library.CommentParsing import ParsePcdErrorCode
 | |
| 
 | |
| ##
 | |
| # _DecBase class for parsing
 | |
| #
 | |
| class _DecBase:
 | |
|     def __init__(self, RawData):
 | |
|         self._RawData = RawData
 | |
|         self._ItemDict = {}
 | |
|         self._LocalMacro = {}
 | |
|         #
 | |
|         # Data parsed by 'self' are saved to this object
 | |
|         #
 | |
|         self.ItemObject = None
 | |
| 
 | |
|     def GetDataObject(self):
 | |
|         return self.ItemObject
 | |
| 
 | |
|     def GetLocalMacro(self):
 | |
|         return self._LocalMacro
 | |
| 
 | |
|     ## BlockStart
 | |
|     #
 | |
|     # Called if a new section starts
 | |
|     #
 | |
|     def BlockStart(self):
 | |
|         self._LocalMacro = {}
 | |
| 
 | |
|     ## _CheckReDefine
 | |
|     #
 | |
|     # @param Key: to be checked if multi-defined
 | |
|     # @param Scope: Format: [[SectionName, Arch], ...].
 | |
|     #               If scope is none, use global scope
 | |
|     #
 | |
|     def _CheckReDefine(self, Key, Scope = None):
 | |
|         if not Scope:
 | |
|             Scope = self._RawData.CurrentScope
 | |
|             return
 | |
| 
 | |
|         SecArch = []
 | |
|         #
 | |
|         # Copy scope to SecArch, avoid Scope be changed outside
 | |
|         #
 | |
|         SecArch[0:1] = Scope[:]
 | |
|         if Key not in self._ItemDict:
 | |
|             self._ItemDict[Key] = [[SecArch, self._RawData.LineIndex]]
 | |
|             return
 | |
| 
 | |
|         for Value in self._ItemDict[Key]:
 | |
|             for SubValue in Scope:
 | |
|                 #
 | |
|                 # If current is common section
 | |
|                 #
 | |
|                 if SubValue[-1] == 'COMMON':
 | |
|                     for Other in Value[0]:
 | |
|                         # Key in common cannot be redefined in other arches
 | |
|                         # [:-1] means stripping arch info
 | |
|                         if Other[:-1] == SubValue[:-1]:
 | |
|                             self._LoggerError(ST.ERR_DECPARSE_REDEFINE % (Key, Value[1]))
 | |
|                             return
 | |
|                     continue
 | |
|                 CommonScope = []
 | |
|                 CommonScope[0:1] = SubValue
 | |
|                 CommonScope[-1] = 'COMMON'
 | |
|                 #
 | |
|                 # Cannot be redefined if this key already defined in COMMON Or defined in same arch
 | |
|                 #
 | |
|                 if SubValue in Value[0] or CommonScope in Value[0]:
 | |
|                     self._LoggerError(ST.ERR_DECPARSE_REDEFINE % (Key, Value[1]))
 | |
|                     return
 | |
|         self._ItemDict[Key].append([SecArch, self._RawData.LineIndex])
 | |
| 
 | |
|     ## CheckRequiredFields
 | |
|     # Some sections need to check if some fields exist, define section for example
 | |
|     # Derived class can re-implement, top parser will call this function after all parsing done
 | |
|     #
 | |
|     def CheckRequiredFields(self):
 | |
|         if self._RawData:
 | |
|             pass
 | |
|         return True
 | |
| 
 | |
|     ## IsItemRequired
 | |
|     # In DEC spec, sections must have at least one statement except user
 | |
|     # extension.
 | |
|     # For example: "[guids" [<attribs>] "]" <EOL> <statements>+
 | |
|     # sub class can override this method to indicate if statement is a must.
 | |
|     #
 | |
|     def _IsStatementRequired(self):
 | |
|         if self._RawData:
 | |
|             pass
 | |
|         return False
 | |
| 
 | |
|     def _LoggerError(self, ErrorString):
 | |
|         Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename,
 | |
|                      Line = self._RawData.LineIndex,
 | |
|                      ExtraData=ErrorString + ST.ERR_DECPARSE_LINE % self._RawData.CurrentLine)
 | |
| 
 | |
|     def _ReplaceMacro(self, String):
 | |
|         if gMACRO_PATTERN.findall(String):
 | |
|             String = ReplaceMacro(String, self._LocalMacro, False,
 | |
|                                   FileName = self._RawData.Filename,
 | |
|                                   Line = ['', self._RawData.LineIndex])
 | |
|             String = ReplaceMacro(String, self._RawData.Macros, False,
 | |
|                                   FileName = self._RawData.Filename,
 | |
|                                   Line = ['', self._RawData.LineIndex])
 | |
|             MacroUsed = gMACRO_PATTERN.findall(String)
 | |
|             if MacroUsed:
 | |
|                 Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE,
 | |
|                              File=self._RawData.Filename,
 | |
|                              Line = self._RawData.LineIndex,
 | |
|                              ExtraData = ST.ERR_DECPARSE_MACRO_RESOLVE % (str(MacroUsed), String))
 | |
|         return String
 | |
| 
 | |
|     def _MacroParser(self, String):
 | |
|         TokenList = GetSplitValueList(String, ' ', 1)
 | |
|         if len(TokenList) < 2 or TokenList[1] == '':
 | |
|             self._LoggerError(ST.ERR_DECPARSE_MACRO_PAIR)
 | |
| 
 | |
|         TokenList = GetSplitValueList(TokenList[1], DT.TAB_EQUAL_SPLIT, 1)
 | |
|         if TokenList[0] == '':
 | |
|             self._LoggerError(ST.ERR_DECPARSE_MACRO_NAME)
 | |
|         elif not IsValidToken(MACRO_PATTERN, TokenList[0]):
 | |
|             self._LoggerError(ST.ERR_DECPARSE_MACRO_NAME_UPPER % TokenList[0])
 | |
| 
 | |
|         if len(TokenList) == 1:
 | |
|             self._LocalMacro[TokenList[0]] = ''
 | |
|         else:
 | |
|             self._LocalMacro[TokenList[0]] = self._ReplaceMacro(TokenList[1])
 | |
| 
 | |
|     ## _ParseItem
 | |
|     #
 | |
|     # Parse specified item, this function must be derived by subclass
 | |
|     #
 | |
|     def _ParseItem(self):
 | |
|         if self._RawData:
 | |
|             pass
 | |
|         #
 | |
|         # Should never be called
 | |
|         #
 | |
|         return None
 | |
| 
 | |
| 
 | |
|     ## _TailCommentStrategy
 | |
|     #
 | |
|     # This function can be derived to parse tail comment
 | |
|     # default is it will not consume any lines
 | |
|     #
 | |
|     # @param Comment: Comment of current line
 | |
|     #
 | |
|     def _TailCommentStrategy(self, Comment):
 | |
|         if Comment:
 | |
|             pass
 | |
|         if self._RawData:
 | |
|             pass
 | |
|         return False
 | |
| 
 | |
|     ## _StopCurrentParsing
 | |
|     #
 | |
|     # Called in Parse if current parsing should be stopped when encounter some
 | |
|     # keyword
 | |
|     # Default is section start and end
 | |
|     #
 | |
|     # @param Line: Current line
 | |
|     #
 | |
|     def _StopCurrentParsing(self, Line):
 | |
|         if self._RawData:
 | |
|             pass
 | |
|         return Line[0] == DT.TAB_SECTION_START and Line[-1] == DT.TAB_SECTION_END
 | |
| 
 | |
|     ## _TryBackSlash
 | |
|     #
 | |
|     # Split comment and DEC content, concatenate lines if end of char is '\'
 | |
|     #
 | |
|     # @param ProcessedLine: ProcessedLine line
 | |
|     # @param ProcessedComments: ProcessedComments line
 | |
|     #
 | |
|     def _TryBackSlash(self, ProcessedLine, ProcessedComments):
 | |
|         CatLine = ''
 | |
|         Comment = ''
 | |
|         Line = ProcessedLine
 | |
|         CommentList = ProcessedComments
 | |
|         while not self._RawData.IsEndOfFile():
 | |
|             if Line == '':
 | |
|                 self._LoggerError(ST.ERR_DECPARSE_BACKSLASH_EMPTY)
 | |
|                 break
 | |
| 
 | |
|             if Comment:
 | |
|                 CommentList.append((Comment, self._RawData.LineIndex))
 | |
|             if Line[-1] != DT.TAB_SLASH:
 | |
|                 CatLine += Line
 | |
|                 break
 | |
|             elif len(Line) < 2 or Line[-2] != ' ':
 | |
|                 self._LoggerError(ST.ERR_DECPARSE_BACKSLASH)
 | |
|             else:
 | |
|                 CatLine += Line[:-1]
 | |
|                 Line, Comment = CleanString(self._RawData.GetNextLine())
 | |
|         #
 | |
|         # Reach end of content
 | |
|         #
 | |
|         if self._RawData.IsEndOfFile():
 | |
|             if not CatLine:
 | |
|                 if ProcessedLine[-1] == DT.TAB_SLASH:
 | |
|                     self._LoggerError(ST.ERR_DECPARSE_BACKSLASH_EMPTY)
 | |
|                 CatLine = ProcessedLine
 | |
|             else:
 | |
|                 if not Line or Line[-1] == DT.TAB_SLASH:
 | |
|                     self._LoggerError(ST.ERR_DECPARSE_BACKSLASH_EMPTY)
 | |
|                 CatLine += Line
 | |
| 
 | |
|         #
 | |
|         # All MACRO values defined by the DEFINE statements in any section
 | |
|         # (except [Userextensions] sections for Intel) of the INF or DEC file
 | |
|         # must be expanded before processing of the file.
 | |
|         #
 | |
|         __IsReplaceMacro = True
 | |
|         Header = self._RawData.CurrentScope[0] if self._RawData.CurrentScope else None
 | |
|         if Header and len(Header) > 2:
 | |
|             if Header[0].upper() == 'USEREXTENSIONS' and not (Header[1] == 'TianoCore' and Header[2] == '"ExtraFiles"'):
 | |
|                 __IsReplaceMacro = False
 | |
|         if __IsReplaceMacro:
 | |
|             self._RawData.CurrentLine = self._ReplaceMacro(CatLine)
 | |
|         else:
 | |
|             self._RawData.CurrentLine = CatLine
 | |
| 
 | |
|         return CatLine, CommentList
 | |
| 
 | |
|     ## Parse
 | |
|     # This is a template method in which other member functions which might
 | |
|     # override by sub class are called. It is responsible for reading file
 | |
|     # line by line, and call other member functions to parse. This function
 | |
|     # should not be re-implement by sub class.
 | |
|     #
 | |
|     def Parse(self):
 | |
|         HeadComments = []
 | |
|         TailComments = []
 | |
| 
 | |
|         #======================================================================
 | |
|         # CurComments may pointer to HeadComments or TailComments
 | |
|         #======================================================================
 | |
|         CurComments = HeadComments
 | |
|         CurObj = None
 | |
|         ItemNum = 0
 | |
|         FromBuf = False
 | |
| 
 | |
|         #======================================================================
 | |
|         # Used to report error information if empty section found
 | |
|         #======================================================================
 | |
|         Index = self._RawData.LineIndex
 | |
|         LineStr = self._RawData.CurrentLine
 | |
|         while not self._RawData.IsEndOfFile() or self._RawData.NextLine:
 | |
|             if self._RawData.NextLine:
 | |
|                 #==============================================================
 | |
|                 # Have processed line in buffer
 | |
|                 #==============================================================
 | |
|                 Line = self._RawData.NextLine
 | |
|                 HeadComments.extend(self._RawData.HeadComment)
 | |
|                 TailComments.extend(self._RawData.TailComment)
 | |
|                 self._RawData.ResetNext()
 | |
|                 Comment = ''
 | |
|                 FromBuf = True
 | |
|             else:
 | |
|                 #==============================================================
 | |
|                 # No line in buffer, read next line
 | |
|                 #==============================================================
 | |
|                 Line, Comment = CleanString(self._RawData.GetNextLine())
 | |
|                 FromBuf = False
 | |
|             if Line:
 | |
|                 if not FromBuf and CurObj and TailComments:
 | |
|                     #==========================================================
 | |
|                     # Set tail comments to previous statement if not empty.
 | |
|                     #==========================================================
 | |
|                     CurObj.SetTailComment(CurObj.GetTailComment()+TailComments)
 | |
| 
 | |
|                 if not FromBuf:
 | |
|                     del TailComments[:]
 | |
|                 CurComments = TailComments
 | |
|                 Comments = []
 | |
|                 if Comment:
 | |
|                     Comments = [(Comment, self._RawData.LineIndex)]
 | |
| 
 | |
|                 #==============================================================
 | |
|                 # Try if last char of line has backslash
 | |
|                 #==============================================================
 | |
|                 Line, Comments = self._TryBackSlash(Line, Comments)
 | |
|                 CurComments.extend(Comments)
 | |
| 
 | |
|                 #==============================================================
 | |
|                 # Macro found
 | |
|                 #==============================================================
 | |
|                 if Line.startswith('DEFINE '):
 | |
|                     self._MacroParser(Line)
 | |
|                     del HeadComments[:]
 | |
|                     del TailComments[:]
 | |
|                     CurComments = HeadComments
 | |
|                     continue
 | |
| 
 | |
|                 if self._StopCurrentParsing(Line):
 | |
|                     #==========================================================
 | |
|                     # This line does not belong to this parse,
 | |
|                     # Save it, can be used by next parse
 | |
|                     #==========================================================
 | |
|                     self._RawData.SetNext(Line, HeadComments, TailComments)
 | |
|                     break
 | |
| 
 | |
|                 Obj = self._ParseItem()
 | |
|                 ItemNum += 1
 | |
|                 if Obj:
 | |
|                     Obj.SetHeadComment(Obj.GetHeadComment()+HeadComments)
 | |
|                     Obj.SetTailComment(Obj.GetTailComment()+TailComments)
 | |
|                     del HeadComments[:]
 | |
|                     del TailComments[:]
 | |
|                     CurObj = Obj
 | |
|                 else:
 | |
|                     CurObj = None
 | |
|             else:
 | |
|                 if id(CurComments) == id(TailComments):
 | |
|                     #==========================================================
 | |
|                     # Check if this comment belongs to tail comment
 | |
|                     #==========================================================
 | |
|                     if not self._TailCommentStrategy(Comment):
 | |
|                         CurComments = HeadComments
 | |
| 
 | |
|                 if Comment:
 | |
|                     CurComments.append(((Comment, self._RawData.LineIndex)))
 | |
|                 else:
 | |
|                     del CurComments[:]
 | |
| 
 | |
|         if self._IsStatementRequired() and ItemNum == 0:
 | |
|             Logger.Error(
 | |
|                     TOOL_NAME, FILE_PARSE_FAILURE,
 | |
|                     File=self._RawData.Filename,
 | |
|                     Line=Index,
 | |
|                     ExtraData=ST.ERR_DECPARSE_STATEMENT_EMPTY % LineStr
 | |
|             )
 | |
| 
 | |
| ## _DecDefine
 | |
| # Parse define section
 | |
| #
 | |
| class _DecDefine(_DecBase):
 | |
|     def __init__(self, RawData):
 | |
|         _DecBase.__init__(self, RawData)
 | |
|         self.ItemObject = DecDefineObject(RawData.Filename)
 | |
|         self._LocalMacro = self._RawData.Macros
 | |
|         self._DefSecNum = 0
 | |
| 
 | |
|         #
 | |
|         # Each field has a function to validate
 | |
|         #
 | |
|         self.DefineValidation = {
 | |
|             DT.TAB_DEC_DEFINES_DEC_SPECIFICATION   :   self._SetDecSpecification,
 | |
|             DT.TAB_DEC_DEFINES_PACKAGE_NAME        :   self._SetPackageName,
 | |
|             DT.TAB_DEC_DEFINES_PACKAGE_GUID        :   self._SetPackageGuid,
 | |
|             DT.TAB_DEC_DEFINES_PACKAGE_VERSION     :   self._SetPackageVersion,
 | |
|             DT.TAB_DEC_DEFINES_PKG_UNI_FILE        :   self._SetPackageUni,
 | |
|         }
 | |
| 
 | |
|     def BlockStart(self):
 | |
|         self._DefSecNum += 1
 | |
|         if self._DefSecNum > 1:
 | |
|             self._LoggerError(ST.ERR_DECPARSE_DEFINE_MULTISEC)
 | |
| 
 | |
|     ## CheckRequiredFields
 | |
|     #
 | |
|     # Check required fields: DEC_SPECIFICATION, PACKAGE_NAME
 | |
|     #                        PACKAGE_GUID, PACKAGE_VERSION
 | |
|     #
 | |
|     def CheckRequiredFields(self):
 | |
|         Ret = False
 | |
|         if self.ItemObject.GetPackageSpecification() == '':
 | |
|             Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename,
 | |
|                          ExtraData=ST.ERR_DECPARSE_DEFINE_REQUIRED % DT.TAB_DEC_DEFINES_DEC_SPECIFICATION)
 | |
|         elif self.ItemObject.GetPackageName() == '':
 | |
|             Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename,
 | |
|                          ExtraData=ST.ERR_DECPARSE_DEFINE_REQUIRED % DT.TAB_DEC_DEFINES_PACKAGE_NAME)
 | |
|         elif self.ItemObject.GetPackageGuid() == '':
 | |
|             Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename,
 | |
|                          ExtraData=ST.ERR_DECPARSE_DEFINE_REQUIRED % DT.TAB_DEC_DEFINES_PACKAGE_GUID)
 | |
|         elif self.ItemObject.GetPackageVersion() == '':
 | |
|             Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename,
 | |
|                          ExtraData=ST.ERR_DECPARSE_DEFINE_REQUIRED % DT.TAB_DEC_DEFINES_PACKAGE_VERSION)
 | |
|         else:
 | |
|             Ret = True
 | |
|         return Ret
 | |
| 
 | |
|     def _ParseItem(self):
 | |
|         Line = self._RawData.CurrentLine
 | |
|         TokenList = GetSplitValueList(Line, DT.TAB_EQUAL_SPLIT, 1)
 | |
|         if TokenList[0] == DT.TAB_DEC_DEFINES_PKG_UNI_FILE:
 | |
|             self.DefineValidation[TokenList[0]](TokenList[1])
 | |
|         elif len(TokenList) < 2:
 | |
|             self._LoggerError(ST.ERR_DECPARSE_DEFINE_FORMAT)
 | |
|         elif TokenList[0] not in self.DefineValidation:
 | |
|             self._LoggerError(ST.ERR_DECPARSE_DEFINE_UNKNOWKEY % TokenList[0])
 | |
|         else:
 | |
|             self.DefineValidation[TokenList[0]](TokenList[1])
 | |
| 
 | |
|         DefineItem = DecDefineItemObject()
 | |
|         DefineItem.Key   = TokenList[0]
 | |
|         DefineItem.Value = TokenList[1]
 | |
|         self.ItemObject.AddItem(DefineItem, self._RawData.CurrentScope)
 | |
|         return DefineItem
 | |
| 
 | |
|     def _SetDecSpecification(self, Token):
 | |
|         if self.ItemObject.GetPackageSpecification():
 | |
|             self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_DEC_SPECIFICATION)
 | |
|         if not IsValidToken('0[xX][0-9a-fA-F]{8}', Token):
 | |
|             if not IsValidDecVersionVal(Token):
 | |
|                 self._LoggerError(ST.ERR_DECPARSE_DEFINE_SPEC)
 | |
|         self.ItemObject.SetPackageSpecification(Token)
 | |
| 
 | |
|     def _SetPackageName(self, Token):
 | |
|         if self.ItemObject.GetPackageName():
 | |
|             self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_PACKAGE_NAME)
 | |
|         if not IsValidWord(Token):
 | |
|             self._LoggerError(ST.ERR_DECPARSE_DEFINE_PKGNAME)
 | |
|         self.ItemObject.SetPackageName(Token)
 | |
| 
 | |
|     def _SetPackageGuid(self, Token):
 | |
|         if self.ItemObject.GetPackageGuid():
 | |
|             self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_PACKAGE_GUID)
 | |
|         if not CheckGuidRegFormat(Token):
 | |
|             self._LoggerError(ST.ERR_DECPARSE_DEFINE_PKGGUID)
 | |
|         self.ItemObject.SetPackageGuid(Token)
 | |
| 
 | |
|     def _SetPackageVersion(self, Token):
 | |
|         if self.ItemObject.GetPackageVersion():
 | |
|             self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_PACKAGE_VERSION)
 | |
|         if not IsValidToken(VERSION_PATTERN, Token):
 | |
|             self._LoggerError(ST.ERR_DECPARSE_DEFINE_PKGVERSION)
 | |
|         else:
 | |
|             if not DT.TAB_SPLIT in Token:
 | |
|                 Token = Token + '.0'
 | |
|             self.ItemObject.SetPackageVersion(Token)
 | |
| 
 | |
|     def _SetPackageUni(self, Token):
 | |
|         if self.ItemObject.GetPackageUniFile():
 | |
|             self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_PKG_UNI_FILE)
 | |
|         self.ItemObject.SetPackageUniFile(Token)
 | |
| 
 | |
| ## _DecInclude
 | |
| #
 | |
| # Parse include section
 | |
| #
 | |
| class _DecInclude(_DecBase):
 | |
|     def __init__(self, RawData):
 | |
|         _DecBase.__init__(self, RawData)
 | |
|         self.ItemObject = DecIncludeObject(RawData.Filename)
 | |
| 
 | |
|     def _ParseItem(self):
 | |
|         Line = self._RawData.CurrentLine
 | |
| 
 | |
|         if not IsValidPath(Line, self._RawData.PackagePath):
 | |
|             self._LoggerError(ST.ERR_DECPARSE_INCLUDE % Line)
 | |
| 
 | |
|         Item = DecIncludeItemObject(StripRoot(self._RawData.PackagePath, Line), self._RawData.PackagePath)
 | |
|         self.ItemObject.AddItem(Item, self._RawData.CurrentScope)
 | |
|         return Item
 | |
| 
 | |
| ## _DecLibraryclass
 | |
| #
 | |
| # Parse library class section
 | |
| #
 | |
| class _DecLibraryclass(_DecBase):
 | |
|     def __init__(self, RawData):
 | |
|         _DecBase.__init__(self, RawData)
 | |
|         self.ItemObject = DecLibraryclassObject(RawData.Filename)
 | |
| 
 | |
|     def _ParseItem(self):
 | |
|         Line = self._RawData.CurrentLine
 | |
|         TokenList = GetSplitValueList(Line, DT.TAB_VALUE_SPLIT)
 | |
|         if len(TokenList) != 2:
 | |
|             self._LoggerError(ST.ERR_DECPARSE_LIBCLASS_SPLIT)
 | |
|         if TokenList[0] == '' or TokenList[1] == '':
 | |
|             self._LoggerError(ST.ERR_DECPARSE_LIBCLASS_EMPTY)
 | |
|         if not IsValidToken('[A-Z][0-9A-Za-z]*', TokenList[0]):
 | |
|             self._LoggerError(ST.ERR_DECPARSE_LIBCLASS_LIB)
 | |
| 
 | |
|         self._CheckReDefine(TokenList[0])
 | |
| 
 | |
|         Value = TokenList[1]
 | |
|         #
 | |
|         # Must end with .h
 | |
|         #
 | |
|         if not Value.endswith('.h'):
 | |
|             self._LoggerError(ST.ERR_DECPARSE_LIBCLASS_PATH_EXT)
 | |
| 
 | |
|         #
 | |
|         # Path must be existed
 | |
|         #
 | |
|         if not IsValidPath(Value, self._RawData.PackagePath):
 | |
|             self._LoggerError(ST.ERR_DECPARSE_INCLUDE % Value)
 | |
| 
 | |
|         Item = DecLibraryclassItemObject(TokenList[0], StripRoot(self._RawData.PackagePath, Value),
 | |
|                                          self._RawData.PackagePath)
 | |
|         self.ItemObject.AddItem(Item, self._RawData.CurrentScope)
 | |
|         return Item
 | |
| 
 | |
| ## _DecPcd
 | |
| #
 | |
| # Parse PCD section
 | |
| #
 | |
| class _DecPcd(_DecBase):
 | |
|     def __init__(self, RawData):
 | |
|         _DecBase.__init__(self, RawData)
 | |
|         self.ItemObject = DecPcdObject(RawData.Filename)
 | |
|         #
 | |
|         # Used to check duplicate token
 | |
|         # Key is token space and token number (integer), value is C name
 | |
|         #
 | |
|         self.TokenMap = {}
 | |
| 
 | |
|     def _ParseItem(self):
 | |
|         Line = self._RawData.CurrentLine
 | |
|         TokenList = Line.split(DT.TAB_VALUE_SPLIT)
 | |
|         if len(TokenList) < 4:
 | |
|             self._LoggerError(ST.ERR_DECPARSE_PCD_SPLIT)
 | |
| 
 | |
|         #
 | |
|         # Token space guid C name
 | |
|         #
 | |
|         PcdName = GetSplitValueList(TokenList[0], DT.TAB_SPLIT)
 | |
|         if len(PcdName) != 2 or PcdName[0] == '' or PcdName[1] == '':
 | |
|             self._LoggerError(ST.ERR_DECPARSE_PCD_NAME)
 | |
| 
 | |
|         Guid = PcdName[0]
 | |
|         if not IsValidToken(CVAR_PATTERN, Guid):
 | |
|             self._LoggerError(ST.ERR_DECPARSE_PCD_CVAR_GUID)
 | |
| 
 | |
|         #
 | |
|         # PCD C name
 | |
|         #
 | |
|         CName = PcdName[1]
 | |
|         if not IsValidToken(CVAR_PATTERN, CName):
 | |
|             self._LoggerError(ST.ERR_DECPARSE_PCD_CVAR_PCDCNAME)
 | |
| 
 | |
|         self._CheckReDefine(Guid + DT.TAB_SPLIT + CName)
 | |
| 
 | |
|         #
 | |
|         # Default value, may be C array, string or number
 | |
|         #
 | |
|         Data = DT.TAB_VALUE_SPLIT.join(TokenList[1:-2]).strip()
 | |
| 
 | |
|         #
 | |
|         # PCD data type
 | |
|         #
 | |
|         DataType = TokenList[-2].strip()
 | |
|         Valid, Cause = IsValidPcdDatum(DataType, Data)
 | |
|         if not Valid:
 | |
|             self._LoggerError(Cause)
 | |
|         PcdType = self._RawData.CurrentScope[0][0]
 | |
|         if PcdType == DT.TAB_PCDS_FEATURE_FLAG_NULL.upper() and DataType != 'BOOLEAN':
 | |
|             self._LoggerError(ST.ERR_DECPARSE_PCD_FEATUREFLAG)
 | |
|         #
 | |
|         # Token value is the last element in list.
 | |
|         #
 | |
|         Token = TokenList[-1].strip()
 | |
|         if not IsValidToken(PCD_TOKEN_PATTERN, Token):
 | |
|             self._LoggerError(ST.ERR_DECPARSE_PCD_TOKEN % Token)
 | |
|         elif not Token.startswith('0x') and not Token.startswith('0X'):
 | |
|             if int(Token) > 4294967295:
 | |
|                 self._LoggerError(ST.ERR_DECPARSE_PCD_TOKEN_INT % Token)
 | |
|             Token = '0x%x' % int(Token)
 | |
| 
 | |
|         IntToken = int(Token, 0)
 | |
|         if (Guid, IntToken) in self.TokenMap:
 | |
|             if self.TokenMap[Guid, IntToken] != CName:
 | |
|                 self._LoggerError(ST.ERR_DECPARSE_PCD_TOKEN_UNIQUE%(Token))
 | |
|         else:
 | |
|             self.TokenMap[Guid, IntToken] = CName
 | |
| 
 | |
|         Item = DecPcdItemObject(Guid, CName, Data, DataType, Token)
 | |
|         self.ItemObject.AddItem(Item, self._RawData.CurrentScope)
 | |
|         return Item
 | |
| 
 | |
| ## _DecGuid
 | |
| #
 | |
| # Parse GUID, PPI, Protocol section
 | |
| #
 | |
| class _DecGuid(_DecBase):
 | |
|     def __init__(self, RawData):
 | |
|         _DecBase.__init__(self, RawData)
 | |
|         self.GuidObj = DecGuidObject(RawData.Filename)
 | |
|         self.PpiObj = DecPpiObject(RawData.Filename)
 | |
|         self.ProtocolObj = DecProtocolObject(RawData.Filename)
 | |
|         self.ObjectDict = \
 | |
|         {
 | |
|             DT.TAB_GUIDS.upper()     :   self.GuidObj,
 | |
|             DT.TAB_PPIS.upper()      :   self.PpiObj,
 | |
|             DT.TAB_PROTOCOLS.upper() :   self.ProtocolObj
 | |
|         }
 | |
| 
 | |
|     def GetDataObject(self):
 | |
|         if self._RawData.CurrentScope:
 | |
|             return self.ObjectDict[self._RawData.CurrentScope[0][0]]
 | |
|         return None
 | |
| 
 | |
|     def GetGuidObject(self):
 | |
|         return self.GuidObj
 | |
| 
 | |
|     def GetPpiObject(self):
 | |
|         return self.PpiObj
 | |
| 
 | |
|     def GetProtocolObject(self):
 | |
|         return self.ProtocolObj
 | |
| 
 | |
|     def _ParseItem(self):
 | |
|         Line = self._RawData.CurrentLine
 | |
|         TokenList = GetSplitValueList(Line, DT.TAB_EQUAL_SPLIT, 1)
 | |
|         if len(TokenList) < 2:
 | |
|             self._LoggerError(ST.ERR_DECPARSE_CGUID)
 | |
|         if TokenList[0] == '':
 | |
|             self._LoggerError(ST.ERR_DECPARSE_CGUID_NAME)
 | |
|         if TokenList[1] == '':
 | |
|             self._LoggerError(ST.ERR_DECPARSE_CGUID_GUID)
 | |
|         if not IsValidToken(CVAR_PATTERN, TokenList[0]):
 | |
|             self._LoggerError(ST.ERR_DECPARSE_PCD_CVAR_GUID)
 | |
| 
 | |
|         self._CheckReDefine(TokenList[0])
 | |
| 
 | |
|         if TokenList[1][0] != '{':
 | |
|             if not CheckGuidRegFormat(TokenList[1]):
 | |
|                 self._LoggerError(ST.ERR_DECPARSE_DEFINE_PKGGUID)
 | |
|             GuidString = TokenList[1]
 | |
|         else:
 | |
|             #
 | |
|             # Convert C format GUID to GUID string and Simple error check
 | |
|             #
 | |
|             GuidString = GuidStructureStringToGuidString(TokenList[1])
 | |
|             if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidString == '':
 | |
|                 self._LoggerError(ST.ERR_DECPARSE_CGUID_GUIDFORMAT)
 | |
| 
 | |
|             #
 | |
|             # Check C format GUID
 | |
|             #
 | |
|             if not IsValidCFormatGuid(TokenList[1]):
 | |
|                 self._LoggerError(ST.ERR_DECPARSE_CGUID_GUIDFORMAT)
 | |
| 
 | |
|         Item = DecGuidItemObject(TokenList[0], TokenList[1], GuidString)
 | |
|         ItemObject = self.ObjectDict[self._RawData.CurrentScope[0][0]]
 | |
|         ItemObject.AddItem(Item, self._RawData.CurrentScope)
 | |
|         return Item
 | |
| 
 | |
| ## _DecUserExtension
 | |
| #
 | |
| # Parse user extension section
 | |
| #
 | |
| class _DecUserExtension(_DecBase):
 | |
|     def __init__(self, RawData):
 | |
|         _DecBase.__init__(self, RawData)
 | |
|         self.ItemObject = DecUserExtensionObject(RawData.Filename)
 | |
|         self._Headers = []
 | |
|         self._CurItems = []
 | |
| 
 | |
|     def BlockStart(self):
 | |
|         self._CurItems = []
 | |
|         for Header in self._RawData.CurrentScope:
 | |
|             if Header in self._Headers:
 | |
|                 self._LoggerError(ST.ERR_DECPARSE_UE_DUPLICATE)
 | |
|             else:
 | |
|                 self._Headers.append(Header)
 | |
| 
 | |
|             for Item in self._CurItems:
 | |
|                 if Item.UserId == Header[1] and Item.IdString == Header[2]:
 | |
|                     Item.ArchAndModuleType.append(Header[3])
 | |
|                     break
 | |
|             else:
 | |
|                 Item = DecUserExtensionItemObject()
 | |
|                 Item.UserId = Header[1]
 | |
|                 Item.IdString = Header[2]
 | |
|                 Item.ArchAndModuleType.append(Header[3])
 | |
|                 self._CurItems.append(Item)
 | |
|                 self.ItemObject.AddItem(Item, None)
 | |
|         self._LocalMacro = {}
 | |
| 
 | |
|     def _ParseItem(self):
 | |
|         Line = self._RawData.CurrentLine
 | |
|         Item = None
 | |
|         for Item in self._CurItems:
 | |
|             if Item.UserString:
 | |
|                 Item.UserString = '\n'.join([Item.UserString, Line])
 | |
|             else:
 | |
|                 Item.UserString = Line
 | |
|         return Item
 | |
| 
 | |
| ## Dec
 | |
| #
 | |
| # Top dec parser
 | |
| #
 | |
| class Dec(_DecBase, _DecComments):
 | |
|     def __init__(self, DecFile, Parse = True):
 | |
|         try:
 | |
|             Content = ConvertSpecialChar(open(DecFile, 'r').readlines())
 | |
|         except BaseException:
 | |
|             Logger.Error(TOOL_NAME, FILE_OPEN_FAILURE, File=DecFile,
 | |
|                          ExtraData=ST.ERR_DECPARSE_FILEOPEN % DecFile)
 | |
| 
 | |
|         #
 | |
|         # Pre-parser for Private section
 | |
|         #
 | |
|         self._Private = ''
 | |
|         __IsFoundPrivate = False
 | |
|         NewContent = []
 | |
|         for Line in Content:
 | |
|             Line = Line.strip()
 | |
|             if Line.startswith(DT.TAB_SECTION_START) and Line.endswith(DT.TAB_PRIVATE + DT.TAB_SECTION_END):
 | |
|                 __IsFoundPrivate = True
 | |
|             if Line.startswith(DT.TAB_SECTION_START) and Line.endswith(DT.TAB_SECTION_END)\
 | |
|                and not Line.endswith(DT.TAB_PRIVATE + DT.TAB_SECTION_END):
 | |
|                 __IsFoundPrivate = False
 | |
|             if __IsFoundPrivate:
 | |
|                 self._Private += Line + '\r'
 | |
|             if not __IsFoundPrivate:
 | |
|                 NewContent.append(Line + '\r')
 | |
| 
 | |
|         RawData = FileContent(DecFile, NewContent)
 | |
| 
 | |
|         _DecComments.__init__(self)
 | |
|         _DecBase.__init__(self, RawData)
 | |
| 
 | |
|         self.BinaryHeadComment = []
 | |
|         self.PcdErrorCommentDict = {}
 | |
| 
 | |
|         self._Define    = _DecDefine(RawData)
 | |
|         self._Include   = _DecInclude(RawData)
 | |
|         self._Guid      = _DecGuid(RawData)
 | |
|         self._LibClass  = _DecLibraryclass(RawData)
 | |
|         self._Pcd       = _DecPcd(RawData)
 | |
|         self._UserEx    = _DecUserExtension(RawData)
 | |
| 
 | |
|         #
 | |
|         # DEC file supported data types (one type per section)
 | |
|         #
 | |
|         self._SectionParser = {
 | |
|             DT.TAB_DEC_DEFINES.upper()                     :   self._Define,
 | |
|             DT.TAB_INCLUDES.upper()                        :   self._Include,
 | |
|             DT.TAB_LIBRARY_CLASSES.upper()                 :   self._LibClass,
 | |
|             DT.TAB_GUIDS.upper()                           :   self._Guid,
 | |
|             DT.TAB_PPIS.upper()                            :   self._Guid,
 | |
|             DT.TAB_PROTOCOLS.upper()                       :   self._Guid,
 | |
|             DT.TAB_PCDS_FIXED_AT_BUILD_NULL.upper()        :   self._Pcd,
 | |
|             DT.TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper()   :   self._Pcd,
 | |
|             DT.TAB_PCDS_FEATURE_FLAG_NULL.upper()          :   self._Pcd,
 | |
|             DT.TAB_PCDS_DYNAMIC_NULL.upper()               :   self._Pcd,
 | |
|             DT.TAB_PCDS_DYNAMIC_EX_NULL.upper()            :   self._Pcd,
 | |
|             DT.TAB_USER_EXTENSIONS.upper()                 :   self._UserEx
 | |
|         }
 | |
| 
 | |
|         if Parse:
 | |
|             self.ParseDecComment()
 | |
|             self.Parse()
 | |
|             #
 | |
|             # Parsing done, check required fields
 | |
|             #
 | |
|             self.CheckRequiredFields()
 | |
| 
 | |
|     def CheckRequiredFields(self):
 | |
|         for SectionParser in self._SectionParser.values():
 | |
|             if not SectionParser.CheckRequiredFields():
 | |
|                 return False
 | |
|         return True
 | |
| 
 | |
|     ##
 | |
|     # Parse DEC file
 | |
|     #
 | |
|     def ParseDecComment(self):
 | |
|         IsFileHeader = False
 | |
|         IsBinaryHeader = False
 | |
|         FileHeaderLineIndex = -1
 | |
|         BinaryHeaderLineIndex = -1
 | |
|         TokenSpaceGuidCName = ''
 | |
| 
 | |
|         #
 | |
|         # Parse PCD error comment section
 | |
|         #
 | |
|         while not self._RawData.IsEndOfFile():
 | |
|             self._RawData.CurrentLine = self._RawData.GetNextLine()
 | |
|             if self._RawData.CurrentLine.startswith(DT.TAB_COMMENT_SPLIT) and \
 | |
|                 DT.TAB_SECTION_START in self._RawData.CurrentLine and \
 | |
|                 DT.TAB_SECTION_END in self._RawData.CurrentLine:
 | |
|                 self._RawData.CurrentLine = self._RawData.CurrentLine.replace(DT.TAB_COMMENT_SPLIT, '').strip()
 | |
| 
 | |
|                 if self._RawData.CurrentLine[0] == DT.TAB_SECTION_START and \
 | |
|                     self._RawData.CurrentLine[-1] == DT.TAB_SECTION_END:
 | |
|                     RawSection = self._RawData.CurrentLine[1:-1].strip()
 | |
|                     if RawSection.upper().startswith(DT.TAB_PCD_ERROR.upper()+'.'):
 | |
|                         TokenSpaceGuidCName = RawSection.split(DT.TAB_PCD_ERROR+'.')[1].strip()
 | |
|                         continue
 | |
| 
 | |
|             if TokenSpaceGuidCName and self._RawData.CurrentLine.startswith(DT.TAB_COMMENT_SPLIT):
 | |
|                 self._RawData.CurrentLine = self._RawData.CurrentLine.replace(DT.TAB_COMMENT_SPLIT, '').strip()
 | |
|                 if self._RawData.CurrentLine != '':
 | |
|                     if DT.TAB_VALUE_SPLIT not in self._RawData.CurrentLine:
 | |
|                         self._LoggerError(ST.ERR_DECPARSE_PCDERRORMSG_MISS_VALUE_SPLIT)
 | |
| 
 | |
|                     PcdErrorNumber, PcdErrorMsg = GetSplitValueList(self._RawData.CurrentLine, DT.TAB_VALUE_SPLIT, 1)
 | |
|                     PcdErrorNumber = ParsePcdErrorCode(PcdErrorNumber, self._RawData.Filename, self._RawData.LineIndex)
 | |
|                     if not PcdErrorMsg.strip():
 | |
|                         self._LoggerError(ST.ERR_DECPARSE_PCD_MISS_ERRORMSG)
 | |
| 
 | |
|                     self.PcdErrorCommentDict[(TokenSpaceGuidCName, PcdErrorNumber)] = PcdErrorMsg.strip()
 | |
|             else:
 | |
|                 TokenSpaceGuidCName = ''
 | |
| 
 | |
|         self._RawData.LineIndex = 0
 | |
|         self._RawData.CurrentLine = ''
 | |
|         self._RawData.NextLine = ''
 | |
| 
 | |
|         while not self._RawData.IsEndOfFile():
 | |
|             Line, Comment = CleanString(self._RawData.GetNextLine())
 | |
| 
 | |
|             #
 | |
|             # Header must be pure comment
 | |
|             #
 | |
|             if Line != '':
 | |
|                 self._RawData.UndoNextLine()
 | |
|                 break
 | |
| 
 | |
|             if Comment and Comment.startswith(DT.TAB_SPECIAL_COMMENT) and Comment.find(DT.TAB_HEADER_COMMENT) > 0 \
 | |
|                 and not Comment[2:Comment.find(DT.TAB_HEADER_COMMENT)].strip():
 | |
|                 IsFileHeader = True
 | |
|                 IsBinaryHeader = False
 | |
|                 FileHeaderLineIndex = self._RawData.LineIndex
 | |
| 
 | |
|             #
 | |
|             # Get license information before '@file'
 | |
|             #
 | |
|             if not IsFileHeader and not IsBinaryHeader and Comment and Comment.startswith(DT.TAB_COMMENT_SPLIT) and \
 | |
|             DT.TAB_BINARY_HEADER_COMMENT not in Comment:
 | |
|                 self._HeadComment.append((Comment, self._RawData.LineIndex))
 | |
| 
 | |
|             if Comment and IsFileHeader and \
 | |
|             not(Comment.startswith(DT.TAB_SPECIAL_COMMENT) \
 | |
|             and Comment.find(DT.TAB_BINARY_HEADER_COMMENT) > 0):
 | |
|                 self._HeadComment.append((Comment, self._RawData.LineIndex))
 | |
|             #
 | |
|             # Double '#' indicates end of header comments
 | |
|             #
 | |
|             if (not Comment or Comment == DT.TAB_SPECIAL_COMMENT) and IsFileHeader:
 | |
|                 IsFileHeader = False
 | |
|                 continue
 | |
| 
 | |
|             if Comment and Comment.startswith(DT.TAB_SPECIAL_COMMENT) \
 | |
|             and Comment.find(DT.TAB_BINARY_HEADER_COMMENT) > 0:
 | |
|                 IsBinaryHeader = True
 | |
|                 IsFileHeader = False
 | |
|                 BinaryHeaderLineIndex = self._RawData.LineIndex
 | |
| 
 | |
|             if Comment and IsBinaryHeader:
 | |
|                 self.BinaryHeadComment.append((Comment, self._RawData.LineIndex))
 | |
|             #
 | |
|             # Double '#' indicates end of header comments
 | |
|             #
 | |
|             if (not Comment or Comment == DT.TAB_SPECIAL_COMMENT) and IsBinaryHeader:
 | |
|                 IsBinaryHeader = False
 | |
|                 break
 | |
| 
 | |
|             if FileHeaderLineIndex > -1 and not IsFileHeader and not IsBinaryHeader:
 | |
|                 break
 | |
| 
 | |
|         if FileHeaderLineIndex > BinaryHeaderLineIndex and FileHeaderLineIndex > -1 and BinaryHeaderLineIndex > -1:
 | |
|             self._LoggerError(ST.ERR_BINARY_HEADER_ORDER)
 | |
| 
 | |
|         if FileHeaderLineIndex == -1:
 | |
| #            self._LoggerError(ST.ERR_NO_SOURCE_HEADER)
 | |
|             Logger.Error(TOOL_NAME, FORMAT_INVALID,
 | |
|                          ST.ERR_NO_SOURCE_HEADER,
 | |
|                          File=self._RawData.Filename)
 | |
|         return
 | |
| 
 | |
|     def _StopCurrentParsing(self, Line):
 | |
|         return False
 | |
| 
 | |
|     def _ParseItem(self):
 | |
|         self._SectionHeaderParser()
 | |
|         if len(self._RawData.CurrentScope) == 0:
 | |
|             self._LoggerError(ST.ERR_DECPARSE_SECTION_EMPTY)
 | |
|         SectionObj = self._SectionParser[self._RawData.CurrentScope[0][0]]
 | |
|         SectionObj.BlockStart()
 | |
|         SectionObj.Parse()
 | |
|         return SectionObj.GetDataObject()
 | |
| 
 | |
|     def _UserExtentionSectionParser(self):
 | |
|         self._RawData.CurrentScope = []
 | |
|         ArchList = set()
 | |
|         Section = self._RawData.CurrentLine[1:-1]
 | |
|         Par = ParserHelper(Section, self._RawData.Filename)
 | |
|         while not Par.End():
 | |
|             #
 | |
|             # User extention
 | |
|             #
 | |
|             Token = Par.GetToken()
 | |
|             if Token.upper() != DT.TAB_USER_EXTENSIONS.upper():
 | |
|                 self._LoggerError(ST.ERR_DECPARSE_SECTION_UE)
 | |
|             UserExtension = Token.upper()
 | |
|             Par.AssertChar(DT.TAB_SPLIT, ST.ERR_DECPARSE_SECTION_UE, self._RawData.LineIndex)
 | |
| 
 | |
|             #
 | |
|             # UserID
 | |
|             #
 | |
|             Token = Par.GetToken()
 | |
|             if not IsValidUserId(Token):
 | |
|                 self._LoggerError(ST.ERR_DECPARSE_SECTION_UE_USERID)
 | |
|             UserId = Token
 | |
|             Par.AssertChar(DT.TAB_SPLIT, ST.ERR_DECPARSE_SECTION_UE, self._RawData.LineIndex)
 | |
|             #
 | |
|             # IdString
 | |
|             #
 | |
|             Token = Par.GetToken()
 | |
|             if not IsValidIdString(Token):
 | |
|                 self._LoggerError(ST.ERR_DECPARSE_SECTION_UE_IDSTRING)
 | |
|             IdString = Token
 | |
|             Arch = 'COMMON'
 | |
|             if Par.Expect(DT.TAB_SPLIT):
 | |
|                 Token = Par.GetToken()
 | |
|                 Arch = Token.upper()
 | |
|                 if not IsValidArch(Arch):
 | |
|                     self._LoggerError(ST.ERR_DECPARSE_ARCH)
 | |
|             ArchList.add(Arch)
 | |
|             if [UserExtension, UserId, IdString, Arch] not in \
 | |
|                 self._RawData.CurrentScope:
 | |
|                 self._RawData.CurrentScope.append(
 | |
|                     [UserExtension, UserId, IdString, Arch]
 | |
|                 )
 | |
|             if not Par.Expect(DT.TAB_COMMA_SPLIT):
 | |
|                 break
 | |
|             elif Par.End():
 | |
|                 self._LoggerError(ST.ERR_DECPARSE_SECTION_COMMA)
 | |
|         Par.AssertEnd(ST.ERR_DECPARSE_SECTION_UE, self._RawData.LineIndex)
 | |
|         if 'COMMON' in ArchList and len(ArchList) > 1:
 | |
|             self._LoggerError(ST.ERR_DECPARSE_SECTION_COMMON)
 | |
| 
 | |
|     ## Section header parser
 | |
|     #
 | |
|     # The section header is always in following format:
 | |
|     #
 | |
|     # [section_name.arch<.platform|module_type>]
 | |
|     #
 | |
|     def _SectionHeaderParser(self):
 | |
|         if self._RawData.CurrentLine[0] != DT.TAB_SECTION_START or self._RawData.CurrentLine[-1] != DT.TAB_SECTION_END:
 | |
|             self._LoggerError(ST.ERR_DECPARSE_SECTION_IDENTIFY)
 | |
| 
 | |
|         RawSection = self._RawData.CurrentLine[1:-1].strip().upper()
 | |
|         #
 | |
|         # Check defines section which is only allowed to occur once and
 | |
|         # no arch can be followed
 | |
|         #
 | |
|         if RawSection.startswith(DT.TAB_DEC_DEFINES.upper()):
 | |
|             if RawSection != DT.TAB_DEC_DEFINES.upper():
 | |
|                 self._LoggerError(ST.ERR_DECPARSE_DEFINE_SECNAME)
 | |
|         #
 | |
|         # Check user extension section
 | |
|         #
 | |
|         if RawSection.startswith(DT.TAB_USER_EXTENSIONS.upper()):
 | |
|             return self._UserExtentionSectionParser()
 | |
|         self._RawData.CurrentScope = []
 | |
|         SectionNames = []
 | |
|         ArchList = set()
 | |
|         for Item in GetSplitValueList(RawSection, DT.TAB_COMMA_SPLIT):
 | |
|             if Item == '':
 | |
|                 self._LoggerError(ST.ERR_DECPARSE_SECTION_SUBEMPTY % self._RawData.CurrentLine)
 | |
| 
 | |
|             ItemList = GetSplitValueList(Item, DT.TAB_SPLIT)
 | |
|             #
 | |
|             # different types of PCD are permissible in one section
 | |
|             #
 | |
|             SectionName = ItemList[0]
 | |
|             if SectionName not in self._SectionParser:
 | |
|                 self._LoggerError(ST.ERR_DECPARSE_SECTION_UNKNOW % SectionName)
 | |
|             if SectionName not in SectionNames:
 | |
|                 SectionNames.append(SectionName)
 | |
|             #
 | |
|             # In DEC specification, all section headers have at most two part:
 | |
|             # SectionName.Arch except UserExtension
 | |
|             #
 | |
|             if len(ItemList) > 2:
 | |
|                 self._LoggerError(ST.ERR_DECPARSE_SECTION_SUBTOOMANY % Item)
 | |
| 
 | |
|             if DT.TAB_PCDS_FEATURE_FLAG_NULL.upper() in SectionNames and len(SectionNames) > 1:
 | |
|                 self._LoggerError(ST.ERR_DECPARSE_SECTION_FEATUREFLAG % DT.TAB_PCDS_FEATURE_FLAG_NULL)
 | |
|             #
 | |
|             # S1 is always Arch
 | |
|             #
 | |
|             if len(ItemList) > 1:
 | |
|                 Str1 = ItemList[1]
 | |
|                 if not IsValidArch(Str1):
 | |
|                     self._LoggerError(ST.ERR_DECPARSE_ARCH)
 | |
|             else:
 | |
|                 Str1 = 'COMMON'
 | |
|             ArchList.add(Str1)
 | |
| 
 | |
|             if [SectionName, Str1] not in self._RawData.CurrentScope:
 | |
|                 self._RawData.CurrentScope.append([SectionName, Str1])
 | |
|         #
 | |
|         # 'COMMON' must not be used with specific ARCHs at the same section
 | |
|         #
 | |
|         if 'COMMON' in ArchList and len(ArchList) > 1:
 | |
|             self._LoggerError(ST.ERR_DECPARSE_SECTION_COMMON)
 | |
|         if len(SectionNames) == 0:
 | |
|             self._LoggerError(ST.ERR_DECPARSE_SECTION_SUBEMPTY % self._RawData.CurrentLine)
 | |
|         if len(SectionNames) != 1:
 | |
|             for Sec in SectionNames:
 | |
|                 if not Sec.startswith(DT.TAB_PCDS.upper()):
 | |
|                     self._LoggerError(ST.ERR_DECPARSE_SECTION_NAME % str(SectionNames))
 | |
| 
 | |
|     def GetDefineSectionMacro(self):
 | |
|         return self._Define.GetLocalMacro()
 | |
|     def GetDefineSectionObject(self):
 | |
|         return self._Define.GetDataObject()
 | |
|     def GetIncludeSectionObject(self):
 | |
|         return self._Include.GetDataObject()
 | |
|     def GetGuidSectionObject(self):
 | |
|         return self._Guid.GetGuidObject()
 | |
|     def GetProtocolSectionObject(self):
 | |
|         return self._Guid.GetProtocolObject()
 | |
|     def GetPpiSectionObject(self):
 | |
|         return self._Guid.GetPpiObject()
 | |
|     def GetLibraryClassSectionObject(self):
 | |
|         return self._LibClass.GetDataObject()
 | |
|     def GetPcdSectionObject(self):
 | |
|         return self._Pcd.GetDataObject()
 | |
|     def GetUserExtensionSectionObject(self):
 | |
|         return self._UserEx.GetDataObject()
 | |
|     def GetPackageSpecification(self):
 | |
|         return self._Define.GetDataObject().GetPackageSpecification()
 | |
|     def GetPackageName(self):
 | |
|         return self._Define.GetDataObject().GetPackageName()
 | |
|     def GetPackageGuid(self):
 | |
|         return self._Define.GetDataObject().GetPackageGuid()
 | |
|     def GetPackageVersion(self):
 | |
|         return self._Define.GetDataObject().GetPackageVersion()
 | |
|     def GetPackageUniFile(self):
 | |
|         return self._Define.GetDataObject().GetPackageUniFile()
 | |
|     def GetPrivateSections(self):
 | |
|         return self._Private
 |