2 # preprocess source file
4 # Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
6 # SPDX-License-Identifier: BSD-2-Clause-Patent
12 from __future__
import print_function
13 from __future__
import absolute_import
15 import Common
.LongFilePathOs
as os
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
25 IncludeFileListDict
= {}
26 IncludePathListDict
= {}
30 ## GetFuncDeclPattern() method
32 # Get the pattern of function declaration
34 # @return p: the pattern of function declaration
36 def GetFuncDeclPattern():
37 p
= re
.compile(r
'(EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\).*', re
.DOTALL
)
40 ## GetArrayPattern() method
42 # Get the pattern of array
44 # @return p: the pattern of array
46 def GetArrayPattern():
47 p
= re
.compile(r
'[_\w]*\s*[\[.*\]]+')
50 ## GetTypedefFuncPointerPattern() method
52 # Get the pattern of function pointer
54 # @return p: the pattern of function pointer
56 def GetTypedefFuncPointerPattern():
57 p
= re
.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re
.DOTALL
)
62 # Get global database instance
64 # @return EotGlobalData.gDb: the global database instance
67 return EotGlobalData
.gDb
69 ## PrintErrorMsg() method
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
78 def PrintErrorMsg(ErrorType
, Msg
, TableName
, ItemId
):
79 Msg
= Msg
.replace('\n', '').replace('\r', '')
80 MsgPartList
= Msg
.split()
82 for Part
in MsgPartList
:
85 GetDB().TblReport
.Insert(ErrorType
, OtherMsg
= Msg
, BelongsToTable
= TableName
, BelongsToItem
= ItemId
)
89 # Find type of input string
91 # @param Str: String to be parsed
93 # @return Type: The type of the string
96 Type
= DataClass
.MODEL_UNKNOWN
97 Str
= Str
.replace('#', '# ')
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
112 Type
= DataClass
.MODEL_UNKNOWN
115 ## GetIdentifierList() method
117 # Get id of all files
119 # @return IdList: The list of all id of files
121 def GetIdentifierList():
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])
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])
133 FuncDeclPattern
= GetFuncDeclPattern()
134 ArrayPattern
= GetArrayPattern()
135 for var
in FileProfile
.VariableDeclarationList
:
136 DeclText
= var
.Declarator
.strip()
137 while DeclText
.startswith('*'):
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]
148 while Index
< len(FuncNamePartList
) - 1:
149 var
.Modifier
+= ' ' + FuncNamePartList
[Index
]
150 var
.Declarator
= var
.Declarator
.lstrip().lstrip(FuncNamePartList
[Index
])
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])
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
]
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])
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])
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
)
185 for su
in FileProfile
.StructUnionDefinitionList
:
186 Type
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
188 if su
.Content
.startswith('union'):
189 Type
= DataClass
.MODEL_IDENTIFIER_UNION
191 LBPos
= su
.Content
.find('{')
192 RBPos
= su
.Content
.find('}')
193 if LBPos
== -1 or RBPos
== -1:
194 Name
= su
.Content
[SkipLen
:].strip()
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])
202 TdFuncPointerPattern
= GetTypedefFuncPointerPattern()
203 for td
in FileProfile
.TypedefDefinitionList
:
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('*')
213 Modifier
+= ' ' + TmpStr
[0:StarPos
]
214 while TmpStr
[StarPos
] == '*':
215 Modifier
+= ' ' + '*'
217 TmpStr
= TmpStr
[StarPos
:].strip()
218 RBPos
= TmpStr
.find(')')
219 Name
= TmpStr
[0:RBPos
]
220 Value
= 'FP' + TmpStr
[RBPos
+ 1:]
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])
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])
230 ## GetParamList() method
232 # Get a list of parameters
234 # @param FuncDeclarator: Function declarator
235 # @param FuncNameLine: Line number of function name
236 # @param FuncNameOffset: Offset of function name
238 # @return ParamIdList: A list of parameters
240 def GetParamList(FuncDeclarator
, FuncNameLine
= 0, FuncNameOffset
= 0):
242 DeclSplitList
= FuncDeclarator
.split('(')
243 if len(DeclSplitList
) < 2:
245 FuncName
= DeclSplitList
[0]
246 ParamStr
= DeclSplitList
[1].rstrip(')')
250 while FuncName
.find('\n', Start
) != -1:
253 Start
+= FuncName
.find('\n', Start
)
255 OffsetSkipped
+= len(FuncName
[Start
:])
256 OffsetSkipped
+= 1 #skip '('
257 ParamBeginLine
= FuncNameLine
+ LineSkipped
258 ParamBeginOffset
= OffsetSkipped
259 for p
in ParamStr
.split(','):
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'
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()
283 while p
.find('\n', Start
) != -1:
286 Start
+= p
.find('\n', Start
)
288 OffsetSkipped
+= len(p
[Start
:])
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 ','
301 # Get a list of functions
303 # @return FuncObjList: A list of function objects
305 def GetFunctionList():
307 for FuncDef
in FileProfile
.FunctionDefinitionList
:
309 DeclText
= FuncDef
.Declarator
.strip()
310 while DeclText
.startswith('*'):
311 FuncDef
.Modifier
+= '*'
312 DeclText
= DeclText
.lstrip('*').strip()
314 FuncDef
.Declarator
= FuncDef
.Declarator
.lstrip('*')
315 DeclSplitList
= FuncDef
.Declarator
.split('(')
316 if len(DeclSplitList
) < 2:
319 FuncName
= DeclSplitList
[0]
320 FuncNamePartList
= FuncName
.split()
321 if len(FuncNamePartList
) > 1:
322 FuncName
= FuncNamePartList
[-1]
324 while Index
< len(FuncNamePartList
) - 1:
325 FuncDef
.Modifier
+= ' ' + FuncNamePartList
[Index
]
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
)
333 ## CreateCCodeDB() method
335 # Create database for all c code
337 # @param FileNameList: A list of all c code file names
339 def CreateCCodeDB(FileNameList
):
341 ParseErrorFileList
= []
343 for FullName
in FileNameList
:
344 if os
.path
.splitext(FullName
)[1] in ('.h', '.c'):
345 if FullName
.lower() in ParsedFiles
:
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
)
352 collector
.ParseFile()
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()
363 if len(ParseErrorFileList
) > 0:
364 EdkLogger
.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList
))
366 Db
= EotGlobalData
.gDb
367 for file in FileObjList
:
368 Db
.InsertOneFile(file)
370 Db
.UpdateIdentifierBelongsToFunction()
374 # This acts like the main() function for the script, unless it is 'import'ed into another
377 if __name__
== '__main__':
379 EdkLogger
.Initialize()
380 EdkLogger
.SetLevel(EdkLogger
.QUIET
)
381 CollectSourceCodeDataIntoDB(sys
.argv
[1])