## @file # preprocess source file # # Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
# # SPDX-License-Identifier: BSD-2-Clause-Patent # ## # Import Modules # from __future__ import print_function from __future__ import absolute_import import sys import Common.LongFilePathOs as os import re from . import CodeFragmentCollector from . import FileProfile from CommonDataClass import DataClass from Common import EdkLogger from .EotToolError import * from . import EotGlobalData # Global Dicts IncludeFileListDict = {} IncludePathListDict = {} ComplexTypeDict = {} SUDict = {} ## GetFuncDeclPattern() method # # Get the pattern of function declaration # # @return p: the pattern of function declaration # def GetFuncDeclPattern(): p = re.compile(r'(EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\).*', re.DOTALL) return p ## GetArrayPattern() method # # Get the pattern of array # # @return p: the pattern of array # def GetArrayPattern(): p = re.compile(r'[_\w]*\s*[\[.*\]]+') return p ## GetTypedefFuncPointerPattern() method # # Get the pattern of function pointer # # @return p: the pattern of function pointer # def GetTypedefFuncPointerPattern(): p = re.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re.DOTALL) return p ## GetDB() method # # Get global database instance # # @return EotGlobalData.gDb: the global database instance # def GetDB(): return EotGlobalData.gDb ## PrintErrorMsg() method # # print error message # # @param ErrorType: Type of error # @param Msg: Error message # @param TableName: table name of error found # @param ItemId: id of item # def PrintErrorMsg(ErrorType, Msg, TableName, ItemId): Msg = Msg.replace('\n', '').replace('\r', '') MsgPartList = Msg.split() Msg = '' for Part in MsgPartList: Msg += Part Msg += ' ' GetDB().TblReport.Insert(ErrorType, OtherMsg = Msg, BelongsToTable = TableName, BelongsToItem = ItemId) ## GetIdType() method # # Find type of input string # # @param Str: String to be parsed # # @return Type: The type of the string # def GetIdType(Str): Type = DataClass.MODEL_UNKNOWN Str = Str.replace('#', '# ') List = Str.split() if List[1] == 'include': Type = DataClass.MODEL_IDENTIFIER_INCLUDE elif List[1] == 'define': Type = DataClass.MODEL_IDENTIFIER_MACRO_DEFINE elif List[1] == 'ifdef': Type = DataClass.MODEL_IDENTIFIER_MACRO_IFDEF elif List[1] == 'ifndef': Type = DataClass.MODEL_IDENTIFIER_MACRO_IFNDEF elif List[1] == 'endif': Type = DataClass.MODEL_IDENTIFIER_MACRO_ENDIF elif List[1] == 'pragma': Type = DataClass.MODEL_IDENTIFIER_MACRO_PROGMA else: Type = DataClass.MODEL_UNKNOWN return Type ## GetIdentifierList() method # # Get id of all files # # @return IdList: The list of all id of files # def GetIdentifierList(): IdList = [] for pp in FileProfile.PPDirectiveList: Type = GetIdType(pp.Content) IdPP = DataClass.IdentifierClass(-1, '', '', '', pp.Content, Type, -1, -1, pp.StartPos[0], pp.StartPos[1], pp.EndPos[0], pp.EndPos[1]) IdList.append(IdPP) for ae in FileProfile.AssignmentExpressionList: IdAE = DataClass.IdentifierClass(-1, ae.Operator, '', ae.Name, ae.Value, DataClass.MODEL_IDENTIFIER_ASSIGNMENT_EXPRESSION, -1, -1, ae.StartPos[0], ae.StartPos[1], ae.EndPos[0], ae.EndPos[1]) IdList.append(IdAE) FuncDeclPattern = GetFuncDeclPattern() ArrayPattern = GetArrayPattern() for var in FileProfile.VariableDeclarationList: DeclText = var.Declarator.strip() while DeclText.startswith('*'): var.Modifier += '*' DeclText = DeclText.lstrip('*').strip() var.Declarator = DeclText if FuncDeclPattern.match(var.Declarator): DeclSplitList = var.Declarator.split('(') FuncName = DeclSplitList[0] FuncNamePartList = FuncName.split() if len(FuncNamePartList) > 1: FuncName = FuncNamePartList[-1] Index = 0 while Index < len(FuncNamePartList) - 1: var.Modifier += ' ' + FuncNamePartList[Index] var.Declarator = var.Declarator.lstrip().lstrip(FuncNamePartList[Index]) Index += 1 IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', var.Declarator, '', DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, -1, -1, var.StartPos[0], var.StartPos[1], var.EndPos[0], var.EndPos[1]) IdList.append(IdVar) continue if var.Declarator.find('{') == -1: for decl in var.Declarator.split(','): DeclList = decl.split('=') Name = DeclList[0].strip() if ArrayPattern.match(Name): LSBPos = var.Declarator.find('[') var.Modifier += ' ' + Name[LSBPos:] Name = Name[0:LSBPos] IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', Name, (len(DeclList) > 1 and [DeclList[1]]or [''])[0], DataClass.MODEL_IDENTIFIER_VARIABLE, -1, -1, var.StartPos[0], var.StartPos[1], var.EndPos[0], var.EndPos[1]) IdList.append(IdVar) else: DeclList = var.Declarator.split('=') Name = DeclList[0].strip() if ArrayPattern.match(Name): LSBPos = var.Declarator.find('[') var.Modifier += ' ' + Name[LSBPos:] Name = Name[0:LSBPos] IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', Name, (len(DeclList) > 1 and [DeclList[1]]or [''])[0], DataClass.MODEL_IDENTIFIER_VARIABLE, -1, -1, var.StartPos[0], var.StartPos[1], var.EndPos[0], var.EndPos[1]) IdList.append(IdVar) for enum in FileProfile.EnumerationDefinitionList: LBPos = enum.Content.find('{') RBPos = enum.Content.find('}') Name = enum.Content[4:LBPos].strip() Value = enum.Content[LBPos+1:RBPos] IdEnum = DataClass.IdentifierClass(-1, '', '', Name, Value, DataClass.MODEL_IDENTIFIER_ENUMERATE, -1, -1, enum.StartPos[0], enum.StartPos[1], enum.EndPos[0], enum.EndPos[1]) IdList.append(IdEnum) for su in FileProfile.StructUnionDefinitionList: Type = DataClass.MODEL_IDENTIFIER_STRUCTURE SkipLen = 6 if su.Content.startswith('union'): Type = DataClass.MODEL_IDENTIFIER_UNION SkipLen = 5 LBPos = su.Content.find('{') RBPos = su.Content.find('}') if LBPos == -1 or RBPos == -1: Name = su.Content[SkipLen:].strip() Value = '' else: Name = su.Content[SkipLen:LBPos].strip() Value = su.Content[LBPos+1:RBPos] IdPE = DataClass.IdentifierClass(-1, '', '', Name, Value, Type, -1, -1, su.StartPos[0], su.StartPos[1], su.EndPos[0], su.EndPos[1]) IdList.append(IdPE) TdFuncPointerPattern = GetTypedefFuncPointerPattern() for td in FileProfile.TypedefDefinitionList: Modifier = '' Name = td.ToType Value = td.FromType if TdFuncPointerPattern.match(td.ToType): Modifier = td.FromType LBPos = td.ToType.find('(') TmpStr = td.ToType[LBPos+1:].strip() StarPos = TmpStr.find('*') if StarPos != -1: Modifier += ' ' + TmpStr[0:StarPos] while TmpStr[StarPos] == '*': Modifier += ' ' + '*' StarPos += 1 TmpStr = TmpStr[StarPos:].strip() RBPos = TmpStr.find(')') Name = TmpStr[0:RBPos] Value = 'FP' + TmpStr[RBPos + 1:] IdTd = DataClass.IdentifierClass(-1, Modifier, '', Name, Value, DataClass.MODEL_IDENTIFIER_TYPEDEF, -1, -1, td.StartPos[0], td.StartPos[1], td.EndPos[0], td.EndPos[1]) IdList.append(IdTd) for funcCall in FileProfile.FunctionCallingList: IdFC = DataClass.IdentifierClass(-1, '', '', funcCall.FuncName, funcCall.ParamList, DataClass.MODEL_IDENTIFIER_FUNCTION_CALLING, -1, -1, funcCall.StartPos[0], funcCall.StartPos[1], funcCall.EndPos[0], funcCall.EndPos[1]) IdList.append(IdFC) return IdList ## GetParamList() method # # Get a list of parameters # # @param FuncDeclarator: Function declarator # @param FuncNameLine: Line number of function name # @param FuncNameOffset: Offset of function name # # @return ParamIdList: A list of parameters # def GetParamList(FuncDeclarator, FuncNameLine = 0, FuncNameOffset = 0): ParamIdList = [] DeclSplitList = FuncDeclarator.split('(') if len(DeclSplitList) < 2: return ParamIdList FuncName = DeclSplitList[0] ParamStr = DeclSplitList[1].rstrip(')') LineSkipped = 0 OffsetSkipped = 0 Start = 0 while FuncName.find('\n', Start) != -1: LineSkipped += 1 OffsetSkipped = 0 Start += FuncName.find('\n', Start) Start += 1 OffsetSkipped += len(FuncName[Start:]) OffsetSkipped += 1 #skip '(' ParamBeginLine = FuncNameLine + LineSkipped ParamBeginOffset = OffsetSkipped for p in ParamStr.split(','): ListP = p.split() if len(ListP) == 0: continue ParamName = ListP[-1] DeclText = ParamName.strip() RightSpacePos = p.rfind(ParamName) ParamModifier = p[0:RightSpacePos] if ParamName == 'OPTIONAL': if ParamModifier == '': ParamModifier += ' ' + 'OPTIONAL' DeclText = '' else: ParamName = ListP[-2] DeclText = ParamName.strip() RightSpacePos = p.rfind(ParamName) ParamModifier = p[0:RightSpacePos] ParamModifier += 'OPTIONAL' while DeclText.startswith('*'): ParamModifier += ' ' + '*' DeclText = DeclText.lstrip('*').strip() ParamName = DeclText Start = 0 while p.find('\n', Start) != -1: LineSkipped += 1 OffsetSkipped = 0 Start += p.find('\n', Start) Start += 1 OffsetSkipped += len(p[Start:]) ParamEndLine = ParamBeginLine + LineSkipped ParamEndOffset = OffsetSkipped IdParam = DataClass.IdentifierClass(-1, ParamModifier, '', ParamName, '', DataClass.MODEL_IDENTIFIER_PARAMETER, -1, -1, ParamBeginLine, ParamBeginOffset, ParamEndLine, ParamEndOffset) ParamIdList.append(IdParam) ParamBeginLine = ParamEndLine ParamBeginOffset = OffsetSkipped + 1 #skip ',' return ParamIdList ## GetFunctionList() # # Get a list of functions # # @return FuncObjList: A list of function objects # def GetFunctionList(): FuncObjList = [] for FuncDef in FileProfile.FunctionDefinitionList: ParamIdList = [] DeclText = FuncDef.Declarator.strip() while DeclText.startswith('*'): FuncDef.Modifier += '*' DeclText = DeclText.lstrip('*').strip() FuncDef.Declarator = FuncDef.Declarator.lstrip('*') DeclSplitList = FuncDef.Declarator.split('(') if len(DeclSplitList) < 2: continue FuncName = DeclSplitList[0] FuncNamePartList = FuncName.split() if len(FuncNamePartList) > 1: FuncName = FuncNamePartList[-1] Index = 0 while Index < len(FuncNamePartList) - 1: FuncDef.Modifier += ' ' + FuncNamePartList[Index] Index += 1 FuncObj = DataClass.FunctionClass(-1, FuncDef.Declarator, FuncDef.Modifier, FuncName.strip(), '', FuncDef.StartPos[0], FuncDef.StartPos[1], FuncDef.EndPos[0], FuncDef.EndPos[1], FuncDef.LeftBracePos[0], FuncDef.LeftBracePos[1], -1, ParamIdList, []) FuncObjList.append(FuncObj) return FuncObjList ## CreateCCodeDB() method # # Create database for all c code # # @param FileNameList: A list of all c code file names # def CreateCCodeDB(FileNameList): FileObjList = [] ParseErrorFileList = [] ParsedFiles = {} for FullName in FileNameList: if os.path.splitext(FullName)[1] in ('.h', '.c'): if FullName.lower() in ParsedFiles: continue ParsedFiles[FullName.lower()] = 1 EdkLogger.info("Parsing " + FullName) model = FullName.endswith('c') and DataClass.MODEL_FILE_C or DataClass.MODEL_FILE_H collector = CodeFragmentCollector.CodeFragmentCollector(FullName) try: collector.ParseFile() except: ParseErrorFileList.append(FullName) BaseName = os.path.basename(FullName) DirName = os.path.dirname(FullName) Ext = os.path.splitext(BaseName)[1].lstrip('.') ModifiedTime = os.path.getmtime(FullName) FileObj = DataClass.FileClass(-1, BaseName, Ext, DirName, FullName, model, ModifiedTime, GetFunctionList(), GetIdentifierList(), []) FileObjList.append(FileObj) collector.CleanFileProfileBuffer() if len(ParseErrorFileList) > 0: EdkLogger.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList)) Db = EotGlobalData.gDb for file in FileObjList: Db.InsertOneFile(file) Db.UpdateIdentifierBelongsToFunction() ## # # This acts like the main() function for the script, unless it is 'import'ed into another # script. # if __name__ == '__main__': EdkLogger.Initialize() EdkLogger.SetLevel(EdkLogger.QUIET) CollectSourceCodeDataIntoDB(sys.argv[1]) print('Done!')