2 # preprocess source file
4 # Copyright (c) 2007 - 2010, Intel Corporation
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
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.
21 import CodeFragmentCollector
23 from CommonDataClass
import DataClass
24 from Common
import EdkLogger
25 from EotToolError
import *
29 IncludeFileListDict
= {}
30 IncludePathListDict
= {}
34 ## GetIgnoredDirListPattern() method
36 # Get the pattern of ignored direction list
38 # @return p: the pattern of ignored direction list
40 def GetIgnoredDirListPattern():
41 p
= re
.compile(r
'.*[\\/](?:BUILD|INTELRESTRICTEDTOOLS|INTELRESTRICTEDPKG|PCCTS)[\\/].*')
44 ## GetFuncDeclPattern() method
46 # Get the pattern of function declaration
48 # @return p: the pattern of function declaration
50 def GetFuncDeclPattern():
51 p
= re
.compile(r
'(EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\).*', re
.DOTALL
)
54 ## GetArrayPattern() method
56 # Get the pattern of array
58 # @return p: the pattern of array
60 def GetArrayPattern():
61 p
= re
.compile(r
'[_\w]*\s*[\[.*\]]+')
64 ## GetTypedefFuncPointerPattern() method
66 # Get the pattern of function pointer
68 # @return p: the pattern of function pointer
70 def GetTypedefFuncPointerPattern():
71 p
= re
.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re
.DOTALL
)
76 # Get global database instance
78 # @return EotGlobalData.gDb: the global database instance
81 return EotGlobalData
.gDb
83 ## PrintErrorMsg() method
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
92 def PrintErrorMsg(ErrorType
, Msg
, TableName
, ItemId
):
93 Msg
= Msg
.replace('\n', '').replace('\r', '')
94 MsgPartList
= Msg
.split()
96 for Part
in MsgPartList
:
99 GetDB().TblReport
.Insert(ErrorType
, OtherMsg
= Msg
, BelongsToTable
= TableName
, BelongsToItem
= ItemId
)
101 ## GetIdType() method
103 # Find type of input string
105 # @param Str: String to be parsed
107 # @return Type: The type of the string
110 Type
= DataClass
.MODEL_UNKNOWN
111 Str
= Str
.replace('#', '# ')
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
126 Type
= DataClass
.MODEL_UNKNOWN
129 ## GetIdentifierList() method
131 # Get id of all files
133 # @return IdList: The list of all id of files
135 def GetIdentifierList():
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])
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])
147 FuncDeclPattern
= GetFuncDeclPattern()
148 ArrayPattern
= GetArrayPattern()
149 for var
in FileProfile
.VariableDeclarationList
:
150 DeclText
= var
.Declarator
.strip()
151 while DeclText
.startswith('*'):
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]
162 while Index
< len(FuncNamePartList
) - 1:
163 var
.Modifier
+= ' ' + FuncNamePartList
[Index
]
164 var
.Declarator
= var
.Declarator
.lstrip().lstrip(FuncNamePartList
[Index
])
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])
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
]
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])
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])
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
)
199 for su
in FileProfile
.StructUnionDefinitionList
:
200 Type
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
202 if su
.Content
.startswith('union'):
203 Type
= DataClass
.MODEL_IDENTIFIER_UNION
205 LBPos
= su
.Content
.find('{')
206 RBPos
= su
.Content
.find('}')
207 if LBPos
== -1 or RBPos
== -1:
208 Name
= su
.Content
[SkipLen
:].strip()
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])
216 TdFuncPointerPattern
= GetTypedefFuncPointerPattern()
217 for td
in FileProfile
.TypedefDefinitionList
:
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('*')
227 Modifier
+= ' ' + TmpStr
[0:StarPos
]
228 while TmpStr
[StarPos
] == '*':
229 Modifier
+= ' ' + '*'
231 TmpStr
= TmpStr
[StarPos
:].strip()
232 RBPos
= TmpStr
.find(')')
233 Name
= TmpStr
[0:RBPos
]
234 Value
= 'FP' + TmpStr
[RBPos
+ 1:]
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])
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])
244 ## GetParamList() method
246 # Get a list of parameters
248 # @param FuncDeclarator: Function declarator
249 # @param FuncNameLine: Line number of function name
250 # @param FuncNameOffset: Offset of function name
252 # @return ParamIdList: A list of parameters
254 def GetParamList(FuncDeclarator
, FuncNameLine
= 0, FuncNameOffset
= 0):
256 DeclSplitList
= FuncDeclarator
.split('(')
257 if len(DeclSplitList
) < 2:
259 FuncName
= DeclSplitList
[0]
260 ParamStr
= DeclSplitList
[1].rstrip(')')
264 while FuncName
.find('\n', Start
) != -1:
267 Start
+= FuncName
.find('\n', Start
)
269 OffsetSkipped
+= len(FuncName
[Start
:])
270 OffsetSkipped
+= 1 #skip '('
271 ParamBeginLine
= FuncNameLine
+ LineSkipped
272 ParamBeginOffset
= OffsetSkipped
273 for p
in ParamStr
.split(','):
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'
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()
297 while p
.find('\n', Start
) != -1:
300 Start
+= p
.find('\n', Start
)
302 OffsetSkipped
+= len(p
[Start
:])
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 ','
315 # Get a list of functions
317 # @return FuncObjList: A list of function objects
319 def GetFunctionList():
321 for FuncDef
in FileProfile
.FunctionDefinitionList
:
323 DeclText
= FuncDef
.Declarator
.strip()
324 while DeclText
.startswith('*'):
325 FuncDef
.Modifier
+= '*'
326 DeclText
= DeclText
.lstrip('*').strip()
328 FuncDef
.Declarator
= FuncDef
.Declarator
.lstrip('*')
329 DeclSplitList
= FuncDef
.Declarator
.split('(')
330 if len(DeclSplitList
) < 2:
333 FuncName
= DeclSplitList
[0]
334 FuncNamePartList
= FuncName
.split()
335 if len(FuncNamePartList
) > 1:
336 FuncName
= FuncNamePartList
[-1]
338 while Index
< len(FuncNamePartList
) - 1:
339 FuncDef
.Modifier
+= ' ' + FuncNamePartList
[Index
]
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
)
347 ## CreateCCodeDB() method
349 # Create database for all c code
351 # @param FileNameList: A list of all c code file names
353 def CreateCCodeDB(FileNameList
):
355 ParseErrorFileList
= []
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
)
363 collector
.ParseFile()
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()
374 if len(ParseErrorFileList
) > 0:
375 EdkLogger
.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList
))
377 Db
= EotGlobalData
.gDb
378 for file in FileObjList
:
379 Db
.InsertOneFile(file)
381 Db
.UpdateIdentifierBelongsToFunction()
385 # This acts like the main() function for the script, unless it is 'import'ed into another
388 if __name__
== '__main__':
390 EdkLogger
.Initialize()
391 EdkLogger
.SetLevel(EdkLogger
.QUIET
)
392 CollectSourceCodeDataIntoDB(sys
.argv
[1])