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