2 # preprocess source file
4 # Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
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
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.
19 import Common
.LongFilePathOs
as os
21 import CodeFragmentCollector
23 from CommonDataClass
import DataClass
24 from Common
import EdkLogger
25 from EotToolError
import *
29 IncludeFileListDict
= {}
30 IncludePathListDict
= {}
34 ## GetFuncDeclPattern() method
36 # Get the pattern of function declaration
38 # @return p: the pattern of function declaration
40 def GetFuncDeclPattern():
41 p
= re
.compile(r
'(EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\).*', re
.DOTALL
)
44 ## GetArrayPattern() method
46 # Get the pattern of array
48 # @return p: the pattern of array
50 def GetArrayPattern():
51 p
= re
.compile(r
'[_\w]*\s*[\[.*\]]+')
54 ## GetTypedefFuncPointerPattern() method
56 # Get the pattern of function pointer
58 # @return p: the pattern of function pointer
60 def GetTypedefFuncPointerPattern():
61 p
= re
.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re
.DOTALL
)
66 # Get global database instance
68 # @return EotGlobalData.gDb: the global database instance
71 return EotGlobalData
.gDb
73 ## PrintErrorMsg() method
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
82 def PrintErrorMsg(ErrorType
, Msg
, TableName
, ItemId
):
83 Msg
= Msg
.replace('\n', '').replace('\r', '')
84 MsgPartList
= Msg
.split()
86 for Part
in MsgPartList
:
89 GetDB().TblReport
.Insert(ErrorType
, OtherMsg
= Msg
, BelongsToTable
= TableName
, BelongsToItem
= ItemId
)
93 # Find type of input string
95 # @param Str: String to be parsed
97 # @return Type: The type of the string
100 Type
= DataClass
.MODEL_UNKNOWN
101 Str
= Str
.replace('#', '# ')
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
116 Type
= DataClass
.MODEL_UNKNOWN
119 ## GetIdentifierList() method
121 # Get id of all files
123 # @return IdList: The list of all id of files
125 def GetIdentifierList():
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])
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])
137 FuncDeclPattern
= GetFuncDeclPattern()
138 ArrayPattern
= GetArrayPattern()
139 for var
in FileProfile
.VariableDeclarationList
:
140 DeclText
= var
.Declarator
.strip()
141 while DeclText
.startswith('*'):
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]
152 while Index
< len(FuncNamePartList
) - 1:
153 var
.Modifier
+= ' ' + FuncNamePartList
[Index
]
154 var
.Declarator
= var
.Declarator
.lstrip().lstrip(FuncNamePartList
[Index
])
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])
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
]
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])
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])
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
)
189 for su
in FileProfile
.StructUnionDefinitionList
:
190 Type
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
192 if su
.Content
.startswith('union'):
193 Type
= DataClass
.MODEL_IDENTIFIER_UNION
195 LBPos
= su
.Content
.find('{')
196 RBPos
= su
.Content
.find('}')
197 if LBPos
== -1 or RBPos
== -1:
198 Name
= su
.Content
[SkipLen
:].strip()
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])
206 TdFuncPointerPattern
= GetTypedefFuncPointerPattern()
207 for td
in FileProfile
.TypedefDefinitionList
:
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('*')
217 Modifier
+= ' ' + TmpStr
[0:StarPos
]
218 while TmpStr
[StarPos
] == '*':
219 Modifier
+= ' ' + '*'
221 TmpStr
= TmpStr
[StarPos
:].strip()
222 RBPos
= TmpStr
.find(')')
223 Name
= TmpStr
[0:RBPos
]
224 Value
= 'FP' + TmpStr
[RBPos
+ 1:]
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])
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])
234 ## GetParamList() method
236 # Get a list of parameters
238 # @param FuncDeclarator: Function declarator
239 # @param FuncNameLine: Line number of function name
240 # @param FuncNameOffset: Offset of function name
242 # @return ParamIdList: A list of parameters
244 def GetParamList(FuncDeclarator
, FuncNameLine
= 0, FuncNameOffset
= 0):
246 DeclSplitList
= FuncDeclarator
.split('(')
247 if len(DeclSplitList
) < 2:
249 FuncName
= DeclSplitList
[0]
250 ParamStr
= DeclSplitList
[1].rstrip(')')
254 while FuncName
.find('\n', Start
) != -1:
257 Start
+= FuncName
.find('\n', Start
)
259 OffsetSkipped
+= len(FuncName
[Start
:])
260 OffsetSkipped
+= 1 #skip '('
261 ParamBeginLine
= FuncNameLine
+ LineSkipped
262 ParamBeginOffset
= OffsetSkipped
263 for p
in ParamStr
.split(','):
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'
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()
287 while p
.find('\n', Start
) != -1:
290 Start
+= p
.find('\n', Start
)
292 OffsetSkipped
+= len(p
[Start
:])
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 ','
305 # Get a list of functions
307 # @return FuncObjList: A list of function objects
309 def GetFunctionList():
311 for FuncDef
in FileProfile
.FunctionDefinitionList
:
313 DeclText
= FuncDef
.Declarator
.strip()
314 while DeclText
.startswith('*'):
315 FuncDef
.Modifier
+= '*'
316 DeclText
= DeclText
.lstrip('*').strip()
318 FuncDef
.Declarator
= FuncDef
.Declarator
.lstrip('*')
319 DeclSplitList
= FuncDef
.Declarator
.split('(')
320 if len(DeclSplitList
) < 2:
323 FuncName
= DeclSplitList
[0]
324 FuncNamePartList
= FuncName
.split()
325 if len(FuncNamePartList
) > 1:
326 FuncName
= FuncNamePartList
[-1]
328 while Index
< len(FuncNamePartList
) - 1:
329 FuncDef
.Modifier
+= ' ' + FuncNamePartList
[Index
]
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
)
337 ## CreateCCodeDB() method
339 # Create database for all c code
341 # @param FileNameList: A list of all c code file names
343 def CreateCCodeDB(FileNameList
):
345 ParseErrorFileList
= []
347 for FullName
in FileNameList
:
348 if os
.path
.splitext(FullName
)[1] in ('.h', '.c'):
349 if FullName
.lower() in ParsedFiles
:
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
)
356 collector
.ParseFile()
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()
367 if len(ParseErrorFileList
) > 0:
368 EdkLogger
.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList
))
370 Db
= EotGlobalData
.gDb
371 for file in FileObjList
:
372 Db
.InsertOneFile(file)
374 Db
.UpdateIdentifierBelongsToFunction()
378 # This acts like the main() function for the script, unless it is 'import'ed into another
381 if __name__
== '__main__':
383 EdkLogger
.Initialize()
384 EdkLogger
.SetLevel(EdkLogger
.QUIET
)
385 CollectSourceCodeDataIntoDB(sys
.argv
[1])