Sync BaseTools Branch (version r2271) to EDKII main trunk.
BaseTool Branch: https://edk2-buildtools.svn.sourceforge.net/svnroot/edk2-buildtools/branches/Releases/BaseTools_r2100 Signed-off-by: lgao4 Reviewed-by: hchen30 git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12214 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
989
BaseTools/Source/Python/UPT/Parser/DecParser.py
Normal file
989
BaseTools/Source/Python/UPT/Parser/DecParser.py
Normal file
@@ -0,0 +1,989 @@
|
||||
## @file
|
||||
# This file is used to parse DEC file. It will consumed by DecParser
|
||||
#
|
||||
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials are licensed and made available
|
||||
# under the terms and conditions of the BSD License which accompanies this
|
||||
# distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
'''
|
||||
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
|
||||
|
||||
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 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.String import ReplaceMacro
|
||||
from Library.String import GetSplitValueList
|
||||
from Library.String import gMACRO_PATTERN
|
||||
from Library.String import ConvertSpecialChar
|
||||
|
||||
##
|
||||
# _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
|
||||
|
||||
## 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
|
||||
|
||||
self._RawData.CurrentLine = self._ReplaceMacro(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,
|
||||
}
|
||||
|
||||
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:
|
||||
pass
|
||||
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()
|
||||
if TokenList[0] != DT.TAB_DEC_DEFINES_PKG_UNI_FILE:
|
||||
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):
|
||||
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._PkgVersion = 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 long(Token) > 4294967295:
|
||||
self._LoggerError(ST.ERR_DECPARSE_PCD_TOKEN_INT % Token)
|
||||
Token = hex(long(Token))[:-1]
|
||||
|
||||
IntToken = long(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 extention 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, 'rb').readlines())
|
||||
except BaseException:
|
||||
Logger.Error(TOOL_NAME, FILE_OPEN_FAILURE, File=DecFile,
|
||||
ExtraData=ST.ERR_DECPARSE_FILEOPEN % DecFile)
|
||||
RawData = FileContent(DecFile, Content)
|
||||
|
||||
_DecComments.__init__(self)
|
||||
_DecBase.__init__(self, RawData)
|
||||
|
||||
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):
|
||||
while not self._RawData.IsEndOfFile():
|
||||
Line, Comment = CleanString(self._RawData.GetNextLine())
|
||||
#
|
||||
# Header must be pure comment
|
||||
#
|
||||
if Line != '':
|
||||
self._RawData.UndoNextLine()
|
||||
break
|
||||
|
||||
if Comment:
|
||||
self._HeadComment.append((Comment, self._RawData.LineIndex))
|
||||
#
|
||||
# Double '#' indicates end of header comments
|
||||
#
|
||||
if not Comment or Comment == DT.TAB_SPECIAL_COMMENT:
|
||||
break
|
||||
|
||||
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 UserExtention
|
||||
#
|
||||
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 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()
|
371
BaseTools/Source/Python/UPT/Parser/DecParserMisc.py
Normal file
371
BaseTools/Source/Python/UPT/Parser/DecParserMisc.py
Normal file
@@ -0,0 +1,371 @@
|
||||
## @file
|
||||
# This file is used to define helper class and function for DEC parser
|
||||
#
|
||||
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials are licensed and made available
|
||||
# under the terms and conditions of the BSD License which accompanies this
|
||||
# distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
'''
|
||||
DecParserMisc
|
||||
'''
|
||||
|
||||
## Import modules
|
||||
#
|
||||
import os
|
||||
import Logger.Log as Logger
|
||||
from Logger.ToolError import FILE_PARSE_FAILURE
|
||||
from Logger import StringTable as ST
|
||||
from Library.DataType import TAB_COMMENT_SPLIT
|
||||
from Library.DataType import TAB_COMMENT_EDK1_SPLIT
|
||||
from Library.ExpressionValidate import IsValidBareCString
|
||||
from Library.ParserValidate import IsValidCFormatGuid
|
||||
from Library.ExpressionValidate import IsValidLogicalExpr
|
||||
from Library.ExpressionValidate import IsValidStringTest
|
||||
from Library.Misc import CheckGuidRegFormat
|
||||
|
||||
TOOL_NAME = 'DecParser'
|
||||
VERSION_PATTERN = '[0-9]+(\.[0-9]+)?'
|
||||
CVAR_PATTERN = '[_a-zA-Z][a-zA-Z0-9_]*'
|
||||
PCD_TOKEN_PATTERN = '(0[xX]0*[a-fA-F0-9]{1,8})|([0-9]+)'
|
||||
MACRO_PATTERN = '[A-Z][_A-Z0-9]*'
|
||||
|
||||
## FileContent
|
||||
# Class to hold DEC file information
|
||||
#
|
||||
class FileContent:
|
||||
def __init__(self, Filename, FileContent2):
|
||||
self.Filename = Filename
|
||||
self.PackagePath, self.PackageFile = os.path.split(Filename)
|
||||
self.LineIndex = 0
|
||||
self.CurrentLine = ''
|
||||
self.NextLine = ''
|
||||
self.HeadComment = []
|
||||
self.TailComment = []
|
||||
self.CurrentScope = None
|
||||
self.Content = FileContent2
|
||||
self.Macros = {}
|
||||
self.FileLines = len(FileContent2)
|
||||
|
||||
def GetNextLine(self):
|
||||
if self.LineIndex >= self.FileLines:
|
||||
return ''
|
||||
Line = self.Content[self.LineIndex]
|
||||
self.LineIndex += 1
|
||||
return Line
|
||||
|
||||
def UndoNextLine(self):
|
||||
if self.LineIndex > 0:
|
||||
self.LineIndex -= 1
|
||||
|
||||
def ResetNext(self):
|
||||
self.HeadComment = []
|
||||
self.TailComment = []
|
||||
self.NextLine = ''
|
||||
|
||||
def SetNext(self, Line, HeadComment, TailComment):
|
||||
self.NextLine = Line
|
||||
self.HeadComment = HeadComment
|
||||
self.TailComment = TailComment
|
||||
|
||||
def IsEndOfFile(self):
|
||||
return self.LineIndex >= self.FileLines
|
||||
|
||||
|
||||
## StripRoot
|
||||
#
|
||||
# Strip root path
|
||||
#
|
||||
# @param Root: Root must be absolute path
|
||||
# @param Path: Path to be stripped
|
||||
#
|
||||
def StripRoot(Root, Path):
|
||||
OrigPath = Path
|
||||
Root = os.path.normpath(Root)
|
||||
Path = os.path.normpath(Path)
|
||||
if not os.path.isabs(Root):
|
||||
return OrigPath
|
||||
if Path.startswith(Root):
|
||||
Path = Path[len(Root):]
|
||||
if Path and Path[0] == os.sep:
|
||||
Path = Path[1:]
|
||||
return Path
|
||||
return OrigPath
|
||||
|
||||
## CleanString
|
||||
#
|
||||
# Split comments in a string
|
||||
# Remove spaces
|
||||
#
|
||||
# @param Line: The string to be cleaned
|
||||
# @param CommentCharacter: Comment char, used to ignore comment content,
|
||||
# default is DataType.TAB_COMMENT_SPLIT
|
||||
#
|
||||
def CleanString(Line, CommentCharacter=TAB_COMMENT_SPLIT, \
|
||||
AllowCppStyleComment=False):
|
||||
#
|
||||
# remove whitespace
|
||||
#
|
||||
Line = Line.strip()
|
||||
#
|
||||
# Replace EDK1's comment character
|
||||
#
|
||||
if AllowCppStyleComment:
|
||||
Line = Line.replace(TAB_COMMENT_EDK1_SPLIT, CommentCharacter)
|
||||
#
|
||||
# separate comments and statements
|
||||
#
|
||||
Comment = ''
|
||||
InQuote = False
|
||||
for Index in range(0, len(Line)):
|
||||
if Line[Index] == '"':
|
||||
InQuote = not InQuote
|
||||
continue
|
||||
if Line[Index] == CommentCharacter and not InQuote:
|
||||
Comment = Line[Index:].strip()
|
||||
Line = Line[0:Index].strip()
|
||||
break
|
||||
|
||||
return Line, Comment
|
||||
|
||||
|
||||
## IsValidHexByte
|
||||
#
|
||||
# Check if Token is HexByte: <HexByte> ::= 0x <HexDigit>{1,2}
|
||||
#
|
||||
# @param Token: Token to be checked
|
||||
#
|
||||
def IsValidHexByte(Token):
|
||||
Token = Token.strip()
|
||||
if not Token.lower().startswith('0x') or not (len(Token) < 5 and len(Token) > 2):
|
||||
return False
|
||||
try:
|
||||
Token = long(Token, 0)
|
||||
except BaseException:
|
||||
return False
|
||||
return True
|
||||
|
||||
## IsValidNList
|
||||
#
|
||||
# Check if Value has the format of <HexByte> ["," <HexByte>]{0,}
|
||||
# <HexByte> ::= "0x" <HexDigit>{1,2}
|
||||
#
|
||||
# @param Value: Value to be checked
|
||||
#
|
||||
def IsValidNList(Value):
|
||||
Par = ParserHelper(Value)
|
||||
if Par.End():
|
||||
return False
|
||||
while not Par.End():
|
||||
Token = Par.GetToken(',\t ')
|
||||
if not IsValidHexByte(Token):
|
||||
return False
|
||||
if Par.Expect(','):
|
||||
if Par.End():
|
||||
return False
|
||||
continue
|
||||
else:
|
||||
break
|
||||
return Par.End()
|
||||
|
||||
## IsValidCArray
|
||||
#
|
||||
# check Array is valid
|
||||
#
|
||||
# @param Array: The input Array
|
||||
#
|
||||
def IsValidCArray(Array):
|
||||
Par = ParserHelper(Array)
|
||||
if not Par.Expect('{'):
|
||||
return False
|
||||
if Par.End():
|
||||
return False
|
||||
while not Par.End():
|
||||
Token = Par.GetToken(',}\t ')
|
||||
#
|
||||
# 0xa, 0xaa
|
||||
#
|
||||
if not IsValidHexByte(Token):
|
||||
return False
|
||||
if Par.Expect(','):
|
||||
if Par.End():
|
||||
return False
|
||||
continue
|
||||
elif Par.Expect('}'):
|
||||
#
|
||||
# End of C array
|
||||
#
|
||||
break
|
||||
else:
|
||||
return False
|
||||
return Par.End()
|
||||
|
||||
## IsValidPcdDatum
|
||||
#
|
||||
# check PcdDatum is valid
|
||||
#
|
||||
# @param Type: The pcd Type
|
||||
# @param Value: The pcd Value
|
||||
#
|
||||
def IsValidPcdDatum(Type, Value):
|
||||
if Type not in ["UINT8", "UINT16", "UINT32", "UINT64", "VOID*", "BOOLEAN"]:
|
||||
return False, ST.ERR_DECPARSE_PCD_TYPE
|
||||
if Type == "VOID*":
|
||||
if not ((Value.startswith('L"') or Value.startswith('"') and \
|
||||
Value.endswith('"'))
|
||||
or (IsValidCArray(Value)) or (IsValidCFormatGuid(Value)) \
|
||||
or (IsValidNList(Value)) or (CheckGuidRegFormat(Value))
|
||||
):
|
||||
return False, ST.ERR_DECPARSE_PCD_VOID % (Value, Type)
|
||||
RealString = Value[Value.find('"') + 1 :-1]
|
||||
if RealString:
|
||||
if not IsValidBareCString(RealString):
|
||||
return False, ST.ERR_DECPARSE_PCD_VOID % (Value, Type)
|
||||
elif Type == 'BOOLEAN':
|
||||
if Value in ['TRUE', 'FALSE', 'true', 'false', 'True', 'False',
|
||||
'0x1', '0x01', '1', '0x0', '0x00', '0']:
|
||||
return True, ""
|
||||
Valid, Cause = IsValidStringTest(Value)
|
||||
if not Valid:
|
||||
Valid, Cause = IsValidLogicalExpr(Value)
|
||||
if not Valid:
|
||||
return False, Cause
|
||||
else:
|
||||
if Value and (Value[0] == '-' or Value[0] == '+'):
|
||||
return False, ST.ERR_DECPARSE_PCD_INT_NEGTIVE % (Value, Type)
|
||||
try:
|
||||
StrVal = Value
|
||||
if Value and not Value.startswith('0x') \
|
||||
and not Value.startswith('0X'):
|
||||
Value = Value.lstrip('0')
|
||||
if not Value:
|
||||
return True, ""
|
||||
Value = long(Value, 0)
|
||||
TypeLenMap = {
|
||||
#
|
||||
# 0x00 - 0xff
|
||||
#
|
||||
'UINT8' : 2,
|
||||
#
|
||||
# 0x0000 - 0xffff
|
||||
#
|
||||
'UINT16' : 4,
|
||||
#
|
||||
# 0x00000000 - 0xffffffff
|
||||
#
|
||||
'UINT32' : 8,
|
||||
#
|
||||
# 0x0 - 0xffffffffffffffff
|
||||
#
|
||||
'UINT64' : 16
|
||||
}
|
||||
HexStr = hex(Value)
|
||||
#
|
||||
# First two chars of HexStr are 0x and tail char is L
|
||||
#
|
||||
if TypeLenMap[Type] < len(HexStr) - 3:
|
||||
return False, ST.ERR_DECPARSE_PCD_INT_EXCEED % (StrVal, Type)
|
||||
except BaseException:
|
||||
return False, ST.ERR_DECPARSE_PCD_INT % (Value, Type)
|
||||
|
||||
return True, ""
|
||||
|
||||
## ParserHelper
|
||||
#
|
||||
class ParserHelper:
|
||||
def __init__(self, String, File=''):
|
||||
self._String = String
|
||||
self._StrLen = len(String)
|
||||
self._Index = 0
|
||||
self._File = File
|
||||
|
||||
## End
|
||||
#
|
||||
# End
|
||||
#
|
||||
def End(self):
|
||||
self.__SkipWhitespace()
|
||||
return self._Index >= self._StrLen
|
||||
|
||||
## __SkipWhitespace
|
||||
#
|
||||
# Skip whitespace
|
||||
#
|
||||
def __SkipWhitespace(self):
|
||||
for Char in self._String[self._Index:]:
|
||||
if Char not in ' \t':
|
||||
break
|
||||
self._Index += 1
|
||||
|
||||
## Expect
|
||||
#
|
||||
# Expect char in string
|
||||
#
|
||||
# @param ExpectChar: char expected in index of string
|
||||
#
|
||||
def Expect(self, ExpectChar):
|
||||
self.__SkipWhitespace()
|
||||
for Char in self._String[self._Index:]:
|
||||
if Char != ExpectChar:
|
||||
return False
|
||||
else:
|
||||
self._Index += 1
|
||||
return True
|
||||
#
|
||||
# Index out of bound of String
|
||||
#
|
||||
return False
|
||||
|
||||
## GetToken
|
||||
#
|
||||
# Get token until encounter StopChar, front whitespace is consumed
|
||||
#
|
||||
# @param StopChar: Get token until encounter char in StopChar
|
||||
# @param StkipPair: Only can be ' or ", StopChar in SkipPair are skipped
|
||||
#
|
||||
def GetToken(self, StopChar='.,|\t ', SkipPair='"'):
|
||||
self.__SkipWhitespace()
|
||||
PreIndex = self._Index
|
||||
InQuote = False
|
||||
LastChar = ''
|
||||
for Char in self._String[self._Index:]:
|
||||
if Char == SkipPair and LastChar != '\\':
|
||||
InQuote = not InQuote
|
||||
if Char in StopChar and not InQuote:
|
||||
break
|
||||
self._Index += 1
|
||||
if Char == '\\' and LastChar == '\\':
|
||||
LastChar = ''
|
||||
else:
|
||||
LastChar = Char
|
||||
return self._String[PreIndex:self._Index]
|
||||
|
||||
## AssertChar
|
||||
#
|
||||
# Assert char at current index of string is AssertChar, or will report
|
||||
# error message
|
||||
#
|
||||
# @param AssertChar: AssertChar
|
||||
# @param ErrorString: ErrorString
|
||||
# @param ErrorLineNum: ErrorLineNum
|
||||
#
|
||||
def AssertChar(self, AssertChar, ErrorString, ErrorLineNum):
|
||||
if not self.Expect(AssertChar):
|
||||
Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._File,
|
||||
Line=ErrorLineNum, ExtraData=ErrorString)
|
||||
|
||||
## AssertEnd
|
||||
#
|
||||
# @param ErrorString: ErrorString
|
||||
# @param ErrorLineNum: ErrorLineNum
|
||||
#
|
||||
def AssertEnd(self, ErrorString, ErrorLineNum):
|
||||
self.__SkipWhitespace()
|
||||
if self._Index != self._StrLen:
|
||||
Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._File,
|
||||
Line=ErrorLineNum, ExtraData=ErrorString)
|
219
BaseTools/Source/Python/UPT/Parser/InfAsBuiltProcess.py
Normal file
219
BaseTools/Source/Python/UPT/Parser/InfAsBuiltProcess.py
Normal file
@@ -0,0 +1,219 @@
|
||||
## @file
|
||||
# This file is used to provide method for process AsBuilt INF file. It will consumed by InfParser
|
||||
#
|
||||
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials are licensed and made available
|
||||
# under the terms and conditions of the BSD License which accompanies this
|
||||
# distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
'''
|
||||
InfAsBuiltProcess
|
||||
'''
|
||||
## Import modules
|
||||
#
|
||||
|
||||
import os
|
||||
import re
|
||||
from Library import GlobalData
|
||||
|
||||
import Logger.Log as Logger
|
||||
from Logger import StringTable as ST
|
||||
from Logger import ToolError
|
||||
|
||||
from Library.String import GetSplitValueList
|
||||
from Library.Misc import GetHelpStringByRemoveHashKey
|
||||
from Library.Misc import ValidFile
|
||||
from Library.Misc import ProcessLineExtender
|
||||
from Library.ParserValidate import IsValidPath
|
||||
from Library.Parsing import MacroParser
|
||||
from Parser.InfParserMisc import InfExpandMacro
|
||||
|
||||
from Library import DataType as DT
|
||||
|
||||
## GetLibInstanceInfo
|
||||
#
|
||||
# Get the information from Library Instance INF file.
|
||||
#
|
||||
# @param string. A string start with # and followed by INF file path
|
||||
# @param WorkSpace. The WorkSpace directory used to combined with INF file path.
|
||||
#
|
||||
# @return GUID, Version
|
||||
def GetLibInstanceInfo(String, WorkSpace, LineNo):
|
||||
|
||||
FileGuidString = ""
|
||||
VerString = ""
|
||||
|
||||
OrignalString = String
|
||||
String = String.strip()
|
||||
if not String:
|
||||
return None, None
|
||||
#
|
||||
# Remove "#" characters at the beginning
|
||||
#
|
||||
String = GetHelpStringByRemoveHashKey(String)
|
||||
String = String.strip()
|
||||
|
||||
FileLinesList = GetFileLineContent(String, WorkSpace, LineNo, OrignalString)
|
||||
|
||||
|
||||
ReFindFileGuidPattern = re.compile("^\s*FILE_GUID\s*=.*$")
|
||||
ReFindVerStringPattern = re.compile("^\s*VERSION_STRING\s*=.*$")
|
||||
|
||||
FileLinesList = ProcessLineExtender(FileLinesList)
|
||||
|
||||
for Line in FileLinesList:
|
||||
if ReFindFileGuidPattern.match(Line):
|
||||
FileGuidString = Line
|
||||
if ReFindVerStringPattern.match(Line):
|
||||
VerString = Line
|
||||
|
||||
if FileGuidString:
|
||||
FileGuidString = GetSplitValueList(FileGuidString, '=', 1)[1]
|
||||
if VerString:
|
||||
VerString = GetSplitValueList(VerString, '=', 1)[1]
|
||||
|
||||
return FileGuidString, VerString
|
||||
|
||||
## GetPackageListInfo
|
||||
#
|
||||
# Get the package information from INF file.
|
||||
#
|
||||
# @param string. A string start with # and followed by INF file path
|
||||
# @param WorkSpace. The WorkSpace directory used to combined with INF file path.
|
||||
#
|
||||
# @return GUID, Version
|
||||
def GetPackageListInfo(FileNameString, WorkSpace, LineNo):
|
||||
PackageInfoList = []
|
||||
DefineSectionMacros = {}
|
||||
PackageSectionMacros = {}
|
||||
|
||||
FileLinesList = GetFileLineContent(FileNameString, WorkSpace, LineNo, '')
|
||||
|
||||
RePackageHeader = re.compile('^\s*\[Packages.*\].*$')
|
||||
ReDefineHeader = re.compile('^\s*\[Defines].*$')
|
||||
|
||||
PackageHederFlag = False
|
||||
DefineHeaderFlag = False
|
||||
LineNo = -1
|
||||
for Line in FileLinesList:
|
||||
LineNo += 1
|
||||
Line = Line.strip()
|
||||
|
||||
if Line.startswith('['):
|
||||
PackageHederFlag = False
|
||||
DefineHeaderFlag = False
|
||||
|
||||
if Line.startswith("#"):
|
||||
continue
|
||||
|
||||
if not Line:
|
||||
continue
|
||||
|
||||
#
|
||||
# Found [Packages] section
|
||||
#
|
||||
if RePackageHeader.match(Line):
|
||||
PackageHederFlag = True
|
||||
continue
|
||||
|
||||
#
|
||||
# Found [Define] section
|
||||
#
|
||||
if ReDefineHeader.match(Line):
|
||||
DefineHeaderFlag = True
|
||||
continue
|
||||
|
||||
if DefineHeaderFlag:
|
||||
#
|
||||
# Find Macro
|
||||
#
|
||||
Name, Value = MacroParser((Line, LineNo),
|
||||
FileNameString,
|
||||
DT.MODEL_META_DATA_HEADER,
|
||||
DefineSectionMacros)
|
||||
|
||||
if Name != None:
|
||||
DefineSectionMacros[Name] = Value
|
||||
continue
|
||||
|
||||
if PackageHederFlag:
|
||||
|
||||
#
|
||||
# Find Macro
|
||||
#
|
||||
Name, Value = MacroParser((Line, LineNo),
|
||||
FileNameString,
|
||||
DT.MODEL_META_DATA_PACKAGE,
|
||||
DefineSectionMacros)
|
||||
if Name != None:
|
||||
PackageSectionMacros[Name] = Value
|
||||
continue
|
||||
|
||||
#
|
||||
# Replace with Local section Macro and [Defines] section Macro.
|
||||
#
|
||||
Line = InfExpandMacro(Line, (FileNameString, Line, LineNo), DefineSectionMacros, PackageSectionMacros, True)
|
||||
|
||||
Line = GetSplitValueList(Line, "#", 1)[0]
|
||||
Line = GetSplitValueList(Line, "|", 1)[0]
|
||||
PackageInfoList.append(Line)
|
||||
|
||||
return PackageInfoList
|
||||
|
||||
def GetFileLineContent(FileName, WorkSpace, LineNo, OriginalString):
|
||||
|
||||
if not LineNo:
|
||||
LineNo = -1
|
||||
|
||||
#
|
||||
# Validate file name exist.
|
||||
#
|
||||
FullFileName = os.path.normpath(os.path.realpath(os.path.join(WorkSpace, FileName)))
|
||||
if not (ValidFile(FullFileName)):
|
||||
Logger.Error("InfParser",
|
||||
ToolError.FORMAT_INVALID,
|
||||
ST.ERR_FILELIST_EXIST%(FileName),
|
||||
File=GlobalData.gINF_MODULE_NAME,
|
||||
Line=LineNo,
|
||||
ExtraData=OriginalString)
|
||||
|
||||
#
|
||||
# Validate file exist/format.
|
||||
#
|
||||
if IsValidPath(FileName, WorkSpace):
|
||||
IsValidFileFlag = True
|
||||
else:
|
||||
Logger.Error("InfParser",
|
||||
ToolError.FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID%(FileName),
|
||||
File=GlobalData.gINF_MODULE_NAME,
|
||||
Line=LineNo,
|
||||
ExtraData=OriginalString)
|
||||
return False
|
||||
|
||||
FileLinesList = []
|
||||
|
||||
if IsValidFileFlag:
|
||||
try:
|
||||
FullFileName = FullFileName.replace('\\', '/')
|
||||
Inputfile = open(FullFileName, "rb", 0)
|
||||
try:
|
||||
FileLinesList = Inputfile.readlines()
|
||||
except BaseException:
|
||||
Logger.Error("InfParser", ToolError.FILE_READ_FAILURE, ST.ERR_FILE_OPEN_FAILURE, File=FullFileName)
|
||||
finally:
|
||||
Inputfile.close()
|
||||
except BaseException:
|
||||
Logger.Error("InfParser",
|
||||
ToolError.FILE_READ_FAILURE,
|
||||
ST.ERR_FILE_OPEN_FAILURE,
|
||||
File=FullFileName)
|
||||
|
||||
FileLinesList = ProcessLineExtender(FileLinesList)
|
||||
|
||||
return FileLinesList
|
||||
|
217
BaseTools/Source/Python/UPT/Parser/InfBinarySectionParser.py
Normal file
217
BaseTools/Source/Python/UPT/Parser/InfBinarySectionParser.py
Normal file
@@ -0,0 +1,217 @@
|
||||
## @file
|
||||
# This file contained the parser for [Binaries] sections in INF file
|
||||
#
|
||||
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials are licensed and made available
|
||||
# under the terms and conditions of the BSD License which accompanies this
|
||||
# distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
'''
|
||||
InfBinarySectionParser
|
||||
'''
|
||||
##
|
||||
# Import Modules
|
||||
#
|
||||
|
||||
import Logger.Log as Logger
|
||||
from Logger import StringTable as ST
|
||||
from Logger.ToolError import FORMAT_INVALID
|
||||
from Parser.InfParserMisc import InfExpandMacro
|
||||
from Library import DataType as DT
|
||||
from Library.Parsing import MacroParser
|
||||
from Library.Misc import GetSplitValueList
|
||||
from Object.Parser.InfCommonObject import InfLineCommentObject
|
||||
from Object.Parser.InfCommonObject import CurrentLine
|
||||
from Parser.InfParserMisc import InfParserSectionRoot
|
||||
|
||||
class InfBinarySectionParser(InfParserSectionRoot):
|
||||
## InfBinaryParser
|
||||
#
|
||||
#
|
||||
def InfBinaryParser(self, SectionString, InfSectionObject, FileName):
|
||||
#
|
||||
# Macro defined in this section
|
||||
#
|
||||
SectionMacros = {}
|
||||
ValueList = []
|
||||
#
|
||||
# For UI (UI, SEC_UI, UNI_UI) binaries
|
||||
# One and only one UI section can be included
|
||||
#
|
||||
UiBinaryList = []
|
||||
#
|
||||
# For Version (VER, SEC_VER, UNI_VER).
|
||||
# One and only one VER section on be included
|
||||
#
|
||||
VerBinaryList = []
|
||||
#
|
||||
# For other common type binaries
|
||||
#
|
||||
ComBinaryList = []
|
||||
|
||||
StillCommentFalg = False
|
||||
HeaderComments = []
|
||||
LineComment = None
|
||||
|
||||
AllSectionContent = ''
|
||||
#
|
||||
# Parse section content
|
||||
#
|
||||
for Line in SectionString:
|
||||
BinLineContent = Line[0]
|
||||
BinLineNo = Line[1]
|
||||
|
||||
if BinLineContent.strip() == '':
|
||||
continue
|
||||
|
||||
CurrentLineObj = CurrentLine()
|
||||
CurrentLineObj.FileName = FileName
|
||||
CurrentLineObj.LineString = BinLineContent
|
||||
CurrentLineObj.LineNo = BinLineNo
|
||||
#
|
||||
# Found Header Comments
|
||||
#
|
||||
if BinLineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
|
||||
#
|
||||
# Last line is comments, and this line go on.
|
||||
#
|
||||
if StillCommentFalg:
|
||||
HeaderComments.append(Line)
|
||||
AllSectionContent += BinLineContent + DT.END_OF_LINE
|
||||
continue
|
||||
#
|
||||
# First time encounter comment
|
||||
#
|
||||
else:
|
||||
#
|
||||
# Clear original data
|
||||
#
|
||||
HeaderComments = []
|
||||
HeaderComments.append(Line)
|
||||
AllSectionContent += BinLineContent + DT.END_OF_LINE
|
||||
StillCommentFalg = True
|
||||
continue
|
||||
else:
|
||||
StillCommentFalg = False
|
||||
|
||||
if len(HeaderComments) >= 1:
|
||||
LineComment = InfLineCommentObject()
|
||||
LineCommentContent = ''
|
||||
for Item in HeaderComments:
|
||||
LineCommentContent += Item[0] + DT.END_OF_LINE
|
||||
LineComment.SetHeaderComments(LineCommentContent)
|
||||
|
||||
#
|
||||
# Find Tail comment.
|
||||
#
|
||||
if BinLineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
|
||||
TailComments = BinLineContent[BinLineContent.find(DT.TAB_COMMENT_SPLIT):]
|
||||
BinLineContent = BinLineContent[:BinLineContent.find(DT.TAB_COMMENT_SPLIT)]
|
||||
if LineComment == None:
|
||||
LineComment = InfLineCommentObject()
|
||||
LineComment.SetTailComments(TailComments)
|
||||
|
||||
#
|
||||
# Find Macro
|
||||
#
|
||||
MacroDef = MacroParser((BinLineContent, BinLineNo),
|
||||
FileName,
|
||||
DT.MODEL_EFI_BINARY_FILE,
|
||||
self.FileLocalMacros)
|
||||
if MacroDef[0] != None:
|
||||
SectionMacros[MacroDef[0]] = MacroDef[1]
|
||||
LineComment = None
|
||||
HeaderComments = []
|
||||
continue
|
||||
|
||||
#
|
||||
# Replace with Local section Macro and [Defines] section Macro.
|
||||
#
|
||||
LineContent = InfExpandMacro(BinLineContent,
|
||||
(FileName, BinLineContent, BinLineNo),
|
||||
self.FileLocalMacros,
|
||||
SectionMacros, True)
|
||||
|
||||
AllSectionContent += LineContent + DT.END_OF_LINE
|
||||
TokenList = GetSplitValueList(LineContent, DT.TAB_VALUE_SPLIT, 1)
|
||||
ValueList[0:len(TokenList)] = TokenList
|
||||
|
||||
#
|
||||
# Should equal to UI/SEC_UI/UNI_UI
|
||||
#
|
||||
ValueList[0] = ValueList[0].strip()
|
||||
if ValueList[0] == DT.BINARY_FILE_TYPE_UNI_UI or \
|
||||
ValueList[0] == DT.BINARY_FILE_TYPE_SEC_UI or \
|
||||
ValueList[0] == DT.BINARY_FILE_TYPE_UI:
|
||||
if len(ValueList) == 2:
|
||||
TokenList = GetSplitValueList(ValueList[1],
|
||||
DT.TAB_VALUE_SPLIT,
|
||||
2)
|
||||
NewValueList = []
|
||||
NewValueList.append(ValueList[0])
|
||||
for Item in TokenList:
|
||||
NewValueList.append(Item)
|
||||
UiBinaryList.append((NewValueList,
|
||||
LineComment,
|
||||
CurrentLineObj))
|
||||
#
|
||||
# Should equal to VER/SEC_VER/UNI_VER
|
||||
#
|
||||
elif ValueList[0] == DT.BINARY_FILE_TYPE_UNI_VER or \
|
||||
ValueList[0] == DT.BINARY_FILE_TYPE_SEC_VER or \
|
||||
ValueList[0] == DT.BINARY_FILE_TYPE_VER:
|
||||
if len(ValueList) == 2:
|
||||
TokenList = GetSplitValueList(ValueList[1],
|
||||
DT.TAB_VALUE_SPLIT,
|
||||
2)
|
||||
NewValueList = []
|
||||
NewValueList.append(ValueList[0])
|
||||
for Item in TokenList:
|
||||
NewValueList.append(Item)
|
||||
VerBinaryList.append((NewValueList,
|
||||
LineComment,
|
||||
CurrentLineObj))
|
||||
else:
|
||||
if len(ValueList) == 2:
|
||||
TokenList = GetSplitValueList(ValueList[1],
|
||||
DT.TAB_VALUE_SPLIT,
|
||||
4)
|
||||
NewValueList = []
|
||||
NewValueList.append(ValueList[0])
|
||||
for Item in TokenList:
|
||||
NewValueList.append(Item)
|
||||
ComBinaryList.append((NewValueList,
|
||||
LineComment,
|
||||
CurrentLineObj))
|
||||
|
||||
ValueList = []
|
||||
LineComment = None
|
||||
TailComments = ''
|
||||
HeaderComments = []
|
||||
continue
|
||||
|
||||
#
|
||||
# Current section archs
|
||||
#
|
||||
ArchList = []
|
||||
for Item in self.LastSectionHeaderContent:
|
||||
if Item[1] not in ArchList:
|
||||
ArchList.append(Item[1])
|
||||
InfSectionObject.SetSupArchList(Item[1])
|
||||
|
||||
InfSectionObject.SetAllContent(AllSectionContent)
|
||||
if not InfSectionObject.SetBinary(UiBinaryList,
|
||||
VerBinaryList,
|
||||
ComBinaryList,
|
||||
ArchList):
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR%("[Binaries]"),
|
||||
File=FileName,
|
||||
Line=Item[3])
|
||||
|
@@ -0,0 +1,218 @@
|
||||
## @file
|
||||
# This file contained the parser for BuildOption sections in INF file
|
||||
#
|
||||
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials are licensed and made available
|
||||
# under the terms and conditions of the BSD License which accompanies this
|
||||
# distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
|
||||
'''
|
||||
InfBuildOptionSectionParser
|
||||
'''
|
||||
##
|
||||
# Import Modules
|
||||
#
|
||||
from Library import DataType as DT
|
||||
from Library import GlobalData
|
||||
import Logger.Log as Logger
|
||||
from Logger import StringTable as ST
|
||||
from Logger.ToolError import FORMAT_INVALID
|
||||
from Parser.InfParserMisc import InfExpandMacro
|
||||
from Library.Misc import GetSplitValueList
|
||||
from Parser.InfParserMisc import IsAsBuildOptionInfo
|
||||
from Library.Misc import GetHelpStringByRemoveHashKey
|
||||
from Library.ParserValidate import IsValidFamily
|
||||
from Library.ParserValidate import IsValidBuildOptionName
|
||||
from Parser.InfParserMisc import InfParserSectionRoot
|
||||
|
||||
class InfBuildOptionSectionParser(InfParserSectionRoot):
|
||||
## InfBuildOptionParser
|
||||
#
|
||||
#
|
||||
def InfBuildOptionParser(self, SectionString, InfSectionObject, FileName):
|
||||
|
||||
BuildOptionList = []
|
||||
SectionContent = ''
|
||||
|
||||
if not GlobalData.gIS_BINARY_INF:
|
||||
ValueList = []
|
||||
LineNo = 0
|
||||
|
||||
for Line in SectionString:
|
||||
LineContent = Line[0]
|
||||
LineNo = Line[1]
|
||||
TailComments = ''
|
||||
ReplaceFlag = False
|
||||
|
||||
if LineContent.strip() == '':
|
||||
SectionContent += LineContent + DT.END_OF_LINE
|
||||
continue
|
||||
#
|
||||
# Found Comment
|
||||
#
|
||||
if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
|
||||
SectionContent += LineContent + DT.END_OF_LINE
|
||||
continue
|
||||
|
||||
#
|
||||
# Find Tail comment.
|
||||
#
|
||||
if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
|
||||
TailComments = LineContent[LineContent.find(DT.TAB_COMMENT_SPLIT):]
|
||||
LineContent = LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)]
|
||||
|
||||
TokenList = GetSplitValueList(LineContent, DT.TAB_DEQUAL_SPLIT, 1)
|
||||
if len(TokenList) == 2:
|
||||
#
|
||||
# "Replace" type build option
|
||||
#
|
||||
TokenList.append('True')
|
||||
ReplaceFlag = True
|
||||
else:
|
||||
TokenList = GetSplitValueList(LineContent, DT.TAB_EQUAL_SPLIT, 1)
|
||||
#
|
||||
# "Append" type build option
|
||||
#
|
||||
if len(TokenList) == 2:
|
||||
TokenList.append('False')
|
||||
else:
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_BUILD_OPTION_FORMAT_INVALID,
|
||||
ExtraData=LineContent,
|
||||
File=FileName,
|
||||
Line=LineNo)
|
||||
|
||||
ValueList[0:len(TokenList)] = TokenList
|
||||
|
||||
#
|
||||
# Replace with [Defines] section Macro
|
||||
#
|
||||
ValueList[0] = InfExpandMacro(ValueList[0], (FileName, LineContent, LineNo),
|
||||
self.FileLocalMacros, None)
|
||||
ValueList[1] = InfExpandMacro(ValueList[1], (FileName, LineContent, LineNo),
|
||||
self.FileLocalMacros, None, True)
|
||||
EqualString = ''
|
||||
if not ReplaceFlag:
|
||||
EqualString = ' = '
|
||||
else:
|
||||
EqualString = ' == '
|
||||
|
||||
SectionContent += ValueList[0] + EqualString + ValueList[1] + TailComments + DT.END_OF_LINE
|
||||
|
||||
Family = GetSplitValueList(ValueList[0], DT.TAB_COLON_SPLIT, 1)
|
||||
if len(Family) == 2:
|
||||
if not IsValidFamily(Family[0]):
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_BUILD_OPTION_FORMAT_INVALID,
|
||||
ExtraData=LineContent,
|
||||
File=FileName,
|
||||
Line=LineNo)
|
||||
if not IsValidBuildOptionName(Family[1]):
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_BUILD_OPTION_FORMAT_INVALID,
|
||||
ExtraData=LineContent,
|
||||
File=FileName,
|
||||
Line=LineNo)
|
||||
if len(Family) == 1:
|
||||
if not IsValidBuildOptionName(Family[0]):
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_BUILD_OPTION_FORMAT_INVALID,
|
||||
ExtraData=LineContent,
|
||||
File=FileName,
|
||||
Line=LineNo)
|
||||
|
||||
BuildOptionList.append(ValueList)
|
||||
ValueList = []
|
||||
continue
|
||||
else:
|
||||
BuildOptionList = InfAsBuiltBuildOptionParser(SectionString, FileName)
|
||||
|
||||
#
|
||||
# Current section archs
|
||||
#
|
||||
ArchList = []
|
||||
LastItem = ''
|
||||
for Item in self.LastSectionHeaderContent:
|
||||
LastItem = Item
|
||||
if not (Item[1] == '' or Item[1] == '') and Item[1] not in ArchList:
|
||||
ArchList.append(Item[1])
|
||||
InfSectionObject.SetSupArchList(Item[1])
|
||||
|
||||
InfSectionObject.SetAllContent(SectionContent)
|
||||
if not InfSectionObject.SetBuildOptions(BuildOptionList, ArchList, SectionContent):
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR%("[BuilOptions]"),
|
||||
File=FileName,
|
||||
Line=LastItem[3])
|
||||
|
||||
## InfBuildOptionParser
|
||||
#
|
||||
#
|
||||
def InfAsBuiltBuildOptionParser(SectionString, FileName):
|
||||
BuildOptionList = []
|
||||
#
|
||||
# AsBuild Binary INF file.
|
||||
#
|
||||
AsBuildOptionFlag = False
|
||||
BuildOptionItem = []
|
||||
Count = 0
|
||||
for Line in SectionString:
|
||||
Count += 1
|
||||
LineContent = Line[0]
|
||||
LineNo = Line[1]
|
||||
|
||||
#
|
||||
# The last line
|
||||
#
|
||||
if len(SectionString) == Count:
|
||||
if LineContent.strip().startswith("##") and AsBuildOptionFlag:
|
||||
BuildOptionList.append(BuildOptionItem)
|
||||
BuildOptionList.append([GetHelpStringByRemoveHashKey(LineContent)])
|
||||
elif LineContent.strip().startswith("#") and AsBuildOptionFlag:
|
||||
BuildOptionInfo = GetHelpStringByRemoveHashKey(LineContent)
|
||||
BuildOptionItem.append(BuildOptionInfo)
|
||||
BuildOptionList.append(BuildOptionItem)
|
||||
else:
|
||||
if len(BuildOptionItem) > 0:
|
||||
BuildOptionList.append(BuildOptionItem)
|
||||
|
||||
break
|
||||
|
||||
if LineContent.strip() == '':
|
||||
AsBuildOptionFlag = False
|
||||
continue
|
||||
|
||||
if LineContent.strip().startswith("##") and AsBuildOptionFlag:
|
||||
if len(BuildOptionItem) > 0:
|
||||
BuildOptionList.append(BuildOptionItem)
|
||||
|
||||
BuildOptionItem = []
|
||||
|
||||
if not LineContent.strip().startswith("#"):
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_BO_CONTATIN_ASBUILD_AND_COMMON,
|
||||
File=FileName,
|
||||
Line=LineNo,
|
||||
ExtraData=LineContent)
|
||||
|
||||
if IsAsBuildOptionInfo(LineContent):
|
||||
AsBuildOptionFlag = True
|
||||
continue
|
||||
|
||||
if AsBuildOptionFlag:
|
||||
BuildOptionInfo = GetHelpStringByRemoveHashKey(LineContent)
|
||||
BuildOptionItem.append(BuildOptionInfo)
|
||||
|
||||
return BuildOptionList
|
197
BaseTools/Source/Python/UPT/Parser/InfDefineSectionParser.py
Normal file
197
BaseTools/Source/Python/UPT/Parser/InfDefineSectionParser.py
Normal file
@@ -0,0 +1,197 @@
|
||||
## @file
|
||||
# This file contained the parser for define sections in INF file
|
||||
#
|
||||
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials are licensed and made available
|
||||
# under the terms and conditions of the BSD License which accompanies this
|
||||
# distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
|
||||
'''
|
||||
InfDefineSectionParser
|
||||
'''
|
||||
##
|
||||
# Import Modules
|
||||
#
|
||||
import re
|
||||
|
||||
from Library import DataType as DT
|
||||
from Library import GlobalData
|
||||
from Library.Parsing import MacroParser
|
||||
from Library.Misc import GetSplitValueList
|
||||
from Library.ParserValidate import IsValidArch
|
||||
from Object.Parser.InfCommonObject import InfLineCommentObject
|
||||
from Object.Parser.InfDefineObject import InfDefMember
|
||||
from Parser.InfParserMisc import InfExpandMacro
|
||||
from Object.Parser.InfMisc import ErrorInInf
|
||||
from Logger import StringTable as ST
|
||||
from Parser.InfParserMisc import InfParserSectionRoot
|
||||
|
||||
## __GetValidateArchList
|
||||
#
|
||||
#
|
||||
def GetValidateArchList(LineContent):
|
||||
|
||||
TempArch = ''
|
||||
ArchList = []
|
||||
ValidateAcrhPatten = re.compile(r"^\s*#\s*VALID_ARCHITECTURES\s*=\s*.*$", re.DOTALL)
|
||||
|
||||
if ValidateAcrhPatten.match(LineContent):
|
||||
TempArch = GetSplitValueList(LineContent, DT.TAB_EQUAL_SPLIT, 1)[1]
|
||||
|
||||
TempArch = GetSplitValueList(TempArch, '(', 1)[0]
|
||||
|
||||
ArchList = re.split('\s+', TempArch)
|
||||
NewArchList = []
|
||||
for Arch in ArchList:
|
||||
if IsValidArch(Arch):
|
||||
NewArchList.append(Arch)
|
||||
|
||||
ArchList = NewArchList
|
||||
|
||||
return ArchList
|
||||
|
||||
class InfDefinSectionParser(InfParserSectionRoot):
|
||||
def InfDefineParser(self, SectionString, InfSectionObject, FileName, SectionComment):
|
||||
|
||||
if SectionComment:
|
||||
pass
|
||||
#
|
||||
# Parser Defines section content and fill self._ContentList dict.
|
||||
#
|
||||
StillCommentFalg = False
|
||||
HeaderComments = []
|
||||
SectionContent = ''
|
||||
ArchList = []
|
||||
_ContentList = []
|
||||
_ValueList = []
|
||||
#
|
||||
# Add WORKSPACE to global Marco dict.
|
||||
#
|
||||
self.FileLocalMacros['WORKSPACE'] = GlobalData.gWORKSPACE
|
||||
|
||||
for Line in SectionString:
|
||||
LineContent = Line[0]
|
||||
LineNo = Line[1]
|
||||
TailComments = ''
|
||||
LineComment = None
|
||||
|
||||
LineInfo = ['', -1, '']
|
||||
LineInfo[0] = FileName
|
||||
LineInfo[1] = LineNo
|
||||
LineInfo[2] = LineContent
|
||||
|
||||
if LineContent.strip() == '':
|
||||
continue
|
||||
#
|
||||
# The first time encountered VALIDATE_ARCHITECHERS will be considered as support arch list.
|
||||
#
|
||||
if not ArchList:
|
||||
ArchList = GetValidateArchList(LineContent)
|
||||
|
||||
#
|
||||
# Parser Comment
|
||||
#
|
||||
if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
|
||||
#
|
||||
# Last line is comments, and this line go on.
|
||||
#
|
||||
if StillCommentFalg:
|
||||
HeaderComments.append(Line)
|
||||
SectionContent += LineContent + DT.END_OF_LINE
|
||||
continue
|
||||
#
|
||||
# First time encounter comment
|
||||
#
|
||||
else:
|
||||
#
|
||||
# Clear original data
|
||||
#
|
||||
HeaderComments = []
|
||||
HeaderComments.append(Line)
|
||||
StillCommentFalg = True
|
||||
SectionContent += LineContent + DT.END_OF_LINE
|
||||
continue
|
||||
else:
|
||||
StillCommentFalg = False
|
||||
|
||||
if len(HeaderComments) >= 1:
|
||||
LineComment = InfLineCommentObject()
|
||||
LineCommentContent = ''
|
||||
for Item in HeaderComments:
|
||||
LineCommentContent += Item[0] + DT.END_OF_LINE
|
||||
LineComment.SetHeaderComments(LineCommentContent)
|
||||
|
||||
#
|
||||
# Find Tail comment.
|
||||
#
|
||||
if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
|
||||
TailComments = LineContent[LineContent.find(DT.TAB_COMMENT_SPLIT):]
|
||||
LineContent = LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)]
|
||||
if LineComment == None:
|
||||
LineComment = InfLineCommentObject()
|
||||
LineComment.SetTailComments(TailComments)
|
||||
|
||||
#
|
||||
# Find Macro
|
||||
#
|
||||
Name, Value = MacroParser((LineContent, LineNo),
|
||||
FileName,
|
||||
DT.MODEL_META_DATA_HEADER,
|
||||
self.FileLocalMacros)
|
||||
if Name != None:
|
||||
self.FileLocalMacros[Name] = Value
|
||||
continue
|
||||
|
||||
#
|
||||
# Replace with [Defines] section Macro
|
||||
#
|
||||
LineContent = InfExpandMacro(LineContent,
|
||||
(FileName, LineContent, LineNo),
|
||||
self.FileLocalMacros,
|
||||
None, True)
|
||||
|
||||
SectionContent += LineContent + DT.END_OF_LINE
|
||||
|
||||
TokenList = GetSplitValueList(LineContent, DT.TAB_EQUAL_SPLIT, 1)
|
||||
if len(TokenList) < 2:
|
||||
ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_NO_VALUE,
|
||||
LineInfo=LineInfo)
|
||||
_ValueList[0:len(TokenList)] = TokenList
|
||||
if not _ValueList[0]:
|
||||
ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_NO_NAME,
|
||||
LineInfo=LineInfo)
|
||||
if not _ValueList[1]:
|
||||
ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_NO_VALUE,
|
||||
LineInfo=LineInfo)
|
||||
|
||||
Name, Value = _ValueList[0], _ValueList[1]
|
||||
|
||||
InfDefMemberObj = InfDefMember(Name, Value)
|
||||
if (LineComment != None):
|
||||
InfDefMemberObj.Comments.SetHeaderComments(LineComment.GetHeaderComments())
|
||||
InfDefMemberObj.Comments.SetTailComments(LineComment.GetTailComments())
|
||||
|
||||
InfDefMemberObj.CurrentLine.SetFileName(self.FullPath)
|
||||
InfDefMemberObj.CurrentLine.SetLineString(LineContent)
|
||||
InfDefMemberObj.CurrentLine.SetLineNo(LineNo)
|
||||
|
||||
_ContentList.append(InfDefMemberObj)
|
||||
HeaderComments = []
|
||||
TailComments = ''
|
||||
|
||||
#
|
||||
# Current Define section archs
|
||||
#
|
||||
if not ArchList:
|
||||
ArchList = ['COMMON']
|
||||
|
||||
InfSectionObject.SetAllContent(SectionContent)
|
||||
|
||||
InfSectionObject.SetDefines(_ContentList, Arch=ArchList)
|
||||
|
104
BaseTools/Source/Python/UPT/Parser/InfDepexSectionParser.py
Normal file
104
BaseTools/Source/Python/UPT/Parser/InfDepexSectionParser.py
Normal file
@@ -0,0 +1,104 @@
|
||||
## @file
|
||||
# This file contained the parser for [Depex] sections in INF file
|
||||
#
|
||||
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials are licensed and made available
|
||||
# under the terms and conditions of the BSD License which accompanies this
|
||||
# distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
'''
|
||||
InfDepexSectionParser
|
||||
'''
|
||||
##
|
||||
# Import Modules
|
||||
#
|
||||
import re
|
||||
import Logger.Log as Logger
|
||||
from Logger import StringTable as ST
|
||||
from Logger.ToolError import FORMAT_INVALID
|
||||
from Parser.InfParserMisc import InfExpandMacro
|
||||
from Library import DataType as DT
|
||||
from Library.Misc import GetSplitValueList
|
||||
from Parser.InfParserMisc import InfParserSectionRoot
|
||||
|
||||
class InfDepexSectionParser(InfParserSectionRoot):
|
||||
## InfDepexParser
|
||||
#
|
||||
# For now, only separate Depex String and comments.
|
||||
# Have two types of section header.
|
||||
# 1. [Depex.Arch.ModuleType, ...]
|
||||
# 2. [Depex.Arch|FFE, ...]
|
||||
#
|
||||
def InfDepexParser(self, SectionString, InfSectionObject, FileName):
|
||||
DepexContent = []
|
||||
DepexComment = []
|
||||
ValueList = []
|
||||
#
|
||||
# Parse section content
|
||||
#
|
||||
for Line in SectionString:
|
||||
LineContent = Line[0]
|
||||
LineNo = Line[1]
|
||||
|
||||
#
|
||||
# Found comment
|
||||
#
|
||||
if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
|
||||
DepexComment.append((LineContent, LineNo))
|
||||
continue
|
||||
#
|
||||
# Replace with [Defines] section Macro
|
||||
#
|
||||
LineContent = InfExpandMacro(LineContent,
|
||||
(FileName, LineContent, Line[1]),
|
||||
self.FileLocalMacros,
|
||||
None, True)
|
||||
|
||||
CommentCount = LineContent.find(DT.TAB_COMMENT_SPLIT)
|
||||
|
||||
if CommentCount > -1:
|
||||
DepexComment.append((LineContent[CommentCount:], LineNo))
|
||||
LineContent = LineContent[:CommentCount-1]
|
||||
|
||||
|
||||
CommentCount = -1
|
||||
DepexContent.append((LineContent, LineNo))
|
||||
|
||||
TokenList = GetSplitValueList(LineContent, DT.TAB_COMMENT_SPLIT)
|
||||
ValueList[0:len(TokenList)] = TokenList
|
||||
|
||||
#
|
||||
# Current section archs
|
||||
#
|
||||
KeyList = []
|
||||
LastItem = ''
|
||||
for Item in self.LastSectionHeaderContent:
|
||||
LastItem = Item
|
||||
if (Item[1], Item[2], Item[3]) not in KeyList:
|
||||
KeyList.append((Item[1], Item[2], Item[3]))
|
||||
|
||||
NewCommentList = []
|
||||
FormatCommentLn = -1
|
||||
ReFormatComment = re.compile(r"""#(?:\s*)\[(.*?)\](?:.*)""", re.DOTALL)
|
||||
for CommentItem in DepexComment:
|
||||
CommentContent = CommentItem[0]
|
||||
if ReFormatComment.match(CommentContent) != None:
|
||||
FormatCommentLn = CommentItem[1] + 1
|
||||
continue
|
||||
|
||||
if CommentItem[1] != FormatCommentLn:
|
||||
NewCommentList.append(CommentContent)
|
||||
else:
|
||||
FormatCommentLn = CommentItem[1] + 1
|
||||
|
||||
if not InfSectionObject.SetDepex(DepexContent, KeyList = KeyList, CommentList = NewCommentList):
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR%("[Depex]"),
|
||||
File=FileName,
|
||||
Line=LastItem[3])
|
@@ -0,0 +1,382 @@
|
||||
## @file
|
||||
# This file contained the parser for [Guids], [Ppis], [Protocols] sections in INF file
|
||||
#
|
||||
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials are licensed and made available
|
||||
# under the terms and conditions of the BSD License which accompanies this
|
||||
# distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
'''
|
||||
InfGuidPpiProtocolSectionParser
|
||||
'''
|
||||
##
|
||||
# Import Modules
|
||||
#
|
||||
|
||||
import Logger.Log as Logger
|
||||
from Logger import StringTable as ST
|
||||
from Logger.ToolError import FORMAT_INVALID
|
||||
from Parser.InfParserMisc import InfExpandMacro
|
||||
from Library import DataType as DT
|
||||
from Library import GlobalData
|
||||
from Library.Parsing import MacroParser
|
||||
from Library.Misc import GetSplitValueList
|
||||
from Library.ParserValidate import IsValidIdString
|
||||
from Library.ParserValidate import IsValidUserId
|
||||
from Library.ParserValidate import IsValidArch
|
||||
from Parser.InfParserMisc import InfParserSectionRoot
|
||||
|
||||
class InfGuidPpiProtocolSectionParser(InfParserSectionRoot):
|
||||
## InfGuidParser
|
||||
#
|
||||
#
|
||||
def InfGuidParser(self, SectionString, InfSectionObject, FileName):
|
||||
#
|
||||
# Macro defined in this section
|
||||
#
|
||||
SectionMacros = {}
|
||||
ValueList = []
|
||||
GuidList = []
|
||||
CommentsList = []
|
||||
CurrentLineVar = None
|
||||
#
|
||||
# Parse section content
|
||||
#
|
||||
for Line in SectionString:
|
||||
LineContent = Line[0]
|
||||
LineNo = Line[1]
|
||||
|
||||
if LineContent.strip() == '':
|
||||
CommentsList = []
|
||||
continue
|
||||
|
||||
if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
|
||||
CommentsList.append(Line)
|
||||
continue
|
||||
else:
|
||||
#
|
||||
# Encounter a GUID entry
|
||||
#
|
||||
if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
|
||||
CommentsList.append((
|
||||
LineContent[LineContent.find(DT.TAB_COMMENT_SPLIT):],
|
||||
LineNo))
|
||||
LineContent = \
|
||||
LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)]
|
||||
|
||||
if LineContent != '':
|
||||
#
|
||||
# Find Macro
|
||||
#
|
||||
Name, Value = MacroParser((LineContent, LineNo),
|
||||
FileName,
|
||||
DT.MODEL_EFI_GUID,
|
||||
self.FileLocalMacros)
|
||||
if Name != None:
|
||||
SectionMacros[Name] = Value
|
||||
CommentsList = []
|
||||
ValueList = []
|
||||
continue
|
||||
|
||||
TokenList = GetSplitValueList(LineContent, DT.TAB_VALUE_SPLIT, 1)
|
||||
ValueList[0:len(TokenList)] = TokenList
|
||||
|
||||
#
|
||||
# Replace with Local section Macro and [Defines] section Macro.
|
||||
#
|
||||
ValueList = [InfExpandMacro(Value, (FileName, LineContent, LineNo),
|
||||
self.FileLocalMacros, SectionMacros, True)
|
||||
for Value in ValueList]
|
||||
|
||||
CurrentLineVar = (LineContent, LineNo, FileName)
|
||||
|
||||
|
||||
if len(ValueList) >= 1:
|
||||
GuidList.append((ValueList, CommentsList, CurrentLineVar))
|
||||
CommentsList = []
|
||||
ValueList = []
|
||||
continue
|
||||
|
||||
#
|
||||
# Current section archs
|
||||
#
|
||||
ArchList = []
|
||||
LineIndex = -1
|
||||
for Item in self.LastSectionHeaderContent:
|
||||
LineIndex = Item[3]
|
||||
if Item[1] not in ArchList:
|
||||
ArchList.append(Item[1])
|
||||
|
||||
if not InfSectionObject.SetGuid(GuidList, Arch=ArchList):
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Guid]"),
|
||||
File=FileName,
|
||||
Line=LineIndex)
|
||||
|
||||
## InfPpiParser
|
||||
#
|
||||
#
|
||||
def InfPpiParser(self, SectionString, InfSectionObject, FileName):
|
||||
#
|
||||
# Macro defined in this section
|
||||
#
|
||||
SectionMacros = {}
|
||||
ValueList = []
|
||||
PpiList = []
|
||||
CommentsList = []
|
||||
CurrentLineVar = None
|
||||
#
|
||||
# Parse section content
|
||||
#
|
||||
for Line in SectionString:
|
||||
LineContent = Line[0]
|
||||
LineNo = Line[1]
|
||||
|
||||
if LineContent.strip() == '':
|
||||
CommentsList = []
|
||||
continue
|
||||
|
||||
if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
|
||||
CommentsList.append(Line)
|
||||
continue
|
||||
else:
|
||||
#
|
||||
# Encounter a PPI entry
|
||||
#
|
||||
if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
|
||||
CommentsList.append((
|
||||
LineContent[LineContent.find(DT.TAB_COMMENT_SPLIT):],
|
||||
LineNo))
|
||||
LineContent = \
|
||||
LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)]
|
||||
|
||||
if LineContent != '':
|
||||
#
|
||||
# Find Macro
|
||||
#
|
||||
Name, Value = MacroParser((LineContent, LineNo),
|
||||
FileName,
|
||||
DT.MODEL_EFI_PPI,
|
||||
self.FileLocalMacros)
|
||||
if Name != None:
|
||||
SectionMacros[Name] = Value
|
||||
ValueList = []
|
||||
CommentsList = []
|
||||
continue
|
||||
|
||||
TokenList = GetSplitValueList(LineContent, DT.TAB_VALUE_SPLIT, 1)
|
||||
ValueList[0:len(TokenList)] = TokenList
|
||||
|
||||
#
|
||||
# Replace with Local section Macro and [Defines] section Macro.
|
||||
#
|
||||
ValueList = [InfExpandMacro(Value, (FileName, LineContent, LineNo), self.FileLocalMacros, SectionMacros)
|
||||
for Value in ValueList]
|
||||
|
||||
CurrentLineVar = (LineContent, LineNo, FileName)
|
||||
|
||||
if len(ValueList) >= 1:
|
||||
PpiList.append((ValueList, CommentsList, CurrentLineVar))
|
||||
ValueList = []
|
||||
CommentsList = []
|
||||
continue
|
||||
|
||||
#
|
||||
# Current section archs
|
||||
#
|
||||
ArchList = []
|
||||
LineIndex = -1
|
||||
for Item in self.LastSectionHeaderContent:
|
||||
LineIndex = Item[3]
|
||||
if Item[1] not in ArchList:
|
||||
ArchList.append(Item[1])
|
||||
|
||||
if not InfSectionObject.SetPpi(PpiList, Arch=ArchList):
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Ppis]"),
|
||||
File=FileName,
|
||||
Line=LineIndex)
|
||||
|
||||
## InfUserExtensionParser
|
||||
#
|
||||
#
|
||||
def InfUserExtensionParser(self, SectionString, InfSectionObject, FileName):
|
||||
|
||||
UserExtensionContent = ''
|
||||
|
||||
#
|
||||
# Parse section content
|
||||
#
|
||||
for Line in SectionString:
|
||||
LineContent = Line[0]
|
||||
LineNo = Line[1]
|
||||
|
||||
if LineContent.strip() == '':
|
||||
continue
|
||||
#
|
||||
# Replace with [Defines] section Macro
|
||||
#
|
||||
LineContent = InfExpandMacro(LineContent,
|
||||
(FileName, LineContent, LineNo),
|
||||
self.FileLocalMacros,
|
||||
None)
|
||||
|
||||
UserExtensionContent += LineContent + DT.END_OF_LINE
|
||||
|
||||
continue
|
||||
|
||||
#
|
||||
# Current section UserId, IdString
|
||||
#
|
||||
IdContentList = []
|
||||
LastItem = ''
|
||||
SectionLineNo = None
|
||||
for Item in self.LastSectionHeaderContent:
|
||||
UserId = Item[1]
|
||||
IdString = Item[2]
|
||||
Arch = Item[3]
|
||||
SectionLineNo = Item[4]
|
||||
if not IsValidArch(Arch):
|
||||
Logger.Error(
|
||||
'InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (Arch),
|
||||
File=GlobalData.gINF_MODULE_NAME,
|
||||
Line=SectionLineNo,
|
||||
ExtraData=None)
|
||||
|
||||
if (UserId, IdString, Arch) not in IdContentList:
|
||||
#
|
||||
# To check the UserId and IdString valid or not.
|
||||
#
|
||||
if not IsValidUserId(UserId):
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_UE_SECTION_USER_ID_ERROR % (Item[1]),
|
||||
File=GlobalData.gINF_MODULE_NAME,
|
||||
Line=SectionLineNo,
|
||||
ExtraData=None)
|
||||
|
||||
if not IsValidIdString(IdString):
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_UE_SECTION_ID_STRING_ERROR % (IdString),
|
||||
File=GlobalData.gINF_MODULE_NAME, Line=SectionLineNo,
|
||||
ExtraData=None)
|
||||
IdContentList.append((UserId, IdString, Arch))
|
||||
else:
|
||||
#
|
||||
# Each UserExtensions section header must have a unique set
|
||||
# of UserId, IdString and Arch values.
|
||||
# This means that the same UserId can be used in more than one
|
||||
# section header, provided the IdString or Arch values are
|
||||
# different. The same IdString values can be used in more than
|
||||
# one section header if the UserId or Arch values are
|
||||
# different. The same UserId and the same IdString can be used
|
||||
# in a section header if the Arch values are different in each
|
||||
# of the section headers.
|
||||
#
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_UE_SECTION_DUPLICATE_ERROR % (
|
||||
IdString),
|
||||
File=GlobalData.gINF_MODULE_NAME,
|
||||
Line=SectionLineNo,
|
||||
ExtraData=None)
|
||||
LastItem = Item
|
||||
|
||||
if not InfSectionObject.SetUserExtension(UserExtensionContent,
|
||||
IdContent=IdContentList,
|
||||
LineNo=SectionLineNo):
|
||||
Logger.Error\
|
||||
('InfParser', FORMAT_INVALID, \
|
||||
ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[UserExtension]"), \
|
||||
File=FileName, Line=LastItem[4])
|
||||
|
||||
def InfProtocolParser(self, SectionString, InfSectionObject, FileName):
|
||||
#
|
||||
# Macro defined in this section
|
||||
#
|
||||
SectionMacros = {}
|
||||
ValueList = []
|
||||
ProtocolList = []
|
||||
CommentsList = []
|
||||
CurrentLineVar = None
|
||||
#
|
||||
# Parse section content
|
||||
#
|
||||
for Line in SectionString:
|
||||
LineContent = Line[0]
|
||||
LineNo = Line[1]
|
||||
|
||||
if LineContent.strip() == '':
|
||||
CommentsList = []
|
||||
continue
|
||||
|
||||
if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
|
||||
CommentsList.append(Line)
|
||||
continue
|
||||
else:
|
||||
#
|
||||
# Encounter a Protocol entry
|
||||
#
|
||||
if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
|
||||
CommentsList.append((
|
||||
LineContent[LineContent.find(DT.TAB_COMMENT_SPLIT):],
|
||||
LineNo))
|
||||
LineContent = \
|
||||
LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)]
|
||||
|
||||
if LineContent != '':
|
||||
#
|
||||
# Find Macro
|
||||
#
|
||||
Name, Value = MacroParser((LineContent, LineNo),
|
||||
FileName,
|
||||
DT.MODEL_EFI_PROTOCOL,
|
||||
self.FileLocalMacros)
|
||||
if Name != None:
|
||||
SectionMacros[Name] = Value
|
||||
ValueList = []
|
||||
CommentsList = []
|
||||
continue
|
||||
|
||||
TokenList = GetSplitValueList(LineContent, DT.TAB_VALUE_SPLIT, 1)
|
||||
ValueList[0:len(TokenList)] = TokenList
|
||||
|
||||
#
|
||||
# Replace with Local section Macro and [Defines] section Macro.
|
||||
#
|
||||
ValueList = [InfExpandMacro(Value, (FileName, LineContent, LineNo), self.FileLocalMacros, SectionMacros)
|
||||
for Value in ValueList]
|
||||
|
||||
CurrentLineVar = (LineContent, LineNo, FileName)
|
||||
|
||||
if len(ValueList) >= 1:
|
||||
ProtocolList.append((ValueList, CommentsList, CurrentLineVar))
|
||||
ValueList = []
|
||||
CommentsList = []
|
||||
continue
|
||||
|
||||
#
|
||||
# Current section archs
|
||||
#
|
||||
ArchList = []
|
||||
LineIndex = -1
|
||||
for Item in self.LastSectionHeaderContent:
|
||||
LineIndex = Item[3]
|
||||
if Item[1] not in ArchList:
|
||||
ArchList.append(Item[1])
|
||||
|
||||
if not InfSectionObject.SetProtocol(ProtocolList, Arch=ArchList):
|
||||
Logger.Error\
|
||||
('InfParser', FORMAT_INVALID, \
|
||||
ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Protocol]"), \
|
||||
File=FileName, Line=LineIndex)
|
209
BaseTools/Source/Python/UPT/Parser/InfLibrarySectionParser.py
Normal file
209
BaseTools/Source/Python/UPT/Parser/InfLibrarySectionParser.py
Normal file
@@ -0,0 +1,209 @@
|
||||
## @file
|
||||
# This file contained the parser for [Libraries] sections in INF file
|
||||
#
|
||||
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials are licensed and made available
|
||||
# under the terms and conditions of the BSD License which accompanies this
|
||||
# distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
'''
|
||||
InfLibrarySectionParser
|
||||
'''
|
||||
##
|
||||
# Import Modules
|
||||
#
|
||||
|
||||
import Logger.Log as Logger
|
||||
from Logger import StringTable as ST
|
||||
from Logger.ToolError import FORMAT_INVALID
|
||||
from Parser.InfParserMisc import InfExpandMacro
|
||||
from Library import DataType as DT
|
||||
from Library.Parsing import MacroParser
|
||||
from Library.Misc import GetSplitValueList
|
||||
from Object.Parser.InfCommonObject import InfLineCommentObject
|
||||
from Library import GlobalData
|
||||
from Parser.InfParserMisc import IsLibInstanceInfo
|
||||
from Parser.InfAsBuiltProcess import GetLibInstanceInfo
|
||||
from Parser.InfParserMisc import InfParserSectionRoot
|
||||
|
||||
class InfLibrarySectionParser(InfParserSectionRoot):
|
||||
## InfLibraryParser
|
||||
#
|
||||
#
|
||||
def InfLibraryParser(self, SectionString, InfSectionObject, FileName):
|
||||
#
|
||||
# For Common INF file
|
||||
#
|
||||
if not GlobalData.gIS_BINARY_INF:
|
||||
#
|
||||
# Macro defined in this section
|
||||
#
|
||||
SectionMacros = {}
|
||||
ValueList = []
|
||||
LibraryList = []
|
||||
LibStillCommentFalg = False
|
||||
LibHeaderComments = []
|
||||
LibLineComment = None
|
||||
#
|
||||
# Parse section content
|
||||
#
|
||||
for Line in SectionString:
|
||||
LibLineContent = Line[0]
|
||||
LibLineNo = Line[1]
|
||||
|
||||
if LibLineContent.strip() == '':
|
||||
continue
|
||||
|
||||
#
|
||||
# Found Header Comments
|
||||
#
|
||||
if LibLineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
|
||||
#
|
||||
# Last line is comments, and this line go on.
|
||||
#
|
||||
if LibStillCommentFalg:
|
||||
LibHeaderComments.append(Line)
|
||||
continue
|
||||
#
|
||||
# First time encounter comment
|
||||
#
|
||||
else:
|
||||
#
|
||||
# Clear original data
|
||||
#
|
||||
LibHeaderComments = []
|
||||
LibHeaderComments.append(Line)
|
||||
LibStillCommentFalg = True
|
||||
continue
|
||||
else:
|
||||
LibStillCommentFalg = False
|
||||
|
||||
if len(LibHeaderComments) >= 1:
|
||||
LibLineComment = InfLineCommentObject()
|
||||
LineCommentContent = ''
|
||||
for Item in LibHeaderComments:
|
||||
LineCommentContent += Item[0] + DT.END_OF_LINE
|
||||
LibLineComment.SetHeaderComments(LineCommentContent)
|
||||
|
||||
#
|
||||
# Find Tail comment.
|
||||
#
|
||||
if LibLineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
|
||||
LibTailComments = LibLineContent[LibLineContent.find(DT.TAB_COMMENT_SPLIT):]
|
||||
LibLineContent = LibLineContent[:LibLineContent.find(DT.TAB_COMMENT_SPLIT)]
|
||||
if LibLineComment == None:
|
||||
LibLineComment = InfLineCommentObject()
|
||||
LibLineComment.SetTailComments(LibTailComments)
|
||||
|
||||
#
|
||||
# Find Macro
|
||||
#
|
||||
Name, Value = MacroParser((LibLineContent, LibLineNo),
|
||||
FileName,
|
||||
DT.MODEL_EFI_LIBRARY_CLASS,
|
||||
self.FileLocalMacros)
|
||||
if Name != None:
|
||||
SectionMacros[Name] = Value
|
||||
LibLineComment = None
|
||||
LibHeaderComments = []
|
||||
continue
|
||||
|
||||
TokenList = GetSplitValueList(LibLineContent, DT.TAB_VALUE_SPLIT, 1)
|
||||
ValueList[0:len(TokenList)] = TokenList
|
||||
|
||||
#
|
||||
# Replace with Local section Macro and [Defines] section Macro.
|
||||
#
|
||||
ValueList = [InfExpandMacro(Value, (FileName, LibLineContent, LibLineNo),
|
||||
self.FileLocalMacros, SectionMacros, True)
|
||||
for Value in ValueList]
|
||||
|
||||
LibraryList.append((ValueList, LibLineComment,
|
||||
(LibLineContent, LibLineNo, FileName)))
|
||||
ValueList = []
|
||||
LibLineComment = None
|
||||
LibTailComments = ''
|
||||
LibHeaderComments = []
|
||||
|
||||
continue
|
||||
|
||||
#
|
||||
# Current section archs
|
||||
#
|
||||
KeyList = []
|
||||
for Item in self.LastSectionHeaderContent:
|
||||
if (Item[1], Item[2]) not in KeyList:
|
||||
KeyList.append((Item[1], Item[2]))
|
||||
|
||||
if not InfSectionObject.SetLibraryClasses(LibraryList, KeyList = KeyList):
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Library]"),
|
||||
File=FileName,
|
||||
Line=Item[3])
|
||||
#
|
||||
# For Binary INF
|
||||
#
|
||||
else:
|
||||
self.InfAsBuiltLibraryParser(SectionString, InfSectionObject, FileName)
|
||||
|
||||
def InfAsBuiltLibraryParser(self, SectionString, InfSectionObject, FileName):
|
||||
LibraryList = []
|
||||
LibInsFlag = False
|
||||
for Line in SectionString:
|
||||
LineContent = Line[0]
|
||||
LineNo = Line[1]
|
||||
|
||||
if LineContent.strip() == '':
|
||||
LibInsFlag = False
|
||||
continue
|
||||
|
||||
if not LineContent.strip().startswith("#"):
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_LIB_CONTATIN_ASBUILD_AND_COMMON,
|
||||
File=FileName,
|
||||
Line=LineNo,
|
||||
ExtraData=LineContent)
|
||||
|
||||
if IsLibInstanceInfo(LineContent):
|
||||
LibInsFlag = True
|
||||
continue
|
||||
|
||||
if LibInsFlag:
|
||||
LibGuid, LibVer = GetLibInstanceInfo(LineContent, GlobalData.gWORKSPACE, LineNo)
|
||||
#
|
||||
# If the VERSION_STRING is missing from the INF file, tool should default to "0".
|
||||
#
|
||||
if LibVer == '':
|
||||
LibVer = '0'
|
||||
if LibGuid != '':
|
||||
LibraryList.append((LibGuid, LibVer))
|
||||
else:
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_LIB_INSTANCE_MISS_GUID,
|
||||
File=FileName,
|
||||
Line=LineNo,
|
||||
ExtraData=LineContent)
|
||||
|
||||
#
|
||||
# Current section archs
|
||||
#
|
||||
KeyList = []
|
||||
Item = ['', '', '']
|
||||
for Item in self.LastSectionHeaderContent:
|
||||
if (Item[1], Item[2]) not in KeyList:
|
||||
KeyList.append((Item[1], Item[2]))
|
||||
|
||||
if not InfSectionObject.SetLibraryClasses(LibraryList, KeyList = KeyList):
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Library]"),
|
||||
File=FileName,
|
||||
Line=Item[3])
|
140
BaseTools/Source/Python/UPT/Parser/InfPackageSectionParser.py
Normal file
140
BaseTools/Source/Python/UPT/Parser/InfPackageSectionParser.py
Normal file
@@ -0,0 +1,140 @@
|
||||
## @file
|
||||
# This file contained the parser for [Packages] sections in INF file
|
||||
#
|
||||
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials are licensed and made available
|
||||
# under the terms and conditions of the BSD License which accompanies this
|
||||
# distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
'''
|
||||
InfPackageSectionParser
|
||||
'''
|
||||
##
|
||||
# Import Modules
|
||||
#
|
||||
|
||||
import Logger.Log as Logger
|
||||
from Logger import StringTable as ST
|
||||
from Logger.ToolError import FORMAT_INVALID
|
||||
from Parser.InfParserMisc import InfExpandMacro
|
||||
from Library import DataType as DT
|
||||
from Library.Parsing import MacroParser
|
||||
from Library.Misc import GetSplitValueList
|
||||
from Object.Parser.InfCommonObject import InfLineCommentObject
|
||||
from Parser.InfParserMisc import InfParserSectionRoot
|
||||
|
||||
class InfPackageSectionParser(InfParserSectionRoot):
|
||||
## InfPackageParser
|
||||
#
|
||||
#
|
||||
def InfPackageParser(self, SectionString, InfSectionObject, FileName):
|
||||
#
|
||||
# Macro defined in this section
|
||||
#
|
||||
SectionMacros = {}
|
||||
ValueList = []
|
||||
PackageList = []
|
||||
StillCommentFalg = False
|
||||
HeaderComments = []
|
||||
LineComment = None
|
||||
#
|
||||
# Parse section content
|
||||
#
|
||||
for Line in SectionString:
|
||||
PkgLineContent = Line[0]
|
||||
PkgLineNo = Line[1]
|
||||
|
||||
if PkgLineContent.strip() == '':
|
||||
continue
|
||||
|
||||
#
|
||||
# Find Header Comments
|
||||
#
|
||||
if PkgLineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
|
||||
#
|
||||
# Last line is comments, and this line go on.
|
||||
#
|
||||
if StillCommentFalg:
|
||||
HeaderComments.append(Line)
|
||||
continue
|
||||
#
|
||||
# First time encounter comment
|
||||
#
|
||||
else:
|
||||
#
|
||||
# Clear original data
|
||||
#
|
||||
HeaderComments = []
|
||||
HeaderComments.append(Line)
|
||||
StillCommentFalg = True
|
||||
continue
|
||||
else:
|
||||
StillCommentFalg = False
|
||||
|
||||
if len(HeaderComments) >= 1:
|
||||
LineComment = InfLineCommentObject()
|
||||
LineCommentContent = ''
|
||||
for Item in HeaderComments:
|
||||
LineCommentContent += Item[0] + DT.END_OF_LINE
|
||||
LineComment.SetHeaderComments(LineCommentContent)
|
||||
|
||||
#
|
||||
# Find Tail comment.
|
||||
#
|
||||
if PkgLineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
|
||||
TailComments = PkgLineContent[PkgLineContent.find(DT.TAB_COMMENT_SPLIT):]
|
||||
PkgLineContent = PkgLineContent[:PkgLineContent.find(DT.TAB_COMMENT_SPLIT)]
|
||||
if LineComment == None:
|
||||
LineComment = InfLineCommentObject()
|
||||
LineComment.SetTailComments(TailComments)
|
||||
#
|
||||
# Find Macro
|
||||
#
|
||||
Name, Value = MacroParser((PkgLineContent, PkgLineNo),
|
||||
FileName,
|
||||
DT.MODEL_META_DATA_PACKAGE,
|
||||
self.FileLocalMacros)
|
||||
if Name != None:
|
||||
SectionMacros[Name] = Value
|
||||
LineComment = None
|
||||
HeaderComments = []
|
||||
continue
|
||||
|
||||
TokenList = GetSplitValueList(PkgLineContent, DT.TAB_VALUE_SPLIT, 1)
|
||||
ValueList[0:len(TokenList)] = TokenList
|
||||
|
||||
#
|
||||
# Replace with Local section Macro and [Defines] section Macro.
|
||||
#
|
||||
ValueList = [InfExpandMacro(Value, (FileName, PkgLineContent, PkgLineNo),
|
||||
self.FileLocalMacros, SectionMacros, True)
|
||||
for Value in ValueList]
|
||||
|
||||
PackageList.append((ValueList, LineComment,
|
||||
(PkgLineContent, PkgLineNo, FileName)))
|
||||
ValueList = []
|
||||
LineComment = None
|
||||
TailComments = ''
|
||||
HeaderComments = []
|
||||
continue
|
||||
|
||||
#
|
||||
# Current section archs
|
||||
#
|
||||
ArchList = []
|
||||
for Item in self.LastSectionHeaderContent:
|
||||
if Item[1] not in ArchList:
|
||||
ArchList.append(Item[1])
|
||||
|
||||
if not InfSectionObject.SetPackages(PackageList, Arch = ArchList):
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR\
|
||||
%("[Packages]"),
|
||||
File=FileName,
|
||||
Line=Item[3])
|
612
BaseTools/Source/Python/UPT/Parser/InfParser.py
Normal file
612
BaseTools/Source/Python/UPT/Parser/InfParser.py
Normal file
@@ -0,0 +1,612 @@
|
||||
## @file
|
||||
# This file contained the parser for INF file
|
||||
#
|
||||
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials are licensed and made available
|
||||
# under the terms and conditions of the BSD License which accompanies this
|
||||
# distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
|
||||
'''
|
||||
InfParser
|
||||
'''
|
||||
|
||||
##
|
||||
# Import Modules
|
||||
#
|
||||
import re
|
||||
import os
|
||||
from copy import deepcopy
|
||||
|
||||
from Library.String import GetSplitValueList
|
||||
from Library.String import ConvertSpecialChar
|
||||
from Library.Misc import ProcessLineExtender
|
||||
from Library.Parsing import NormPath
|
||||
from Library.ParserValidate import IsValidInfMoudleTypeList
|
||||
from Library.ParserValidate import IsValidArch
|
||||
from Library import DataType as DT
|
||||
from Library import GlobalData
|
||||
|
||||
import Logger.Log as Logger
|
||||
from Logger import StringTable as ST
|
||||
from Logger.ToolError import FORMAT_INVALID
|
||||
from Logger.ToolError import FILE_READ_FAILURE
|
||||
from Logger.ToolError import PARSER_ERROR
|
||||
|
||||
from Object.Parser.InfCommonObject import InfSectionCommonDef
|
||||
from Parser.InfSectionParser import InfSectionParser
|
||||
from Parser.InfParserMisc import gINF_SECTION_DEF
|
||||
from Parser.InfParserMisc import IsBinaryInf
|
||||
|
||||
## OpenInfFile
|
||||
#
|
||||
#
|
||||
def OpenInfFile(Filename):
|
||||
FileLinesList = []
|
||||
|
||||
try:
|
||||
FInputfile = open(Filename, "rb", 0)
|
||||
try:
|
||||
FileLinesList = FInputfile.readlines()
|
||||
except BaseException:
|
||||
Logger.Error("InfParser",
|
||||
FILE_READ_FAILURE,
|
||||
ST.ERR_FILE_OPEN_FAILURE,
|
||||
File=Filename)
|
||||
finally:
|
||||
FInputfile.close()
|
||||
except BaseException:
|
||||
Logger.Error("InfParser",
|
||||
FILE_READ_FAILURE,
|
||||
ST.ERR_FILE_OPEN_FAILURE,
|
||||
File=Filename)
|
||||
|
||||
return FileLinesList
|
||||
|
||||
## InfParser
|
||||
#
|
||||
# This class defined the structure used in InfParser object
|
||||
#
|
||||
# @param InfObject: Inherited from InfSectionParser class
|
||||
# @param Filename: Input value for Filename of INF file, default is
|
||||
# None
|
||||
# @param WorkspaceDir: Input value for current workspace directory,
|
||||
# default is None
|
||||
#
|
||||
class InfParser(InfSectionParser):
|
||||
|
||||
def __init__(self, Filename = None, WorkspaceDir = None):
|
||||
|
||||
#
|
||||
# Call parent class construct function
|
||||
#
|
||||
super(InfParser, self).__init__()
|
||||
|
||||
self.WorkspaceDir = WorkspaceDir
|
||||
self.SupArchList = DT.ARCH_LIST
|
||||
self.EventList = []
|
||||
self.HobList = []
|
||||
self.BootModeList = []
|
||||
|
||||
#
|
||||
# Load Inf file if filename is not None
|
||||
#
|
||||
if Filename != None:
|
||||
self.ParseInfFile(Filename)
|
||||
|
||||
## Parse INF file
|
||||
#
|
||||
# Parse the file if it exists
|
||||
#
|
||||
# @param Filename: Input value for filename of INF file
|
||||
#
|
||||
def ParseInfFile(self, Filename):
|
||||
|
||||
Filename = NormPath(Filename)
|
||||
(Path, Name) = os.path.split(Filename)
|
||||
self.FullPath = Filename
|
||||
self.RelaPath = Path
|
||||
self.FileName = Name
|
||||
GlobalData.gINF_MODULE_DIR = Path
|
||||
GlobalData.gINF_MODULE_NAME = self.FullPath
|
||||
GlobalData.gIS_BINARY_INF = False
|
||||
#
|
||||
# Initialize common data
|
||||
#
|
||||
LineNo = 0
|
||||
CurrentSection = DT.MODEL_UNKNOWN
|
||||
SectionLines = []
|
||||
|
||||
#
|
||||
# Flags
|
||||
#
|
||||
HeaderCommentStart = False
|
||||
HeaderCommentEnd = False
|
||||
|
||||
#
|
||||
# While Section ends. parse whole section contents.
|
||||
#
|
||||
NewSectionStartFlag = False
|
||||
FirstSectionStartFlag = False
|
||||
|
||||
#
|
||||
# Parse file content
|
||||
#
|
||||
CommentBlock = []
|
||||
|
||||
#
|
||||
# Variables for Event/Hob/BootMode
|
||||
#
|
||||
self.EventList = []
|
||||
self.HobList = []
|
||||
self.BootModeList = []
|
||||
SectionType = ''
|
||||
|
||||
FileLinesList = OpenInfFile (Filename)
|
||||
|
||||
#
|
||||
# One INF file can only has one [Defines] section.
|
||||
#
|
||||
DefineSectionParsedFlag = False
|
||||
|
||||
#
|
||||
# Convert special characters in lines to space character.
|
||||
#
|
||||
FileLinesList = ConvertSpecialChar(FileLinesList)
|
||||
|
||||
#
|
||||
# Process Line Extender
|
||||
#
|
||||
FileLinesList = ProcessLineExtender(FileLinesList)
|
||||
|
||||
#
|
||||
# Judge whether the INF file is Binary INF or not
|
||||
#
|
||||
if IsBinaryInf(FileLinesList):
|
||||
GlobalData.gIS_BINARY_INF = True
|
||||
|
||||
InfSectionCommonDefObj = None
|
||||
|
||||
for Line in FileLinesList:
|
||||
LineNo = LineNo + 1
|
||||
Line = Line.strip()
|
||||
if (LineNo < len(FileLinesList) - 1):
|
||||
NextLine = FileLinesList[LineNo].strip()
|
||||
|
||||
#
|
||||
# blank line
|
||||
#
|
||||
if (Line == '' or not Line) and LineNo == len(FileLinesList):
|
||||
LastSectionFalg = True
|
||||
|
||||
#
|
||||
# check whether file header comment section started
|
||||
#
|
||||
if Line.startswith(DT.TAB_SPECIAL_COMMENT) and \
|
||||
(Line.find(DT.TAB_HEADER_COMMENT) > -1) and \
|
||||
not HeaderCommentStart:
|
||||
if CurrentSection != DT.MODEL_UNKNOWN:
|
||||
Logger.Error("Parser",
|
||||
PARSER_ERROR,
|
||||
ST.ERR_INF_PARSER_HEADER_FILE,
|
||||
File=Filename,
|
||||
Line=LineNo,
|
||||
RaiseError = Logger.IS_RAISE_ERROR)
|
||||
else:
|
||||
CurrentSection = DT.MODEL_META_DATA_FILE_HEADER
|
||||
#
|
||||
# Append the first line to section lines.
|
||||
#
|
||||
SectionLines.append((Line, LineNo))
|
||||
HeaderCommentStart = True
|
||||
continue
|
||||
|
||||
#
|
||||
# Collect Header content.
|
||||
#
|
||||
if (Line.startswith(DT.TAB_COMMENT_SPLIT) and CurrentSection == DT.MODEL_META_DATA_FILE_HEADER) and\
|
||||
HeaderCommentStart and not Line.startswith(DT.TAB_SPECIAL_COMMENT) and not\
|
||||
HeaderCommentEnd and NextLine != '':
|
||||
SectionLines.append((Line, LineNo))
|
||||
continue
|
||||
#
|
||||
# Header content end
|
||||
#
|
||||
if (Line.startswith(DT.TAB_SPECIAL_COMMENT) or not Line.strip().startswith("#")) and HeaderCommentStart \
|
||||
and not HeaderCommentEnd:
|
||||
SectionLines.append((Line, LineNo))
|
||||
HeaderCommentStart = False
|
||||
#
|
||||
# Call Header comment parser.
|
||||
#
|
||||
self.InfHeaderParser(SectionLines, self.InfHeader, self.FileName)
|
||||
SectionLines = []
|
||||
HeaderCommentEnd = True
|
||||
continue
|
||||
|
||||
#
|
||||
# Find a new section tab
|
||||
# Or at the last line of INF file,
|
||||
# need to process the last section.
|
||||
#
|
||||
LastSectionFalg = False
|
||||
if LineNo == len(FileLinesList):
|
||||
LastSectionFalg = True
|
||||
|
||||
if Line.startswith(DT.TAB_COMMENT_SPLIT) and not Line.startswith(DT.TAB_SPECIAL_COMMENT):
|
||||
SectionLines.append((Line, LineNo))
|
||||
if not LastSectionFalg:
|
||||
continue
|
||||
|
||||
#
|
||||
# Encountered a section. start with '[' and end with ']'
|
||||
#
|
||||
if (Line.startswith(DT.TAB_SECTION_START) and \
|
||||
Line.find(DT.TAB_SECTION_END) > -1) or LastSectionFalg:
|
||||
if not LastSectionFalg:
|
||||
#
|
||||
# check to prevent '#' inside section header
|
||||
#
|
||||
HeaderContent = Line[1:Line.find(DT.TAB_SECTION_END)]
|
||||
if HeaderContent.find(DT.TAB_COMMENT_SPLIT) != -1:
|
||||
Logger.Error("InfParser",
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_DEFINE_SECTION_HEADER_INVALID,
|
||||
File=self.FullPath,
|
||||
Line=LineNo,
|
||||
ExtraData=Line)
|
||||
|
||||
#
|
||||
# Keep last time section header content for section parser
|
||||
# usage.
|
||||
#
|
||||
self.LastSectionHeaderContent = deepcopy(self.SectionHeaderContent)
|
||||
|
||||
#
|
||||
# TailComments in section define.
|
||||
#
|
||||
TailComments = ''
|
||||
CommentIndex = Line.find(DT.TAB_COMMENT_SPLIT)
|
||||
if CommentIndex > -1:
|
||||
TailComments = Line[CommentIndex:]
|
||||
Line = Line[:CommentIndex]
|
||||
|
||||
InfSectionCommonDefObj = InfSectionCommonDef()
|
||||
if TailComments != '':
|
||||
InfSectionCommonDefObj.SetTailComments(TailComments)
|
||||
if CommentBlock != '':
|
||||
InfSectionCommonDefObj.SetHeaderComments(CommentBlock)
|
||||
CommentBlock = []
|
||||
#
|
||||
# Call section parser before section header parer to avoid encounter EDKI INF file
|
||||
#
|
||||
if CurrentSection == DT.MODEL_META_DATA_DEFINE:
|
||||
DefineSectionParsedFlag = self._CallSectionParsers(CurrentSection,
|
||||
DefineSectionParsedFlag, SectionLines,
|
||||
InfSectionCommonDefObj, LineNo)
|
||||
#
|
||||
# Compare the new section name with current
|
||||
#
|
||||
self.SectionHeaderParser(Line, self.FileName, LineNo)
|
||||
|
||||
self._CheckSectionHeaders(Line, LineNo)
|
||||
|
||||
SectionType = _ConvertSecNameToType(self.SectionHeaderContent[0][0])
|
||||
|
||||
if not FirstSectionStartFlag:
|
||||
CurrentSection = SectionType
|
||||
FirstSectionStartFlag = True
|
||||
else:
|
||||
NewSectionStartFlag = True
|
||||
else:
|
||||
SectionLines.append((Line, LineNo))
|
||||
continue
|
||||
|
||||
if LastSectionFalg:
|
||||
SectionLines, CurrentSection = self._ProcessLastSection(SectionLines, Line, LineNo, CurrentSection)
|
||||
|
||||
#
|
||||
# End of section content collect.
|
||||
# Parser the section content collected previously.
|
||||
#
|
||||
if NewSectionStartFlag or LastSectionFalg:
|
||||
if CurrentSection != DT.MODEL_META_DATA_DEFINE or \
|
||||
(LastSectionFalg and CurrentSection == DT.MODEL_META_DATA_DEFINE):
|
||||
DefineSectionParsedFlag = self._CallSectionParsers(CurrentSection,
|
||||
DefineSectionParsedFlag, SectionLines,
|
||||
InfSectionCommonDefObj, LineNo)
|
||||
|
||||
CurrentSection = SectionType
|
||||
#
|
||||
# Clear section lines
|
||||
#
|
||||
SectionLines = []
|
||||
#
|
||||
# End of for
|
||||
#
|
||||
#
|
||||
# Found the first section, No file header.
|
||||
#
|
||||
if not DefineSectionParsedFlag:
|
||||
Logger.Error("InfParser",
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_HEADER_MISSGING,
|
||||
File=self.FullPath)
|
||||
|
||||
#
|
||||
# extract [Event] [Hob] [BootMode] sections
|
||||
#
|
||||
self._ExtractEventHobBootMod(FileLinesList)
|
||||
|
||||
## _CheckSectionHeaders
|
||||
#
|
||||
#
|
||||
def _CheckSectionHeaders(self, Line, LineNo):
|
||||
if len(self.SectionHeaderContent) == 0:
|
||||
Logger.Error("InfParser",
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_DEFINE_SECTION_HEADER_INVALID,
|
||||
File=self.FullPath,
|
||||
Line=LineNo, ExtraData=Line)
|
||||
else:
|
||||
for SectionItem in self.SectionHeaderContent:
|
||||
ArchList = []
|
||||
#
|
||||
# Not cover Depex/UserExtension section header
|
||||
# check.
|
||||
#
|
||||
if SectionItem[0].strip().upper() == DT.TAB_INF_FIXED_PCD.upper() or \
|
||||
SectionItem[0].strip().upper() == DT.TAB_INF_PATCH_PCD.upper() or \
|
||||
SectionItem[0].strip().upper() == DT.TAB_INF_PCD_EX.upper() or \
|
||||
SectionItem[0].strip().upper() == DT.TAB_INF_PCD.upper() or \
|
||||
SectionItem[0].strip().upper() == DT.TAB_INF_FEATURE_PCD.upper():
|
||||
ArchList = GetSplitValueList(SectionItem[1].strip(), ' ')
|
||||
else:
|
||||
ArchList = [SectionItem[1].strip()]
|
||||
|
||||
for Arch in ArchList:
|
||||
if (not IsValidArch(Arch)) and \
|
||||
(SectionItem[0].strip().upper() != DT.TAB_DEPEX.upper()) and \
|
||||
(SectionItem[0].strip().upper() != DT.TAB_USER_EXTENSIONS.upper()) and \
|
||||
(SectionItem[0].strip().upper() != DT.TAB_COMMON_DEFINES.upper()):
|
||||
Logger.Error("InfParser",
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(SectionItem[1]),
|
||||
File=self.FullPath,
|
||||
Line=LineNo, ExtraData=Line)
|
||||
#
|
||||
# Check if the ModuleType is valid
|
||||
#
|
||||
ChkModSectionList = ['LIBRARYCLASSES']
|
||||
if (self.SectionHeaderContent[0][0].upper() in ChkModSectionList):
|
||||
if SectionItem[2].strip().upper():
|
||||
MoudleTypeList = GetSplitValueList(
|
||||
SectionItem[2].strip().upper())
|
||||
if (not IsValidInfMoudleTypeList(MoudleTypeList)):
|
||||
Logger.Error("InfParser",
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(SectionItem[2]),
|
||||
File=self.FullPath, Line=LineNo,
|
||||
ExtraData=Line)
|
||||
|
||||
## _CallSectionParsers
|
||||
#
|
||||
#
|
||||
def _CallSectionParsers(self, CurrentSection, DefineSectionParsedFlag,
|
||||
SectionLines, InfSectionCommonDefObj, LineNo):
|
||||
if CurrentSection == DT.MODEL_META_DATA_DEFINE:
|
||||
if not DefineSectionParsedFlag:
|
||||
self.InfDefineParser(SectionLines,
|
||||
self.InfDefSection,
|
||||
self.FullPath,
|
||||
InfSectionCommonDefObj)
|
||||
DefineSectionParsedFlag = True
|
||||
else:
|
||||
Logger.Error("Parser",
|
||||
PARSER_ERROR,
|
||||
ST.ERR_INF_PARSER_MULTI_DEFINE_SECTION,
|
||||
File=self.FullPath,
|
||||
RaiseError = Logger.IS_RAISE_ERROR)
|
||||
|
||||
elif CurrentSection == DT.MODEL_META_DATA_BUILD_OPTION:
|
||||
self.InfBuildOptionParser(SectionLines,
|
||||
self.InfBuildOptionSection,
|
||||
self.FullPath)
|
||||
|
||||
elif CurrentSection == DT.MODEL_EFI_LIBRARY_CLASS:
|
||||
self.InfLibraryParser(SectionLines,
|
||||
self.InfLibraryClassSection,
|
||||
self.FullPath)
|
||||
|
||||
elif CurrentSection == DT.MODEL_META_DATA_PACKAGE:
|
||||
self.InfPackageParser(SectionLines,
|
||||
self.InfPackageSection,
|
||||
self.FullPath)
|
||||
#
|
||||
# [Pcd] Sections, put it together
|
||||
#
|
||||
elif CurrentSection == DT.MODEL_PCD_FIXED_AT_BUILD or \
|
||||
CurrentSection == DT.MODEL_PCD_PATCHABLE_IN_MODULE or \
|
||||
CurrentSection == DT.MODEL_PCD_FEATURE_FLAG or \
|
||||
CurrentSection == DT.MODEL_PCD_DYNAMIC_EX or \
|
||||
CurrentSection == DT.MODEL_PCD_DYNAMIC:
|
||||
self.InfPcdParser(SectionLines,
|
||||
self.InfPcdSection,
|
||||
self.FullPath)
|
||||
|
||||
elif CurrentSection == DT.MODEL_EFI_SOURCE_FILE:
|
||||
self.InfSourceParser(SectionLines,
|
||||
self.InfSourcesSection,
|
||||
self.FullPath)
|
||||
|
||||
elif CurrentSection == DT.MODEL_META_DATA_USER_EXTENSION:
|
||||
self.InfUserExtensionParser(SectionLines,
|
||||
self.InfUserExtensionSection,
|
||||
self.FullPath)
|
||||
|
||||
elif CurrentSection == DT.MODEL_EFI_PROTOCOL:
|
||||
self.InfProtocolParser(SectionLines,
|
||||
self.InfProtocolSection,
|
||||
self.FullPath)
|
||||
|
||||
elif CurrentSection == DT.MODEL_EFI_PPI:
|
||||
self.InfPpiParser(SectionLines,
|
||||
self.InfPpiSection,
|
||||
self.FullPath)
|
||||
|
||||
elif CurrentSection == DT.MODEL_EFI_GUID:
|
||||
self.InfGuidParser(SectionLines,
|
||||
self.InfGuidSection,
|
||||
self.FullPath)
|
||||
|
||||
elif CurrentSection == DT.MODEL_EFI_DEPEX:
|
||||
self.InfDepexParser(SectionLines,
|
||||
self.InfDepexSection,
|
||||
self.FullPath)
|
||||
|
||||
elif CurrentSection == DT.MODEL_EFI_BINARY_FILE:
|
||||
self.InfBinaryParser(SectionLines,
|
||||
self.InfBinariesSection,
|
||||
self.FullPath)
|
||||
#
|
||||
# Unknown section type found, raise error.
|
||||
#
|
||||
else:
|
||||
if len(self.SectionHeaderContent) >= 1:
|
||||
Logger.Error("Parser",
|
||||
PARSER_ERROR,
|
||||
ST.ERR_INF_PARSER_UNKNOWN_SECTION,
|
||||
File=self.FullPath, Line=LineNo,
|
||||
RaiseError = Logger.IS_RAISE_ERROR)
|
||||
else:
|
||||
Logger.Error("Parser",
|
||||
PARSER_ERROR,
|
||||
ST.ERR_INF_PARSER_NO_SECTION_ERROR,
|
||||
File=self.FullPath, Line=LineNo,
|
||||
RaiseError = Logger.IS_RAISE_ERROR)
|
||||
|
||||
return DefineSectionParsedFlag
|
||||
|
||||
def _ExtractEventHobBootMod(self, FileLinesList):
|
||||
SpecialSectionStart = False
|
||||
CheckLocation = False
|
||||
GFindSpecialCommentRe = \
|
||||
re.compile(r"""#(?:\s*)\[(.*?)\](?:.*)""", re.DOTALL)
|
||||
GFindNewSectionRe2 = \
|
||||
re.compile(r"""#?(\s*)\[(.*?)\](.*)""", re.DOTALL)
|
||||
LineNum = 0
|
||||
Element = []
|
||||
for Line in FileLinesList:
|
||||
Line = Line.strip()
|
||||
LineNum += 1
|
||||
MatchObject = GFindSpecialCommentRe.search(Line)
|
||||
if MatchObject:
|
||||
SpecialSectionStart = True
|
||||
Element = []
|
||||
if MatchObject.group(1).upper().startswith("EVENT"):
|
||||
List = self.EventList
|
||||
elif MatchObject.group(1).upper().startswith("HOB"):
|
||||
List = self.HobList
|
||||
elif MatchObject.group(1).upper().startswith("BOOTMODE"):
|
||||
List = self.BootModeList
|
||||
else:
|
||||
SpecialSectionStart = False
|
||||
CheckLocation = False
|
||||
if SpecialSectionStart:
|
||||
Element.append([Line, LineNum])
|
||||
List.append(Element)
|
||||
else:
|
||||
#
|
||||
# if currently in special section, try to detect end of current section
|
||||
#
|
||||
MatchObject = GFindNewSectionRe2.search(Line)
|
||||
if SpecialSectionStart:
|
||||
if MatchObject:
|
||||
SpecialSectionStart = False
|
||||
CheckLocation = False
|
||||
Element = []
|
||||
elif not Line:
|
||||
SpecialSectionStart = False
|
||||
CheckLocation = True
|
||||
Element = []
|
||||
else:
|
||||
if not Line.startswith(DT.TAB_COMMENT_SPLIT):
|
||||
Logger.Warn("Parser",
|
||||
ST.WARN_SPECIAL_SECTION_LOCATION_WRONG,
|
||||
File=self.FullPath, Line=LineNum)
|
||||
SpecialSectionStart = False
|
||||
CheckLocation = False
|
||||
Element = []
|
||||
else:
|
||||
Element.append([Line, LineNum])
|
||||
else:
|
||||
if CheckLocation:
|
||||
if MatchObject:
|
||||
CheckLocation = False
|
||||
elif Line:
|
||||
Logger.Warn("Parser",
|
||||
ST.WARN_SPECIAL_SECTION_LOCATION_WRONG,
|
||||
File=self.FullPath, Line=LineNum)
|
||||
CheckLocation = False
|
||||
|
||||
if len(self.BootModeList) >= 1:
|
||||
self.InfSpecialCommentParser(self.BootModeList,
|
||||
self.InfSpecialCommentSection,
|
||||
self.FileName,
|
||||
DT.TYPE_BOOTMODE_SECTION)
|
||||
|
||||
if len(self.EventList) >= 1:
|
||||
self.InfSpecialCommentParser(self.EventList,
|
||||
self.InfSpecialCommentSection,
|
||||
self.FileName,
|
||||
DT.TYPE_EVENT_SECTION)
|
||||
|
||||
if len(self.HobList) >= 1:
|
||||
self.InfSpecialCommentParser(self.HobList,
|
||||
self.InfSpecialCommentSection,
|
||||
self.FileName,
|
||||
DT.TYPE_HOB_SECTION)
|
||||
## _ProcessLastSection
|
||||
#
|
||||
#
|
||||
def _ProcessLastSection(self, SectionLines, Line, LineNo, CurrentSection):
|
||||
#
|
||||
# The last line is a section header. will discard it.
|
||||
#
|
||||
if not (Line.startswith(DT.TAB_SECTION_START) and Line.find(DT.TAB_SECTION_END) > -1):
|
||||
SectionLines.append((Line, LineNo))
|
||||
|
||||
if len(self.SectionHeaderContent) >= 1:
|
||||
TemSectionName = self.SectionHeaderContent[0][0].upper()
|
||||
if TemSectionName.upper() not in gINF_SECTION_DEF.keys():
|
||||
Logger.Error("InfParser",
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_UNKNOWN_SECTION,
|
||||
File=self.FullPath,
|
||||
Line=LineNo,
|
||||
ExtraData=Line,
|
||||
RaiseError = Logger.IS_RAISE_ERROR
|
||||
)
|
||||
else:
|
||||
CurrentSection = gINF_SECTION_DEF[TemSectionName]
|
||||
self.LastSectionHeaderContent = self.SectionHeaderContent
|
||||
|
||||
return SectionLines, CurrentSection
|
||||
|
||||
## _ConvertSecNameToType
|
||||
#
|
||||
#
|
||||
def _ConvertSecNameToType(SectionName):
|
||||
SectionType = ''
|
||||
if SectionName.upper() not in gINF_SECTION_DEF.keys():
|
||||
SectionType = DT.MODEL_UNKNOWN
|
||||
else:
|
||||
SectionType = gINF_SECTION_DEF[SectionName.upper()]
|
||||
|
||||
return SectionType
|
||||
|
218
BaseTools/Source/Python/UPT/Parser/InfParserMisc.py
Normal file
218
BaseTools/Source/Python/UPT/Parser/InfParserMisc.py
Normal file
@@ -0,0 +1,218 @@
|
||||
## @file
|
||||
# This file contained the miscellaneous functions for INF parser
|
||||
#
|
||||
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials are licensed and made available
|
||||
# under the terms and conditions of the BSD License which accompanies this
|
||||
# distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
|
||||
'''
|
||||
InfParserMisc
|
||||
'''
|
||||
|
||||
##
|
||||
# Import Modules
|
||||
#
|
||||
import re
|
||||
|
||||
|
||||
from Library import DataType as DT
|
||||
|
||||
|
||||
from Library.String import gMACRO_PATTERN
|
||||
from Library.String import ReplaceMacro
|
||||
from Object.Parser.InfMisc import ErrorInInf
|
||||
from Logger.StringTable import ERR_MARCO_DEFINITION_MISS_ERROR
|
||||
|
||||
#
|
||||
# Global variable
|
||||
#
|
||||
|
||||
#
|
||||
# Sections can exist in INF file
|
||||
#
|
||||
gINF_SECTION_DEF = {
|
||||
DT.TAB_UNKNOWN.upper() : DT.MODEL_UNKNOWN,
|
||||
DT.TAB_HEADER.upper() : DT.MODEL_META_DATA_FILE_HEADER,
|
||||
DT.TAB_INF_DEFINES.upper() : DT.MODEL_META_DATA_DEFINE,
|
||||
DT.TAB_BUILD_OPTIONS.upper() : DT.MODEL_META_DATA_BUILD_OPTION,
|
||||
DT.TAB_LIBRARY_CLASSES.upper() : DT.MODEL_EFI_LIBRARY_CLASS,
|
||||
DT.TAB_PACKAGES.upper() : DT.MODEL_META_DATA_PACKAGE,
|
||||
DT.TAB_INF_FIXED_PCD.upper() : DT.MODEL_PCD_FIXED_AT_BUILD,
|
||||
DT.TAB_INF_PATCH_PCD.upper() : DT.MODEL_PCD_PATCHABLE_IN_MODULE,
|
||||
DT.TAB_INF_FEATURE_PCD.upper() : DT.MODEL_PCD_FEATURE_FLAG,
|
||||
DT.TAB_INF_PCD_EX.upper() : DT.MODEL_PCD_DYNAMIC_EX,
|
||||
DT.TAB_INF_PCD.upper() : DT.MODEL_PCD_DYNAMIC,
|
||||
DT.TAB_SOURCES.upper() : DT.MODEL_EFI_SOURCE_FILE,
|
||||
DT.TAB_GUIDS.upper() : DT.MODEL_EFI_GUID,
|
||||
DT.TAB_PROTOCOLS.upper() : DT.MODEL_EFI_PROTOCOL,
|
||||
DT.TAB_PPIS.upper() : DT.MODEL_EFI_PPI,
|
||||
DT.TAB_DEPEX.upper() : DT.MODEL_EFI_DEPEX,
|
||||
DT.TAB_BINARIES.upper() : DT.MODEL_EFI_BINARY_FILE,
|
||||
DT.TAB_USER_EXTENSIONS.upper() : DT.MODEL_META_DATA_USER_EXTENSION
|
||||
#
|
||||
# EDK1 section
|
||||
# TAB_NMAKE.upper() : MODEL_META_DATA_NMAKE
|
||||
#
|
||||
}
|
||||
|
||||
## InfExpandMacro
|
||||
#
|
||||
# Expand MACRO definition with MACROs defined in [Defines] section and specific section.
|
||||
# The MACROs defined in specific section has high priority and will be expanded firstly.
|
||||
#
|
||||
# @param LineInfo Contain information of FileName, LineContent, LineNo
|
||||
# @param GlobalMacros MACROs defined in INF [Defines] section
|
||||
# @param SectionMacros MACROs defined in INF specific section
|
||||
# @param Flag If the flag set to True, need to skip macros in a quoted string
|
||||
#
|
||||
def InfExpandMacro(Content, LineInfo, GlobalMacros=None, SectionMacros=None, Flag=False):
|
||||
if GlobalMacros == None:
|
||||
GlobalMacros = {}
|
||||
if SectionMacros == None:
|
||||
SectionMacros = {}
|
||||
|
||||
FileName = LineInfo[0]
|
||||
LineContent = LineInfo[1]
|
||||
LineNo = LineInfo[2]
|
||||
|
||||
NewLineInfo = (FileName, LineNo, LineContent)
|
||||
|
||||
#
|
||||
# First, replace MARCOs with value defined in specific section
|
||||
#
|
||||
Content = ReplaceMacro (Content,
|
||||
SectionMacros,
|
||||
False,
|
||||
(LineContent, LineNo),
|
||||
FileName,
|
||||
Flag)
|
||||
#
|
||||
# Then replace MARCOs with value defined in [Defines] section
|
||||
#
|
||||
Content = ReplaceMacro (Content,
|
||||
GlobalMacros,
|
||||
False,
|
||||
(LineContent, LineNo),
|
||||
FileName,
|
||||
Flag)
|
||||
|
||||
MacroUsed = gMACRO_PATTERN.findall(Content)
|
||||
#
|
||||
# no macro found in String, stop replacing
|
||||
#
|
||||
if len(MacroUsed) == 0:
|
||||
return Content
|
||||
else:
|
||||
for Macro in MacroUsed:
|
||||
gQuotedMacro = re.compile(".*\".*\$\(%s\).*\".*"%(Macro))
|
||||
if not gQuotedMacro.match(Content):
|
||||
#
|
||||
# Still have MACROs can't be expanded.
|
||||
#
|
||||
ErrorInInf (ERR_MARCO_DEFINITION_MISS_ERROR,
|
||||
LineInfo=NewLineInfo)
|
||||
|
||||
return Content
|
||||
|
||||
|
||||
## IsBinaryInf
|
||||
#
|
||||
# Judge whether the INF file is Binary INF or Common INF
|
||||
#
|
||||
# @param FileLineList A list contain all INF file content.
|
||||
#
|
||||
def IsBinaryInf(FileLineList):
|
||||
if not FileLineList:
|
||||
return False
|
||||
|
||||
ReIsSourcesSection = re.compile("^\s*\[Sources.*\]\s.*$", re.IGNORECASE)
|
||||
ReIsBinarySection = re.compile("^\s*\[Binaries.*\]\s.*$", re.IGNORECASE)
|
||||
BinarySectionFoundFlag = False
|
||||
|
||||
for Line in FileLineList:
|
||||
if ReIsSourcesSection.match(Line):
|
||||
return False
|
||||
if ReIsBinarySection.match(Line):
|
||||
BinarySectionFoundFlag = True
|
||||
|
||||
if BinarySectionFoundFlag:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
## IsLibInstanceInfo
|
||||
#
|
||||
# Judge whether the string contain the information of ## @LIB_INSTANCES.
|
||||
#
|
||||
# @param String
|
||||
#
|
||||
# @return Flag
|
||||
#
|
||||
def IsLibInstanceInfo(String):
|
||||
ReIsLibInstance = re.compile("^\s*##\s*@LIB_INSTANCES\s*$")
|
||||
if ReIsLibInstance.match(String):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
## IsAsBuildOptionInfo
|
||||
#
|
||||
# Judge whether the string contain the information of ## @ASBUILD.
|
||||
#
|
||||
# @param String
|
||||
#
|
||||
# @return Flag
|
||||
#
|
||||
def IsAsBuildOptionInfo(String):
|
||||
ReIsAsBuildInstance = re.compile("^\s*##\s*@AsBuilt\s*$")
|
||||
if ReIsAsBuildInstance.match(String):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
class InfParserSectionRoot(object):
|
||||
def __init__(self):
|
||||
#
|
||||
# Macros defined in [Define] section are file scope global
|
||||
#
|
||||
self.FileLocalMacros = {}
|
||||
|
||||
#
|
||||
# Current Section Header content.
|
||||
#
|
||||
self.SectionHeaderContent = []
|
||||
|
||||
#
|
||||
# Last time Section Header content.
|
||||
#
|
||||
self.LastSectionHeaderContent = []
|
||||
|
||||
self.FullPath = ''
|
||||
|
||||
self.InfDefSection = None
|
||||
self.InfBuildOptionSection = None
|
||||
self.InfLibraryClassSection = None
|
||||
self.InfPackageSection = None
|
||||
self.InfPcdSection = None
|
||||
self.InfSourcesSection = None
|
||||
self.InfUserExtensionSection = None
|
||||
self.InfProtocolSection = None
|
||||
self.InfPpiSection = None
|
||||
self.InfGuidSection = None
|
||||
self.InfDepexSection = None
|
||||
self.InfPeiDepexSection = None
|
||||
self.InfDxeDepexSection = None
|
||||
self.InfSmmDepexSection = None
|
||||
self.InfBinariesSection = None
|
||||
self.InfHeader = None
|
||||
self.InfSpecialCommentSection = None
|
184
BaseTools/Source/Python/UPT/Parser/InfPcdSectionParser.py
Normal file
184
BaseTools/Source/Python/UPT/Parser/InfPcdSectionParser.py
Normal file
@@ -0,0 +1,184 @@
|
||||
## @file
|
||||
# This file contained the parser for [Pcds] sections in INF file
|
||||
#
|
||||
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials are licensed and made available
|
||||
# under the terms and conditions of the BSD License which accompanies this
|
||||
# distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
'''
|
||||
InfPcdSectionParser
|
||||
'''
|
||||
##
|
||||
# Import Modules
|
||||
#
|
||||
|
||||
import Logger.Log as Logger
|
||||
from Logger import StringTable as ST
|
||||
from Logger.ToolError import FORMAT_INVALID
|
||||
from Parser.InfParserMisc import InfExpandMacro
|
||||
from Library import DataType as DT
|
||||
from Library.Parsing import MacroParser
|
||||
from Library.Misc import GetSplitValueList
|
||||
from Library import GlobalData
|
||||
from Library.String import SplitPcdEntry
|
||||
from Parser.InfParserMisc import InfParserSectionRoot
|
||||
|
||||
class InfPcdSectionParser(InfParserSectionRoot):
|
||||
## Section PCD related parser
|
||||
#
|
||||
# For 5 types of PCD list below, all use this function.
|
||||
# 'FixedPcd', 'FeaturePcd', 'PatchPcd', 'Pcd', 'PcdEx'
|
||||
#
|
||||
# This is a INF independent parser, the validation in this parser only
|
||||
# cover
|
||||
# INF spec scope, will not cross DEC/DSC to check pcd value
|
||||
#
|
||||
def InfPcdParser(self, SectionString, InfSectionObject, FileName):
|
||||
KeysList = []
|
||||
PcdList = []
|
||||
CommentsList = []
|
||||
ValueList = []
|
||||
#
|
||||
# Current section archs
|
||||
#
|
||||
LineIndex = -1
|
||||
for Item in self.LastSectionHeaderContent:
|
||||
if (Item[0], Item[1], Item[3]) not in KeysList:
|
||||
KeysList.append((Item[0], Item[1], Item[3]))
|
||||
LineIndex = Item[3]
|
||||
|
||||
if (Item[0].upper() == DT.TAB_INF_FIXED_PCD.upper() or \
|
||||
Item[0].upper() == DT.TAB_INF_FEATURE_PCD.upper() or \
|
||||
Item[0].upper() == DT.TAB_INF_PCD.upper()) and GlobalData.gIS_BINARY_INF:
|
||||
Logger.Error('InfParser', FORMAT_INVALID, ST.ERR_ASBUILD_PCD_SECTION_TYPE%("\"" + Item[0] + "\""),
|
||||
File=FileName, Line=LineIndex)
|
||||
|
||||
#
|
||||
# For Common INF file
|
||||
#
|
||||
if not GlobalData.gIS_BINARY_INF:
|
||||
#
|
||||
# Macro defined in this section
|
||||
#
|
||||
SectionMacros = {}
|
||||
for Line in SectionString:
|
||||
PcdLineContent = Line[0]
|
||||
PcdLineNo = Line[1]
|
||||
if PcdLineContent.strip() == '':
|
||||
CommentsList = []
|
||||
continue
|
||||
|
||||
if PcdLineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
|
||||
CommentsList.append(Line)
|
||||
continue
|
||||
else:
|
||||
#
|
||||
# Encounter a PCD entry
|
||||
#
|
||||
if PcdLineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
|
||||
CommentsList.append((
|
||||
PcdLineContent[PcdLineContent.find(DT.TAB_COMMENT_SPLIT):],
|
||||
PcdLineNo))
|
||||
PcdLineContent = PcdLineContent[:PcdLineContent.find(DT.TAB_COMMENT_SPLIT)]
|
||||
|
||||
if PcdLineContent != '':
|
||||
#
|
||||
# Find Macro
|
||||
#
|
||||
Name, Value = MacroParser((PcdLineContent, PcdLineNo),
|
||||
FileName,
|
||||
DT.MODEL_EFI_PCD,
|
||||
self.FileLocalMacros)
|
||||
if Name != None:
|
||||
SectionMacros[Name] = Value
|
||||
ValueList = []
|
||||
CommentsList = []
|
||||
continue
|
||||
|
||||
PcdEntryReturn = SplitPcdEntry(PcdLineContent)
|
||||
|
||||
if not PcdEntryReturn[1]:
|
||||
TokenList = ['']
|
||||
else:
|
||||
TokenList = PcdEntryReturn[0]
|
||||
|
||||
ValueList[0:len(TokenList)] = TokenList
|
||||
|
||||
#
|
||||
# Replace with Local section Macro and [Defines] section Macro.
|
||||
#
|
||||
ValueList = [InfExpandMacro(Value, (FileName, PcdLineContent, PcdLineNo),
|
||||
self.FileLocalMacros, SectionMacros, True)
|
||||
for Value in ValueList]
|
||||
|
||||
if len(ValueList) >= 1:
|
||||
PcdList.append((ValueList, CommentsList, (PcdLineContent, PcdLineNo, FileName)))
|
||||
ValueList = []
|
||||
CommentsList = []
|
||||
continue
|
||||
#
|
||||
# For Binary INF file
|
||||
#
|
||||
else:
|
||||
for Line in SectionString:
|
||||
LineContent = Line[0].strip()
|
||||
LineNo = Line[1]
|
||||
|
||||
if LineContent == '':
|
||||
CommentsList = []
|
||||
continue
|
||||
|
||||
if LineContent.startswith(DT.TAB_COMMENT_SPLIT):
|
||||
CommentsList.append(LineContent)
|
||||
continue
|
||||
#
|
||||
# Have comments at tail.
|
||||
#
|
||||
CommentIndex = LineContent.find(DT.TAB_COMMENT_SPLIT)
|
||||
if CommentIndex > -1:
|
||||
CommentsList.append(LineContent[CommentIndex+1:])
|
||||
LineContent = LineContent[:CommentIndex]
|
||||
|
||||
TokenList = GetSplitValueList(LineContent, DT.TAB_VALUE_SPLIT)
|
||||
#
|
||||
# PatchablePcd
|
||||
# TokenSpace.CName | Value | Offset
|
||||
#
|
||||
if KeysList[0][0].upper() == DT.TAB_INF_PATCH_PCD.upper():
|
||||
if len(TokenList) != 3:
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_ASBUILD_PATCHPCD_FORMAT_INVALID,
|
||||
File=FileName,
|
||||
Line=LineNo,
|
||||
ExtraData=LineContent)
|
||||
#
|
||||
elif KeysList[0][0].upper() == DT.TAB_INF_PCD_EX.upper():
|
||||
if len(TokenList) != 2:
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_ASBUILD_PCDEX_FORMAT_INVALID,
|
||||
File=FileName,
|
||||
Line=LineNo,
|
||||
ExtraData=LineContent)
|
||||
ValueList[0:len(TokenList)] = TokenList
|
||||
if len(ValueList) >= 1:
|
||||
PcdList.append((ValueList, CommentsList, (LineContent, LineNo, FileName)))
|
||||
ValueList = []
|
||||
CommentsList = []
|
||||
continue
|
||||
|
||||
if not InfSectionObject.SetPcds(PcdList, KeysList = KeysList,
|
||||
PackageInfo = self.InfPackageSection.GetPackages()):
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR%("[PCD]"),
|
||||
File=FileName,
|
||||
Line=LineIndex)
|
||||
|
490
BaseTools/Source/Python/UPT/Parser/InfSectionParser.py
Normal file
490
BaseTools/Source/Python/UPT/Parser/InfSectionParser.py
Normal file
@@ -0,0 +1,490 @@
|
||||
## @file
|
||||
# This file contained the parser for sections in INF file
|
||||
#
|
||||
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials are licensed and made available
|
||||
# under the terms and conditions of the BSD License which accompanies this
|
||||
# distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
|
||||
'''
|
||||
InfSectionParser
|
||||
'''
|
||||
##
|
||||
# Import Modules
|
||||
#
|
||||
from copy import deepcopy
|
||||
import re
|
||||
|
||||
from Library.String import GetSplitValueList
|
||||
from Library.CommentParsing import ParseHeaderCommentSection
|
||||
from Library.CommentParsing import ParseComment
|
||||
|
||||
from Library import DataType as DT
|
||||
|
||||
import Logger.Log as Logger
|
||||
from Logger import StringTable as ST
|
||||
from Logger.ToolError import FORMAT_INVALID
|
||||
|
||||
from Object.Parser.InfDefineObject import InfDefObject
|
||||
from Object.Parser.InfBuildOptionObject import InfBuildOptionsObject
|
||||
from Object.Parser.InfLibraryClassesObject import InfLibraryClassObject
|
||||
from Object.Parser.InfPackagesObject import InfPackageObject
|
||||
from Object.Parser.InfPcdObject import InfPcdObject
|
||||
from Object.Parser.InfSoucesObject import InfSourcesObject
|
||||
from Object.Parser.InfUserExtensionObject import InfUserExtensionObject
|
||||
from Object.Parser.InfProtocolObject import InfProtocolObject
|
||||
from Object.Parser.InfPpiObject import InfPpiObject
|
||||
from Object.Parser.InfGuidObject import InfGuidObject
|
||||
from Object.Parser.InfDepexObject import InfDepexObject
|
||||
from Object.Parser.InfBinaryObject import InfBinariesObject
|
||||
from Object.Parser.InfHeaderObject import InfHeaderObject
|
||||
from Object.Parser.InfMisc import InfSpecialCommentObject
|
||||
from Object.Parser.InfMisc import InfHobObject
|
||||
from Object.Parser.InfMisc import InfBootModeObject
|
||||
from Object.Parser.InfMisc import InfEventObject
|
||||
from Parser.InfParserMisc import gINF_SECTION_DEF
|
||||
from Parser.InfDefineSectionParser import InfDefinSectionParser
|
||||
from Parser.InfBuildOptionSectionParser import InfBuildOptionSectionParser
|
||||
from Parser.InfSourceSectionParser import InfSourceSectionParser
|
||||
from Parser.InfLibrarySectionParser import InfLibrarySectionParser
|
||||
from Parser.InfPackageSectionParser import InfPackageSectionParser
|
||||
from Parser.InfGuidPpiProtocolSectionParser import InfGuidPpiProtocolSectionParser
|
||||
from Parser.InfBinarySectionParser import InfBinarySectionParser
|
||||
from Parser.InfPcdSectionParser import InfPcdSectionParser
|
||||
from Parser.InfDepexSectionParser import InfDepexSectionParser
|
||||
|
||||
## GetSpecialStr2
|
||||
#
|
||||
# GetSpecialStr2
|
||||
#
|
||||
def GetSpecialStr2(ItemList, FileName, LineNo, SectionString):
|
||||
Str2 = ''
|
||||
#
|
||||
# S2 may be Platform or ModuleType
|
||||
#
|
||||
if len(ItemList) == 3:
|
||||
#
|
||||
# Except [LibraryClass], [Depex]
|
||||
# section can has more than 2 items in section header string,
|
||||
# others should report error.
|
||||
#
|
||||
if not (ItemList[0].upper() == DT.TAB_LIBRARY_CLASSES.upper() or \
|
||||
ItemList[0].upper() == DT.TAB_DEPEX.upper() or \
|
||||
ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper()):
|
||||
if ItemList[2] != '':
|
||||
Logger.Error('Parser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID % (SectionString),
|
||||
File=FileName,
|
||||
Line=LineNo,
|
||||
ExtraData=SectionString)
|
||||
Str2 = ItemList[2]
|
||||
elif len(ItemList) == 4:
|
||||
#
|
||||
# Except [UserExtension]
|
||||
# section can has 4 items in section header string,
|
||||
# others should report error.
|
||||
#
|
||||
if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper() or ItemList[0].upper() == DT.TAB_DEPEX.upper():
|
||||
if ItemList[3] != '':
|
||||
Logger.Error('Parser', FORMAT_INVALID, ST.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID \
|
||||
% (SectionString), File=FileName, Line=LineNo, ExtraData=SectionString)
|
||||
|
||||
if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper():
|
||||
Str2 = ItemList[2] + ' | ' + ItemList[3]
|
||||
else:
|
||||
Str2 = ItemList[2]
|
||||
|
||||
elif len(ItemList) > 4:
|
||||
Logger.Error('Parser', FORMAT_INVALID, ST.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID \
|
||||
% (SectionString), File=FileName, Line=LineNo, ExtraData=SectionString)
|
||||
|
||||
return Str2
|
||||
|
||||
## ProcessUseExtHeader
|
||||
#
|
||||
#
|
||||
def ProcessUseExtHeader(ItemList):
|
||||
NewItemList = []
|
||||
AppendContent = ''
|
||||
CompleteFlag = False
|
||||
for Item in ItemList:
|
||||
if Item.startswith('\"') and not Item.endswith('\"'):
|
||||
AppendContent = Item
|
||||
CompleteFlag = True
|
||||
elif Item.endswith('\"') and not Item.startswith('\"'):
|
||||
#
|
||||
# Should not have an userId or IdString not starts with " before but ends with ".
|
||||
#
|
||||
if not CompleteFlag:
|
||||
return False, []
|
||||
AppendContent = AppendContent + "." + Item
|
||||
NewItemList.append(AppendContent)
|
||||
CompleteFlag = False
|
||||
AppendContent = ''
|
||||
elif Item.endswith('\"') and Item.startswith('\"'):
|
||||
#
|
||||
# Common item, not need to combine the information
|
||||
#
|
||||
NewItemList.append(Item)
|
||||
else:
|
||||
if not CompleteFlag:
|
||||
NewItemList.append(Item)
|
||||
else:
|
||||
AppendContent = AppendContent + "." + Item
|
||||
|
||||
if len(NewItemList) > 4:
|
||||
return False, []
|
||||
|
||||
return True, NewItemList
|
||||
|
||||
## GetArch
|
||||
#
|
||||
# GetArch
|
||||
#
|
||||
def GetArch(ItemList, ArchList, FileName, LineNo, SectionString):
|
||||
#
|
||||
# S1 is always Arch
|
||||
#
|
||||
if len(ItemList) > 1:
|
||||
Arch = ItemList[1]
|
||||
else:
|
||||
Arch = 'COMMON'
|
||||
ArchList.add(Arch)
|
||||
|
||||
#
|
||||
# 'COMMON' must not be used with specific ARCHs at the same section
|
||||
#
|
||||
if 'COMMON' in ArchList and len(ArchList) > 1:
|
||||
Logger.Error('Parser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_SECTION_ARCH_CONFLICT,
|
||||
File=FileName,
|
||||
Line=LineNo,
|
||||
ExtraData=SectionString)
|
||||
|
||||
return Arch, ArchList
|
||||
|
||||
## InfSectionParser
|
||||
#
|
||||
# Inherit from object
|
||||
#
|
||||
class InfSectionParser(InfDefinSectionParser,
|
||||
InfBuildOptionSectionParser,
|
||||
InfSourceSectionParser,
|
||||
InfLibrarySectionParser,
|
||||
InfPackageSectionParser,
|
||||
InfGuidPpiProtocolSectionParser,
|
||||
InfBinarySectionParser,
|
||||
InfPcdSectionParser,
|
||||
InfDepexSectionParser):
|
||||
#
|
||||
# Parser objects used to implement singleton
|
||||
#
|
||||
MetaFiles = {}
|
||||
|
||||
## Factory method
|
||||
#
|
||||
# One file, one parser object. This factory method makes sure that there's
|
||||
# only one object constructed for one meta file.
|
||||
#
|
||||
# @param Class class object of real AutoGen class
|
||||
# (InfParser, DecParser or DscParser)
|
||||
# @param FilePath The path of meta file
|
||||
#
|
||||
def __new__(cls, FilePath, *args, **kwargs):
|
||||
if args:
|
||||
pass
|
||||
if kwargs:
|
||||
pass
|
||||
if FilePath in cls.MetaFiles:
|
||||
return cls.MetaFiles[FilePath]
|
||||
else:
|
||||
ParserObject = super(InfSectionParser, cls).__new__(cls)
|
||||
cls.MetaFiles[FilePath] = ParserObject
|
||||
return ParserObject
|
||||
|
||||
def __init__(self):
|
||||
InfDefinSectionParser.__init__(self)
|
||||
InfBuildOptionSectionParser.__init__(self)
|
||||
InfSourceSectionParser.__init__(self)
|
||||
InfLibrarySectionParser.__init__(self)
|
||||
InfPackageSectionParser.__init__(self)
|
||||
InfGuidPpiProtocolSectionParser.__init__(self)
|
||||
InfBinarySectionParser.__init__(self)
|
||||
InfPcdSectionParser.__init__(self)
|
||||
InfDepexSectionParser.__init__(self)
|
||||
#
|
||||
# Initialize all objects that an INF file will generated.
|
||||
#
|
||||
self.InfDefSection = InfDefObject()
|
||||
self.InfBuildOptionSection = InfBuildOptionsObject()
|
||||
self.InfLibraryClassSection = InfLibraryClassObject()
|
||||
self.InfPackageSection = InfPackageObject()
|
||||
self.InfPcdSection = InfPcdObject(self.MetaFiles.keys()[0])
|
||||
self.InfSourcesSection = InfSourcesObject()
|
||||
self.InfUserExtensionSection = InfUserExtensionObject()
|
||||
self.InfProtocolSection = InfProtocolObject()
|
||||
self.InfPpiSection = InfPpiObject()
|
||||
self.InfGuidSection = InfGuidObject()
|
||||
self.InfDepexSection = InfDepexObject()
|
||||
self.InfPeiDepexSection = InfDepexObject()
|
||||
self.InfDxeDepexSection = InfDepexObject()
|
||||
self.InfSmmDepexSection = InfDepexObject()
|
||||
self.InfBinariesSection = InfBinariesObject()
|
||||
self.InfHeader = InfHeaderObject()
|
||||
self.InfSpecialCommentSection = InfSpecialCommentObject()
|
||||
|
||||
#
|
||||
# A List for store define section content.
|
||||
#
|
||||
self._PcdNameList = []
|
||||
self._SectionName = ''
|
||||
self._SectionType = 0
|
||||
self.RelaPath = ''
|
||||
self.FileName = ''
|
||||
|
||||
#
|
||||
# File Header content parser
|
||||
#
|
||||
def InfHeaderParser(self, Content, InfHeaderObject2, FileName):
|
||||
(Abstract, Description, Copyright, License) = ParseHeaderCommentSection(Content, FileName)
|
||||
#
|
||||
# Not process file name now, for later usage.
|
||||
#
|
||||
if self.FileName:
|
||||
pass
|
||||
|
||||
#
|
||||
# Insert Abstract, Description, CopyRight, License into header object
|
||||
#
|
||||
InfHeaderObject2.SetAbstract(Abstract)
|
||||
InfHeaderObject2.SetDescription(Description)
|
||||
InfHeaderObject2.SetCopyright(Copyright)
|
||||
InfHeaderObject2.SetLicense(License)
|
||||
|
||||
|
||||
|
||||
|
||||
## Section header parser
|
||||
#
|
||||
# The section header is always in following format:
|
||||
#
|
||||
# [section_name.arch<.platform|module_type>]
|
||||
#
|
||||
# @param String A string contained the content need to be parsed.
|
||||
#
|
||||
def SectionHeaderParser(self, SectionString, FileName, LineNo):
|
||||
_Scope = []
|
||||
_SectionName = ''
|
||||
ArchList = set()
|
||||
_ValueList = []
|
||||
_PcdNameList = [DT.TAB_INF_FIXED_PCD.upper(),
|
||||
DT.TAB_INF_FEATURE_PCD.upper(),
|
||||
DT.TAB_INF_PATCH_PCD.upper(),
|
||||
DT.TAB_INF_PCD.upper(),
|
||||
DT.TAB_INF_PCD_EX.upper()
|
||||
]
|
||||
SectionString = SectionString.strip()
|
||||
for Item in GetSplitValueList(SectionString[1:-1], DT.TAB_COMMA_SPLIT):
|
||||
if Item == '':
|
||||
Logger.Error('Parser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (""),
|
||||
File=FileName,
|
||||
Line=LineNo,
|
||||
ExtraData=SectionString)
|
||||
ItemList = GetSplitValueList(Item, DT.TAB_SPLIT)
|
||||
#
|
||||
# different section should not mix in one section
|
||||
# Allow different PCD type sections mixed together
|
||||
#
|
||||
if _SectionName.upper() not in _PcdNameList:
|
||||
if _SectionName != '' and _SectionName.upper() != ItemList[0].upper():
|
||||
Logger.Error('Parser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_SECTION_NAME_DUPLICATE,
|
||||
File=FileName,
|
||||
Line=LineNo,
|
||||
ExtraData=SectionString)
|
||||
elif _PcdNameList[1] in [_SectionName.upper(), ItemList[0].upper()] and \
|
||||
(_SectionName.upper()!= ItemList[0].upper()):
|
||||
Logger.Error('Parser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (""),
|
||||
File=FileName,
|
||||
Line=LineNo,
|
||||
ExtraData=SectionString)
|
||||
|
||||
_SectionName = ItemList[0]
|
||||
if _SectionName.upper() in gINF_SECTION_DEF:
|
||||
self._SectionType = gINF_SECTION_DEF[_SectionName.upper()]
|
||||
else:
|
||||
self._SectionType = DT.MODEL_UNKNOWN
|
||||
Logger.Error("Parser",
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_UNKNOWN_SECTION,
|
||||
File=FileName,
|
||||
Line=LineNo,
|
||||
ExtraData=SectionString)
|
||||
|
||||
#
|
||||
# Get Arch
|
||||
#
|
||||
Str1, ArchList = GetArch(ItemList, ArchList, FileName, LineNo, SectionString)
|
||||
|
||||
#
|
||||
# For [Defines] section, do special check.
|
||||
#
|
||||
if ItemList[0].upper() == DT.TAB_COMMON_DEFINES.upper():
|
||||
if len(ItemList) != 1:
|
||||
Logger.Error('Parser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (SectionString),
|
||||
File=FileName, Line=LineNo, ExtraData=SectionString)
|
||||
|
||||
#
|
||||
# For [UserExtension] section, do special check.
|
||||
#
|
||||
if ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper():
|
||||
|
||||
RetValue = ProcessUseExtHeader(ItemList)
|
||||
|
||||
if not RetValue[0]:
|
||||
Logger.Error('Parser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (SectionString),
|
||||
File=FileName, Line=LineNo, ExtraData=SectionString)
|
||||
else:
|
||||
ItemList = RetValue[1]
|
||||
|
||||
if len(ItemList) == 3:
|
||||
ItemList.append('COMMON')
|
||||
|
||||
Str1 = ItemList[1]
|
||||
|
||||
#
|
||||
# For Library classes, need to check module type.
|
||||
#
|
||||
if ItemList[0].upper() == DT.TAB_LIBRARY_CLASSES.upper() and len(ItemList) == 3:
|
||||
if ItemList[2] != '':
|
||||
ModuleTypeList = GetSplitValueList(ItemList[2], DT.TAB_VALUE_SPLIT)
|
||||
for Item in ModuleTypeList:
|
||||
if Item.strip() not in DT.MODULE_LIST:
|
||||
Logger.Error('Parser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_DEFINE_MODULETYPE_INVALID % (Item),
|
||||
File=FileName,
|
||||
Line=LineNo,
|
||||
ExtraData=SectionString)
|
||||
#
|
||||
# GetSpecialStr2
|
||||
#
|
||||
Str2 = GetSpecialStr2(ItemList, FileName, LineNo, SectionString)
|
||||
|
||||
_Scope.append([Str1, Str2])
|
||||
|
||||
_NewValueList = []
|
||||
_AppendFlag = True
|
||||
if _SectionName.upper() in _PcdNameList:
|
||||
for ValueItem in _ValueList:
|
||||
if _SectionName.upper() == ValueItem[0].upper() and Str1.upper() not in ValueItem[1].split():
|
||||
ValueItem[1] = ValueItem[1] + " " + Str1
|
||||
_AppendFlag = False
|
||||
elif _SectionName.upper() == ValueItem[0].upper() and Str1.upper() in ValueItem[1].split():
|
||||
_AppendFlag = False
|
||||
|
||||
_NewValueList.append(ValueItem)
|
||||
|
||||
_ValueList = _NewValueList
|
||||
|
||||
if _AppendFlag:
|
||||
if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper():
|
||||
_ValueList.append([_SectionName, Str1, Str2, LineNo])
|
||||
else:
|
||||
if len(ItemList) == 4:
|
||||
_ValueList.append([_SectionName, Str1, Str2, ItemList[3], LineNo])
|
||||
|
||||
self.SectionHeaderContent = deepcopy(_ValueList)
|
||||
|
||||
## GenSpecialSectionList
|
||||
#
|
||||
# @param SpecialSectionList: a list of list, of which item's format
|
||||
# (Comment, LineNum)
|
||||
# @param ContainerFile: Input value for filename of Inf file
|
||||
#
|
||||
def InfSpecialCommentParser (self, SpecialSectionList, InfSectionObject, ContainerFile, SectionType):
|
||||
ReFindSpecialCommentRe = re.compile(r"""#(?:\s*)\[(.*?)\](?:.*)""", re.DOTALL)
|
||||
ReFindHobArchRe = re.compile(r"""[Hh][Oo][Bb]\.([^,]*)""", re.DOTALL)
|
||||
if self.FileName:
|
||||
pass
|
||||
SpecialObjectList = []
|
||||
ArchList = []
|
||||
if SectionType == DT.TYPE_EVENT_SECTION:
|
||||
TokenDict = DT.EVENT_TOKENS
|
||||
elif SectionType == DT.TYPE_HOB_SECTION:
|
||||
TokenDict = DT.HOB_TOKENS
|
||||
else:
|
||||
TokenDict = DT.BOOTMODE_TOKENS
|
||||
|
||||
for List in SpecialSectionList:
|
||||
#
|
||||
# Hob has Arch attribute, need to be handled specially here
|
||||
#
|
||||
if SectionType == DT.TYPE_HOB_SECTION:
|
||||
|
||||
MatchObject = ReFindSpecialCommentRe.search(List[0][0])
|
||||
HobSectionStr = MatchObject.group(1)
|
||||
ArchList = []
|
||||
for Match in ReFindHobArchRe.finditer(HobSectionStr):
|
||||
Arch = Match.groups(1)[0].upper()
|
||||
ArchList.append(Arch)
|
||||
CommentSoFar = ''
|
||||
for Index in xrange(1, len(List)):
|
||||
Result = ParseComment(List[Index], DT.ALL_USAGE_TOKENS, TokenDict, [], False)
|
||||
Usage = Result[0]
|
||||
Type = Result[1]
|
||||
HelpText = Result[3]
|
||||
|
||||
if Usage == DT.ITEM_UNDEFINED and Type == DT.ITEM_UNDEFINED:
|
||||
if HelpText is None:
|
||||
HelpText = ''
|
||||
if not HelpText.endswith('\n'):
|
||||
HelpText += '\n'
|
||||
CommentSoFar += HelpText
|
||||
else:
|
||||
if HelpText:
|
||||
CommentSoFar += HelpText
|
||||
if SectionType == DT.TYPE_EVENT_SECTION:
|
||||
SpecialObject = InfEventObject()
|
||||
SpecialObject.SetEventType(Type)
|
||||
SpecialObject.SetUsage(Usage)
|
||||
SpecialObject.SetHelpString(CommentSoFar)
|
||||
elif SectionType == DT.TYPE_HOB_SECTION:
|
||||
SpecialObject = InfHobObject()
|
||||
SpecialObject.SetHobType(Type)
|
||||
SpecialObject.SetUsage(Usage)
|
||||
SpecialObject.SetHelpString(CommentSoFar)
|
||||
if len(ArchList) >= 1:
|
||||
SpecialObject.SetSupArchList(ArchList)
|
||||
else:
|
||||
SpecialObject = InfBootModeObject()
|
||||
SpecialObject.SetSupportedBootModes(Type)
|
||||
SpecialObject.SetUsage(Usage)
|
||||
SpecialObject.SetHelpString(CommentSoFar)
|
||||
|
||||
SpecialObjectList.append(SpecialObject)
|
||||
CommentSoFar = ''
|
||||
if not InfSectionObject.SetSpecialComments(SpecialObjectList,
|
||||
SectionType):
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (SectionType),
|
||||
ContainerFile
|
||||
)
|
145
BaseTools/Source/Python/UPT/Parser/InfSourceSectionParser.py
Normal file
145
BaseTools/Source/Python/UPT/Parser/InfSourceSectionParser.py
Normal file
@@ -0,0 +1,145 @@
|
||||
## @file
|
||||
# This file contained the parser for [Sources] sections in INF file
|
||||
#
|
||||
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials are licensed and made available
|
||||
# under the terms and conditions of the BSD License which accompanies this
|
||||
# distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
'''
|
||||
InfSourceSectionParser
|
||||
'''
|
||||
##
|
||||
# Import Modules
|
||||
#
|
||||
|
||||
import Logger.Log as Logger
|
||||
from Logger import StringTable as ST
|
||||
from Logger.ToolError import FORMAT_INVALID
|
||||
from Parser.InfParserMisc import InfExpandMacro
|
||||
from Library import DataType as DT
|
||||
from Library.Parsing import MacroParser
|
||||
from Library.Misc import GetSplitValueList
|
||||
from Object.Parser.InfCommonObject import InfLineCommentObject
|
||||
from Parser.InfParserMisc import InfParserSectionRoot
|
||||
|
||||
class InfSourceSectionParser(InfParserSectionRoot):
|
||||
## InfSourceParser
|
||||
#
|
||||
#
|
||||
def InfSourceParser(self, SectionString, InfSectionObject, FileName):
|
||||
SectionMacros = {}
|
||||
ValueList = []
|
||||
SourceList = []
|
||||
StillCommentFalg = False
|
||||
HeaderComments = []
|
||||
LineComment = None
|
||||
SectionContent = ''
|
||||
for Line in SectionString:
|
||||
SrcLineContent = Line[0]
|
||||
SrcLineNo = Line[1]
|
||||
|
||||
if SrcLineContent.strip() == '':
|
||||
continue
|
||||
|
||||
#
|
||||
# Found Header Comments
|
||||
#
|
||||
if SrcLineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
|
||||
#
|
||||
# Last line is comments, and this line go on.
|
||||
#
|
||||
if StillCommentFalg:
|
||||
HeaderComments.append(Line)
|
||||
SectionContent += SrcLineContent + DT.END_OF_LINE
|
||||
continue
|
||||
#
|
||||
# First time encounter comment
|
||||
#
|
||||
else:
|
||||
#
|
||||
# Clear original data
|
||||
#
|
||||
HeaderComments = []
|
||||
HeaderComments.append(Line)
|
||||
StillCommentFalg = True
|
||||
SectionContent += SrcLineContent + DT.END_OF_LINE
|
||||
continue
|
||||
else:
|
||||
StillCommentFalg = False
|
||||
|
||||
if len(HeaderComments) >= 1:
|
||||
LineComment = InfLineCommentObject()
|
||||
LineCommentContent = ''
|
||||
for Item in HeaderComments:
|
||||
LineCommentContent += Item[0] + DT.END_OF_LINE
|
||||
LineComment.SetHeaderComments(LineCommentContent)
|
||||
|
||||
#
|
||||
# Find Tail comment.
|
||||
#
|
||||
if SrcLineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
|
||||
TailComments = SrcLineContent[SrcLineContent.find(DT.TAB_COMMENT_SPLIT):]
|
||||
SrcLineContent = SrcLineContent[:SrcLineContent.find(DT.TAB_COMMENT_SPLIT)]
|
||||
if LineComment == None:
|
||||
LineComment = InfLineCommentObject()
|
||||
LineComment.SetTailComments(TailComments)
|
||||
|
||||
#
|
||||
# Find Macro
|
||||
#
|
||||
Name, Value = MacroParser((SrcLineContent, SrcLineNo),
|
||||
FileName,
|
||||
DT.MODEL_EFI_SOURCE_FILE,
|
||||
self.FileLocalMacros)
|
||||
if Name != None:
|
||||
SectionMacros[Name] = Value
|
||||
LineComment = None
|
||||
HeaderComments = []
|
||||
continue
|
||||
|
||||
#
|
||||
# Replace with Local section Macro and [Defines] section Macro.
|
||||
#
|
||||
SrcLineContent = InfExpandMacro(SrcLineContent,
|
||||
(FileName, SrcLineContent, SrcLineNo),
|
||||
self.FileLocalMacros,
|
||||
SectionMacros)
|
||||
|
||||
TokenList = GetSplitValueList(SrcLineContent, DT.TAB_VALUE_SPLIT, 4)
|
||||
ValueList[0:len(TokenList)] = TokenList
|
||||
|
||||
#
|
||||
# Store section content string after MACRO replaced.
|
||||
#
|
||||
SectionContent += SrcLineContent + DT.END_OF_LINE
|
||||
|
||||
SourceList.append((ValueList, LineComment,
|
||||
(SrcLineContent, SrcLineNo, FileName)))
|
||||
ValueList = []
|
||||
LineComment = None
|
||||
TailComments = ''
|
||||
HeaderComments = []
|
||||
continue
|
||||
|
||||
#
|
||||
# Current section archs
|
||||
#
|
||||
ArchList = []
|
||||
for Item in self.LastSectionHeaderContent:
|
||||
if Item[1] not in ArchList:
|
||||
ArchList.append(Item[1])
|
||||
InfSectionObject.SetSupArchList(Item[1])
|
||||
|
||||
InfSectionObject.SetAllContent(SectionContent)
|
||||
if not InfSectionObject.SetSources(SourceList, Arch = ArchList):
|
||||
Logger.Error('InfParser',
|
||||
FORMAT_INVALID,
|
||||
ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Sources]"),
|
||||
File=FileName,
|
||||
Line=Item[3])
|
20
BaseTools/Source/Python/UPT/Parser/__init__.py
Normal file
20
BaseTools/Source/Python/UPT/Parser/__init__.py
Normal file
@@ -0,0 +1,20 @@
|
||||
## @file
|
||||
# Python 'Parser' package initialization file.
|
||||
#
|
||||
# This file is required to make Python interpreter treat the directory
|
||||
# as containing package.
|
||||
#
|
||||
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials are licensed and made available
|
||||
# under the terms and conditions of the BSD License which accompanies this
|
||||
# distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
|
||||
'''
|
||||
Parser
|
||||
'''
|
Reference in New Issue
Block a user