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.
18 from __future__
import print_function
20 import Common
.LongFilePathOs
as os
22 import CodeFragmentCollector
24 from CommonDataClass
import DataClass
25 from Common
import EdkLogger
26 from EotToolError
import *
30 IncludeFileListDict
= {}
31 IncludePathListDict
= {}
35 ## GetFuncDeclPattern() method
37 # Get the pattern of function declaration
39 # @return p: the pattern of function declaration
41 def GetFuncDeclPattern():
42 p
= re
.compile(r
'(EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\).*', re
.DOTALL
)
45 ## GetArrayPattern() method
47 # Get the pattern of array
49 # @return p: the pattern of array
51 def GetArrayPattern():
52 p
= re
.compile(r
'[_\w]*\s*[\[.*\]]+')
55 ## GetTypedefFuncPointerPattern() method
57 # Get the pattern of function pointer
59 # @return p: the pattern of function pointer
61 def GetTypedefFuncPointerPattern():
62 p
= re
.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re
.DOTALL
)
67 # Get global database instance
69 # @return EotGlobalData.gDb: the global database instance
72 return EotGlobalData
.gDb
74 ## PrintErrorMsg() method
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
83 def PrintErrorMsg(ErrorType
, Msg
, TableName
, ItemId
):
84 Msg
= Msg
.replace('\n', '').replace('\r', '')
85 MsgPartList
= Msg
.split()
87 for Part
in MsgPartList
:
90 GetDB().TblReport
.Insert(ErrorType
, OtherMsg
= Msg
, BelongsToTable
= TableName
, BelongsToItem
= ItemId
)
94 # Find type of input string
96 # @param Str: String to be parsed
98 # @return Type: The type of the string
101 Type
= DataClass
.MODEL_UNKNOWN
102 Str
= Str
.replace('#', '# ')
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
117 Type
= DataClass
.MODEL_UNKNOWN
120 ## GetIdentifierList() method
122 # Get id of all files
124 # @return IdList: The list of all id of files
126 def GetIdentifierList():
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])
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])
138 FuncDeclPattern
= GetFuncDeclPattern()
139 ArrayPattern
= GetArrayPattern()
140 for var
in FileProfile
.VariableDeclarationList
:
141 DeclText
= var
.Declarator
.strip()
142 while DeclText
.startswith('*'):
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]
153 while Index
< len(FuncNamePartList
) - 1:
154 var
.Modifier
+= ' ' + FuncNamePartList
[Index
]
155 var
.Declarator
= var
.Declarator
.lstrip().lstrip(FuncNamePartList
[Index
])
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])
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
]
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])
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])
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
)
190 for su
in FileProfile
.StructUnionDefinitionList
:
191 Type
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
193 if su
.Content
.startswith('union'):
194 Type
= DataClass
.MODEL_IDENTIFIER_UNION
196 LBPos
= su
.Content
.find('{')
197 RBPos
= su
.Content
.find('}')
198 if LBPos
== -1 or RBPos
== -1:
199 Name
= su
.Content
[SkipLen
:].strip()
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])
207 TdFuncPointerPattern
= GetTypedefFuncPointerPattern()
208 for td
in FileProfile
.TypedefDefinitionList
:
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('*')
218 Modifier
+= ' ' + TmpStr
[0:StarPos
]
219 while TmpStr
[StarPos
] == '*':
220 Modifier
+= ' ' + '*'
222 TmpStr
= TmpStr
[StarPos
:].strip()
223 RBPos
= TmpStr
.find(')')
224 Name
= TmpStr
[0:RBPos
]
225 Value
= 'FP' + TmpStr
[RBPos
+ 1:]
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])
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])
235 ## GetParamList() method
237 # Get a list of parameters
239 # @param FuncDeclarator: Function declarator
240 # @param FuncNameLine: Line number of function name
241 # @param FuncNameOffset: Offset of function name
243 # @return ParamIdList: A list of parameters
245 def GetParamList(FuncDeclarator
, FuncNameLine
= 0, FuncNameOffset
= 0):
247 DeclSplitList
= FuncDeclarator
.split('(')
248 if len(DeclSplitList
) < 2:
250 FuncName
= DeclSplitList
[0]
251 ParamStr
= DeclSplitList
[1].rstrip(')')
255 while FuncName
.find('\n', Start
) != -1:
258 Start
+= FuncName
.find('\n', Start
)
260 OffsetSkipped
+= len(FuncName
[Start
:])
261 OffsetSkipped
+= 1 #skip '('
262 ParamBeginLine
= FuncNameLine
+ LineSkipped
263 ParamBeginOffset
= OffsetSkipped
264 for p
in ParamStr
.split(','):
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'
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()
288 while p
.find('\n', Start
) != -1:
291 Start
+= p
.find('\n', Start
)
293 OffsetSkipped
+= len(p
[Start
:])
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 ','
306 # Get a list of functions
308 # @return FuncObjList: A list of function objects
310 def GetFunctionList():
312 for FuncDef
in FileProfile
.FunctionDefinitionList
:
314 DeclText
= FuncDef
.Declarator
.strip()
315 while DeclText
.startswith('*'):
316 FuncDef
.Modifier
+= '*'
317 DeclText
= DeclText
.lstrip('*').strip()
319 FuncDef
.Declarator
= FuncDef
.Declarator
.lstrip('*')
320 DeclSplitList
= FuncDef
.Declarator
.split('(')
321 if len(DeclSplitList
) < 2:
324 FuncName
= DeclSplitList
[0]
325 FuncNamePartList
= FuncName
.split()
326 if len(FuncNamePartList
) > 1:
327 FuncName
= FuncNamePartList
[-1]
329 while Index
< len(FuncNamePartList
) - 1:
330 FuncDef
.Modifier
+= ' ' + FuncNamePartList
[Index
]
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
)
338 ## CreateCCodeDB() method
340 # Create database for all c code
342 # @param FileNameList: A list of all c code file names
344 def CreateCCodeDB(FileNameList
):
346 ParseErrorFileList
= []
348 for FullName
in FileNameList
:
349 if os
.path
.splitext(FullName
)[1] in ('.h', '.c'):
350 if FullName
.lower() in ParsedFiles
:
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
)
357 collector
.ParseFile()
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()
368 if len(ParseErrorFileList
) > 0:
369 EdkLogger
.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList
))
371 Db
= EotGlobalData
.gDb
372 for file in FileObjList
:
373 Db
.InsertOneFile(file)
375 Db
.UpdateIdentifierBelongsToFunction()
379 # This acts like the main() function for the script, unless it is 'import'ed into another
382 if __name__
== '__main__':
384 EdkLogger
.Initialize()
385 EdkLogger
.SetLevel(EdkLogger
.QUIET
)
386 CollectSourceCodeDataIntoDB(sys
.argv
[1])