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
19 from __future__
import absolute_import
21 import Common
.LongFilePathOs
as os
23 from . import CodeFragmentCollector
24 from . import FileProfile
25 from CommonDataClass
import DataClass
26 from Common
import EdkLogger
27 from .EotToolError
import *
28 from . import EotGlobalData
31 IncludeFileListDict
= {}
32 IncludePathListDict
= {}
36 ## GetFuncDeclPattern() method
38 # Get the pattern of function declaration
40 # @return p: the pattern of function declaration
42 def GetFuncDeclPattern():
43 p
= re
.compile(r
'(EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\).*', re
.DOTALL
)
46 ## GetArrayPattern() method
48 # Get the pattern of array
50 # @return p: the pattern of array
52 def GetArrayPattern():
53 p
= re
.compile(r
'[_\w]*\s*[\[.*\]]+')
56 ## GetTypedefFuncPointerPattern() method
58 # Get the pattern of function pointer
60 # @return p: the pattern of function pointer
62 def GetTypedefFuncPointerPattern():
63 p
= re
.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re
.DOTALL
)
68 # Get global database instance
70 # @return EotGlobalData.gDb: the global database instance
73 return EotGlobalData
.gDb
75 ## PrintErrorMsg() method
79 # @param ErrorType: Type of error
80 # @param Msg: Error message
81 # @param TableName: table name of error found
82 # @param ItemId: id of item
84 def PrintErrorMsg(ErrorType
, Msg
, TableName
, ItemId
):
85 Msg
= Msg
.replace('\n', '').replace('\r', '')
86 MsgPartList
= Msg
.split()
88 for Part
in MsgPartList
:
91 GetDB().TblReport
.Insert(ErrorType
, OtherMsg
= Msg
, BelongsToTable
= TableName
, BelongsToItem
= ItemId
)
95 # Find type of input string
97 # @param Str: String to be parsed
99 # @return Type: The type of the string
102 Type
= DataClass
.MODEL_UNKNOWN
103 Str
= Str
.replace('#', '# ')
105 if List
[1] == 'include':
106 Type
= DataClass
.MODEL_IDENTIFIER_INCLUDE
107 elif List
[1] == 'define':
108 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_DEFINE
109 elif List
[1] == 'ifdef':
110 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_IFDEF
111 elif List
[1] == 'ifndef':
112 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_IFNDEF
113 elif List
[1] == 'endif':
114 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_ENDIF
115 elif List
[1] == 'pragma':
116 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_PROGMA
118 Type
= DataClass
.MODEL_UNKNOWN
121 ## GetIdentifierList() method
123 # Get id of all files
125 # @return IdList: The list of all id of files
127 def GetIdentifierList():
130 for pp
in FileProfile
.PPDirectiveList
:
131 Type
= GetIdType(pp
.Content
)
132 IdPP
= DataClass
.IdentifierClass(-1, '', '', '', pp
.Content
, Type
, -1, -1, pp
.StartPos
[0], pp
.StartPos
[1], pp
.EndPos
[0], pp
.EndPos
[1])
135 for ae
in FileProfile
.AssignmentExpressionList
:
136 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])
139 FuncDeclPattern
= GetFuncDeclPattern()
140 ArrayPattern
= GetArrayPattern()
141 for var
in FileProfile
.VariableDeclarationList
:
142 DeclText
= var
.Declarator
.strip()
143 while DeclText
.startswith('*'):
145 DeclText
= DeclText
.lstrip('*').strip()
146 var
.Declarator
= DeclText
147 if FuncDeclPattern
.match(var
.Declarator
):
148 DeclSplitList
= var
.Declarator
.split('(')
149 FuncName
= DeclSplitList
[0]
150 FuncNamePartList
= FuncName
.split()
151 if len(FuncNamePartList
) > 1:
152 FuncName
= FuncNamePartList
[-1]
154 while Index
< len(FuncNamePartList
) - 1:
155 var
.Modifier
+= ' ' + FuncNamePartList
[Index
]
156 var
.Declarator
= var
.Declarator
.lstrip().lstrip(FuncNamePartList
[Index
])
158 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])
162 if var
.Declarator
.find('{') == -1:
163 for decl
in var
.Declarator
.split(','):
164 DeclList
= decl
.split('=')
165 Name
= DeclList
[0].strip()
166 if ArrayPattern
.match(Name
):
167 LSBPos
= var
.Declarator
.find('[')
168 var
.Modifier
+= ' ' + Name
[LSBPos
:]
169 Name
= Name
[0:LSBPos
]
171 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])
174 DeclList
= var
.Declarator
.split('=')
175 Name
= DeclList
[0].strip()
176 if ArrayPattern
.match(Name
):
177 LSBPos
= var
.Declarator
.find('[')
178 var
.Modifier
+= ' ' + Name
[LSBPos
:]
179 Name
= Name
[0:LSBPos
]
180 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])
183 for enum
in FileProfile
.EnumerationDefinitionList
:
184 LBPos
= enum
.Content
.find('{')
185 RBPos
= enum
.Content
.find('}')
186 Name
= enum
.Content
[4:LBPos
].strip()
187 Value
= enum
.Content
[LBPos
+1:RBPos
]
188 IdEnum
= DataClass
.IdentifierClass(-1, '', '', Name
, Value
, DataClass
.MODEL_IDENTIFIER_ENUMERATE
, -1, -1, enum
.StartPos
[0], enum
.StartPos
[1], enum
.EndPos
[0], enum
.EndPos
[1])
189 IdList
.append(IdEnum
)
191 for su
in FileProfile
.StructUnionDefinitionList
:
192 Type
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
194 if su
.Content
.startswith('union'):
195 Type
= DataClass
.MODEL_IDENTIFIER_UNION
197 LBPos
= su
.Content
.find('{')
198 RBPos
= su
.Content
.find('}')
199 if LBPos
== -1 or RBPos
== -1:
200 Name
= su
.Content
[SkipLen
:].strip()
203 Name
= su
.Content
[SkipLen
:LBPos
].strip()
204 Value
= su
.Content
[LBPos
+1:RBPos
]
205 IdPE
= DataClass
.IdentifierClass(-1, '', '', Name
, Value
, Type
, -1, -1, su
.StartPos
[0], su
.StartPos
[1], su
.EndPos
[0], su
.EndPos
[1])
208 TdFuncPointerPattern
= GetTypedefFuncPointerPattern()
209 for td
in FileProfile
.TypedefDefinitionList
:
213 if TdFuncPointerPattern
.match(td
.ToType
):
214 Modifier
= td
.FromType
215 LBPos
= td
.ToType
.find('(')
216 TmpStr
= td
.ToType
[LBPos
+1:].strip()
217 StarPos
= TmpStr
.find('*')
219 Modifier
+= ' ' + TmpStr
[0:StarPos
]
220 while TmpStr
[StarPos
] == '*':
221 Modifier
+= ' ' + '*'
223 TmpStr
= TmpStr
[StarPos
:].strip()
224 RBPos
= TmpStr
.find(')')
225 Name
= TmpStr
[0:RBPos
]
226 Value
= 'FP' + TmpStr
[RBPos
+ 1:]
228 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])
231 for funcCall
in FileProfile
.FunctionCallingList
:
232 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])
236 ## GetParamList() method
238 # Get a list of parameters
240 # @param FuncDeclarator: Function declarator
241 # @param FuncNameLine: Line number of function name
242 # @param FuncNameOffset: Offset of function name
244 # @return ParamIdList: A list of parameters
246 def GetParamList(FuncDeclarator
, FuncNameLine
= 0, FuncNameOffset
= 0):
248 DeclSplitList
= FuncDeclarator
.split('(')
249 if len(DeclSplitList
) < 2:
251 FuncName
= DeclSplitList
[0]
252 ParamStr
= DeclSplitList
[1].rstrip(')')
256 while FuncName
.find('\n', Start
) != -1:
259 Start
+= FuncName
.find('\n', Start
)
261 OffsetSkipped
+= len(FuncName
[Start
:])
262 OffsetSkipped
+= 1 #skip '('
263 ParamBeginLine
= FuncNameLine
+ LineSkipped
264 ParamBeginOffset
= OffsetSkipped
265 for p
in ParamStr
.split(','):
269 ParamName
= ListP
[-1]
270 DeclText
= ParamName
.strip()
271 RightSpacePos
= p
.rfind(ParamName
)
272 ParamModifier
= p
[0:RightSpacePos
]
273 if ParamName
== 'OPTIONAL':
274 if ParamModifier
== '':
275 ParamModifier
+= ' ' + 'OPTIONAL'
278 ParamName
= ListP
[-2]
279 DeclText
= ParamName
.strip()
280 RightSpacePos
= p
.rfind(ParamName
)
281 ParamModifier
= p
[0:RightSpacePos
]
282 ParamModifier
+= 'OPTIONAL'
283 while DeclText
.startswith('*'):
284 ParamModifier
+= ' ' + '*'
285 DeclText
= DeclText
.lstrip('*').strip()
289 while p
.find('\n', Start
) != -1:
292 Start
+= p
.find('\n', Start
)
294 OffsetSkipped
+= len(p
[Start
:])
296 ParamEndLine
= ParamBeginLine
+ LineSkipped
297 ParamEndOffset
= OffsetSkipped
298 IdParam
= DataClass
.IdentifierClass(-1, ParamModifier
, '', ParamName
, '', DataClass
.MODEL_IDENTIFIER_PARAMETER
, -1, -1, ParamBeginLine
, ParamBeginOffset
, ParamEndLine
, ParamEndOffset
)
299 ParamIdList
.append(IdParam
)
300 ParamBeginLine
= ParamEndLine
301 ParamBeginOffset
= OffsetSkipped
+ 1 #skip ','
307 # Get a list of functions
309 # @return FuncObjList: A list of function objects
311 def GetFunctionList():
313 for FuncDef
in FileProfile
.FunctionDefinitionList
:
315 DeclText
= FuncDef
.Declarator
.strip()
316 while DeclText
.startswith('*'):
317 FuncDef
.Modifier
+= '*'
318 DeclText
= DeclText
.lstrip('*').strip()
320 FuncDef
.Declarator
= FuncDef
.Declarator
.lstrip('*')
321 DeclSplitList
= FuncDef
.Declarator
.split('(')
322 if len(DeclSplitList
) < 2:
325 FuncName
= DeclSplitList
[0]
326 FuncNamePartList
= FuncName
.split()
327 if len(FuncNamePartList
) > 1:
328 FuncName
= FuncNamePartList
[-1]
330 while Index
< len(FuncNamePartList
) - 1:
331 FuncDef
.Modifier
+= ' ' + FuncNamePartList
[Index
]
334 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
, [])
335 FuncObjList
.append(FuncObj
)
339 ## CreateCCodeDB() method
341 # Create database for all c code
343 # @param FileNameList: A list of all c code file names
345 def CreateCCodeDB(FileNameList
):
347 ParseErrorFileList
= []
349 for FullName
in FileNameList
:
350 if os
.path
.splitext(FullName
)[1] in ('.h', '.c'):
351 if FullName
.lower() in ParsedFiles
:
353 ParsedFiles
[FullName
.lower()] = 1
354 EdkLogger
.info("Parsing " + FullName
)
355 model
= FullName
.endswith('c') and DataClass
.MODEL_FILE_C
or DataClass
.MODEL_FILE_H
356 collector
= CodeFragmentCollector
.CodeFragmentCollector(FullName
)
358 collector
.ParseFile()
360 ParseErrorFileList
.append(FullName
)
361 BaseName
= os
.path
.basename(FullName
)
362 DirName
= os
.path
.dirname(FullName
)
363 Ext
= os
.path
.splitext(BaseName
)[1].lstrip('.')
364 ModifiedTime
= os
.path
.getmtime(FullName
)
365 FileObj
= DataClass
.FileClass(-1, BaseName
, Ext
, DirName
, FullName
, model
, ModifiedTime
, GetFunctionList(), GetIdentifierList(), [])
366 FileObjList
.append(FileObj
)
367 collector
.CleanFileProfileBuffer()
369 if len(ParseErrorFileList
) > 0:
370 EdkLogger
.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList
))
372 Db
= EotGlobalData
.gDb
373 for file in FileObjList
:
374 Db
.InsertOneFile(file)
376 Db
.UpdateIdentifierBelongsToFunction()
380 # This acts like the main() function for the script, unless it is 'import'ed into another
383 if __name__
== '__main__':
385 EdkLogger
.Initialize()
386 EdkLogger
.SetLevel(EdkLogger
.QUIET
)
387 CollectSourceCodeDataIntoDB(sys
.argv
[1])