]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Eot/c.py
BaseTools: Replace BSD License with BSD+Patent License
[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 # SPDX-License-Identifier: BSD-2-Clause-Patent
7 #
8
9 ##
10 # Import Modules
11 #
12 from __future__ import print_function
13 from __future__ import absolute_import
14 import sys
15 import Common.LongFilePathOs as os
16 import re
17 from . import CodeFragmentCollector
18 from . import FileProfile
19 from CommonDataClass import DataClass
20 from Common import EdkLogger
21 from .EotToolError import *
22 from . import EotGlobalData
23
24 # Global Dicts
25 IncludeFileListDict = {}
26 IncludePathListDict = {}
27 ComplexTypeDict = {}
28 SUDict = {}
29
30 ## GetFuncDeclPattern() method
31 #
32 # Get the pattern of function declaration
33 #
34 # @return p: the pattern of function declaration
35 #
36 def 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 #
46 def 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 #
56 def 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 #
66 def 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 #
78 def 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 #
95 def 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 #
121 def 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 #
240 def 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 #
305 def 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 #
339 def 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 #
377 if __name__ == '__main__':
378
379 EdkLogger.Initialize()
380 EdkLogger.SetLevel(EdkLogger.QUIET)
381 CollectSourceCodeDataIntoDB(sys.argv[1])
382
383 print('Done!')