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