BaseTools: use built in OrderedDict instead of custom version.
[mirror_edk2.git] / BaseTools / Source / Python / Eot / Parser.py
1 ## @file
2 # This file is used to define common parsing related functions used in parsing
3 # Inf/Dsc/Makefile process
4 #
5 # Copyright (c) 2008 - 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
10 #
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.
13 #
14
15 ##
16 # Import Modules
17 #
18 import Common.LongFilePathOs as os, re
19 import Common.EdkLogger as EdkLogger
20 from Common.DataType import *
21 from CommonDataClass.DataClass import *
22 from Common.String import CleanString, GetSplitValueList, ReplaceMacro
23 import EotGlobalData
24 from Common.String import GetSplitList
25 from Common.LongFilePathSupport import OpenLongFilePath as open
26
27 ## PreProcess() method
28 #
29 # Pre process a file
30 #
31 # 1. Remove all comments
32 # 2. Merge multiple lines code to one line
33 #
34 # @param Filename: Name of the file to be parsed
35 # @param MergeMultipleLines: Switch for if merge multiple lines
36 # @param LineNo: Default line no
37 #
38 # @return Lines: The file contents after remvoing comments
39 #
40 def PreProcess(Filename, MergeMultipleLines = True, LineNo = -1):
41 Lines = []
42 Filename = os.path.normpath(Filename)
43 if not os.path.isfile(Filename):
44 EdkLogger.error("Eot", EdkLogger.FILE_NOT_FOUND, ExtraData=Filename)
45
46 IsFindBlockComment = False
47 IsFindBlockCode = False
48 ReservedLine = ''
49 ReservedLineLength = 0
50 for Line in open(Filename, 'r'):
51 Line = Line.strip()
52 # Remove comment block
53 if Line.find(TAB_COMMENT_EDK_START) > -1:
54 ReservedLine = GetSplitList(Line, TAB_COMMENT_EDK_START, 1)[0]
55 IsFindBlockComment = True
56 if Line.find(TAB_COMMENT_EDK_END) > -1:
57 Line = ReservedLine + GetSplitList(Line, TAB_COMMENT_EDK_END, 1)[1]
58 ReservedLine = ''
59 IsFindBlockComment = False
60 if IsFindBlockComment:
61 Lines.append('')
62 continue
63
64 # Remove comments at tail and remove spaces again
65 Line = CleanString(Line)
66 if Line == '':
67 Lines.append('')
68 continue
69
70 if MergeMultipleLines:
71 # Add multiple lines to one line
72 if IsFindBlockCode and Line[-1] != TAB_SLASH:
73 ReservedLine = (ReservedLine + TAB_SPACE_SPLIT + Line).strip()
74 Lines.append(ReservedLine)
75 for Index in (0, ReservedLineLength):
76 Lines.append('')
77 ReservedLine = ''
78 ReservedLineLength = 0
79 IsFindBlockCode = False
80 continue
81 if Line[-1] == TAB_SLASH:
82 ReservedLine = ReservedLine + TAB_SPACE_SPLIT + Line[0:-1].strip()
83 ReservedLineLength = ReservedLineLength + 1
84 IsFindBlockCode = True
85 continue
86
87 Lines.append(Line)
88
89 return Lines
90
91 ## AddToGlobalMacro() method
92 #
93 # Add a macro to EotGlobalData.gMACRO
94 #
95 # @param Name: Name of the macro
96 # @param Value: Value of the macro
97 #
98 def AddToGlobalMacro(Name, Value):
99 Value = ReplaceMacro(Value, EotGlobalData.gMACRO, True)
100 EotGlobalData.gMACRO[Name] = Value
101
102 ## AddToSelfMacro() method
103 #
104 # Parse a line of macro definition and add it to a macro set
105 #
106 # @param SelfMacro: The self macro set
107 # @param Line: The line of a macro definition
108 #
109 # @return Name: Name of macro
110 # @return Value: Value of macro
111 #
112 def AddToSelfMacro(SelfMacro, Line):
113 Name, Value = '', ''
114 List = GetSplitValueList(Line, TAB_EQUAL_SPLIT, 1)
115 if len(List) == 2:
116 Name = List[0]
117 Value = List[1]
118 Value = ReplaceMacro(Value, EotGlobalData.gMACRO, True)
119 Value = ReplaceMacro(Value, SelfMacro, True)
120 SelfMacro[Name] = Value
121
122 return (Name, Value)
123
124 ## GetIncludeListOfFile() method
125 #
126 # Get the include path list for a source file
127 #
128 # 1. Find the source file belongs to which INF file
129 # 2. Find the inf's package
130 # 3. Return the include path list of the package
131 #
132 # @param WorkSpace: WORKSPACE path
133 # @param Filepath: File path
134 # @param Db: Eot database
135 #
136 # @return IncludeList: A list of include directories
137 #
138 def GetIncludeListOfFile(WorkSpace, Filepath, Db):
139 IncludeList = []
140 Filepath = os.path.normpath(Filepath)
141 SqlCommand = """
142 select Value1 from Inf where Model = %s and BelongsToFile in(
143 select distinct B.BelongsToFile from File as A left join Inf as B
144 where A.ID = B.BelongsToFile and B.Model = %s and (A.Path || '%s' || B.Value1) = '%s')""" \
145 % (MODEL_META_DATA_PACKAGE, MODEL_EFI_SOURCE_FILE, '\\', Filepath)
146 RecordSet = Db.TblFile.Exec(SqlCommand)
147 for Record in RecordSet:
148 DecFullPath = os.path.normpath(os.path.join(WorkSpace, Record[0]))
149 (DecPath, DecName) = os.path.split(DecFullPath)
150 SqlCommand = """select Value1 from Dec where BelongsToFile =
151 (select ID from File where FullPath = '%s') and Model = %s""" \
152 % (DecFullPath, MODEL_EFI_INCLUDE)
153 NewRecordSet = Db.TblDec.Exec(SqlCommand)
154 for NewRecord in NewRecordSet:
155 IncludePath = os.path.normpath(os.path.join(DecPath, NewRecord[0]))
156 if IncludePath not in IncludeList:
157 IncludeList.append(IncludePath)
158
159 return IncludeList
160
161 ## GetTableList() method
162 #
163 # Search table file and find all small tables
164 #
165 # @param FileModelList: Model code for the file list
166 # @param Table: Table to insert records
167 # @param Db: Eot database
168 #
169 # @return TableList: A list of tables
170 #
171 def GetTableList(FileModelList, Table, Db):
172 TableList = []
173 SqlCommand = """select ID, FullPath from File where Model in %s""" % str(FileModelList)
174 RecordSet = Db.TblFile.Exec(SqlCommand)
175 for Record in RecordSet:
176 TableName = Table + str(Record[0])
177 TableList.append([TableName, Record[1]])
178
179 return TableList
180
181 ## GetAllIncludeDir() method
182 #
183 # Find all Include directories
184 #
185 # @param Db: Eot database
186 #
187 # @return IncludeList: A list of include directories
188 #
189 def GetAllIncludeDirs(Db):
190 IncludeList = []
191 SqlCommand = """select distinct Value1 from Inf where Model = %s order by Value1""" % MODEL_EFI_INCLUDE
192 RecordSet = Db.TblInf.Exec(SqlCommand)
193
194 for Record in RecordSet:
195 IncludeList.append(Record[0])
196
197 return IncludeList
198
199 ## GetAllIncludeFiles() method
200 #
201 # Find all Include files
202 #
203 # @param Db: Eot database
204 #
205 # @return IncludeFileList: A list of include files
206 #
207 def GetAllIncludeFiles(Db):
208 IncludeList = GetAllIncludeDirs(Db)
209 IncludeFileList = []
210
211 for Dir in IncludeList:
212 if os.path.isdir(Dir):
213 SubDir = os.listdir(Dir)
214 for Item in SubDir:
215 if os.path.isfile(Item):
216 IncludeFileList.append(Item)
217
218 return IncludeFileList
219
220 ## GetAllSourceFiles() method
221 #
222 # Find all source files
223 #
224 # @param Db: Eot database
225 #
226 # @return SourceFileList: A list of source files
227 #
228 def GetAllSourceFiles(Db):
229 SourceFileList = []
230 SqlCommand = """select distinct Value1 from Inf where Model = %s order by Value1""" % MODEL_EFI_SOURCE_FILE
231 RecordSet = Db.TblInf.Exec(SqlCommand)
232
233 for Record in RecordSet:
234 SourceFileList.append(Record[0])
235
236 return SourceFileList
237
238 ## GetAllFiles() method
239 #
240 # Find all files, both source files and include files
241 #
242 # @param Db: Eot database
243 #
244 # @return FileList: A list of files
245 #
246 def GetAllFiles(Db):
247 FileList = []
248 IncludeFileList = GetAllIncludeFiles(Db)
249 SourceFileList = GetAllSourceFiles(Db)
250 for Item in IncludeFileList:
251 if os.path.isfile(Item) and Item not in FileList:
252 FileList.append(Item)
253 for Item in SourceFileList:
254 if os.path.isfile(Item) and Item not in FileList:
255 FileList.append(Item)
256
257 return FileList
258
259 ## ParseConditionalStatement() method
260 #
261 # Parse conditional statement
262 #
263 # @param Line: One line to be parsed
264 # @param Macros: A set of all macro
265 # @param StatusSet: A set of all status
266 #
267 # @retval True: Find keyword of conditional statement
268 # @retval False: Not find keyword of conditional statement
269 #
270 def ParseConditionalStatement(Line, Macros, StatusSet):
271 NewLine = Line.upper()
272 if NewLine.find(TAB_IF_EXIST.upper()) > -1:
273 IfLine = Line[NewLine.find(TAB_IF_EXIST) + len(TAB_IF_EXIST) + 1:].strip()
274 IfLine = ReplaceMacro(IfLine, EotGlobalData.gMACRO, True)
275 IfLine = ReplaceMacro(IfLine, Macros, True)
276 IfLine = IfLine.replace("\"", '')
277 IfLine = IfLine.replace("(", '')
278 IfLine = IfLine.replace(")", '')
279 Status = os.path.exists(os.path.normpath(IfLine))
280 StatusSet.append([Status])
281 return True
282 if NewLine.find(TAB_IF_DEF.upper()) > -1:
283 IfLine = Line[NewLine.find(TAB_IF_DEF) + len(TAB_IF_DEF) + 1:].strip()
284 Status = False
285 if IfLine in Macros or IfLine in EotGlobalData.gMACRO:
286 Status = True
287 StatusSet.append([Status])
288 return True
289 if NewLine.find(TAB_IF_N_DEF.upper()) > -1:
290 IfLine = Line[NewLine.find(TAB_IF_N_DEF) + len(TAB_IF_N_DEF) + 1:].strip()
291 Status = False
292 if IfLine not in Macros and IfLine not in EotGlobalData.gMACRO:
293 Status = True
294 StatusSet.append([Status])
295 return True
296 if NewLine.find(TAB_IF.upper()) > -1:
297 IfLine = Line[NewLine.find(TAB_IF) + len(TAB_IF) + 1:].strip()
298 Status = ParseConditionalStatementMacros(IfLine, Macros)
299 StatusSet.append([Status])
300 return True
301 if NewLine.find(TAB_ELSE_IF.upper()) > -1:
302 IfLine = Line[NewLine.find(TAB_ELSE_IF) + len(TAB_ELSE_IF) + 1:].strip()
303 Status = ParseConditionalStatementMacros(IfLine, Macros)
304 StatusSet[-1].append(Status)
305 return True
306 if NewLine.find(TAB_ELSE.upper()) > -1:
307 Status = False
308 for Item in StatusSet[-1]:
309 Status = Status or Item
310 StatusSet[-1].append(not Status)
311 return True
312 if NewLine.find(TAB_END_IF.upper()) > -1:
313 StatusSet.pop()
314 return True
315
316 return False
317
318 ## ParseConditionalStatement() method
319 #
320 # Parse conditional statement with Macros
321 #
322 # @param Line: One line to be parsed
323 # @param Macros: A set of macros
324 #
325 # @return Line: New line after replacing macros
326 #
327 def ParseConditionalStatementMacros(Line, Macros):
328 if Line.upper().find('DEFINED(') > -1 or Line.upper().find('EXIST') > -1:
329 return False
330 Line = ReplaceMacro(Line, EotGlobalData.gMACRO, True)
331 Line = ReplaceMacro(Line, Macros, True)
332 Line = Line.replace("&&", "and")
333 Line = Line.replace("||", "or")
334 return eval(Line)
335
336 ## GetConditionalStatementStatus() method
337 #
338 # 1. Assume the latest status as True
339 # 2. Pop the top status of status set, previous status
340 # 3. Compare the latest one and the previous one and get new status
341 #
342 # @param StatusSet: A set of all status
343 #
344 # @return Status: The final status
345 #
346 def GetConditionalStatementStatus(StatusSet):
347 Status = True
348 for Item in StatusSet:
349 Status = Status and Item[-1]
350
351 return Status
352
353 ## SearchBelongsToFunction() method
354 #
355 # Search all functions belong to the file
356 #
357 # @param BelongsToFile: File id
358 # @param StartLine: Start line of search scope
359 # @param EndLine: End line of search scope
360 #
361 # @return: The found function
362 #
363 def SearchBelongsToFunction(BelongsToFile, StartLine, EndLine):
364 SqlCommand = """select ID, Name from Function where BelongsToFile = %s and StartLine <= %s and EndLine >= %s""" %(BelongsToFile, StartLine, EndLine)
365 RecordSet = EotGlobalData.gDb.TblFunction.Exec(SqlCommand)
366 if RecordSet != []:
367 return RecordSet[0][0], RecordSet[0][1]
368 else:
369 return -1, ''
370
371 ## SearchPpiCallFunction() method
372 #
373 # Search all used PPI calling function 'PeiServicesReInstallPpi' and 'PeiServicesInstallPpi'
374 # Store the result to database
375 #
376 # @param Identifier: Table id
377 # @param SourceFileID: Source file id
378 # @param SourceFileFullPath: Source file full path
379 # @param ItemMode: Mode of the item
380 #
381 def SearchPpiCallFunction(Identifier, SourceFileID, SourceFileFullPath, ItemMode):
382 ItemName, ItemType, GuidName, GuidMacro, GuidValue = '', 'Ppi', '', '', ''
383 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
384 where (Name like '%%%s%%' and Model = %s)""" \
385 % (Identifier, 'PeiServicesReInstallPpi', MODEL_IDENTIFIER_FUNCTION_CALLING)
386 BelongsToFunctionID, BelongsToFunction = -1, ''
387 Db = EotGlobalData.gDb.TblReport
388 RecordSet = Db.Exec(SqlCommand)
389 for Record in RecordSet:
390 Index = 0
391 BelongsToFile, StartLine, EndLine = Record[2], Record[3], Record[4]
392 BelongsToFunctionID, BelongsToFunction = SearchBelongsToFunction(BelongsToFile, StartLine, EndLine)
393 VariableList = Record[0].split(',')
394 for Variable in VariableList:
395 Variable = Variable.strip()
396 # Get index of the variable
397 if Variable.find('[') > -1:
398 Index = int(Variable[Variable.find('[') + 1 : Variable.find(']')])
399 Variable = Variable[:Variable.find('[')]
400 # Get variable name
401 if Variable.startswith('&'):
402 Variable = Variable[1:]
403 # Get variable value
404 SqlCommand = """select Value from %s where (Name like '%%%s%%') and Model = %s""" \
405 % (Identifier, Variable, MODEL_IDENTIFIER_VARIABLE)
406 NewRecordSet = Db.Exec(SqlCommand)
407 if NewRecordSet:
408 NewRecord = NewRecordSet[0][0]
409 VariableValueList = NewRecord.split('},')
410 if len(VariableValueList) > Index:
411 VariableValue = VariableValueList[Index]
412 NewVariableValueList = VariableValue.split(',')
413 if len(NewVariableValueList) > 1:
414 NewVariableValue = NewVariableValueList[1].strip()
415 if NewVariableValue.startswith('&'):
416 Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, NewVariableValue[1:], GuidMacro, GuidValue, BelongsToFunction, 0)
417 continue
418 else:
419 EotGlobalData.gOP_UN_MATCHED.write('%s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, NewParameter))
420
421 ItemName, ItemType, GuidName, GuidMacro, GuidValue = '', 'Ppi', '', '', ''
422 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
423 where (Value like '%%%s%%' and Model = %s)""" \
424 % (Identifier, 'PeiServicesInstallPpi', MODEL_IDENTIFIER_ASSIGNMENT_EXPRESSION)
425 BelongsToFunctionID, BelongsToFunction = -1, ''
426 Db = EotGlobalData.gDb.TblReport
427 RecordSet = Db.Exec(SqlCommand)
428
429 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
430 where (Name like '%%%s%%' and Model = %s)""" \
431 % (Identifier, 'PeiServicesInstallPpi', MODEL_IDENTIFIER_FUNCTION_CALLING)
432 Db = EotGlobalData.gDb.TblReport
433 RecordSet2 = Db.Exec(SqlCommand)
434
435 for Record in RecordSet + RecordSet2:
436 if Record == []:
437 continue
438 Index = 0
439 BelongsToFile, StartLine, EndLine = Record[2], Record[3], Record[4]
440 BelongsToFunctionID, BelongsToFunction = SearchBelongsToFunction(BelongsToFile, StartLine, EndLine)
441 Variable = Record[0].replace('PeiServicesInstallPpi', '').replace('(', '').replace(')', '').replace('&', '').strip()
442 Variable = Variable[Variable.find(',') + 1:].strip()
443 # Get index of the variable
444 if Variable.find('[') > -1:
445 Index = int(Variable[Variable.find('[') + 1 : Variable.find(']')])
446 Variable = Variable[:Variable.find('[')]
447 # Get variable name
448 if Variable.startswith('&'):
449 Variable = Variable[1:]
450 # Get variable value
451 SqlCommand = """select Value from %s where (Name like '%%%s%%') and Model = %s""" \
452 % (Identifier, Variable, MODEL_IDENTIFIER_VARIABLE)
453 NewRecordSet = Db.Exec(SqlCommand)
454 if NewRecordSet:
455 NewRecord = NewRecordSet[0][0]
456 VariableValueList = NewRecord.split('},')
457 for VariableValue in VariableValueList[Index:]:
458 NewVariableValueList = VariableValue.split(',')
459 if len(NewVariableValueList) > 1:
460 NewVariableValue = NewVariableValueList[1].strip()
461 if NewVariableValue.startswith('&'):
462 Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, NewVariableValue[1:], GuidMacro, GuidValue, BelongsToFunction, 0)
463 continue
464 else:
465 EotGlobalData.gOP_UN_MATCHED.write('%s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, NewParameter))
466
467 ## SearchPpis() method
468 #
469 # Search all used PPI calling function
470 # Store the result to database
471 #
472 # @param SqlCommand: SQL command statement
473 # @param Table: Table id
474 # @param SourceFileID: Source file id
475 # @param SourceFileFullPath: Source file full path
476 # @param ItemMode: Mode of the item
477 # @param PpiMode: Mode of PPI
478 #
479 def SearchPpi(SqlCommand, Table, SourceFileID, SourceFileFullPath, ItemMode, PpiMode = 1):
480 ItemName, ItemType, GuidName, GuidMacro, GuidValue = '', 'Ppi', '', '', ''
481 BelongsToFunctionID, BelongsToFunction = -1, ''
482 Db = EotGlobalData.gDb.TblReport
483 RecordSet = Db.Exec(SqlCommand)
484 for Record in RecordSet:
485 Parameter = GetPpiParameter(Record[0], PpiMode)
486 BelongsToFile, StartLine, EndLine = Record[2], Record[3], Record[4]
487 # Get BelongsToFunction
488 BelongsToFunctionID, BelongsToFunction = SearchBelongsToFunction(BelongsToFile, StartLine, EndLine)
489
490 # Default is Not Found
491 IsFound = False
492
493 # For Consumed Ppi
494 if ItemMode == 'Consumed':
495 if Parameter.startswith('g'):
496 Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, Parameter, GuidMacro, GuidValue, BelongsToFunction, 0)
497 else:
498 EotGlobalData.gOP_UN_MATCHED.write('%s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, Parameter))
499 continue
500
501 # Direct Parameter.Guid
502 SqlCommand = """select Value from %s where (Name like '%%%s.Guid%%' or Name like '%%%s->Guid%%') and Model = %s""" % (Table, Parameter, Parameter, MODEL_IDENTIFIER_ASSIGNMENT_EXPRESSION)
503 NewRecordSet = Db.Exec(SqlCommand)
504 for NewRecord in NewRecordSet:
505 GuidName = GetParameterName(NewRecord[0])
506 Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)
507 IsFound = True
508
509 # Defined Parameter
510 if not IsFound:
511 Key = Parameter
512 if Key.rfind(' ') > -1:
513 Key = Key[Key.rfind(' ') : ].strip().replace('&', '')
514 Value = FindKeyValue(EotGlobalData.gDb.TblFile, Table, Key)
515 List = GetSplitValueList(Value.replace('\n', ''), TAB_COMMA_SPLIT)
516 if len(List) > 1:
517 GuidName = GetParameterName(List[1])
518 Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)
519 IsFound = True
520
521 # A list Parameter
522 if not IsFound:
523 Start = Parameter.find('[')
524 End = Parameter.find(']')
525 if Start > -1 and End > -1 and Start < End:
526 try:
527 Index = int(Parameter[Start + 1 : End])
528 Parameter = Parameter[0 : Start]
529 SqlCommand = """select Value from %s where Name = '%s' and Model = %s""" % (Table, Parameter, MODEL_IDENTIFIER_VARIABLE)
530 NewRecordSet = Db.Exec(SqlCommand)
531 for NewRecord in NewRecordSet:
532 NewParameter = GetSplitValueList(NewRecord[0], '}')[Index]
533 GuidName = GetPpiParameter(NewParameter[NewParameter.find('{') : ])
534 Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)
535 IsFound = True
536 except Exception:
537 pass
538
539 # A External Parameter
540 if not IsFound:
541 SqlCommand = """select File.ID from Inf, File
542 where BelongsToFile = (select BelongsToFile from Inf where Value1 = '%s')
543 and Inf.Model = %s and Inf.Value1 = File.FullPath and File.Model = %s""" % (SourceFileFullPath, MODEL_EFI_SOURCE_FILE, MODEL_FILE_C)
544 NewRecordSet = Db.Exec(SqlCommand)
545 for NewRecord in NewRecordSet:
546 Table = 'Identifier' + str(NewRecord[0])
547 SqlCommand = """select Value from %s where Name = '%s' and Modifier = 'EFI_PEI_PPI_DESCRIPTOR' and Model = %s""" % (Table, Parameter, MODEL_IDENTIFIER_VARIABLE)
548 PpiSet = Db.Exec(SqlCommand)
549 if PpiSet != []:
550 GuidName = GetPpiParameter(PpiSet[0][0])
551 if GuidName != '':
552 Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)
553 IsFound = True
554 break
555
556 if not IsFound:
557 EotGlobalData.gOP_UN_MATCHED.write('%s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, Parameter))
558
559 ## SearchProtocols() method
560 #
561 # Search all used PROTOCOL calling function
562 # Store the result to database
563 #
564 # @param SqlCommand: SQL command statement
565 # @param Table: Table id
566 # @param SourceFileID: Source file id
567 # @param SourceFileFullPath: Source file full path
568 # @param ItemMode: Mode of the item
569 # @param ProtocolMode: Mode of PROTOCOL
570 #
571 def SearchProtocols(SqlCommand, Table, SourceFileID, SourceFileFullPath, ItemMode, ProtocolMode):
572 ItemName, ItemType, GuidName, GuidMacro, GuidValue = '', 'Protocol', '', '', ''
573 BelongsToFunctionID, BelongsToFunction = -1, ''
574 Db = EotGlobalData.gDb.TblReport
575 RecordSet = Db.Exec(SqlCommand)
576 for Record in RecordSet:
577 Parameter = ''
578 BelongsToFile, StartLine, EndLine = Record[2], Record[3], Record[4]
579 # Get BelongsToFunction
580 BelongsToFunctionID, BelongsToFunction = SearchBelongsToFunction(BelongsToFile, StartLine, EndLine)
581
582 # Default is Not Found
583 IsFound = False
584
585 if ProtocolMode == 0 or ProtocolMode == 1:
586 Parameter = GetProtocolParameter(Record[0], ProtocolMode)
587 if Parameter.startswith('g') or Parameter.endswith('Guid') or Parameter == 'ShellEnvProtocol' or Parameter == 'ShellInterfaceProtocol':
588 GuidName = GetParameterName(Parameter)
589 Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)
590 IsFound = True
591
592 if ProtocolMode == 2:
593 Protocols = GetSplitValueList(Record[0], TAB_COMMA_SPLIT)
594 for Protocol in Protocols:
595 if Protocol.startswith('&') and Protocol.endswith('Guid'):
596 GuidName = GetParameterName(Protocol)
597 Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)
598 IsFound = True
599 else:
600 NewValue = FindKeyValue(EotGlobalData.gDb.TblFile, Table, Protocol)
601 if Protocol != NewValue and NewValue.endswith('Guid'):
602 GuidName = GetParameterName(NewValue)
603 Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)
604 IsFound = True
605
606 if not IsFound:
607 if BelongsToFunction in EotGlobalData.gProducedProtocolLibrary or BelongsToFunction in EotGlobalData.gConsumedProtocolLibrary:
608 EotGlobalData.gOP_UN_MATCHED_IN_LIBRARY_CALLING.write('%s, %s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, Parameter, BelongsToFunction))
609 else:
610 EotGlobalData.gOP_UN_MATCHED.write('%s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, Parameter))
611
612 ## SearchFunctionCalling() method
613 #
614 # Search all used PPI/PROTOCOL calling function by library
615 # Store the result to database
616 #
617 # @param SqlCommand: SQL command statement
618 # @param Table: Table id
619 # @param SourceFileID: Source file id
620 # @param SourceFileFullPath: Source file full path
621 # @param ItemType: Type of the item, PPI or PROTOCOL
622 # @param ItemMode: Mode of item
623 #
624 def SearchFunctionCalling(Table, SourceFileID, SourceFileFullPath, ItemType, ItemMode):
625 LibraryList = {}
626 Db = EotGlobalData.gDb.TblReport
627 Parameters, ItemName, GuidName, GuidMacro, GuidValue, BelongsToFunction = [], '', '', '', '', ''
628 if ItemType == 'Protocol' and ItemMode == 'Produced':
629 LibraryList = EotGlobalData.gProducedProtocolLibrary
630 elif ItemType == 'Protocol' and ItemMode == 'Consumed':
631 LibraryList = EotGlobalData.gConsumedProtocolLibrary
632 elif ItemType == 'Protocol' and ItemMode == 'Callback':
633 LibraryList = EotGlobalData.gCallbackProtocolLibrary
634 elif ItemType == 'Ppi' and ItemMode == 'Produced':
635 LibraryList = EotGlobalData.gProducedPpiLibrary
636 elif ItemType == 'Ppi' and ItemMode == 'Consumed':
637 LibraryList = EotGlobalData.gConsumedPpiLibrary
638
639 for Library in LibraryList:
640 Index = LibraryList[Library]
641 SqlCommand = """select Value, StartLine from %s
642 where Name like '%%%s%%' and Model = %s""" \
643 % (Table, Library, MODEL_IDENTIFIER_FUNCTION_CALLING)
644 RecordSet = Db.Exec(SqlCommand)
645 for Record in RecordSet:
646 IsFound = False
647 if Index == -1:
648 ParameterList = GetSplitValueList(Record[0], TAB_COMMA_SPLIT)
649 for Parameter in ParameterList:
650 Parameters.append(GetParameterName(Parameter))
651 else:
652 Parameters = [GetProtocolParameter(Record[0], Index)]
653 StartLine = Record[1]
654 for Parameter in Parameters:
655 if Parameter.startswith('g') or Parameter.endswith('Guid') or Parameter == 'ShellEnvProtocol' or Parameter == 'ShellInterfaceProtocol':
656 GuidName = GetParameterName(Parameter)
657 Db.Insert(-1, '', '', SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, 0)
658 IsFound = True
659
660 if not IsFound:
661 EotGlobalData.gOP_UN_MATCHED.write('%s, %s, %s, %s, %s, %s\n' % (ItemType, ItemMode, SourceFileID, SourceFileFullPath, StartLine, Parameter))
662
663 ## FindProtocols() method
664 #
665 # Find defined protocols
666 #
667 # @param SqlCommand: SQL command statement
668 # @param Table: Table id
669 # @param SourceFileID: Source file id
670 # @param SourceFileFullPath: Source file full path
671 # @param ItemName: String of protocol definition
672 # @param ItemType: Type of the item, PPI or PROTOCOL
673 # @param ItemMode: Mode of item
674 #
675 #def FindProtocols(Db, SqlCommand, Table, SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue):
676 # BelongsToFunction = ''
677 # RecordSet = Db.Exec(SqlCommand)
678 # for Record in RecordSet:
679 # IsFound = True
680 # Parameter = GetProtocolParameter(Record[0])
681
682 ## GetProtocolParameter() method
683 #
684 # Parse string of protocol and find parameters
685 #
686 # @param Parameter: Parameter to be parsed
687 # @param Index: The index of the parameter
688 #
689 # @return: call common GetParameter
690 #
691 def GetProtocolParameter(Parameter, Index = 1):
692 return GetParameter(Parameter, Index)
693
694 ## GetPpiParameter() method
695 #
696 # Parse string of ppi and find parameters
697 #
698 # @param Parameter: Parameter to be parsed
699 # @param Index: The index of the parameter
700 #
701 # @return: call common GetParameter
702 #
703 def GetPpiParameter(Parameter, Index = 1):
704 return GetParameter(Parameter, Index)
705
706 ## GetParameter() method
707 #
708 # Get a parameter by index
709 #
710 # @param Parameter: Parameter to be parsed
711 # @param Index: The index of the parameter
712 #
713 # @return Parameter: The found parameter
714 #
715 def GetParameter(Parameter, Index = 1):
716 ParameterList = GetSplitValueList(Parameter, TAB_COMMA_SPLIT)
717 if len(ParameterList) > Index:
718 Parameter = GetParameterName(ParameterList[Index])
719
720 return Parameter
721
722 return ''
723
724 ## GetParameterName() method
725 #
726 # Get a parameter name
727 #
728 # @param Parameter: Parameter to be parsed
729 #
730 # @return: The name of parameter
731 #
732 def GetParameterName(Parameter):
733 if type(Parameter) == type('') and Parameter.startswith('&'):
734 return Parameter[1:].replace('{', '').replace('}', '').replace('\r', '').replace('\n', '').strip()
735 else:
736 return Parameter.strip()
737
738 ## FindKeyValue() method
739 #
740 # Find key value of a variable
741 #
742 # @param Db: Database to be searched
743 # @param Table: Table to be searched
744 # @param Key: The keyword
745 #
746 # @return Value: The value of the the keyword
747 #
748 def FindKeyValue(Db, Table, Key):
749 SqlCommand = """select Value from %s where Name = '%s' and (Model = %s or Model = %s)""" % (Table, Key, MODEL_IDENTIFIER_VARIABLE, MODEL_IDENTIFIER_ASSIGNMENT_EXPRESSION)
750 RecordSet = Db.Exec(SqlCommand)
751 Value = ''
752 for Record in RecordSet:
753 if Record[0] != 'NULL':
754 Value = FindKeyValue(Db, Table, GetParameterName(Record[0]))
755
756 if Value != '':
757 return Value
758 else:
759 return Key
760
761 ## ParseMapFile() method
762 #
763 # Parse map files to get a dict of 'ModuleName' : {FunName : FunAddress}
764 #
765 # @param Files: A list of map files
766 #
767 # @return AllMaps: An object of all map files
768 #
769 def ParseMapFile(Files):
770 AllMaps = {}
771 CurrentModule = ''
772 CurrentMaps = {}
773 for File in Files:
774 Content = open(File, 'r').readlines()
775 for Line in Content:
776 Line = CleanString(Line)
777 # skip empty line
778 if Line == '':
779 continue
780
781 if Line.find('(') > -1 and Line.find(')') > -1:
782 if CurrentModule != '' and CurrentMaps != {}:
783 AllMaps[CurrentModule] = CurrentMaps
784 CurrentModule = Line[:Line.find('(')]
785 CurrentMaps = {}
786 continue
787 else:
788 Name = ''
789 Address = ''
790 List = Line.split()
791 Address = List[0]
792 if List[1] == 'F' or List[1] == 'FS':
793 Name = List[2]
794 else:
795 Name = List[1]
796 CurrentMaps[Name] = Address
797 continue
798
799 return AllMaps
800
801 ## ConvertGuid
802 #
803 # Convert a GUID to a GUID with all upper letters
804 #
805 # @param guid: The GUID to be converted
806 #
807 # @param newGuid: The GUID with all upper letters.
808 #
809 def ConvertGuid(guid):
810 numList = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
811 newGuid = ''
812 if guid.startswith('g'):
813 guid = guid[1:]
814 for i in guid:
815 if i.upper() == i and i not in numList:
816 newGuid = newGuid + ('_' + i)
817 else:
818 newGuid = newGuid + i.upper()
819 if newGuid.startswith('_'):
820 newGuid = newGuid[1:]
821 if newGuid.endswith('_'):
822 newGuid = newGuid[:-1]
823
824 return newGuid
825
826 ## ConvertGuid2() method
827 #
828 # Convert a GUID to a GUID with new string instead of old string
829 #
830 # @param guid: The GUID to be converted
831 # @param old: Old string to be replaced
832 # @param new: New string to replace the old one
833 #
834 # @param newGuid: The GUID after replacement
835 #
836 def ConvertGuid2(guid, old, new):
837 newGuid = ConvertGuid(guid)
838 newGuid = newGuid.replace(old, new)
839
840 return newGuid
841
842 ##
843 #
844 # This acts like the main() function for the script, unless it is 'import'ed into another
845 # script.
846 #
847 if __name__ == '__main__':
848 pass