1## @file 2# preprocess source file 3# 4# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR> 5# 6# SPDX-License-Identifier: BSD-2-Clause-Patent 7# 8 9## 10# Import Modules 11# 12from __future__ import print_function 13from __future__ import absolute_import 14import sys 15import Common.LongFilePathOs as os 16import re 17from . import CodeFragmentCollector 18from . import FileProfile 19from CommonDataClass import DataClass 20from Common import EdkLogger 21from .EotToolError import * 22from . import EotGlobalData 23 24# Global Dicts 25IncludeFileListDict = {} 26IncludePathListDict = {} 27ComplexTypeDict = {} 28SUDict = {} 29 30## GetFuncDeclPattern() method 31# 32# Get the pattern of function declaration 33# 34# @return p: the pattern of function declaration 35# 36def GetFuncDeclPattern(): 37 p = re.compile(r'(EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\).*', re.DOTALL) 38 return p 39 40## GetArrayPattern() method 41# 42# Get the pattern of array 43# 44# @return p: the pattern of array 45# 46def GetArrayPattern(): 47 p = re.compile(r'[_\w]*\s*[\[.*\]]+') 48 return p 49 50## GetTypedefFuncPointerPattern() method 51# 52# Get the pattern of function pointer 53# 54# @return p: the pattern of function pointer 55# 56def GetTypedefFuncPointerPattern(): 57 p = re.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re.DOTALL) 58 return p 59 60## GetDB() method 61# 62# Get global database instance 63# 64# @return EotGlobalData.gDb: the global database instance 65# 66def GetDB(): 67 return EotGlobalData.gDb 68 69## PrintErrorMsg() method 70# 71# print error message 72# 73# @param ErrorType: Type of error 74# @param Msg: Error message 75# @param TableName: table name of error found 76# @param ItemId: id of item 77# 78def PrintErrorMsg(ErrorType, Msg, TableName, ItemId): 79 Msg = Msg.replace('\n', '').replace('\r', '') 80 MsgPartList = Msg.split() 81 Msg = '' 82 for Part in MsgPartList: 83 Msg += Part 84 Msg += ' ' 85 GetDB().TblReport.Insert(ErrorType, OtherMsg = Msg, BelongsToTable = TableName, BelongsToItem = ItemId) 86 87## GetIdType() method 88# 89# Find type of input string 90# 91# @param Str: String to be parsed 92# 93# @return Type: The type of the string 94# 95def GetIdType(Str): 96 Type = DataClass.MODEL_UNKNOWN 97 Str = Str.replace('#', '# ') 98 List = Str.split() 99 if List[1] == 'include': 100 Type = DataClass.MODEL_IDENTIFIER_INCLUDE 101 elif List[1] == 'define': 102 Type = DataClass.MODEL_IDENTIFIER_MACRO_DEFINE 103 elif List[1] == 'ifdef': 104 Type = DataClass.MODEL_IDENTIFIER_MACRO_IFDEF 105 elif List[1] == 'ifndef': 106 Type = DataClass.MODEL_IDENTIFIER_MACRO_IFNDEF 107 elif List[1] == 'endif': 108 Type = DataClass.MODEL_IDENTIFIER_MACRO_ENDIF 109 elif List[1] == 'pragma': 110 Type = DataClass.MODEL_IDENTIFIER_MACRO_PROGMA 111 else: 112 Type = DataClass.MODEL_UNKNOWN 113 return Type 114 115## GetIdentifierList() method 116# 117# Get id of all files 118# 119# @return IdList: The list of all id of files 120# 121def GetIdentifierList(): 122 IdList = [] 123 124 for pp in FileProfile.PPDirectiveList: 125 Type = GetIdType(pp.Content) 126 IdPP = DataClass.IdentifierClass(-1, '', '', '', pp.Content, Type, -1, -1, pp.StartPos[0], pp.StartPos[1], pp.EndPos[0], pp.EndPos[1]) 127 IdList.append(IdPP) 128 129 for ae in FileProfile.AssignmentExpressionList: 130 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]) 131 IdList.append(IdAE) 132 133 FuncDeclPattern = GetFuncDeclPattern() 134 ArrayPattern = GetArrayPattern() 135 for var in FileProfile.VariableDeclarationList: 136 DeclText = var.Declarator.strip() 137 while DeclText.startswith('*'): 138 var.Modifier += '*' 139 DeclText = DeclText.lstrip('*').strip() 140 var.Declarator = DeclText 141 if FuncDeclPattern.match(var.Declarator): 142 DeclSplitList = var.Declarator.split('(') 143 FuncName = DeclSplitList[0] 144 FuncNamePartList = FuncName.split() 145 if len(FuncNamePartList) > 1: 146 FuncName = FuncNamePartList[-1] 147 Index = 0 148 while Index < len(FuncNamePartList) - 1: 149 var.Modifier += ' ' + FuncNamePartList[Index] 150 var.Declarator = var.Declarator.lstrip().lstrip(FuncNamePartList[Index]) 151 Index += 1 152 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]) 153 IdList.append(IdVar) 154 continue 155 156 if var.Declarator.find('{') == -1: 157 for decl in var.Declarator.split(','): 158 DeclList = decl.split('=') 159 Name = DeclList[0].strip() 160 if ArrayPattern.match(Name): 161 LSBPos = var.Declarator.find('[') 162 var.Modifier += ' ' + Name[LSBPos:] 163 Name = Name[0:LSBPos] 164 165 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]) 166 IdList.append(IdVar) 167 else: 168 DeclList = var.Declarator.split('=') 169 Name = DeclList[0].strip() 170 if ArrayPattern.match(Name): 171 LSBPos = var.Declarator.find('[') 172 var.Modifier += ' ' + Name[LSBPos:] 173 Name = Name[0:LSBPos] 174 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]) 175 IdList.append(IdVar) 176 177 for enum in FileProfile.EnumerationDefinitionList: 178 LBPos = enum.Content.find('{') 179 RBPos = enum.Content.find('}') 180 Name = enum.Content[4:LBPos].strip() 181 Value = enum.Content[LBPos+1:RBPos] 182 IdEnum = DataClass.IdentifierClass(-1, '', '', Name, Value, DataClass.MODEL_IDENTIFIER_ENUMERATE, -1, -1, enum.StartPos[0], enum.StartPos[1], enum.EndPos[0], enum.EndPos[1]) 183 IdList.append(IdEnum) 184 185 for su in FileProfile.StructUnionDefinitionList: 186 Type = DataClass.MODEL_IDENTIFIER_STRUCTURE 187 SkipLen = 6 188 if su.Content.startswith('union'): 189 Type = DataClass.MODEL_IDENTIFIER_UNION 190 SkipLen = 5 191 LBPos = su.Content.find('{') 192 RBPos = su.Content.find('}') 193 if LBPos == -1 or RBPos == -1: 194 Name = su.Content[SkipLen:].strip() 195 Value = '' 196 else: 197 Name = su.Content[SkipLen:LBPos].strip() 198 Value = su.Content[LBPos+1:RBPos] 199 IdPE = DataClass.IdentifierClass(-1, '', '', Name, Value, Type, -1, -1, su.StartPos[0], su.StartPos[1], su.EndPos[0], su.EndPos[1]) 200 IdList.append(IdPE) 201 202 TdFuncPointerPattern = GetTypedefFuncPointerPattern() 203 for td in FileProfile.TypedefDefinitionList: 204 Modifier = '' 205 Name = td.ToType 206 Value = td.FromType 207 if TdFuncPointerPattern.match(td.ToType): 208 Modifier = td.FromType 209 LBPos = td.ToType.find('(') 210 TmpStr = td.ToType[LBPos+1:].strip() 211 StarPos = TmpStr.find('*') 212 if StarPos != -1: 213 Modifier += ' ' + TmpStr[0:StarPos] 214 while TmpStr[StarPos] == '*': 215 Modifier += ' ' + '*' 216 StarPos += 1 217 TmpStr = TmpStr[StarPos:].strip() 218 RBPos = TmpStr.find(')') 219 Name = TmpStr[0:RBPos] 220 Value = 'FP' + TmpStr[RBPos + 1:] 221 222 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]) 223 IdList.append(IdTd) 224 225 for funcCall in FileProfile.FunctionCallingList: 226 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]) 227 IdList.append(IdFC) 228 return IdList 229 230## GetParamList() method 231# 232# Get a list of parameters 233# 234# @param FuncDeclarator: Function declarator 235# @param FuncNameLine: Line number of function name 236# @param FuncNameOffset: Offset of function name 237# 238# @return ParamIdList: A list of parameters 239# 240def GetParamList(FuncDeclarator, FuncNameLine = 0, FuncNameOffset = 0): 241 ParamIdList = [] 242 DeclSplitList = FuncDeclarator.split('(') 243 if len(DeclSplitList) < 2: 244 return ParamIdList 245 FuncName = DeclSplitList[0] 246 ParamStr = DeclSplitList[1].rstrip(')') 247 LineSkipped = 0 248 OffsetSkipped = 0 249 Start = 0 250 while FuncName.find('\n', Start) != -1: 251 LineSkipped += 1 252 OffsetSkipped = 0 253 Start += FuncName.find('\n', Start) 254 Start += 1 255 OffsetSkipped += len(FuncName[Start:]) 256 OffsetSkipped += 1 #skip '(' 257 ParamBeginLine = FuncNameLine + LineSkipped 258 ParamBeginOffset = OffsetSkipped 259 for p in ParamStr.split(','): 260 ListP = p.split() 261 if len(ListP) == 0: 262 continue 263 ParamName = ListP[-1] 264 DeclText = ParamName.strip() 265 RightSpacePos = p.rfind(ParamName) 266 ParamModifier = p[0:RightSpacePos] 267 if ParamName == 'OPTIONAL': 268 if ParamModifier == '': 269 ParamModifier += ' ' + 'OPTIONAL' 270 DeclText = '' 271 else: 272 ParamName = ListP[-2] 273 DeclText = ParamName.strip() 274 RightSpacePos = p.rfind(ParamName) 275 ParamModifier = p[0:RightSpacePos] 276 ParamModifier += 'OPTIONAL' 277 while DeclText.startswith('*'): 278 ParamModifier += ' ' + '*' 279 DeclText = DeclText.lstrip('*').strip() 280 ParamName = DeclText 281 282 Start = 0 283 while p.find('\n', Start) != -1: 284 LineSkipped += 1 285 OffsetSkipped = 0 286 Start += p.find('\n', Start) 287 Start += 1 288 OffsetSkipped += len(p[Start:]) 289 290 ParamEndLine = ParamBeginLine + LineSkipped 291 ParamEndOffset = OffsetSkipped 292 IdParam = DataClass.IdentifierClass(-1, ParamModifier, '', ParamName, '', DataClass.MODEL_IDENTIFIER_PARAMETER, -1, -1, ParamBeginLine, ParamBeginOffset, ParamEndLine, ParamEndOffset) 293 ParamIdList.append(IdParam) 294 ParamBeginLine = ParamEndLine 295 ParamBeginOffset = OffsetSkipped + 1 #skip ',' 296 297 return ParamIdList 298 299## GetFunctionList() 300# 301# Get a list of functions 302# 303# @return FuncObjList: A list of function objects 304# 305def GetFunctionList(): 306 FuncObjList = [] 307 for FuncDef in FileProfile.FunctionDefinitionList: 308 ParamIdList = [] 309 DeclText = FuncDef.Declarator.strip() 310 while DeclText.startswith('*'): 311 FuncDef.Modifier += '*' 312 DeclText = DeclText.lstrip('*').strip() 313 314 FuncDef.Declarator = FuncDef.Declarator.lstrip('*') 315 DeclSplitList = FuncDef.Declarator.split('(') 316 if len(DeclSplitList) < 2: 317 continue 318 319 FuncName = DeclSplitList[0] 320 FuncNamePartList = FuncName.split() 321 if len(FuncNamePartList) > 1: 322 FuncName = FuncNamePartList[-1] 323 Index = 0 324 while Index < len(FuncNamePartList) - 1: 325 FuncDef.Modifier += ' ' + FuncNamePartList[Index] 326 Index += 1 327 328 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, []) 329 FuncObjList.append(FuncObj) 330 331 return FuncObjList 332 333## CreateCCodeDB() method 334# 335# Create database for all c code 336# 337# @param FileNameList: A list of all c code file names 338# 339def CreateCCodeDB(FileNameList): 340 FileObjList = [] 341 ParseErrorFileList = [] 342 ParsedFiles = {} 343 for FullName in FileNameList: 344 if os.path.splitext(FullName)[1] in ('.h', '.c'): 345 if FullName.lower() in ParsedFiles: 346 continue 347 ParsedFiles[FullName.lower()] = 1 348 EdkLogger.info("Parsing " + FullName) 349 model = FullName.endswith('c') and DataClass.MODEL_FILE_C or DataClass.MODEL_FILE_H 350 collector = CodeFragmentCollector.CodeFragmentCollector(FullName) 351 try: 352 collector.ParseFile() 353 except: 354 ParseErrorFileList.append(FullName) 355 BaseName = os.path.basename(FullName) 356 DirName = os.path.dirname(FullName) 357 Ext = os.path.splitext(BaseName)[1].lstrip('.') 358 ModifiedTime = os.path.getmtime(FullName) 359 FileObj = DataClass.FileClass(-1, BaseName, Ext, DirName, FullName, model, ModifiedTime, GetFunctionList(), GetIdentifierList(), []) 360 FileObjList.append(FileObj) 361 collector.CleanFileProfileBuffer() 362 363 if len(ParseErrorFileList) > 0: 364 EdkLogger.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList)) 365 366 Db = EotGlobalData.gDb 367 for file in FileObjList: 368 Db.InsertOneFile(file) 369 370 Db.UpdateIdentifierBelongsToFunction() 371 372## 373# 374# This acts like the main() function for the script, unless it is 'import'ed into another 375# script. 376# 377if __name__ == '__main__': 378 379 EdkLogger.Initialize() 380 EdkLogger.SetLevel(EdkLogger.QUIET) 381 CollectSourceCodeDataIntoDB(sys.argv[1]) 382 383 print('Done!') 384