2 # This file is used to parse meta files
4 # Copyright (c) 2008 - 2020, Intel Corporation. All rights reserved.<BR>
5 # SPDX-License-Identifier: BSD-2-Clause-Patent
11 from __future__
import absolute_import
12 import Common
.LongFilePathOs
as os
16 from hashlib
import md5
17 import Common
.EdkLogger
as EdkLogger
18 import Common
.GlobalData
as GlobalData
19 import Ecc
.EccGlobalData
as EccGlobalData
20 import Ecc
.EccToolError
as EccToolError
22 from CommonDataClass
.DataClass
import *
23 from Common
.DataType
import *
24 from Common
.StringUtils
import *
25 from Common
.Misc
import GuidStructureStringToGuidString
, CheckPcdDatum
, PathClass
, AnalyzePcdData
26 from Common
.Expression
import *
27 from CommonDataClass
.Exceptions
import *
29 from Ecc
.MetaFileWorkspace
.MetaFileTable
import MetaFileStorage
30 from GenFds
.FdfParser
import FdfParser
31 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
32 from Common
.LongFilePathSupport
import CodecOpenLongFilePath
34 ## RegEx for finding file versions
35 hexVersionPattern
= re
.compile(r
'0[xX][\da-f-A-F]{5,8}')
36 decVersionPattern
= re
.compile(r
'\d+\.\d+')
38 ## A decorator used to parse macro definition
39 def ParseMacro(Parser
):
40 def MacroParser(self
):
41 Match
= GlobalData
.gMacroDefPattern
.match(self
._CurrentLine
)
43 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
47 TokenList
= GetSplitValueList(self
._CurrentLine
[Match
.end(1):], TAB_EQUAL_SPLIT
, 1)
50 EdkLogger
.error('Parser', FORMAT_INVALID
, "No macro name given",
51 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
52 if len(TokenList
) < 2:
56 Name
, Value
= TokenList
57 # Global macros can be only defined via environment variable
58 if Name
in GlobalData
.gGlobalDefines
:
59 EdkLogger
.error('Parser', FORMAT_INVALID
, "%s can only be defined via environment variable" % Name
,
60 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
61 # Only upper case letters, digit and '_' are allowed
62 if not GlobalData
.gMacroNamePattern
.match(Name
):
63 EdkLogger
.error('Parser', FORMAT_INVALID
, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
64 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
66 Value
= ReplaceMacro(Value
, self
._Macros
)
67 self
._ItemType
= MODEL_META_DATA_DEFINE
68 # DEFINE defined macros
69 if Type
== TAB_DSC_DEFINES_DEFINE
:
70 if isinstance(self
, DecParser
):
71 if MODEL_META_DATA_HEADER
in self
._SectionType
:
72 self
._FileLocalMacros
[Name
] = Value
74 for Scope
in self
._Scope
:
75 self
._SectionsMacroDict
.setdefault((Scope
[2], Scope
[0], Scope
[1]), {})[Name
] = Value
76 elif self
._SectionType
== MODEL_META_DATA_HEADER
:
77 self
._FileLocalMacros
[Name
] = Value
79 SectionDictKey
= self
._SectionType
, self
._Scope
[0][0], self
._Scope
[0][1]
80 if SectionDictKey
not in self
._SectionsMacroDict
:
81 self
._SectionsMacroDict
[SectionDictKey
] = {}
82 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
83 SectionLocalMacros
[Name
] = Value
84 # EDK_GLOBAL defined macros
85 elif not isinstance(self
, DscParser
):
86 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used in .dsc file",
87 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
88 elif self
._SectionType
!= MODEL_META_DATA_HEADER
:
89 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used under [Defines] section",
90 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
91 elif (Name
in self
._FileLocalMacros
) and (self
._FileLocalMacros
[Name
] != Value
):
92 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
93 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
95 self
._ValueList
= [Type
, Name
, Value
]
99 ## Base class of parser
101 # This class is used for derivation purpose. The specific parser for one kind
102 # type file must derive this class and implement some public interfaces.
104 # @param FilePath The path of platform description file
105 # @param FileType The raw data of DSC file
106 # @param Table Database used to retrieve module/package information
107 # @param Macros Macros used for replacement in file
108 # @param Owner Owner ID (for sub-section parsing)
109 # @param From ID from which the data comes (for !INCLUDE directive)
111 class MetaFileParser(object):
112 # data type (file content) for specific file type
115 # Parser objects used to implement singleton
120 # One file, one parser object. This factory method makes sure that there's
121 # only one object constructed for one meta file.
123 # @param Class class object of real AutoGen class
124 # (InfParser, DecParser or DscParser)
125 # @param FilePath The path of meta file
126 # @param *args The specific class related parameters
127 # @param **kwargs The specific class related dict parameters
129 def __new__(Class
, FilePath
, *args
, **kwargs
):
130 if FilePath
in Class
.MetaFiles
:
131 return Class
.MetaFiles
[FilePath
]
133 ParserObject
= super(MetaFileParser
, Class
).__new
__(Class
)
134 Class
.MetaFiles
[FilePath
] = ParserObject
137 ## Constructor of MetaFileParser
139 # Initialize object of MetaFileParser
141 # @param FilePath The path of platform description file
142 # @param FileType The raw data of DSC file
143 # @param Table Database used to retrieve module/package information
144 # @param Macros Macros used for replacement in file
145 # @param Owner Owner ID (for sub-section parsing)
146 # @param From ID from which the data comes (for !INCLUDE directive)
148 def __init__(self
, FilePath
, FileType
, Table
, Owner
=-1, From
=-1):
150 self
._RawTable
= Table
151 self
._FileType
= FileType
152 self
.MetaFile
= FilePath
154 self
._FileLocalMacros
= {}
155 self
._SectionsMacroDict
= {}
157 # for recursive parsing
158 self
._Owner
= [Owner
]
161 # parsr status for parsing
162 self
._ValueList
= ['', '', '', '', '']
165 self
._CurrentLine
= ''
166 self
._SectionType
= MODEL_UNKNOWN
167 self
._SectionName
= ''
168 self
._InSubsection
= False
169 self
._SubsectionType
= MODEL_UNKNOWN
170 self
._SubsectionName
= ''
171 self
._ItemType
= MODEL_UNKNOWN
174 self
._Finished
= False
175 self
._PostProcessed
= False
176 # Different version of meta-file has different way to parse.
178 # UNI object and extra UNI object
180 self
._UniExtraObj
= None
182 ## Store the parsed data in table
183 def _Store(self
, *Args
):
184 return self
._Table
.Insert(*Args
)
186 ## Virtual method for starting parse
188 raise NotImplementedError
190 ## Notify a post-process is needed
191 def DoPostProcess(self
):
192 self
._PostProcessed
= False
194 ## Set parsing complete flag in both class and table
196 self
._Finished
= True
197 ## Do not set end flag when processing included files
199 self
._Table
.SetEndFlag()
201 def _PostProcess(self
):
202 self
._PostProcessed
= True
204 ## Get the parse complete flag
205 def _GetFinished(self
):
206 return self
._Finished
208 ## Set the complete flag
209 def _SetFinished(self
, Value
):
210 self
._Finished
= Value
212 ## Use [] style to query data in table, just for readability
214 # DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]
216 def __getitem__(self
, DataInfo
):
217 if not isinstance(DataInfo
, type(())):
218 DataInfo
= (DataInfo
,)
220 # Parse the file first, if necessary
221 if not self
._Finished
:
222 if self
._RawTable
.IsIntegrity():
223 self
._Finished
= True
225 self
._Table
= self
._RawTable
226 self
._PostProcessed
= False
229 # No specific ARCH or Platform given, use raw data
230 if self
._RawTable
and (len(DataInfo
) == 1 or DataInfo
[1] is None):
231 return self
._RawTable
.Query(*DataInfo
)
233 # Do post-process if necessary
234 if not self
._PostProcessed
:
237 return self
._Table
.Query(*DataInfo
)
239 ## Data parser for the common format in different type of file
241 # The common format in the meatfile is like
246 def _CommonParser(self
):
247 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
248 self
._ValueList
[0:len(TokenList
)] = TokenList
250 ## Data parser for the format in which there's path
252 # Only path can have macro used. So we need to replace them before use.
255 def _PathParser(self
):
256 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
257 self
._ValueList
[0:len(TokenList
)] = TokenList
258 # Don't do macro replacement for dsc file at this point
259 if not isinstance(self
, DscParser
):
260 Macros
= self
._Macros
261 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
263 ## Skip unsupported data
265 if self
._SectionName
== TAB_USER_EXTENSIONS
.upper() and self
._CurrentLine
.upper().endswith('.UNI'):
266 if EccGlobalData
.gConfig
.UniCheckHelpInfo
== '1' or EccGlobalData
.gConfig
.UniCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
267 ExtraUni
= self
._CurrentLine
.strip()
268 ExtraUniFile
= os
.path
.join(os
.path
.dirname(self
.MetaFile
), ExtraUni
)
269 IsModuleUni
= self
.MetaFile
.upper().endswith('.INF')
270 self
._UniExtraObj
= UniParser(ExtraUniFile
, IsExtraUni
=True, IsModuleUni
=IsModuleUni
)
271 self
._UniExtraObj
.Start()
273 EdkLogger
.warn("Parser", "Unrecognized content", File
=self
.MetaFile
,
274 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
);
275 self
._ValueList
[0:1] = [self
._CurrentLine
]
277 ## Section header parser
279 # The section header is always in following format:
281 # [section_name.arch<.platform|module_type>]
283 def _SectionHeaderParser(self
):
285 self
._SectionName
= ''
287 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
290 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
)
291 # different section should not mix in one section
292 if self
._SectionName
!= '' and self
._SectionName
!= ItemList
[0].upper():
293 EdkLogger
.error('Parser', FORMAT_INVALID
, "Different section names in the same section",
294 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
295 self
._SectionName
= ItemList
[0].upper()
296 if self
._SectionName
in self
.DataType
:
297 self
._SectionType
= self
.DataType
[self
._SectionName
]
299 self
._SectionType
= MODEL_UNKNOWN
300 EdkLogger
.warn("Parser", "Unrecognized section", File
=self
.MetaFile
,
301 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
303 if len(ItemList
) > 1:
304 S1
= ItemList
[1].upper()
308 # S2 may be Platform or ModuleType
309 if len(ItemList
) > 2:
310 S2
= ItemList
[2].upper()
313 self
._Scope
.append([S1
, S2
])
315 # 'COMMON' must not be used with specific ARCHs at the same section
316 if 'COMMON' in ArchList
and len(ArchList
) > 1:
317 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
318 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
319 # If the section information is needed later, it should be stored in database
320 self
._ValueList
[0] = self
._SectionName
322 ## [defines] section parser
324 def _DefineParser(self
):
325 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
326 self
._ValueList
[1:len(TokenList
)] = TokenList
327 if not self
._ValueList
[1]:
328 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
329 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
330 if not self
._ValueList
[2]:
331 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
332 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
334 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
335 Name
, Value
= self
._ValueList
[1], self
._ValueList
[2]
336 # Sometimes, we need to make differences between EDK and EDK2 modules
337 if Name
== 'INF_VERSION':
338 if hexVersionPattern
.match(Value
):
339 self
._Version
= int(Value
, 0)
340 elif decVersionPattern
.match(Value
):
341 ValueList
= Value
.split('.')
342 Major
= int(ValueList
[0], 0)
343 Minor
= int(ValueList
[1], 0)
344 if Major
> 0xffff or Minor
> 0xffff:
345 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid version number",
346 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
347 self
._Version
= int('0x{0:04x}{1:04x}'.format(Major
, Minor
), 0)
349 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid version number",
350 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
351 elif Name
== 'MODULE_UNI_FILE':
352 UniFile
= os
.path
.join(os
.path
.dirname(self
.MetaFile
), Value
)
353 if os
.path
.exists(UniFile
):
354 self
._UniObj
= UniParser(UniFile
, IsExtraUni
=False, IsModuleUni
=True)
357 EdkLogger
.error('Parser', FILE_NOT_FOUND
, "Module UNI file %s is missing." % Value
,
358 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
360 elif Name
== 'PACKAGE_UNI_FILE':
361 UniFile
= os
.path
.join(os
.path
.dirname(self
.MetaFile
), Value
)
362 if os
.path
.exists(UniFile
):
363 self
._UniObj
= UniParser(UniFile
, IsExtraUni
=False, IsModuleUni
=False)
365 if isinstance(self
, InfParser
) and self
._Version
< 0x00010005:
366 # EDK module allows using defines as macros
367 self
._FileLocalMacros
[Name
] = Value
368 self
._Defines
[Name
] = Value
370 ## [BuildOptions] section parser
372 def _BuildOptionParser(self
):
373 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
374 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
375 if len(TokenList2
) == 2:
376 self
._ValueList
[0] = TokenList2
[0] # toolchain family
377 self
._ValueList
[1] = TokenList2
[1] # keys
379 self
._ValueList
[1] = TokenList
[0]
380 if len(TokenList
) == 2 and not isinstance(self
, DscParser
): # value
381 self
._ValueList
[2] = ReplaceMacro(TokenList
[1], self
._Macros
)
383 if self
._ValueList
[1].count('_') != 4:
387 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
388 ExtraData
=self
._CurrentLine
,
390 Line
=self
._LineIndex
+1
393 def _GetMacros(self
):
395 Macros
.update(self
._FileLocalMacros
)
396 Macros
.update(self
._GetApplicableSectionMacro
())
400 ## Get section Macros that are applicable to current line, which may come from other sections
401 ## that share the same name while scope is wider
402 def _GetApplicableSectionMacro(self
):
404 for Scope1
, Scope2
in [("COMMON", "COMMON"), ("COMMON", self
._Scope
[0][1]),
405 (self
._Scope
[0][0], "COMMON"), (self
._Scope
[0][0], self
._Scope
[0][1])]:
406 if (self
._SectionType
, Scope1
, Scope2
) in self
._SectionsMacroDict
:
407 Macros
.update(self
._SectionsMacroDict
[(self
._SectionType
, Scope1
, Scope2
)])
411 Finished
= property(_GetFinished
, _SetFinished
)
412 _Macros
= property(_GetMacros
)
415 ## INF file parser class
417 # @param FilePath The path of platform description file
418 # @param FileType The raw data of DSC file
419 # @param Table Database used to retrieve module/package information
420 # @param Macros Macros used for replacement in file
422 class InfParser(MetaFileParser
):
423 # INF file supported data types (one type per section)
425 TAB_UNKNOWN
.upper() : MODEL_UNKNOWN
,
426 TAB_INF_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
427 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
428 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
429 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
430 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
431 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
432 TAB_PACKAGES
.upper() : MODEL_META_DATA_PACKAGE
,
433 TAB_NMAKE
.upper() : MODEL_META_DATA_NMAKE
,
434 TAB_INF_FIXED_PCD
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
435 TAB_INF_PATCH_PCD
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
436 TAB_INF_FEATURE_PCD
.upper() : MODEL_PCD_FEATURE_FLAG
,
437 TAB_INF_PCD_EX
.upper() : MODEL_PCD_DYNAMIC_EX
,
438 TAB_INF_PCD
.upper() : MODEL_PCD_DYNAMIC
,
439 TAB_SOURCES
.upper() : MODEL_EFI_SOURCE_FILE
,
440 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
441 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
442 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
443 TAB_DEPEX
.upper() : MODEL_EFI_DEPEX
,
444 TAB_BINARIES
.upper() : MODEL_EFI_BINARY_FILE
,
445 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
448 ## Constructor of InfParser
450 # Initialize object of InfParser
452 # @param FilePath The path of module description file
453 # @param FileType The raw data of DSC file
454 # @param Table Database used to retrieve module/package information
455 # @param Macros Macros used for replacement in file
457 def __init__(self
, FilePath
, FileType
, Table
):
458 # prevent re-initialization
459 if hasattr(self
, "_Table"):
461 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
462 self
.TblFile
= EccGlobalData
.gDb
.TblFile
471 Content
= open(str(self
.MetaFile
), 'r').readlines()
473 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
475 # Insert a record for file
477 Filename
= NormPath(self
.MetaFile
)
478 FileID
= self
.TblFile
.GetFileId(Filename
)
482 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_INF
)
484 # parse the file line by line
485 IsFindBlockComment
= False
487 for Index
in range(0, len(Content
)):
488 if self
._SectionType
in [MODEL_EFI_GUID
,
491 MODEL_PCD_FIXED_AT_BUILD
,
492 MODEL_PCD_PATCHABLE_IN_MODULE
,
493 MODEL_PCD_FEATURE_FLAG
,
494 MODEL_PCD_DYNAMIC_EX
,
496 Line
= Content
[Index
].strip()
497 if Line
.startswith(TAB_SPECIAL_COMMENT
):
498 Usage
+= ' ' + Line
[Line
.find(TAB_SPECIAL_COMMENT
):]
500 elif Line
.startswith(TAB_COMMENT_SPLIT
):
502 elif Line
.find(TAB_COMMENT_SPLIT
) > 0:
503 Usage
+= ' ' + Line
[Line
.find(TAB_COMMENT_SPLIT
):]
504 Line
= Line
[:Line
.find(TAB_COMMENT_SPLIT
)]
506 # skip empty, commented, block commented lines
507 Line
= CleanString(Content
[Index
], AllowCppStyleComment
=True)
510 if Index
+ 1 < len(Content
):
511 NextLine
= CleanString(Content
[Index
+ 1])
514 if Line
.find(DataType
.TAB_COMMENT_EDK_START
) > -1:
515 IsFindBlockComment
= True
517 if Line
.find(DataType
.TAB_COMMENT_EDK_END
) > -1:
518 IsFindBlockComment
= False
520 if IsFindBlockComment
:
523 self
._LineIndex
= Index
524 self
._CurrentLine
= Line
527 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
528 self
._SectionHeaderParser
()
529 # Check invalid sections
530 if self
._Version
< 0x00010005:
531 if self
._SectionType
in [MODEL_META_DATA_BUILD_OPTION
,
532 MODEL_EFI_LIBRARY_CLASS
,
533 MODEL_META_DATA_PACKAGE
,
534 MODEL_PCD_FIXED_AT_BUILD
,
535 MODEL_PCD_PATCHABLE_IN_MODULE
,
536 MODEL_PCD_FEATURE_FLAG
,
537 MODEL_PCD_DYNAMIC_EX
,
542 MODEL_META_DATA_USER_EXTENSION
]:
543 EdkLogger
.error('Parser', FORMAT_INVALID
,
544 "Section [%s] is not allowed in inf file without version" % (self
._SectionName
),
545 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
546 elif self
._SectionType
in [MODEL_EFI_INCLUDE
,
547 MODEL_EFI_LIBRARY_INSTANCE
,
548 MODEL_META_DATA_NMAKE
]:
549 EdkLogger
.error('Parser', FORMAT_INVALID
,
550 "Section [%s] is not allowed in inf file with version 0x%08x" % (self
._SectionName
, self
._Version
),
551 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
553 # merge two lines specified by '\' in section NMAKE
554 elif self
._SectionType
== MODEL_META_DATA_NMAKE
:
557 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
560 if NextLine
[0] == TAB_SECTION_START
and NextLine
[-1] == TAB_SECTION_END
:
561 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
564 NmakeLine
= NmakeLine
+ ' ' + Line
[0:-1]
567 self
._CurrentLine
= NmakeLine
+ Line
571 self
._ValueList
= ['', '', '']
572 # parse current line, result will be put in self._ValueList
573 self
._SectionParser
[self
._SectionType
](self
)
574 if self
._ValueList
is None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
578 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
579 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
581 self
._ValueList
[0] = self
._ValueList
[0].replace('/', '\\')
582 Usage
= Usage
.strip()
583 for Arch
, Platform
in self
._Scope
:
584 self
._Store
(self
._SectionType
,
600 if IsFindBlockComment
:
601 EdkLogger
.error("Parser", FORMAT_INVALID
, "Open block comments (starting with /*) are expected to end with */",
605 ## Data parser for the format in which there's path
607 # Only path can have macro used. So we need to replace them before use.
609 def _IncludeParser(self
):
610 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
611 self
._ValueList
[0:len(TokenList
)] = TokenList
612 Macros
= self
._Macros
614 for Index
in range(0, len(self
._ValueList
)):
615 Value
= self
._ValueList
[Index
]
619 self
._ValueList
[Index
] = ReplaceMacro(Value
, Macros
)
621 ## Parse [Sources] section
623 # Only path can have macro used. So we need to replace them before use.
626 def _SourceFileParser(self
):
627 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
628 self
._ValueList
[0:len(TokenList
)] = TokenList
629 Macros
= self
._Macros
630 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
631 if 'COMPONENT_TYPE' in Macros
:
632 if self
._Defines
['COMPONENT_TYPE'].upper() == 'ACPITABLE':
633 self
._ValueList
[0] = GetSplitValueList(self
._ValueList
[0], ' ', 1)[0]
634 if self
._Defines
['BASE_NAME'] == 'Microcode':
636 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
638 ## Parse [Binaries] section
640 # Only path can have macro used. So we need to replace them before use.
643 def _BinaryFileParser(self
):
644 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 2)
645 if len(TokenList
) < 2:
646 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type or path specified",
647 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
648 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
650 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type specified",
651 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
652 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
654 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file path specified",
655 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
656 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
657 self
._ValueList
[0:len(TokenList
)] = TokenList
658 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
660 ## [nmake] section parser (Edk.x style only)
661 def _NmakeParser(self
):
662 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
663 self
._ValueList
[0:len(TokenList
)] = TokenList
665 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
666 # remove self-reference in macro setting
667 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
669 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
671 def _PcdParser(self
):
672 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
673 ValueList
= GetSplitValueList(TokenList
[0], TAB_SPLIT
)
674 if len(ValueList
) != 2:
675 EdkLogger
.error('Parser', FORMAT_INVALID
, "Illegal token space GUID and PCD name format",
676 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
677 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
678 self
._ValueList
[0:1] = ValueList
679 if len(TokenList
) > 1:
680 self
._ValueList
[2] = TokenList
[1]
681 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
682 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
683 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
684 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
686 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
687 if self
._ValueList
[2] != '':
688 InfPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
689 if InfPcdValueList
[0] in ['True', 'true', 'TRUE']:
690 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '1', 1);
691 elif InfPcdValueList
[0] in ['False', 'false', 'FALSE']:
692 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '0', 1);
694 ## [depex] section parser
696 def _DepexParser(self
):
697 self
._ValueList
[0:1] = [self
._CurrentLine
]
700 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
701 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
702 MODEL_META_DATA_BUILD_OPTION
: MetaFileParser
._BuildOptionParser
,
703 MODEL_EFI_INCLUDE
: _IncludeParser
, # for Edk.x modules
704 MODEL_EFI_LIBRARY_INSTANCE
: MetaFileParser
._CommonParser
, # for Edk.x modules
705 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
706 MODEL_META_DATA_PACKAGE
: MetaFileParser
._PathParser
,
707 MODEL_META_DATA_NMAKE
: _NmakeParser
, # for Edk.x modules
708 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
709 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
710 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
711 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
712 MODEL_PCD_DYNAMIC
: _PcdParser
,
713 MODEL_EFI_SOURCE_FILE
: _SourceFileParser
,
714 MODEL_EFI_GUID
: MetaFileParser
._CommonParser
,
715 MODEL_EFI_PROTOCOL
: MetaFileParser
._CommonParser
,
716 MODEL_EFI_PPI
: MetaFileParser
._CommonParser
,
717 MODEL_EFI_DEPEX
: _DepexParser
,
718 MODEL_EFI_BINARY_FILE
: _BinaryFileParser
,
719 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
722 ## DSC file parser class
724 # @param FilePath The path of platform description file
725 # @param FileType The raw data of DSC file
726 # @param Table Database used to retrieve module/package information
727 # @param Macros Macros used for replacement in file
728 # @param Owner Owner ID (for sub-section parsing)
729 # @param From ID from which the data comes (for !INCLUDE directive)
731 class DscParser(MetaFileParser
):
732 # DSC file supported data types (one type per section)
734 TAB_SKUIDS
.upper() : MODEL_EFI_SKU_ID
,
735 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
736 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
737 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
738 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
739 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
740 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
741 TAB_PCDS_DYNAMIC_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_DEFAULT
,
742 TAB_PCDS_DYNAMIC_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_HII
,
743 TAB_PCDS_DYNAMIC_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_VPD
,
744 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT
,
745 TAB_PCDS_DYNAMIC_EX_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_HII
,
746 TAB_PCDS_DYNAMIC_EX_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_VPD
,
747 TAB_COMPONENTS
.upper() : MODEL_META_DATA_COMPONENT
,
748 TAB_DSC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
749 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
750 TAB_DSC_DEFINES_EDKGLOBAL
: MODEL_META_DATA_GLOBAL_DEFINE
,
751 TAB_INCLUDE
.upper() : MODEL_META_DATA_INCLUDE
,
752 TAB_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
753 TAB_IF_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
754 TAB_IF_N_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
,
755 TAB_ELSE_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
,
756 TAB_ELSE
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
757 TAB_END_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
,
758 TAB_ERROR
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR
,
761 # Valid names in define section
768 "PCD_INFO_GENERATION",
769 "SUPPORTED_ARCHITECTURES",
778 "FIX_LOAD_TOP_MEMORY_ADDRESS"
781 SubSectionDefineKeywords
= [
785 SymbolPattern
= ValueExpression
.SymbolPattern
787 ## Constructor of DscParser
789 # Initialize object of DscParser
791 # @param FilePath The path of platform description file
792 # @param FileType The raw data of DSC file
793 # @param Table Database used to retrieve module/package information
794 # @param Macros Macros used for replacement in file
795 # @param Owner Owner ID (for sub-section parsing)
796 # @param From ID from which the data comes (for !INCLUDE directive)
798 def __init__(self
, FilePath
, FileType
, Table
, Owner
=-1, From
=-1):
799 # prevent re-initialization
800 if hasattr(self
, "_Table"):
802 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, Owner
, From
)
803 self
._Version
= 0x00010005 # Only EDK2 dsc file is supported
804 # to store conditional directive evaluation result
805 self
._DirectiveStack
= []
806 self
._DirectiveEvalStack
= []
809 # Final valid replacable symbols
812 # Map the ID between the original table and new table to track
815 self
._IdMapping
= {-1:-1}
817 self
.TblFile
= EccGlobalData
.gDb
.TblFile
824 Content
= open(str(self
.MetaFile
.Path
), 'r').readlines()
826 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
828 # Insert a record for file
830 Filename
= NormPath(self
.MetaFile
.Path
)
831 FileID
= self
.TblFile
.GetFileId(Filename
)
835 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_DSC
)
838 for Index
in range(0, len(Content
)):
839 Line
= CleanString(Content
[Index
])
844 self
._CurrentLine
= Line
845 self
._LineIndex
= Index
846 if self
._InSubsection
and self
._Owner
[-1] == -1:
847 self
._Owner
.append(self
._LastItem
)
850 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
851 self
._SectionType
= MODEL_META_DATA_SECTION_HEADER
853 elif Line
[0] == '}' and self
._InSubsection
:
854 self
._InSubsection
= False
855 self
._SubsectionType
= MODEL_UNKNOWN
856 self
._SubsectionName
= ''
860 elif Line
[0] == TAB_OPTION_START
and Line
[-1] == TAB_OPTION_END
:
861 self
._SubsectionType
= MODEL_META_DATA_SUBSECTION_HEADER
864 self
._DirectiveParser
()
867 if self
._InSubsection
:
868 SectionType
= self
._SubsectionType
870 SectionType
= self
._SectionType
871 self
._ItemType
= SectionType
873 self
._ValueList
= ['', '', '']
874 self
._SectionParser
[SectionType
](self
)
875 if self
._ValueList
is None:
878 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
879 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
881 for Arch
, ModuleType
in self
._Scope
:
882 self
._LastItem
= self
._Store
(
899 if self
._DirectiveStack
:
900 Type
, Line
, Text
= self
._DirectiveStack
[-1]
901 EdkLogger
.error('Parser', FORMAT_INVALID
, "No matching '!endif' found",
902 ExtraData
=Text
, File
=self
.MetaFile
, Line
=Line
)
905 ## <subsection_header> parser
906 def _SubsectionHeaderParser(self
):
907 self
._SubsectionName
= self
._CurrentLine
[1:-1].upper()
908 if self
._SubsectionName
in self
.DataType
:
909 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
911 self
._SubsectionType
= MODEL_UNKNOWN
912 EdkLogger
.warn("Parser", "Unrecognized sub-section", File
=self
.MetaFile
,
913 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
914 self
._ValueList
[0] = self
._SubsectionName
916 ## Directive statement parser
917 def _DirectiveParser(self
):
918 self
._ValueList
= ['', '', '']
919 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
920 self
._ValueList
[0:len(TokenList
)] = TokenList
923 DirectiveName
= self
._ValueList
[0].upper()
924 if DirectiveName
not in self
.DataType
:
925 EdkLogger
.error("Parser", FORMAT_INVALID
, "Unknown directive [%s]" % DirectiveName
,
926 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
927 if DirectiveName
in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self
._ValueList
[1] == '':
928 EdkLogger
.error("Parser", FORMAT_INVALID
, "Missing expression",
929 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
930 ExtraData
=self
._CurrentLine
)
932 ItemType
= self
.DataType
[DirectiveName
]
933 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
934 # Remove all directives between !if and !endif, including themselves
935 while self
._DirectiveStack
:
936 # Remove any !else or !elseif
937 DirectiveInfo
= self
._DirectiveStack
.pop()
938 if DirectiveInfo
[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
939 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
940 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
943 EdkLogger
.error("Parser", FORMAT_INVALID
, "Redundant '!endif'",
944 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
945 ExtraData
=self
._CurrentLine
)
946 elif ItemType
!= MODEL_META_DATA_INCLUDE
:
947 # Break if there's a !else is followed by a !elseif
948 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
and \
949 self
._DirectiveStack
and \
950 self
._DirectiveStack
[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
951 EdkLogger
.error("Parser", FORMAT_INVALID
, "'!elseif' after '!else'",
952 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
953 ExtraData
=self
._CurrentLine
)
954 self
._DirectiveStack
.append((ItemType
, self
._LineIndex
+1, self
._CurrentLine
))
956 EdkLogger
.error('Parser', FORMAT_INVALID
,
957 "No '!include' allowed in included file",
958 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
,
959 Line
=self
._LineIndex
+1)
962 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
963 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
965 self
._LastItem
= self
._Store
(
982 ## [defines] section parser
984 def _DefineParser(self
):
985 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
986 self
._ValueList
[1:len(TokenList
)] = TokenList
989 if not self
._ValueList
[1]:
990 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
991 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
992 if not self
._ValueList
[2]:
993 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
994 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
995 if (not self
._ValueList
[1] in self
.DefineKeywords
and
996 (self
._InSubsection
and self
._ValueList
[1] not in self
.SubSectionDefineKeywords
)):
997 EdkLogger
.error('Parser', FORMAT_INVALID
,
998 "Unknown keyword found: %s. "
999 "If this is a macro you must "
1000 "add it as a DEFINE in the DSC" % self
._ValueList
[1],
1001 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1002 self
._Defines
[self
._ValueList
[1]] = self
._ValueList
[2]
1003 self
._ItemType
= self
.DataType
[TAB_DSC_DEFINES
.upper()]
1006 def _SkuIdParser(self
):
1007 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1008 if len(TokenList
) != 2:
1009 EdkLogger
.error('Parser', FORMAT_INVALID
, "Correct format is '<Integer>|<UiName>'",
1010 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1011 self
._ValueList
[0:len(TokenList
)] = TokenList
1013 ## Parse Edk style of library modules
1014 def _LibraryInstanceParser(self
):
1015 self
._ValueList
[0] = self
._CurrentLine
1017 ## PCD sections parser
1019 # [PcdsFixedAtBuild]
1020 # [PcdsPatchableInModule]
1023 # [PcdsDynamicExDefault]
1024 # [PcdsDynamicExVpd]
1025 # [PcdsDynamicExHii]
1027 # [PcdsDynamicDefault]
1032 def _PcdParser(self
):
1033 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1034 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1035 if len(TokenList
) == 2:
1036 self
._ValueList
[2] = TokenList
[1]
1037 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1038 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1039 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1040 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1041 if self
._ValueList
[2] == '':
1042 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD value given",
1043 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1044 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1045 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1046 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
1047 if DscPcdValueList
[0] in ['True', 'true', 'TRUE']:
1048 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '1', 1);
1049 elif DscPcdValueList
[0] in ['False', 'false', 'FALSE']:
1050 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '0', 1);
1052 ## [components] section parser
1054 def _ComponentParser(self
):
1055 if self
._CurrentLine
[-1] == '{':
1056 self
._ValueList
[0] = self
._CurrentLine
[0:-1].strip()
1057 self
._InSubsection
= True
1059 self
._ValueList
[0] = self
._CurrentLine
1061 ## [LibraryClasses] section
1063 def _LibraryClassParser(self
):
1064 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1065 if len(TokenList
) < 2:
1066 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class or instance specified",
1067 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1068 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1069 if TokenList
[0] == '':
1070 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class specified",
1071 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1072 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1073 if TokenList
[1] == '':
1074 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library instance specified",
1075 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1076 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1078 self
._ValueList
[0:len(TokenList
)] = TokenList
1081 ## [BuildOptions] section parser
1083 def _BuildOptionParser(self
):
1084 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1085 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
1086 if len(TokenList2
) == 2:
1087 self
._ValueList
[0] = TokenList2
[0] # toolchain family
1088 self
._ValueList
[1] = TokenList2
[1] # keys
1090 self
._ValueList
[1] = TokenList
[0]
1091 if len(TokenList
) == 2: # value
1092 self
._ValueList
[2] = TokenList
[1]
1094 if self
._ValueList
[1].count('_') != 4:
1098 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
1099 ExtraData
=self
._CurrentLine
,
1101 Line
=self
._LineIndex
+1
1104 ## Override parent's method since we'll do all macro replacements in parser
1105 def _GetMacros(self
):
1106 Macros
= dict( [('ARCH', 'IA32'), ('FAMILY', TAB_COMPILER_MSFT
), ('TOOL_CHAIN_TAG', 'VS2008x86'), ('TARGET', 'DEBUG')])
1107 Macros
.update(self
._FileLocalMacros
)
1108 Macros
.update(self
._GetApplicableSectionMacro
())
1109 Macros
.update(GlobalData
.gEdkGlobal
)
1110 Macros
.update(GlobalData
.gPlatformDefines
)
1111 Macros
.update(GlobalData
.gCommandLineDefines
)
1112 # PCD cannot be referenced in macro definition
1113 if self
._ItemType
not in [MODEL_META_DATA_DEFINE
, MODEL_META_DATA_GLOBAL_DEFINE
]:
1114 Macros
.update(self
._Symbols
)
1117 def _PostProcess(self
):
1119 MODEL_META_DATA_SECTION_HEADER
: self
.__ProcessSectionHeader
,
1120 MODEL_META_DATA_SUBSECTION_HEADER
: self
.__ProcessSubsectionHeader
,
1121 MODEL_META_DATA_HEADER
: self
.__ProcessDefine
,
1122 MODEL_META_DATA_DEFINE
: self
.__ProcessDefine
,
1123 MODEL_META_DATA_GLOBAL_DEFINE
: self
.__ProcessDefine
,
1124 MODEL_META_DATA_INCLUDE
: self
.__ProcessDirective
,
1125 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
: self
.__ProcessDirective
,
1126 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
: self
.__ProcessDirective
,
1127 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
: self
.__ProcessDirective
,
1128 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
: self
.__ProcessDirective
,
1129 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
: self
.__ProcessDirective
,
1130 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
: self
.__ProcessDirective
,
1131 MODEL_EFI_SKU_ID
: self
.__ProcessSkuId
,
1132 MODEL_EFI_LIBRARY_INSTANCE
: self
.__ProcessLibraryInstance
,
1133 MODEL_EFI_LIBRARY_CLASS
: self
.__ProcessLibraryClass
,
1134 MODEL_PCD_FIXED_AT_BUILD
: self
.__ProcessPcd
,
1135 MODEL_PCD_PATCHABLE_IN_MODULE
: self
.__ProcessPcd
,
1136 MODEL_PCD_FEATURE_FLAG
: self
.__ProcessPcd
,
1137 MODEL_PCD_DYNAMIC_DEFAULT
: self
.__ProcessPcd
,
1138 MODEL_PCD_DYNAMIC_HII
: self
.__ProcessPcd
,
1139 MODEL_PCD_DYNAMIC_VPD
: self
.__ProcessPcd
,
1140 MODEL_PCD_DYNAMIC_EX_DEFAULT
: self
.__ProcessPcd
,
1141 MODEL_PCD_DYNAMIC_EX_HII
: self
.__ProcessPcd
,
1142 MODEL_PCD_DYNAMIC_EX_VPD
: self
.__ProcessPcd
,
1143 MODEL_META_DATA_COMPONENT
: self
.__ProcessComponent
,
1144 MODEL_META_DATA_BUILD_OPTION
: self
.__ProcessBuildOption
,
1145 MODEL_UNKNOWN
: self
._Skip
,
1146 MODEL_META_DATA_USER_EXTENSION
: self
._Skip
,
1147 MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR
: self
._Skip
,
1150 self
._RawTable
= self
._Table
1151 self
._Table
= MetaFileStorage(self
._RawTable
.Cur
, self
.MetaFile
, MODEL_FILE_DSC
, True)
1152 self
._DirectiveStack
= []
1153 self
._DirectiveEvalStack
= []
1154 self
._FileWithError
= self
.MetaFile
1155 self
._FileLocalMacros
= {}
1156 self
._SectionsMacroDict
= {}
1157 GlobalData
.gPlatformDefines
= {}
1159 # Get all macro and PCD which has straitforward value
1160 self
.__RetrievePcdValue
()
1161 self
._Content
= self
._RawTable
.GetAll()
1162 self
._ContentIndex
= 0
1163 while self
._ContentIndex
< len(self
._Content
) :
1164 Id
, self
._ItemType
, V1
, V2
, V3
, S1
, S2
, Owner
, BelongsToFile
, self
._From
, \
1165 LineStart
, ColStart
, LineEnd
, ColEnd
, Enabled
= self
._Content
[self
._ContentIndex
]
1168 self
._FileWithError
= self
.MetaFile
1170 self
._ContentIndex
+= 1
1172 self
._Scope
= [[S1
, S2
]]
1173 self
._LineIndex
= LineStart
- 1
1174 self
._ValueList
= [V1
, V2
, V3
]
1177 Processer
[self
._ItemType
]()
1178 except EvaluationException
as Excpt
:
1180 # Only catch expression evaluation error here. We need to report
1181 # the precise number of line on which the error occurred
1184 # EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
1185 # File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1186 # Line=self._LineIndex+1)
1187 except MacroException
as Excpt
:
1188 EdkLogger
.error('Parser', FORMAT_INVALID
, str(Excpt
),
1189 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1190 Line
=self
._LineIndex
+1)
1192 if self
._ValueList
is None:
1195 NewOwner
= self
._IdMapping
.get(Owner
, -1)
1196 self
._Enabled
= int((not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
))
1197 self
._LastItem
= self
._Store
(
1213 self
._IdMapping
[Id
] = self
._LastItem
1215 RecordList
= self
._Table
.GetAll()
1217 self
._RawTable
.Drop()
1219 for Record
in RecordList
:
1220 EccGlobalData
.gDb
.TblDsc
.Insert(Record
[1], Record
[2], Record
[3], Record
[4], Record
[5], Record
[6], Record
[7], Record
[8], Record
[9], Record
[10], Record
[11], Record
[12], Record
[13], Record
[14])
1221 GlobalData
.gPlatformDefines
.update(self
._FileLocalMacros
)
1222 self
._PostProcessed
= True
1223 self
._Content
= None
1225 def __ProcessSectionHeader(self
):
1226 self
._SectionName
= self
._ValueList
[0]
1227 if self
._SectionName
in self
.DataType
:
1228 self
._SectionType
= self
.DataType
[self
._SectionName
]
1230 self
._SectionType
= MODEL_UNKNOWN
1232 def __ProcessSubsectionHeader(self
):
1233 self
._SubsectionName
= self
._ValueList
[0]
1234 if self
._SubsectionName
in self
.DataType
:
1235 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
1237 self
._SubsectionType
= MODEL_UNKNOWN
1239 def __RetrievePcdValue(self
):
1240 Records
= self
._RawTable
.Query(MODEL_PCD_FEATURE_FLAG
, BelongsToItem
=-1.0)
1241 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1242 Value
, DatumType
, MaxDatumSize
= AnalyzePcdData(Value
)
1243 # Only use PCD whose value is straitforward (no macro and PCD)
1244 if self
.SymbolPattern
.findall(Value
):
1246 Name
= TokenSpaceGuid
+ '.' + PcdName
1247 # Don't use PCD with different values.
1248 if Name
in self
._Symbols
and self
._Symbols
[Name
] != Value
:
1249 self
._Symbols
.pop(Name
)
1251 self
._Symbols
[Name
] = Value
1253 Records
= self
._RawTable
.Query(MODEL_PCD_FIXED_AT_BUILD
, BelongsToItem
=-1.0)
1254 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1255 Value
, DatumType
, MaxDatumSize
= AnalyzePcdData(Value
)
1256 # Only use PCD whose value is straitforward (no macro and PCD)
1257 if self
.SymbolPattern
.findall(Value
):
1259 Name
= TokenSpaceGuid
+'.'+PcdName
1260 # Don't use PCD with different values.
1261 if Name
in self
._Symbols
and self
._Symbols
[Name
] != Value
:
1262 self
._Symbols
.pop(Name
)
1264 self
._Symbols
[Name
] = Value
1266 def __ProcessDefine(self
):
1267 if not self
._Enabled
:
1270 Type
, Name
, Value
= self
._ValueList
1271 Value
= ReplaceMacro(Value
, self
._Macros
, False)
1272 if self
._ItemType
== MODEL_META_DATA_DEFINE
:
1273 if self
._SectionType
== MODEL_META_DATA_HEADER
:
1274 self
._FileLocalMacros
[Name
] = Value
1276 SectionDictKey
= self
._SectionType
, self
._Scope
[0][0], self
._Scope
[0][1]
1277 if SectionDictKey
not in self
._SectionsMacroDict
:
1278 self
._SectionsMacroDict
[SectionDictKey
] = {}
1279 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
1280 SectionLocalMacros
[Name
] = Value
1281 elif self
._ItemType
== MODEL_META_DATA_GLOBAL_DEFINE
:
1282 GlobalData
.gEdkGlobal
[Name
] = Value
1285 # Keyword in [Defines] section can be used as Macros
1287 if (self
._ItemType
== MODEL_META_DATA_HEADER
) and (self
._SectionType
== MODEL_META_DATA_HEADER
):
1288 self
._FileLocalMacros
[Name
] = Value
1290 self
._ValueList
= [Type
, Name
, Value
]
1292 def __ProcessDirective(self
):
1294 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1295 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
]:
1296 Macros
= self
._Macros
1297 Macros
.update(GlobalData
.gGlobalDefines
)
1299 Result
= ValueExpression(self
._ValueList
[1], Macros
)()
1300 except SymbolNotFound
as Exc
:
1301 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1303 except WrnExpression
as Excpt
:
1305 # Catch expression evaluation warning here. We need to report
1306 # the precise number of line and return the evaluation result
1308 EdkLogger
.warn('Parser', "Suspicious expression: %s" % str(Excpt
),
1309 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1310 Line
=self
._LineIndex
+1)
1311 Result
= Excpt
.result
1312 except BadExpression
as Exc
:
1313 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1316 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1317 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1318 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1319 self
._DirectiveStack
.append(self
._ItemType
)
1320 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
:
1321 Result
= bool(Result
)
1323 Macro
= self
._ValueList
[1]
1324 Macro
= Macro
[2:-1] if (Macro
.startswith("$(") and Macro
.endswith(")")) else Macro
1325 Result
= Macro
in self
._Macros
1326 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
:
1328 self
._DirectiveEvalStack
.append(Result
)
1329 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
:
1330 self
._DirectiveStack
.append(self
._ItemType
)
1331 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1332 self
._DirectiveEvalStack
.append(bool(Result
))
1333 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1334 self
._DirectiveStack
[-1] = self
._ItemType
1335 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1336 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1337 # Back to the nearest !if/!ifdef/!ifndef
1338 while self
._DirectiveStack
:
1339 self
._DirectiveEvalStack
.pop()
1340 Directive
= self
._DirectiveStack
.pop()
1341 if Directive
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1342 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1343 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
1344 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1346 elif self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1347 # The included file must be relative to workspace or same directory as DSC file
1348 __IncludeMacros
= {}
1350 # Allow using system environment variables in path after !include
1352 __IncludeMacros
['WORKSPACE'] = GlobalData
.gGlobalDefines
['WORKSPACE']
1355 # Allow using MACROs comes from [Defines] section to keep compatible.
1357 __IncludeMacros
.update(self
._Macros
)
1359 IncludedFile
= NormPath(ReplaceMacro(self
._ValueList
[1], __IncludeMacros
, RaiseError
=True))
1361 # First search the include file under the same directory as DSC file
1363 IncludedFile1
= PathClass(IncludedFile
, self
.MetaFile
.Dir
)
1364 ErrorCode
, ErrorInfo1
= IncludedFile1
.Validate()
1367 # Also search file under the WORKSPACE directory
1369 IncludedFile1
= PathClass(IncludedFile
, GlobalData
.gWorkspace
)
1370 ErrorCode
, ErrorInfo2
= IncludedFile1
.Validate()
1372 EdkLogger
.error('parser', ErrorCode
, File
=self
._FileWithError
,
1373 Line
=self
._LineIndex
+1, ExtraData
=ErrorInfo1
+ "\n"+ ErrorInfo2
)
1375 self
._FileWithError
= IncludedFile1
1377 IncludedFileTable
= MetaFileStorage(self
._Table
.Cur
, IncludedFile1
, MODEL_FILE_DSC
, True)
1378 Owner
= self
._Content
[self
._ContentIndex
-1][0]
1379 Parser
= DscParser(IncludedFile1
, self
._FileType
, IncludedFileTable
,
1380 Owner
=Owner
, From
=Owner
)
1382 # set the parser status with current status
1383 Parser
._SectionName
= self
._SectionName
1384 Parser
._SectionType
= self
._SectionType
1385 Parser
._Scope
= self
._Scope
1386 Parser
._Enabled
= self
._Enabled
1387 # Parse the included file
1390 # update current status with sub-parser's status
1391 self
._SectionName
= Parser
._SectionName
1392 self
._SectionType
= Parser
._SectionType
1393 self
._Scope
= Parser
._Scope
1394 self
._Enabled
= Parser
._Enabled
1396 # Insert all records in the table for the included file into dsc file table
1397 Records
= IncludedFileTable
.GetAll()
1399 self
._Content
[self
._ContentIndex
:self
._ContentIndex
] = Records
1400 self
._Content
.pop(self
._ContentIndex
-1)
1401 self
._ValueList
= None
1402 self
._ContentIndex
-= 1
1404 def __ProcessSkuId(self
):
1405 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=True)
1406 for Value
in self
._ValueList
]
1408 def __ProcessLibraryInstance(self
):
1409 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
1411 def __ProcessLibraryClass(self
):
1412 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, RaiseError
=True)
1414 def __ProcessPcd(self
):
1415 ValueList
= GetSplitValueList(self
._ValueList
[2])
1417 # PCD value can be an expression
1419 if len(ValueList
) > 1 and ValueList
[1] == TAB_VOID
:
1420 PcdValue
= ValueList
[0]
1422 ValueList
[0] = ValueExpression(PcdValue
, self
._Macros
)(True)
1423 except WrnExpression
as Value
:
1424 ValueList
[0] = Value
.result
1426 PcdValue
= ValueList
[-1]
1428 ValueList
[-1] = ValueExpression(PcdValue
, self
._Macros
)(True)
1429 except WrnExpression
as Value
:
1430 ValueList
[-1] = Value
.result
1432 if ValueList
[-1] == 'True':
1434 if ValueList
[-1] == 'False':
1437 self
._ValueList
[2] = '|'.join(ValueList
)
1439 def __ProcessComponent(self
):
1440 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1442 def __ProcessBuildOption(self
):
1443 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=False)
1444 for Value
in self
._ValueList
]
1447 MODEL_META_DATA_HEADER
: _DefineParser
,
1448 MODEL_EFI_SKU_ID
: _SkuIdParser
,
1449 MODEL_EFI_LIBRARY_INSTANCE
: _LibraryInstanceParser
,
1450 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
1451 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1452 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1453 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1454 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
1455 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
1456 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
1457 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
1458 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
1459 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
1460 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
1461 MODEL_META_DATA_BUILD_OPTION
: _BuildOptionParser
,
1462 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1463 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1464 MODEL_META_DATA_SECTION_HEADER
: MetaFileParser
._SectionHeaderParser
,
1465 MODEL_META_DATA_SUBSECTION_HEADER
: _SubsectionHeaderParser
,
1468 _Macros
= property(_GetMacros
)
1470 ## DEC file parser class
1472 # @param FilePath The path of platform description file
1473 # @param FileType The raw data of DSC file
1474 # @param Table Database used to retrieve module/package information
1475 # @param Macros Macros used for replacement in file
1477 class DecParser(MetaFileParser
):
1478 # DEC file supported data types (one type per section)
1480 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1481 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
1482 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1483 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1484 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1485 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1486 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1487 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1488 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1489 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1490 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1491 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1494 ## Constructor of DecParser
1496 # Initialize object of DecParser
1498 # @param FilePath The path of platform description file
1499 # @param FileType The raw data of DSC file
1500 # @param Table Database used to retrieve module/package information
1501 # @param Macros Macros used for replacement in file
1503 def __init__(self
, FilePath
, FileType
, Table
):
1504 # prevent re-initialization
1505 if hasattr(self
, "_Table"):
1507 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
1509 self
._Version
= 0x00010005 # Only EDK2 dec file is supported
1510 self
.TblFile
= EccGlobalData
.gDb
.TblFile
1513 self
._CurrentStructurePcdName
= ""
1514 self
._include
_flag
= False
1515 self
._package
_flag
= False
1521 Content
= open(str(self
.MetaFile
), 'r').readlines()
1523 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1526 # Insert a record for file
1528 Filename
= NormPath(self
.MetaFile
)
1529 FileID
= self
.TblFile
.GetFileId(Filename
)
1531 self
.FileID
= FileID
1533 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_DEC
)
1535 for Index
in range(0, len(Content
)):
1536 Line
, Comment
= CleanString2(Content
[Index
])
1537 self
._CurrentLine
= Line
1538 self
._LineIndex
= Index
1540 # save comment for later use
1542 self
._Comments
.append((Comment
, self
._LineIndex
+1))
1548 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1549 self
._SectionHeaderParser
()
1552 elif len(self
._SectionType
) == 0:
1557 self
._ValueList
= ['', '', '']
1558 self
._SectionParser
[self
._SectionType
[0]](self
)
1559 if self
._ValueList
is None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
1565 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1566 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1568 for Arch
, ModuleType
, Type
in self
._Scope
:
1569 self
._LastItem
= self
._Store
(
1584 for Comment
, LineNo
in self
._Comments
:
1586 MODEL_META_DATA_COMMENT
,
1603 def _GetApplicableSectionMacro(self
):
1605 for S1
, S2
, SectionType
in self
._Scope
:
1606 for Scope1
, Scope2
in [("COMMON", "COMMON"), ("COMMON", S2
), (S1
, "COMMON"), (S1
, S2
)]:
1607 if (SectionType
, Scope1
, Scope2
) in self
._SectionsMacroDict
:
1608 Macros
.update(self
._SectionsMacroDict
[(SectionType
, Scope1
, Scope2
)])
1611 ## Section header parser
1613 # The section header is always in following format:
1615 # [section_name.arch<.platform|module_type>]
1617 def _SectionHeaderParser(self
):
1619 self
._SectionName
= ''
1620 self
._SectionType
= []
1622 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
1625 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
)
1627 # different types of PCD are permissible in one section
1628 self
._SectionName
= ItemList
[0].upper()
1629 if self
._SectionName
in self
.DataType
:
1630 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1631 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1633 EdkLogger
.warn("Parser", "Unrecognized section", File
=self
.MetaFile
,
1634 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
1637 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1641 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1643 Line
=self
._LineIndex
+1,
1644 ExtraData
=self
._CurrentLine
1647 if len(ItemList
) > 1:
1648 S1
= ItemList
[1].upper()
1652 # S2 may be Platform or ModuleType
1653 if len(ItemList
) > 2:
1654 S2
= ItemList
[2].upper()
1657 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1658 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1660 # 'COMMON' must not be used with specific ARCHs at the same section
1661 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1662 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1663 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
1665 ## [guids], [ppis] and [protocols] section parser
1667 def _GuidParser(self
):
1668 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1669 if len(TokenList
) < 2:
1670 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1671 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1672 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1673 if TokenList
[0] == '':
1674 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1675 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1676 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1677 if TokenList
[1] == '':
1678 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1679 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1680 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1681 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1682 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1683 ExtraData
=self
._CurrentLine
+ \
1684 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1685 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1686 self
._ValueList
[0] = TokenList
[0]
1687 #Parse the Guid value format
1688 GuidValueList
= TokenList
[1].strip(' {}').split(',')
1691 if len(GuidValueList
) == 11:
1692 for GuidValue
in GuidValueList
:
1693 GuidValue
= GuidValue
.strip()
1694 if GuidValue
.startswith('0x') or GuidValue
.startswith('0X'):
1695 HexList
.append('0x' + str(GuidValue
[2:]))
1699 if GuidValue
.startswith('{'):
1700 GuidValue
= GuidValue
.lstrip(' {')
1701 HexList
.append('0x' + str(GuidValue
[2:]))
1703 self
._ValueList
[1] = "{ %s, %s, %s, { %s, %s, %s, %s, %s, %s, %s, %s }}" % (HexList
[0], HexList
[1], HexList
[2], HexList
[3], HexList
[4], HexList
[5], HexList
[6], HexList
[7], HexList
[8], HexList
[9], HexList
[10])
1705 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1706 ExtraData
=self
._CurrentLine
+ \
1707 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1708 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1709 self
._ValueList
[0] = ''
1711 def ParsePcdName(self
,namelist
):
1712 if "[" in namelist
[1]:
1713 pcdname
= namelist
[1][:namelist
[1].index("[")]
1714 arrayindex
= namelist
[1][namelist
[1].index("["):]
1715 namelist
[1] = pcdname
1716 if len(namelist
) == 2:
1717 namelist
.append(arrayindex
)
1719 namelist
[2] = ".".join((arrayindex
,namelist
[2]))
1722 def StructPcdParser(self
):
1723 self
._ValueList
[0] = self
._CurrentStructurePcdName
1725 if "|" not in self
._CurrentLine
:
1726 if "<HeaderFiles>" == self
._CurrentLine
:
1727 self
._include
_flag
= True
1728 self
._package
_flag
= False
1729 self
._ValueList
= None
1731 if "<Packages>" == self
._CurrentLine
:
1732 self
._package
_flag
= True
1733 self
._ValueList
= None
1734 self
._include
_flag
= False
1737 if self
._include
_flag
:
1738 self
._ValueList
[1] = "<HeaderFiles>_" + md5(self
._CurrentLine
.encode('utf-8')).hexdigest()
1739 self
._ValueList
[2] = self
._CurrentLine
1740 if self
._package
_flag
and "}" != self
._CurrentLine
:
1741 self
._ValueList
[1] = "<Packages>_" + md5(self
._CurrentLine
.encode('utf-8')).hexdigest()
1742 self
._ValueList
[2] = self
._CurrentLine
1743 if self
._CurrentLine
== "}":
1744 self
._package
_flag
= False
1745 self
._include
_flag
= False
1746 self
._ValueList
= None
1748 PcdTockens
= self
._CurrentLine
.split(TAB_VALUE_SPLIT
)
1749 PcdNames
= self
.ParsePcdName(PcdTockens
[0].split(TAB_SPLIT
))
1750 if len(PcdNames
) == 2:
1751 if PcdNames
[1].strip().endswith("]"):
1752 PcdName
= PcdNames
[1][:PcdNames
[1].index('[')]
1753 Index
= PcdNames
[1][PcdNames
[1].index('['):]
1754 self
._ValueList
[0] = TAB_SPLIT
.join((PcdNames
[0], PcdName
))
1755 self
._ValueList
[1] = Index
1756 self
._ValueList
[2] = PcdTockens
[1]
1758 self
._CurrentStructurePcdName
= ""
1760 if self
._CurrentStructurePcdName
!= TAB_SPLIT
.join(PcdNames
[:2]):
1761 EdkLogger
.error('Parser', FORMAT_INVALID
, "Pcd Name does not match: %s and %s " % (
1762 self
._CurrentStructurePcdName
, TAB_SPLIT
.join(PcdNames
[:2])),
1763 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1764 self
._ValueList
[1] = TAB_SPLIT
.join(PcdNames
[2:])
1765 self
._ValueList
[2] = PcdTockens
[1]
1767 ## PCD sections parser
1769 # [PcdsFixedAtBuild]
1770 # [PcdsPatchableInModule]
1776 def _PcdParser(self
):
1777 if self
._CurrentStructurePcdName
:
1778 self
.StructPcdParser()
1780 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1781 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1782 # check PCD information
1783 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1784 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1785 ExtraData
=self
._CurrentLine
+ \
1786 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1787 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1788 # check PCD datum information
1789 if len(TokenList
) < 2 or TokenList
[1] == '':
1790 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1791 ExtraData
=self
._CurrentLine
+ \
1792 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1793 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1796 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1797 PtrValue
= ValueRe
.findall(TokenList
[1])
1799 # Has VOID* type string, may contain "|" character in the string.
1800 if len(PtrValue
) != 0:
1801 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1802 ValueList
= GetSplitValueList(ptrValueList
)
1803 ValueList
[0] = PtrValue
[0]
1805 ValueList
= GetSplitValueList(TokenList
[1])
1808 # check if there's enough datum information given
1809 if len(ValueList
) != 3:
1810 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1811 ExtraData
=self
._CurrentLine
+ \
1812 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1813 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1814 # check default value
1815 if ValueList
[0] == '':
1816 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1817 ExtraData
=self
._CurrentLine
+ \
1818 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1819 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1821 if ValueList
[1] == '':
1822 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1823 ExtraData
=self
._CurrentLine
+ \
1824 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1825 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1826 # check token of the PCD
1827 if ValueList
[2] == '':
1828 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1829 ExtraData
=self
._CurrentLine
+ \
1830 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1831 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1832 # check format of default value against the datum type
1833 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1835 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1836 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1837 if Cause
== "StructurePcd":
1838 self
._CurrentStructurePcdName
= TAB_SPLIT
.join(self
._ValueList
[0:2])
1839 self
._ValueList
[0] = self
._CurrentStructurePcdName
1840 self
._ValueList
[1] = ValueList
[1].strip()
1842 if EccGlobalData
.gConfig
.UniCheckPCDInfo
== '1' or EccGlobalData
.gConfig
.UniCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
1843 # check Description, Prompt information
1844 PatternDesc
= re
.compile('##\s*([\x21-\x7E\s]*)', re
.S
)
1845 PatternPrompt
= re
.compile('#\s+@Prompt\s+([\x21-\x7E\s]*)', re
.S
)
1848 # check @ValidRange, @ValidList and @Expression format valid
1849 ErrorCodeValid
= '0x0 <= %s <= 0xFFFFFFFF'
1850 PatternValidRangeIn
= '(NOT)?\s*(\d+\s*-\s*\d+|0[xX][a-fA-F0-9]+\s*-\s*0[xX][a-fA-F0-9]+|LT\s*\d+|LT\s*0[xX][a-fA-F0-9]+|GT\s*\d+|GT\s*0[xX][a-fA-F0-9]+|LE\s*\d+|LE\s*0[xX][a-fA-F0-9]+|GE\s*\d+|GE\s*0[xX][a-fA-F0-9]+|XOR\s*\d+|XOR\s*0[xX][a-fA-F0-9]+|EQ\s*\d+|EQ\s*0[xX][a-fA-F0-9]+)'
1851 PatternValidRng
= re
.compile('^' + '(NOT)?\s*' + PatternValidRangeIn
+ '$')
1852 for Comment
in self
._Comments
:
1853 Comm
= Comment
[0].strip()
1857 Description
= PatternDesc
.findall(Comm
)
1859 Prompt
= PatternPrompt
.findall(Comm
)
1861 ValidFormt
= Comm
.lstrip('#')
1862 ValidFormt
= ValidFormt
.lstrip()
1863 if ValidFormt
[0:11] == '@ValidRange':
1864 ValidFormt
= ValidFormt
[11:]
1865 ValidFormt
= ValidFormt
.lstrip()
1867 ErrorCode
, Expression
= ValidFormt
.split('|', 1)
1870 Expression
= ValidFormt
1871 ErrorCode
, Expression
= ErrorCode
.strip(), Expression
.strip()
1873 if not eval(ErrorCodeValid
% ErrorCode
):
1874 EdkLogger
.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1876 EdkLogger
.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1877 if not PatternValidRng
.search(Expression
):
1878 EdkLogger
.warn('Parser', '@ValidRange Expression(%s) of PCD %s is incorrect format.' % (Expression
, TokenList
[0]))
1879 if ValidFormt
[0:10] == '@ValidList':
1880 ValidFormt
= ValidFormt
[10:]
1881 ValidFormt
= ValidFormt
.lstrip()
1883 ErrorCode
, Expression
= ValidFormt
.split('|', 1)
1886 Expression
= ValidFormt
1887 ErrorCode
, Expression
= ErrorCode
.strip(), Expression
.strip()
1889 if not eval(ErrorCodeValid
% ErrorCode
):
1890 EdkLogger
.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1892 EdkLogger
.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1893 Values
= Expression
.split(',')
1894 for Value
in Values
:
1895 Value
= Value
.strip()
1899 EdkLogger
.warn('Parser', '@ValidList Expression of PCD %s include a invalid value(%s).' % (TokenList
[0], Value
))
1901 if ValidFormt
[0:11] == '@Expression':
1902 ValidFormt
= ValidFormt
[11:]
1903 ValidFormt
= ValidFormt
.lstrip()
1905 ErrorCode
, Expression
= ValidFormt
.split('|', 1)
1908 Expression
= ValidFormt
1909 ErrorCode
, Expression
= ErrorCode
.strip(), Expression
.strip()
1911 if not eval(ErrorCodeValid
% ErrorCode
):
1912 EdkLogger
.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1914 EdkLogger
.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1916 EdkLogger
.warn('Parser', '@Expression Expression of PCD %s is incorrect format.' % TokenList
[0])
1918 EdkLogger
.warn('Parser', 'PCD %s Description information is not provided.' % TokenList
[0])
1920 EdkLogger
.warn('Parser', 'PCD %s Prompt information is not provided.' % TokenList
[0])
1921 # check Description, Prompt localization information
1923 self
._UniObj
.CheckPcdInfo(TokenList
[0])
1925 if ValueList
[0] in ['True', 'true', 'TRUE']:
1927 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1930 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
1933 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
1934 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
1935 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
1936 MODEL_EFI_GUID
: _GuidParser
,
1937 MODEL_EFI_PPI
: _GuidParser
,
1938 MODEL_EFI_PROTOCOL
: _GuidParser
,
1939 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1940 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1941 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1942 MODEL_PCD_DYNAMIC
: _PcdParser
,
1943 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
1944 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1945 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1951 # This class defined the structure used in Fdf object
1953 # @param Filename: Input value for Ffilename of Fdf file, default is None
1954 # @param WorkspaceDir: Input value for current workspace directory, default is None
1957 def __init__(self
, Filename
= None, IsToDatabase
= False, WorkspaceDir
= None, Database
= None):
1958 self
.WorkspaceDir
= WorkspaceDir
1959 self
.IsToDatabase
= IsToDatabase
1961 self
.Cur
= Database
.Cur
1962 self
.TblFile
= Database
.TblFile
1963 self
.TblFdf
= Database
.TblFdf
1968 # Load Fdf file if filename is not None
1970 if Filename
is not None:
1972 self
.LoadFdfFile(Filename
)
1977 # Insert a FDF file record into database
1979 def InsertFile(self
, Filename
):
1981 Filename
= NormPath(Filename
)
1982 if Filename
not in self
.FileList
:
1983 FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_FDF
)
1984 self
.FileList
[Filename
] = FileID
1986 return self
.FileList
[Filename
]
1991 # Load the file if it exists
1993 # @param Filename: Input value for filename of Fdf file
1995 def LoadFdfFile(self
, Filename
):
2000 Filename
= NormPath(Filename
)
2001 Fdf
= FdfParser(Filename
)
2005 # Insert inf file and pcd information
2007 if self
.IsToDatabase
:
2008 (Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
) = \
2009 (0, '', '', '', 'COMMON', 'COMMON', -1, -1, -1, -1, -1, -1, 0)
2010 for Index
in range(0, len(Fdf
.Profile
.PcdDict
)):
2012 for Key
in Fdf
.Profile
.PcdDict
.keys():
2016 FileName
= Fdf
.Profile
.PcdFileLineDict
[Key
][0]
2017 StartLine
= Fdf
.Profile
.PcdFileLineDict
[Key
][1]
2018 BelongsToFile
= self
.InsertFile(FileName
)
2019 self
.TblFdf
.Insert(Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
)
2020 for Index
in range(0, len(Fdf
.Profile
.InfList
)):
2021 Model
= MODEL_META_DATA_COMPONENT
2022 Value1
= Fdf
.Profile
.InfList
[Index
]
2024 FileName
= Fdf
.Profile
.InfFileLineList
[Index
][0]
2025 StartLine
= Fdf
.Profile
.InfFileLineList
[Index
][1]
2026 BelongsToFile
= self
.InsertFile(FileName
)
2027 self
.TblFdf
.Insert(Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
)
2029 class UniParser(object):
2030 # IsExtraUni defined the UNI file is Module UNI or extra Module UNI
2031 # IsModuleUni defined the UNI file is Module UNI or Package UNI
2032 def __init__(self
, FilePath
, IsExtraUni
=False, IsModuleUni
=True):
2033 self
.FilePath
= FilePath
2034 self
.FileName
= os
.path
.basename(FilePath
)
2035 self
.IsExtraUni
= IsExtraUni
2036 self
.IsModuleUni
= IsModuleUni
2043 self
.FileIn
= CodecOpenLongFilePath(self
.FilePath
, Mode
='rb', Encoding
='utf_8').read()
2044 except UnicodeError:
2045 self
.FileIn
= CodecOpenLongFilePath(self
.FilePath
, Mode
='rb', Encoding
='utf_16').read()
2046 except UnicodeError:
2047 self
.FileIn
= CodecOpenLongFilePath(self
.FilePath
, Mode
='rb', Encoding
='utf_16_le').read()
2052 if self
.IsModuleUni
:
2054 ModuleName
= self
.CheckKeyValid('STR_PROPERTIES_MODULE_NAME')
2055 self
.PrintLog('STR_PROPERTIES_MODULE_NAME', ModuleName
)
2057 ModuleAbstract
= self
.CheckKeyValid('STR_MODULE_ABSTRACT')
2058 self
.PrintLog('STR_MODULE_ABSTRACT', ModuleAbstract
)
2059 ModuleDescription
= self
.CheckKeyValid('STR_MODULE_DESCRIPTION')
2060 self
.PrintLog('STR_MODULE_DESCRIPTION', ModuleDescription
)
2063 PackageName
= self
.CheckKeyValid('STR_PROPERTIES_PACKAGE_NAME')
2064 self
.PrintLog('STR_PROPERTIES_PACKAGE_NAME', PackageName
)
2066 PackageAbstract
= self
.CheckKeyValid('STR_PACKAGE_ABSTRACT')
2067 self
.PrintLog('STR_PACKAGE_ABSTRACT', PackageAbstract
)
2068 PackageDescription
= self
.CheckKeyValid('STR_PACKAGE_DESCRIPTION')
2069 self
.PrintLog('STR_PACKAGE_DESCRIPTION', PackageDescription
)
2071 def CheckKeyValid(self
, Key
, Contents
=None):
2073 Contents
= self
.FileIn
2074 KeyPattern
= re
.compile('#string\s+%s\s+.*?#language.*?".*?"' % Key
, re
.S
)
2075 if KeyPattern
.search(Contents
):
2079 def CheckPcdInfo(self
, PcdCName
):
2080 PromptKey
= 'STR_%s_PROMPT' % PcdCName
.replace('.', '_')
2081 PcdPrompt
= self
.CheckKeyValid(PromptKey
)
2082 self
.PrintLog(PromptKey
, PcdPrompt
)
2083 HelpKey
= 'STR_%s_HELP' % PcdCName
.replace('.', '_')
2084 PcdHelp
= self
.CheckKeyValid(HelpKey
)
2085 self
.PrintLog(HelpKey
, PcdHelp
)
2087 def PrintLog(self
, Key
, Value
):
2088 if not Value
and Key
not in self
.Missing
:
2089 Msg
= '%s is missing in the %s file.' % (Key
, self
.FileName
)
2090 EdkLogger
.warn('Parser', Msg
)
2091 EccGlobalData
.gDb
.TblReport
.Insert(EccToolError
.ERROR_GENERAL_CHECK_UNI_HELP_INFO
, OtherMsg
=Msg
, BelongsToTable
='File', BelongsToItem
=-2)
2092 self
.Missing
.append(Key
)
2096 # This acts like the main() function for the script, unless it is 'import'ed into another
2099 if __name__
== '__main__':