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