PageRenderTime 30ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/edk2/BaseTools/Source/Python/Eot/c.py

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