2 # This file is used to parse meta files
4 # Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 from __future__
import absolute_import
18 import Common
.LongFilePathOs
as os
23 import Common
.EdkLogger
as EdkLogger
24 import Common
.GlobalData
as GlobalData
25 import Ecc
.EccGlobalData
as EccGlobalData
26 import Ecc
.EccToolError
as EccToolError
28 from CommonDataClass
.DataClass
import *
29 from Common
.DataType
import *
30 from Common
.StringUtils
import *
31 from Common
.Misc
import GuidStructureStringToGuidString
, CheckPcdDatum
, PathClass
, AnalyzePcdData
32 from Common
.Expression
import *
33 from CommonDataClass
.Exceptions
import *
35 from Ecc
.MetaFileWorkspace
.MetaFileTable
import MetaFileStorage
36 from GenFds
.FdfParser
import FdfParser
37 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
38 from Common
.LongFilePathSupport
import CodecOpenLongFilePath
40 ## A decorator used to parse macro definition
41 def ParseMacro(Parser
):
42 def MacroParser(self
):
43 Match
= gMacroDefPattern
.match(self
._CurrentLine
)
45 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
49 TokenList
= GetSplitValueList(self
._CurrentLine
[Match
.end(1):], TAB_EQUAL_SPLIT
, 1)
52 EdkLogger
.error('Parser', FORMAT_INVALID
, "No macro name given",
53 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
54 if len(TokenList
) < 2:
58 Name
, Value
= TokenList
59 # Global macros can be only defined via environment variable
60 if Name
in GlobalData
.gGlobalDefines
:
61 EdkLogger
.error('Parser', FORMAT_INVALID
, "%s can only be defined via environment variable" % Name
,
62 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
63 # Only upper case letters, digit and '_' are allowed
64 if not gMacroNamePattern
.match(Name
):
65 EdkLogger
.error('Parser', FORMAT_INVALID
, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
66 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
68 Value
= ReplaceMacro(Value
, self
._Macros
)
69 self
._ItemType
= MODEL_META_DATA_DEFINE
70 # DEFINE defined macros
71 if Type
== TAB_DSC_DEFINES_DEFINE
:
72 if isinstance(self
, DecParser
):
73 if MODEL_META_DATA_HEADER
in self
._SectionType
:
74 self
._FileLocalMacros
[Name
] = Value
76 for Scope
in self
._Scope
:
77 self
._SectionsMacroDict
.setdefault((Scope
[2], Scope
[0], Scope
[1]), {})[Name
] = Value
78 elif self
._SectionType
== MODEL_META_DATA_HEADER
:
79 self
._FileLocalMacros
[Name
] = Value
81 SectionDictKey
= self
._SectionType
, self
._Scope
[0][0], self
._Scope
[0][1]
82 if SectionDictKey
not in self
._SectionsMacroDict
:
83 self
._SectionsMacroDict
[SectionDictKey
] = {}
84 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
85 SectionLocalMacros
[Name
] = Value
86 # EDK_GLOBAL defined macros
87 elif not isinstance(self
, DscParser
):
88 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used in .dsc file",
89 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
90 elif self
._SectionType
!= MODEL_META_DATA_HEADER
:
91 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used under [Defines] section",
92 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
93 elif (Name
in self
._FileLocalMacros
) and (self
._FileLocalMacros
[Name
] != Value
):
94 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
95 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
97 self
._ValueList
= [Type
, Name
, Value
]
101 ## Base class of parser
103 # This class is used for derivation purpose. The specific parser for one kind
104 # type file must derive this class and implement some public interfaces.
106 # @param FilePath The path of platform description file
107 # @param FileType The raw data of DSC file
108 # @param Table Database used to retrieve module/package information
109 # @param Macros Macros used for replacement in file
110 # @param Owner Owner ID (for sub-section parsing)
111 # @param From ID from which the data comes (for !INCLUDE directive)
113 class MetaFileParser(object):
114 # data type (file content) for specific file type
117 # Parser objects used to implement singleton
122 # One file, one parser object. This factory method makes sure that there's
123 # only one object constructed for one meta file.
125 # @param Class class object of real AutoGen class
126 # (InfParser, DecParser or DscParser)
127 # @param FilePath The path of meta file
128 # @param *args The specific class related parameters
129 # @param **kwargs The specific class related dict parameters
131 def __new__(Class
, FilePath
, *args
, **kwargs
):
132 if FilePath
in Class
.MetaFiles
:
133 return Class
.MetaFiles
[FilePath
]
135 ParserObject
= super(MetaFileParser
, Class
).__new
__(Class
)
136 Class
.MetaFiles
[FilePath
] = ParserObject
139 ## Constructor of MetaFileParser
141 # Initialize object of MetaFileParser
143 # @param FilePath The path of platform description file
144 # @param FileType The raw data of DSC file
145 # @param Table Database used to retrieve module/package information
146 # @param Macros Macros used for replacement in file
147 # @param Owner Owner ID (for sub-section parsing)
148 # @param From ID from which the data comes (for !INCLUDE directive)
150 def __init__(self
, FilePath
, FileType
, Table
, Owner
=-1, From
=-1):
152 self
._RawTable
= Table
153 self
._FileType
= FileType
154 self
.MetaFile
= FilePath
156 self
._FileLocalMacros
= {}
157 self
._SectionsMacroDict
= {}
159 # for recursive parsing
160 self
._Owner
= [Owner
]
163 # parsr status for parsing
164 self
._ValueList
= ['', '', '', '', '']
167 self
._CurrentLine
= ''
168 self
._SectionType
= MODEL_UNKNOWN
169 self
._SectionName
= ''
170 self
._InSubsection
= False
171 self
._SubsectionType
= MODEL_UNKNOWN
172 self
._SubsectionName
= ''
173 self
._ItemType
= MODEL_UNKNOWN
176 self
._Finished
= False
177 self
._PostProcessed
= False
178 # Different version of meta-file has different way to parse.
180 # UNI object and extra UNI object
182 self
._UniExtraObj
= None
184 ## Store the parsed data in table
185 def _Store(self
, *Args
):
186 return self
._Table
.Insert(*Args
)
188 ## Virtual method for starting parse
190 raise NotImplementedError
192 ## Notify a post-process is needed
193 def DoPostProcess(self
):
194 self
._PostProcessed
= False
196 ## Set parsing complete flag in both class and table
198 self
._Finished
= True
199 ## Do not set end flag when processing included files
201 self
._Table
.SetEndFlag()
203 def _PostProcess(self
):
204 self
._PostProcessed
= True
206 ## Get the parse complete flag
207 def _GetFinished(self
):
208 return self
._Finished
210 ## Set the complete flag
211 def _SetFinished(self
, Value
):
212 self
._Finished
= Value
214 ## Use [] style to query data in table, just for readability
216 # DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]
218 def __getitem__(self
, DataInfo
):
219 if not isinstance(DataInfo
, type(())):
220 DataInfo
= (DataInfo
,)
222 # Parse the file first, if necessary
223 if not self
._Finished
:
224 if self
._RawTable
.IsIntegrity():
225 self
._Finished
= True
227 self
._Table
= self
._RawTable
228 self
._PostProcessed
= False
231 # No specific ARCH or Platform given, use raw data
232 if self
._RawTable
and (len(DataInfo
) == 1 or DataInfo
[1] is None):
233 return self
._RawTable
.Query(*DataInfo
)
235 # Do post-process if necessary
236 if not self
._PostProcessed
:
239 return self
._Table
.Query(*DataInfo
)
241 ## Data parser for the common format in different type of file
243 # The common format in the meatfile is like
248 def _CommonParser(self
):
249 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
250 self
._ValueList
[0:len(TokenList
)] = TokenList
252 ## Data parser for the format in which there's path
254 # Only path can have macro used. So we need to replace them before use.
257 def _PathParser(self
):
258 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
259 self
._ValueList
[0:len(TokenList
)] = TokenList
260 # Don't do macro replacement for dsc file at this point
261 if not isinstance(self
, DscParser
):
262 Macros
= self
._Macros
263 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
265 ## Skip unsupported data
267 if self
._SectionName
== TAB_USER_EXTENSIONS
.upper() and self
._CurrentLine
.upper().endswith('.UNI'):
268 if EccGlobalData
.gConfig
.UniCheckHelpInfo
== '1' or EccGlobalData
.gConfig
.UniCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
269 ExtraUni
= self
._CurrentLine
.strip()
270 ExtraUniFile
= os
.path
.join(os
.path
.dirname(self
.MetaFile
), ExtraUni
)
271 IsModuleUni
= self
.MetaFile
.upper().endswith('.INF')
272 self
._UniExtraObj
= UniParser(ExtraUniFile
, IsExtraUni
=True, IsModuleUni
=IsModuleUni
)
273 self
._UniExtraObj
.Start()
275 EdkLogger
.warn("Parser", "Unrecognized content", File
=self
.MetaFile
,
276 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
);
277 self
._ValueList
[0:1] = [self
._CurrentLine
]
279 ## Section header parser
281 # The section header is always in following format:
283 # [section_name.arch<.platform|module_type>]
285 def _SectionHeaderParser(self
):
287 self
._SectionName
= ''
289 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
292 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
)
293 # different section should not mix in one section
294 if self
._SectionName
!= '' and self
._SectionName
!= ItemList
[0].upper():
295 EdkLogger
.error('Parser', FORMAT_INVALID
, "Different section names in the same section",
296 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
297 self
._SectionName
= ItemList
[0].upper()
298 if self
._SectionName
in self
.DataType
:
299 self
._SectionType
= self
.DataType
[self
._SectionName
]
301 self
._SectionType
= MODEL_UNKNOWN
302 EdkLogger
.warn("Parser", "Unrecognized section", File
=self
.MetaFile
,
303 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
305 if len(ItemList
) > 1:
306 S1
= ItemList
[1].upper()
310 # S2 may be Platform or ModuleType
311 if len(ItemList
) > 2:
312 S2
= ItemList
[2].upper()
315 self
._Scope
.append([S1
, S2
])
317 # 'COMMON' must not be used with specific ARCHs at the same section
318 if 'COMMON' in ArchList
and len(ArchList
) > 1:
319 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
320 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
321 # If the section information is needed later, it should be stored in database
322 self
._ValueList
[0] = self
._SectionName
324 ## [defines] section parser
326 def _DefineParser(self
):
327 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
328 self
._ValueList
[1:len(TokenList
)] = TokenList
329 if not self
._ValueList
[1]:
330 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
331 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
332 if not self
._ValueList
[2]:
333 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
334 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
336 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
337 Name
, Value
= self
._ValueList
[1], self
._ValueList
[2]
338 # Sometimes, we need to make differences between EDK and EDK2 modules
339 if Name
== 'INF_VERSION':
341 self
._Version
= int(Value
, 0)
343 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid version number",
344 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
345 elif Name
== 'MODULE_UNI_FILE':
346 UniFile
= os
.path
.join(os
.path
.dirname(self
.MetaFile
), Value
)
347 if os
.path
.exists(UniFile
):
348 self
._UniObj
= UniParser(UniFile
, IsExtraUni
=False, IsModuleUni
=True)
351 EdkLogger
.error('Parser', FILE_NOT_FOUND
, "Module UNI file %s is missing." % Value
,
352 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
354 elif Name
== 'PACKAGE_UNI_FILE':
355 UniFile
= os
.path
.join(os
.path
.dirname(self
.MetaFile
), Value
)
356 if os
.path
.exists(UniFile
):
357 self
._UniObj
= UniParser(UniFile
, IsExtraUni
=False, IsModuleUni
=False)
359 if isinstance(self
, InfParser
) and self
._Version
< 0x00010005:
360 # EDK module allows using defines as macros
361 self
._FileLocalMacros
[Name
] = Value
362 self
._Defines
[Name
] = Value
364 ## [BuildOptions] section parser
366 def _BuildOptionParser(self
):
367 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
368 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
369 if len(TokenList2
) == 2:
370 self
._ValueList
[0] = TokenList2
[0] # toolchain family
371 self
._ValueList
[1] = TokenList2
[1] # keys
373 self
._ValueList
[1] = TokenList
[0]
374 if len(TokenList
) == 2 and not isinstance(self
, DscParser
): # value
375 self
._ValueList
[2] = ReplaceMacro(TokenList
[1], self
._Macros
)
377 if self
._ValueList
[1].count('_') != 4:
381 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
382 ExtraData
=self
._CurrentLine
,
384 Line
=self
._LineIndex
+1
387 def _GetMacros(self
):
389 Macros
.update(self
._FileLocalMacros
)
390 Macros
.update(self
._GetApplicableSectionMacro
())
394 ## Get section Macros that are applicable to current line, which may come from other sections
395 ## that share the same name while scope is wider
396 def _GetApplicableSectionMacro(self
):
398 for Scope1
, Scope2
in [("COMMON", "COMMON"), ("COMMON", self
._Scope
[0][1]),
399 (self
._Scope
[0][0], "COMMON"), (self
._Scope
[0][0], self
._Scope
[0][1])]:
400 if (self
._SectionType
, Scope1
, Scope2
) in self
._SectionsMacroDict
:
401 Macros
.update(self
._SectionsMacroDict
[(self
._SectionType
, Scope1
, Scope2
)])
405 Finished
= property(_GetFinished
, _SetFinished
)
406 _Macros
= property(_GetMacros
)
409 ## INF file parser class
411 # @param FilePath The path of platform description file
412 # @param FileType The raw data of DSC file
413 # @param Table Database used to retrieve module/package information
414 # @param Macros Macros used for replacement in file
416 class InfParser(MetaFileParser
):
417 # INF file supported data types (one type per section)
419 TAB_UNKNOWN
.upper() : MODEL_UNKNOWN
,
420 TAB_INF_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
421 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
422 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
423 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
424 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
425 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
426 TAB_PACKAGES
.upper() : MODEL_META_DATA_PACKAGE
,
427 TAB_NMAKE
.upper() : MODEL_META_DATA_NMAKE
,
428 TAB_INF_FIXED_PCD
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
429 TAB_INF_PATCH_PCD
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
430 TAB_INF_FEATURE_PCD
.upper() : MODEL_PCD_FEATURE_FLAG
,
431 TAB_INF_PCD_EX
.upper() : MODEL_PCD_DYNAMIC_EX
,
432 TAB_INF_PCD
.upper() : MODEL_PCD_DYNAMIC
,
433 TAB_SOURCES
.upper() : MODEL_EFI_SOURCE_FILE
,
434 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
435 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
436 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
437 TAB_DEPEX
.upper() : MODEL_EFI_DEPEX
,
438 TAB_BINARIES
.upper() : MODEL_EFI_BINARY_FILE
,
439 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
442 ## Constructor of InfParser
444 # Initialize object of InfParser
446 # @param FilePath The path of module description file
447 # @param FileType The raw data of DSC file
448 # @param Table Database used to retrieve module/package information
449 # @param Macros Macros used for replacement in file
451 def __init__(self
, FilePath
, FileType
, Table
):
452 # prevent re-initialization
453 if hasattr(self
, "_Table"):
455 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
456 self
.TblFile
= EccGlobalData
.gDb
.TblFile
465 Content
= open(str(self
.MetaFile
), 'r').readlines()
467 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
469 # Insert a record for file
471 Filename
= NormPath(self
.MetaFile
)
472 FileID
= self
.TblFile
.GetFileId(Filename
)
476 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_INF
)
478 # parse the file line by line
479 IsFindBlockComment
= False
481 for Index
in range(0, len(Content
)):
482 if self
._SectionType
in [MODEL_EFI_GUID
,
485 MODEL_PCD_FIXED_AT_BUILD
,
486 MODEL_PCD_PATCHABLE_IN_MODULE
,
487 MODEL_PCD_FEATURE_FLAG
,
488 MODEL_PCD_DYNAMIC_EX
,
490 Line
= Content
[Index
].strip()
491 if Line
.startswith(TAB_SPECIAL_COMMENT
):
492 Usage
+= ' ' + Line
[Line
.find(TAB_SPECIAL_COMMENT
):]
494 elif Line
.startswith(TAB_COMMENT_SPLIT
):
496 elif Line
.find(TAB_COMMENT_SPLIT
) > 0:
497 Usage
+= ' ' + Line
[Line
.find(TAB_COMMENT_SPLIT
):]
498 Line
= Line
[:Line
.find(TAB_COMMENT_SPLIT
)]
500 # skip empty, commented, block commented lines
501 Line
= CleanString(Content
[Index
], AllowCppStyleComment
=True)
504 if Index
+ 1 < len(Content
):
505 NextLine
= CleanString(Content
[Index
+ 1])
508 if Line
.find(DataType
.TAB_COMMENT_EDK_START
) > -1:
509 IsFindBlockComment
= True
511 if Line
.find(DataType
.TAB_COMMENT_EDK_END
) > -1:
512 IsFindBlockComment
= False
514 if IsFindBlockComment
:
517 self
._LineIndex
= Index
518 self
._CurrentLine
= Line
521 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
522 self
._SectionHeaderParser
()
523 # Check invalid sections
524 if self
._Version
< 0x00010005:
525 if self
._SectionType
in [MODEL_META_DATA_BUILD_OPTION
,
526 MODEL_EFI_LIBRARY_CLASS
,
527 MODEL_META_DATA_PACKAGE
,
528 MODEL_PCD_FIXED_AT_BUILD
,
529 MODEL_PCD_PATCHABLE_IN_MODULE
,
530 MODEL_PCD_FEATURE_FLAG
,
531 MODEL_PCD_DYNAMIC_EX
,
536 MODEL_META_DATA_USER_EXTENSION
]:
537 EdkLogger
.error('Parser', FORMAT_INVALID
,
538 "Section [%s] is not allowed in inf file without version" % (self
._SectionName
),
539 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
540 elif self
._SectionType
in [MODEL_EFI_INCLUDE
,
541 MODEL_EFI_LIBRARY_INSTANCE
,
542 MODEL_META_DATA_NMAKE
]:
543 EdkLogger
.error('Parser', FORMAT_INVALID
,
544 "Section [%s] is not allowed in inf file with version 0x%08x" % (self
._SectionName
, self
._Version
),
545 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
547 # merge two lines specified by '\' in section NMAKE
548 elif self
._SectionType
== MODEL_META_DATA_NMAKE
:
551 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
554 if NextLine
[0] == TAB_SECTION_START
and NextLine
[-1] == TAB_SECTION_END
:
555 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
558 NmakeLine
= NmakeLine
+ ' ' + Line
[0:-1]
561 self
._CurrentLine
= NmakeLine
+ Line
565 self
._ValueList
= ['', '', '']
566 # parse current line, result will be put in self._ValueList
567 self
._SectionParser
[self
._SectionType
](self
)
568 if self
._ValueList
is None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
572 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
573 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
575 self
._ValueList
[0] = self
._ValueList
[0].replace('/', '\\')
576 Usage
= Usage
.strip()
577 for Arch
, Platform
in self
._Scope
:
578 self
._Store
(self
._SectionType
,
594 if IsFindBlockComment
:
595 EdkLogger
.error("Parser", FORMAT_INVALID
, "Open block comments (starting with /*) are expected to end with */",
599 ## Data parser for the format in which there's path
601 # Only path can have macro used. So we need to replace them before use.
603 def _IncludeParser(self
):
604 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
605 self
._ValueList
[0:len(TokenList
)] = TokenList
606 Macros
= self
._Macros
608 for Index
in range(0, len(self
._ValueList
)):
609 Value
= self
._ValueList
[Index
]
613 if Value
.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value
.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
614 Value
= '$(EDK_SOURCE)' + Value
[17:]
615 if Value
.find('$(EFI_SOURCE)') > -1 or Value
.find('$(EDK_SOURCE)') > -1:
617 elif Value
.startswith('.'):
619 elif Value
.startswith('$('):
622 Value
= '$(EFI_SOURCE)/' + Value
624 self
._ValueList
[Index
] = ReplaceMacro(Value
, Macros
)
626 ## Parse [Sources] section
628 # Only path can have macro used. So we need to replace them before use.
631 def _SourceFileParser(self
):
632 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
633 self
._ValueList
[0:len(TokenList
)] = TokenList
634 Macros
= self
._Macros
635 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
636 if 'COMPONENT_TYPE' in Macros
:
637 if self
._Defines
['COMPONENT_TYPE'].upper() == 'ACPITABLE':
638 self
._ValueList
[0] = GetSplitValueList(self
._ValueList
[0], ' ', 1)[0]
639 if self
._Defines
['BASE_NAME'] == 'Microcode':
641 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
643 ## Parse [Binaries] section
645 # Only path can have macro used. So we need to replace them before use.
648 def _BinaryFileParser(self
):
649 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 2)
650 if len(TokenList
) < 2:
651 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type or path specified",
652 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
653 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
655 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type specified",
656 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
657 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
659 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file path specified",
660 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
661 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
662 self
._ValueList
[0:len(TokenList
)] = TokenList
663 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
665 ## [nmake] section parser (Edk.x style only)
666 def _NmakeParser(self
):
667 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
668 self
._ValueList
[0:len(TokenList
)] = TokenList
670 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
671 # remove self-reference in macro setting
672 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
674 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
676 def _PcdParser(self
):
677 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
678 ValueList
= GetSplitValueList(TokenList
[0], TAB_SPLIT
)
679 if len(ValueList
) != 2:
680 EdkLogger
.error('Parser', FORMAT_INVALID
, "Illegal token space GUID and PCD name format",
681 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
682 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
683 self
._ValueList
[0:1] = ValueList
684 if len(TokenList
) > 1:
685 self
._ValueList
[2] = TokenList
[1]
686 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
687 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
688 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
689 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
691 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
692 if self
._ValueList
[2] != '':
693 InfPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
694 if InfPcdValueList
[0] in ['True', 'true', 'TRUE']:
695 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '1', 1);
696 elif InfPcdValueList
[0] in ['False', 'false', 'FALSE']:
697 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '0', 1);
699 ## [depex] section parser
701 def _DepexParser(self
):
702 self
._ValueList
[0:1] = [self
._CurrentLine
]
705 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
706 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
707 MODEL_META_DATA_BUILD_OPTION
: MetaFileParser
._BuildOptionParser
,
708 MODEL_EFI_INCLUDE
: _IncludeParser
, # for Edk.x modules
709 MODEL_EFI_LIBRARY_INSTANCE
: MetaFileParser
._CommonParser
, # for Edk.x modules
710 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
711 MODEL_META_DATA_PACKAGE
: MetaFileParser
._PathParser
,
712 MODEL_META_DATA_NMAKE
: _NmakeParser
, # for Edk.x modules
713 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
714 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
715 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
716 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
717 MODEL_PCD_DYNAMIC
: _PcdParser
,
718 MODEL_EFI_SOURCE_FILE
: _SourceFileParser
,
719 MODEL_EFI_GUID
: MetaFileParser
._CommonParser
,
720 MODEL_EFI_PROTOCOL
: MetaFileParser
._CommonParser
,
721 MODEL_EFI_PPI
: MetaFileParser
._CommonParser
,
722 MODEL_EFI_DEPEX
: _DepexParser
,
723 MODEL_EFI_BINARY_FILE
: _BinaryFileParser
,
724 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
727 ## DSC file parser class
729 # @param FilePath The path of platform description file
730 # @param FileType The raw data of DSC file
731 # @param Table Database used to retrieve module/package information
732 # @param Macros Macros used for replacement in file
733 # @param Owner Owner ID (for sub-section parsing)
734 # @param From ID from which the data comes (for !INCLUDE directive)
736 class DscParser(MetaFileParser
):
737 # DSC file supported data types (one type per section)
739 TAB_SKUIDS
.upper() : MODEL_EFI_SKU_ID
,
740 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
741 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
742 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
743 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
744 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
745 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
746 TAB_PCDS_DYNAMIC_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_DEFAULT
,
747 TAB_PCDS_DYNAMIC_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_HII
,
748 TAB_PCDS_DYNAMIC_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_VPD
,
749 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT
,
750 TAB_PCDS_DYNAMIC_EX_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_HII
,
751 TAB_PCDS_DYNAMIC_EX_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_VPD
,
752 TAB_COMPONENTS
.upper() : MODEL_META_DATA_COMPONENT
,
753 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH
.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
,
754 TAB_DSC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
755 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
756 TAB_DSC_DEFINES_EDKGLOBAL
: MODEL_META_DATA_GLOBAL_DEFINE
,
757 TAB_INCLUDE
.upper() : MODEL_META_DATA_INCLUDE
,
758 TAB_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
759 TAB_IF_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
760 TAB_IF_N_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
,
761 TAB_ELSE_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
,
762 TAB_ELSE
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
763 TAB_END_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
,
764 TAB_ERROR
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR
,
767 # Valid names in define section
774 "PCD_INFO_GENERATION",
775 "SUPPORTED_ARCHITECTURES",
784 "FIX_LOAD_TOP_MEMORY_ADDRESS"
787 SubSectionDefineKeywords
= [
791 SymbolPattern
= ValueExpression
.SymbolPattern
793 ## Constructor of DscParser
795 # Initialize object of DscParser
797 # @param FilePath The path of platform description file
798 # @param FileType The raw data of DSC file
799 # @param Table Database used to retrieve module/package information
800 # @param Macros Macros used for replacement in file
801 # @param Owner Owner ID (for sub-section parsing)
802 # @param From ID from which the data comes (for !INCLUDE directive)
804 def __init__(self
, FilePath
, FileType
, Table
, Owner
=-1, From
=-1):
805 # prevent re-initialization
806 if hasattr(self
, "_Table"):
808 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, Owner
, From
)
809 self
._Version
= 0x00010005 # Only EDK2 dsc file is supported
810 # to store conditional directive evaluation result
811 self
._DirectiveStack
= []
812 self
._DirectiveEvalStack
= []
815 # Final valid replacable symbols
818 # Map the ID between the original table and new table to track
821 self
._IdMapping
= {-1:-1}
823 self
.TblFile
= EccGlobalData
.gDb
.TblFile
830 Content
= open(str(self
.MetaFile
.Path
), 'r').readlines()
832 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
834 # Insert a record for file
836 Filename
= NormPath(self
.MetaFile
.Path
)
837 FileID
= self
.TblFile
.GetFileId(Filename
)
841 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_DSC
)
844 for Index
in range(0, len(Content
)):
845 Line
= CleanString(Content
[Index
])
850 self
._CurrentLine
= Line
851 self
._LineIndex
= Index
852 if self
._InSubsection
and self
._Owner
[-1] == -1:
853 self
._Owner
.append(self
._LastItem
)
856 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
857 self
._SectionType
= MODEL_META_DATA_SECTION_HEADER
859 elif Line
[0] == '}' and self
._InSubsection
:
860 self
._InSubsection
= False
861 self
._SubsectionType
= MODEL_UNKNOWN
862 self
._SubsectionName
= ''
866 elif Line
[0] == TAB_OPTION_START
and Line
[-1] == TAB_OPTION_END
:
867 self
._SubsectionType
= MODEL_META_DATA_SUBSECTION_HEADER
870 self
._DirectiveParser
()
873 if self
._InSubsection
:
874 SectionType
= self
._SubsectionType
876 SectionType
= self
._SectionType
877 self
._ItemType
= SectionType
879 self
._ValueList
= ['', '', '']
880 self
._SectionParser
[SectionType
](self
)
881 if self
._ValueList
is None:
884 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
885 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
887 for Arch
, ModuleType
in self
._Scope
:
888 self
._LastItem
= self
._Store
(
905 if self
._DirectiveStack
:
906 Type
, Line
, Text
= self
._DirectiveStack
[-1]
907 EdkLogger
.error('Parser', FORMAT_INVALID
, "No matching '!endif' found",
908 ExtraData
=Text
, File
=self
.MetaFile
, Line
=Line
)
911 ## <subsection_header> parser
912 def _SubsectionHeaderParser(self
):
913 self
._SubsectionName
= self
._CurrentLine
[1:-1].upper()
914 if self
._SubsectionName
in self
.DataType
:
915 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
917 self
._SubsectionType
= MODEL_UNKNOWN
918 EdkLogger
.warn("Parser", "Unrecognized sub-section", File
=self
.MetaFile
,
919 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
920 self
._ValueList
[0] = self
._SubsectionName
922 ## Directive statement parser
923 def _DirectiveParser(self
):
924 self
._ValueList
= ['', '', '']
925 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
926 self
._ValueList
[0:len(TokenList
)] = TokenList
929 DirectiveName
= self
._ValueList
[0].upper()
930 if DirectiveName
not in self
.DataType
:
931 EdkLogger
.error("Parser", FORMAT_INVALID
, "Unknown directive [%s]" % DirectiveName
,
932 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
933 if DirectiveName
in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self
._ValueList
[1] == '':
934 EdkLogger
.error("Parser", FORMAT_INVALID
, "Missing expression",
935 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
936 ExtraData
=self
._CurrentLine
)
938 ItemType
= self
.DataType
[DirectiveName
]
939 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
940 # Remove all directives between !if and !endif, including themselves
941 while self
._DirectiveStack
:
942 # Remove any !else or !elseif
943 DirectiveInfo
= self
._DirectiveStack
.pop()
944 if DirectiveInfo
[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
945 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
946 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
949 EdkLogger
.error("Parser", FORMAT_INVALID
, "Redundant '!endif'",
950 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
951 ExtraData
=self
._CurrentLine
)
952 elif ItemType
!= MODEL_META_DATA_INCLUDE
:
953 # Break if there's a !else is followed by a !elseif
954 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
and \
955 self
._DirectiveStack
and \
956 self
._DirectiveStack
[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
957 EdkLogger
.error("Parser", FORMAT_INVALID
, "'!elseif' after '!else'",
958 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
959 ExtraData
=self
._CurrentLine
)
960 self
._DirectiveStack
.append((ItemType
, self
._LineIndex
+1, self
._CurrentLine
))
962 EdkLogger
.error('Parser', FORMAT_INVALID
,
963 "No '!include' allowed in included file",
964 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
,
965 Line
=self
._LineIndex
+1)
968 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
969 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
971 self
._LastItem
= self
._Store
(
988 ## [defines] section parser
990 def _DefineParser(self
):
991 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
992 self
._ValueList
[1:len(TokenList
)] = TokenList
995 if not self
._ValueList
[1]:
996 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
997 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
998 if not self
._ValueList
[2]:
999 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
1000 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1001 if (not self
._ValueList
[1] in self
.DefineKeywords
and
1002 (self
._InSubsection
and self
._ValueList
[1] not in self
.SubSectionDefineKeywords
)):
1003 EdkLogger
.error('Parser', FORMAT_INVALID
,
1004 "Unknown keyword found: %s. "
1005 "If this is a macro you must "
1006 "add it as a DEFINE in the DSC" % self
._ValueList
[1],
1007 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1008 self
._Defines
[self
._ValueList
[1]] = self
._ValueList
[2]
1009 self
._ItemType
= self
.DataType
[TAB_DSC_DEFINES
.upper()]
1012 def _SkuIdParser(self
):
1013 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1014 if len(TokenList
) != 2:
1015 EdkLogger
.error('Parser', FORMAT_INVALID
, "Correct format is '<Integer>|<UiName>'",
1016 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1017 self
._ValueList
[0:len(TokenList
)] = TokenList
1019 ## Parse Edk style of library modules
1020 def _LibraryInstanceParser(self
):
1021 self
._ValueList
[0] = self
._CurrentLine
1023 ## PCD sections parser
1025 # [PcdsFixedAtBuild]
1026 # [PcdsPatchableInModule]
1029 # [PcdsDynamicExDefault]
1030 # [PcdsDynamicExVpd]
1031 # [PcdsDynamicExHii]
1033 # [PcdsDynamicDefault]
1038 def _PcdParser(self
):
1039 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1040 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1041 if len(TokenList
) == 2:
1042 self
._ValueList
[2] = TokenList
[1]
1043 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1044 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1045 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1046 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1047 if self
._ValueList
[2] == '':
1048 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD value given",
1049 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1050 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1051 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1052 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
1053 if DscPcdValueList
[0] in ['True', 'true', 'TRUE']:
1054 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '1', 1);
1055 elif DscPcdValueList
[0] in ['False', 'false', 'FALSE']:
1056 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '0', 1);
1058 ## [components] section parser
1060 def _ComponentParser(self
):
1061 if self
._CurrentLine
[-1] == '{':
1062 self
._ValueList
[0] = self
._CurrentLine
[0:-1].strip()
1063 self
._InSubsection
= True
1065 self
._ValueList
[0] = self
._CurrentLine
1067 ## [LibraryClasses] section
1069 def _LibraryClassParser(self
):
1070 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1071 if len(TokenList
) < 2:
1072 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class or instance specified",
1073 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1074 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1075 if TokenList
[0] == '':
1076 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class specified",
1077 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1078 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1079 if TokenList
[1] == '':
1080 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library instance specified",
1081 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1082 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1084 self
._ValueList
[0:len(TokenList
)] = TokenList
1086 def _CompponentSourceOverridePathParser(self
):
1087 self
._ValueList
[0] = self
._CurrentLine
1089 ## [BuildOptions] section parser
1091 def _BuildOptionParser(self
):
1092 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1093 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
1094 if len(TokenList2
) == 2:
1095 self
._ValueList
[0] = TokenList2
[0] # toolchain family
1096 self
._ValueList
[1] = TokenList2
[1] # keys
1098 self
._ValueList
[1] = TokenList
[0]
1099 if len(TokenList
) == 2: # value
1100 self
._ValueList
[2] = TokenList
[1]
1102 if self
._ValueList
[1].count('_') != 4:
1106 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
1107 ExtraData
=self
._CurrentLine
,
1109 Line
=self
._LineIndex
+1
1112 ## Override parent's method since we'll do all macro replacements in parser
1113 def _GetMacros(self
):
1114 Macros
= dict( [('ARCH', 'IA32'), ('FAMILY', TAB_COMPILER_MSFT
), ('TOOL_CHAIN_TAG', 'VS2008x86'), ('TARGET', 'DEBUG')])
1115 Macros
.update(self
._FileLocalMacros
)
1116 Macros
.update(self
._GetApplicableSectionMacro
())
1117 Macros
.update(GlobalData
.gEdkGlobal
)
1118 Macros
.update(GlobalData
.gPlatformDefines
)
1119 Macros
.update(GlobalData
.gCommandLineDefines
)
1120 # PCD cannot be referenced in macro definition
1121 if self
._ItemType
not in [MODEL_META_DATA_DEFINE
, MODEL_META_DATA_GLOBAL_DEFINE
]:
1122 Macros
.update(self
._Symbols
)
1125 def _PostProcess(self
):
1127 MODEL_META_DATA_SECTION_HEADER
: self
.__ProcessSectionHeader
,
1128 MODEL_META_DATA_SUBSECTION_HEADER
: self
.__ProcessSubsectionHeader
,
1129 MODEL_META_DATA_HEADER
: self
.__ProcessDefine
,
1130 MODEL_META_DATA_DEFINE
: self
.__ProcessDefine
,
1131 MODEL_META_DATA_GLOBAL_DEFINE
: self
.__ProcessDefine
,
1132 MODEL_META_DATA_INCLUDE
: self
.__ProcessDirective
,
1133 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
: self
.__ProcessDirective
,
1134 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
: self
.__ProcessDirective
,
1135 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
: self
.__ProcessDirective
,
1136 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
: self
.__ProcessDirective
,
1137 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
: self
.__ProcessDirective
,
1138 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
: self
.__ProcessDirective
,
1139 MODEL_EFI_SKU_ID
: self
.__ProcessSkuId
,
1140 MODEL_EFI_LIBRARY_INSTANCE
: self
.__ProcessLibraryInstance
,
1141 MODEL_EFI_LIBRARY_CLASS
: self
.__ProcessLibraryClass
,
1142 MODEL_PCD_FIXED_AT_BUILD
: self
.__ProcessPcd
,
1143 MODEL_PCD_PATCHABLE_IN_MODULE
: self
.__ProcessPcd
,
1144 MODEL_PCD_FEATURE_FLAG
: self
.__ProcessPcd
,
1145 MODEL_PCD_DYNAMIC_DEFAULT
: self
.__ProcessPcd
,
1146 MODEL_PCD_DYNAMIC_HII
: self
.__ProcessPcd
,
1147 MODEL_PCD_DYNAMIC_VPD
: self
.__ProcessPcd
,
1148 MODEL_PCD_DYNAMIC_EX_DEFAULT
: self
.__ProcessPcd
,
1149 MODEL_PCD_DYNAMIC_EX_HII
: self
.__ProcessPcd
,
1150 MODEL_PCD_DYNAMIC_EX_VPD
: self
.__ProcessPcd
,
1151 MODEL_META_DATA_COMPONENT
: self
.__ProcessComponent
,
1152 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: self
.__ProcessSourceOverridePath
,
1153 MODEL_META_DATA_BUILD_OPTION
: self
.__ProcessBuildOption
,
1154 MODEL_UNKNOWN
: self
._Skip
,
1155 MODEL_META_DATA_USER_EXTENSION
: self
._Skip
,
1156 MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR
: self
._Skip
,
1159 self
._RawTable
= self
._Table
1160 self
._Table
= MetaFileStorage(self
._RawTable
.Cur
, self
.MetaFile
, MODEL_FILE_DSC
, True)
1161 self
._DirectiveStack
= []
1162 self
._DirectiveEvalStack
= []
1163 self
._FileWithError
= self
.MetaFile
1164 self
._FileLocalMacros
= {}
1165 self
._SectionsMacroDict
= {}
1166 GlobalData
.gPlatformDefines
= {}
1168 # Get all macro and PCD which has straitforward value
1169 self
.__RetrievePcdValue
()
1170 self
._Content
= self
._RawTable
.GetAll()
1171 self
._ContentIndex
= 0
1172 while self
._ContentIndex
< len(self
._Content
) :
1173 Id
, self
._ItemType
, V1
, V2
, V3
, S1
, S2
, Owner
, BelongsToFile
, self
._From
, \
1174 LineStart
, ColStart
, LineEnd
, ColEnd
, Enabled
= self
._Content
[self
._ContentIndex
]
1177 self
._FileWithError
= self
.MetaFile
1179 self
._ContentIndex
+= 1
1181 self
._Scope
= [[S1
, S2
]]
1182 self
._LineIndex
= LineStart
- 1
1183 self
._ValueList
= [V1
, V2
, V3
]
1186 Processer
[self
._ItemType
]()
1187 except EvaluationException
as Excpt
:
1189 # Only catch expression evaluation error here. We need to report
1190 # the precise number of line on which the error occurred
1193 # EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
1194 # File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1195 # Line=self._LineIndex+1)
1196 except MacroException
as Excpt
:
1197 EdkLogger
.error('Parser', FORMAT_INVALID
, str(Excpt
),
1198 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1199 Line
=self
._LineIndex
+1)
1201 if self
._ValueList
is None:
1204 NewOwner
= self
._IdMapping
.get(Owner
, -1)
1205 self
._Enabled
= int((not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
))
1206 self
._LastItem
= self
._Store
(
1222 self
._IdMapping
[Id
] = self
._LastItem
1224 RecordList
= self
._Table
.GetAll()
1226 self
._RawTable
.Drop()
1228 for Record
in RecordList
:
1229 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])
1230 GlobalData
.gPlatformDefines
.update(self
._FileLocalMacros
)
1231 self
._PostProcessed
= True
1232 self
._Content
= None
1234 def __ProcessSectionHeader(self
):
1235 self
._SectionName
= self
._ValueList
[0]
1236 if self
._SectionName
in self
.DataType
:
1237 self
._SectionType
= self
.DataType
[self
._SectionName
]
1239 self
._SectionType
= MODEL_UNKNOWN
1241 def __ProcessSubsectionHeader(self
):
1242 self
._SubsectionName
= self
._ValueList
[0]
1243 if self
._SubsectionName
in self
.DataType
:
1244 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
1246 self
._SubsectionType
= MODEL_UNKNOWN
1248 def __RetrievePcdValue(self
):
1249 Records
= self
._RawTable
.Query(MODEL_PCD_FEATURE_FLAG
, BelongsToItem
=-1.0)
1250 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1251 Value
, DatumType
, MaxDatumSize
= AnalyzePcdData(Value
)
1252 # Only use PCD whose value is straitforward (no macro and PCD)
1253 if self
.SymbolPattern
.findall(Value
):
1255 Name
= TokenSpaceGuid
+ '.' + PcdName
1256 # Don't use PCD with different values.
1257 if Name
in self
._Symbols
and self
._Symbols
[Name
] != Value
:
1258 self
._Symbols
.pop(Name
)
1260 self
._Symbols
[Name
] = Value
1262 Records
= self
._RawTable
.Query(MODEL_PCD_FIXED_AT_BUILD
, BelongsToItem
=-1.0)
1263 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1264 Value
, DatumType
, MaxDatumSize
= AnalyzePcdData(Value
)
1265 # Only use PCD whose value is straitforward (no macro and PCD)
1266 if self
.SymbolPattern
.findall(Value
):
1268 Name
= TokenSpaceGuid
+'.'+PcdName
1269 # Don't use PCD with different values.
1270 if Name
in self
._Symbols
and self
._Symbols
[Name
] != Value
:
1271 self
._Symbols
.pop(Name
)
1273 self
._Symbols
[Name
] = Value
1275 def __ProcessDefine(self
):
1276 if not self
._Enabled
:
1279 Type
, Name
, Value
= self
._ValueList
1280 Value
= ReplaceMacro(Value
, self
._Macros
, False)
1281 if self
._ItemType
== MODEL_META_DATA_DEFINE
:
1282 if self
._SectionType
== MODEL_META_DATA_HEADER
:
1283 self
._FileLocalMacros
[Name
] = Value
1285 SectionDictKey
= self
._SectionType
, self
._Scope
[0][0], self
._Scope
[0][1]
1286 if SectionDictKey
not in self
._SectionsMacroDict
:
1287 self
._SectionsMacroDict
[SectionDictKey
] = {}
1288 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
1289 SectionLocalMacros
[Name
] = Value
1290 elif self
._ItemType
== MODEL_META_DATA_GLOBAL_DEFINE
:
1291 GlobalData
.gEdkGlobal
[Name
] = Value
1294 # Keyword in [Defines] section can be used as Macros
1296 if (self
._ItemType
== MODEL_META_DATA_HEADER
) and (self
._SectionType
== MODEL_META_DATA_HEADER
):
1297 self
._FileLocalMacros
[Name
] = Value
1299 self
._ValueList
= [Type
, Name
, Value
]
1301 def __ProcessDirective(self
):
1303 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1304 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
]:
1305 Macros
= self
._Macros
1306 Macros
.update(GlobalData
.gGlobalDefines
)
1308 Result
= ValueExpression(self
._ValueList
[1], Macros
)()
1309 except SymbolNotFound
as Exc
:
1310 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1312 except WrnExpression
as Excpt
:
1314 # Catch expression evaluation warning here. We need to report
1315 # the precise number of line and return the evaluation result
1317 EdkLogger
.warn('Parser', "Suspicious expression: %s" % str(Excpt
),
1318 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1319 Line
=self
._LineIndex
+1)
1320 Result
= Excpt
.result
1321 except BadExpression
as Exc
:
1322 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1325 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1326 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1327 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1328 self
._DirectiveStack
.append(self
._ItemType
)
1329 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
:
1330 Result
= bool(Result
)
1332 Macro
= self
._ValueList
[1]
1333 Macro
= Macro
[2:-1] if (Macro
.startswith("$(") and Macro
.endswith(")")) else Macro
1334 Result
= Macro
in self
._Macros
1335 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
:
1337 self
._DirectiveEvalStack
.append(Result
)
1338 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
:
1339 self
._DirectiveStack
.append(self
._ItemType
)
1340 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1341 self
._DirectiveEvalStack
.append(bool(Result
))
1342 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1343 self
._DirectiveStack
[-1] = self
._ItemType
1344 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1345 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1346 # Back to the nearest !if/!ifdef/!ifndef
1347 while self
._DirectiveStack
:
1348 self
._DirectiveEvalStack
.pop()
1349 Directive
= self
._DirectiveStack
.pop()
1350 if Directive
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1351 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1352 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
1353 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1355 elif self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1356 # The included file must be relative to workspace or same directory as DSC file
1357 __IncludeMacros
= {}
1359 # Allow using system environment variables in path after !include
1361 __IncludeMacros
['WORKSPACE'] = GlobalData
.gGlobalDefines
['WORKSPACE']
1362 if "ECP_SOURCE" in GlobalData
.gGlobalDefines
.keys():
1363 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gGlobalDefines
['ECP_SOURCE']
1365 # During GenFds phase call DSC parser, will go into this branch.
1367 elif "ECP_SOURCE" in GlobalData
.gCommandLineDefines
.keys():
1368 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gCommandLineDefines
['ECP_SOURCE']
1370 __IncludeMacros
['EFI_SOURCE'] = GlobalData
.gGlobalDefines
['EFI_SOURCE']
1371 __IncludeMacros
['EDK_SOURCE'] = GlobalData
.gGlobalDefines
['EDK_SOURCE']
1373 # Allow using MACROs comes from [Defines] section to keep compatible.
1375 __IncludeMacros
.update(self
._Macros
)
1377 IncludedFile
= NormPath(ReplaceMacro(self
._ValueList
[1], __IncludeMacros
, RaiseError
=True))
1379 # First search the include file under the same directory as DSC file
1381 IncludedFile1
= PathClass(IncludedFile
, self
.MetaFile
.Dir
)
1382 ErrorCode
, ErrorInfo1
= IncludedFile1
.Validate()
1385 # Also search file under the WORKSPACE directory
1387 IncludedFile1
= PathClass(IncludedFile
, GlobalData
.gWorkspace
)
1388 ErrorCode
, ErrorInfo2
= IncludedFile1
.Validate()
1390 EdkLogger
.error('parser', ErrorCode
, File
=self
._FileWithError
,
1391 Line
=self
._LineIndex
+1, ExtraData
=ErrorInfo1
+ "\n"+ ErrorInfo2
)
1393 self
._FileWithError
= IncludedFile1
1395 IncludedFileTable
= MetaFileStorage(self
._Table
.Cur
, IncludedFile1
, MODEL_FILE_DSC
, True)
1396 Owner
= self
._Content
[self
._ContentIndex
-1][0]
1397 Parser
= DscParser(IncludedFile1
, self
._FileType
, IncludedFileTable
,
1398 Owner
=Owner
, From
=Owner
)
1400 # set the parser status with current status
1401 Parser
._SectionName
= self
._SectionName
1402 Parser
._SectionType
= self
._SectionType
1403 Parser
._Scope
= self
._Scope
1404 Parser
._Enabled
= self
._Enabled
1405 # Parse the included file
1408 # update current status with sub-parser's status
1409 self
._SectionName
= Parser
._SectionName
1410 self
._SectionType
= Parser
._SectionType
1411 self
._Scope
= Parser
._Scope
1412 self
._Enabled
= Parser
._Enabled
1414 # Insert all records in the table for the included file into dsc file table
1415 Records
= IncludedFileTable
.GetAll()
1417 self
._Content
[self
._ContentIndex
:self
._ContentIndex
] = Records
1418 self
._Content
.pop(self
._ContentIndex
-1)
1419 self
._ValueList
= None
1420 self
._ContentIndex
-= 1
1422 def __ProcessSkuId(self
):
1423 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=True)
1424 for Value
in self
._ValueList
]
1426 def __ProcessLibraryInstance(self
):
1427 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
1429 def __ProcessLibraryClass(self
):
1430 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, RaiseError
=True)
1432 def __ProcessPcd(self
):
1433 ValueList
= GetSplitValueList(self
._ValueList
[2])
1435 # PCD value can be an expression
1437 if len(ValueList
) > 1 and ValueList
[1] == TAB_VOID
:
1438 PcdValue
= ValueList
[0]
1440 ValueList
[0] = ValueExpression(PcdValue
, self
._Macros
)(True)
1441 except WrnExpression
as Value
:
1442 ValueList
[0] = Value
.result
1444 PcdValue
= ValueList
[-1]
1446 ValueList
[-1] = ValueExpression(PcdValue
, self
._Macros
)(True)
1447 except WrnExpression
as Value
:
1448 ValueList
[-1] = Value
.result
1450 if ValueList
[-1] == 'True':
1452 if ValueList
[-1] == 'False':
1455 self
._ValueList
[2] = '|'.join(ValueList
)
1457 def __ProcessComponent(self
):
1458 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1460 def __ProcessSourceOverridePath(self
):
1461 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1463 def __ProcessBuildOption(self
):
1464 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=False)
1465 for Value
in self
._ValueList
]
1468 MODEL_META_DATA_HEADER
: _DefineParser
,
1469 MODEL_EFI_SKU_ID
: _SkuIdParser
,
1470 MODEL_EFI_LIBRARY_INSTANCE
: _LibraryInstanceParser
,
1471 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
1472 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1473 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1474 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1475 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
1476 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
1477 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
1478 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
1479 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
1480 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
1481 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
1482 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: _CompponentSourceOverridePathParser
,
1483 MODEL_META_DATA_BUILD_OPTION
: _BuildOptionParser
,
1484 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1485 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1486 MODEL_META_DATA_SECTION_HEADER
: MetaFileParser
._SectionHeaderParser
,
1487 MODEL_META_DATA_SUBSECTION_HEADER
: _SubsectionHeaderParser
,
1490 _Macros
= property(_GetMacros
)
1492 ## DEC file parser class
1494 # @param FilePath The path of platform description file
1495 # @param FileType The raw data of DSC file
1496 # @param Table Database used to retrieve module/package information
1497 # @param Macros Macros used for replacement in file
1499 class DecParser(MetaFileParser
):
1500 # DEC file supported data types (one type per section)
1502 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1503 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
1504 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1505 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1506 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1507 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1508 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1509 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1510 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1511 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1512 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1513 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1516 ## Constructor of DecParser
1518 # Initialize object of DecParser
1520 # @param FilePath The path of platform description file
1521 # @param FileType The raw data of DSC file
1522 # @param Table Database used to retrieve module/package information
1523 # @param Macros Macros used for replacement in file
1525 def __init__(self
, FilePath
, FileType
, Table
):
1526 # prevent re-initialization
1527 if hasattr(self
, "_Table"):
1529 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
1531 self
._Version
= 0x00010005 # Only EDK2 dec file is supported
1532 self
.TblFile
= EccGlobalData
.gDb
.TblFile
1539 Content
= open(str(self
.MetaFile
), 'r').readlines()
1541 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1544 # Insert a record for file
1546 Filename
= NormPath(self
.MetaFile
)
1547 FileID
= self
.TblFile
.GetFileId(Filename
)
1549 self
.FileID
= FileID
1551 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_DEC
)
1553 for Index
in range(0, len(Content
)):
1554 Line
, Comment
= CleanString2(Content
[Index
])
1555 self
._CurrentLine
= Line
1556 self
._LineIndex
= Index
1558 # save comment for later use
1560 self
._Comments
.append((Comment
, self
._LineIndex
+1))
1566 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1567 self
._SectionHeaderParser
()
1570 elif len(self
._SectionType
) == 0:
1575 self
._ValueList
= ['', '', '']
1576 self
._SectionParser
[self
._SectionType
[0]](self
)
1577 if self
._ValueList
is None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
1583 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1584 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1586 for Arch
, ModuleType
, Type
in self
._Scope
:
1587 self
._LastItem
= self
._Store
(
1602 for Comment
, LineNo
in self
._Comments
:
1604 MODEL_META_DATA_COMMENT
,
1621 def _GetApplicableSectionMacro(self
):
1623 for S1
, S2
, SectionType
in self
._Scope
:
1624 for Scope1
, Scope2
in [("COMMON", "COMMON"), ("COMMON", S2
), (S1
, "COMMON"), (S1
, S2
)]:
1625 if (SectionType
, Scope1
, Scope2
) in self
._SectionsMacroDict
:
1626 Macros
.update(self
._SectionsMacroDict
[(SectionType
, Scope1
, Scope2
)])
1629 ## Section header parser
1631 # The section header is always in following format:
1633 # [section_name.arch<.platform|module_type>]
1635 def _SectionHeaderParser(self
):
1637 self
._SectionName
= ''
1638 self
._SectionType
= []
1640 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
1643 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
)
1645 # different types of PCD are permissible in one section
1646 self
._SectionName
= ItemList
[0].upper()
1647 if self
._SectionName
in self
.DataType
:
1648 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1649 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1651 EdkLogger
.warn("Parser", "Unrecognized section", File
=self
.MetaFile
,
1652 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
1655 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1659 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1661 Line
=self
._LineIndex
+1,
1662 ExtraData
=self
._CurrentLine
1665 if len(ItemList
) > 1:
1666 S1
= ItemList
[1].upper()
1670 # S2 may be Platform or ModuleType
1671 if len(ItemList
) > 2:
1672 S2
= ItemList
[2].upper()
1675 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1676 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1678 # 'COMMON' must not be used with specific ARCHs at the same section
1679 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1680 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1681 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
1683 ## [guids], [ppis] and [protocols] section parser
1685 def _GuidParser(self
):
1686 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1687 if len(TokenList
) < 2:
1688 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1689 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1690 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1691 if TokenList
[0] == '':
1692 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1693 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1694 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1695 if TokenList
[1] == '':
1696 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1697 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1698 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1699 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1700 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1701 ExtraData
=self
._CurrentLine
+ \
1702 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1703 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1704 self
._ValueList
[0] = TokenList
[0]
1705 #Parse the Guid value format
1706 GuidValueList
= TokenList
[1].strip(' {}').split(',')
1709 if len(GuidValueList
) == 11:
1710 for GuidValue
in GuidValueList
:
1711 GuidValue
= GuidValue
.strip()
1712 if GuidValue
.startswith('0x') or GuidValue
.startswith('0X'):
1713 HexList
.append('0x' + str(GuidValue
[2:]))
1717 if GuidValue
.startswith('{'):
1718 GuidValue
= GuidValue
.lstrip(' {')
1719 HexList
.append('0x' + str(GuidValue
[2:]))
1721 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])
1723 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1724 ExtraData
=self
._CurrentLine
+ \
1725 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1726 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1727 self
._ValueList
[0] = ''
1729 ## PCD sections parser
1731 # [PcdsFixedAtBuild]
1732 # [PcdsPatchableInModule]
1738 def _PcdParser(self
):
1739 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1740 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1741 # check PCD information
1742 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1743 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1744 ExtraData
=self
._CurrentLine
+ \
1745 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1746 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1747 # check PCD datum information
1748 if len(TokenList
) < 2 or TokenList
[1] == '':
1749 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1750 ExtraData
=self
._CurrentLine
+ \
1751 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1752 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1755 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1756 PtrValue
= ValueRe
.findall(TokenList
[1])
1758 # Has VOID* type string, may contain "|" character in the string.
1759 if len(PtrValue
) != 0:
1760 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1761 ValueList
= GetSplitValueList(ptrValueList
)
1762 ValueList
[0] = PtrValue
[0]
1764 ValueList
= GetSplitValueList(TokenList
[1])
1767 # check if there's enough datum information given
1768 if len(ValueList
) != 3:
1769 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1770 ExtraData
=self
._CurrentLine
+ \
1771 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1772 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1773 # check default value
1774 if ValueList
[0] == '':
1775 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1776 ExtraData
=self
._CurrentLine
+ \
1777 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1778 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1780 if ValueList
[1] == '':
1781 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1782 ExtraData
=self
._CurrentLine
+ \
1783 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1784 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1785 # check token of the PCD
1786 if ValueList
[2] == '':
1787 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1788 ExtraData
=self
._CurrentLine
+ \
1789 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1790 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1791 # check format of default value against the datum type
1792 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1794 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1795 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1797 if EccGlobalData
.gConfig
.UniCheckPCDInfo
== '1' or EccGlobalData
.gConfig
.UniCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
1798 # check Description, Prompt information
1799 PatternDesc
= re
.compile('##\s*([\x21-\x7E\s]*)', re
.S
)
1800 PatternPrompt
= re
.compile('#\s+@Prompt\s+([\x21-\x7E\s]*)', re
.S
)
1803 # check @ValidRange, @ValidList and @Expression format valid
1804 ErrorCodeValid
= '0x0 <= %s <= 0xFFFFFFFF'
1805 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]+)'
1806 PatternValidRng
= re
.compile('^' + '(NOT)?\s*' + PatternValidRangeIn
+ '$')
1807 for Comment
in self
._Comments
:
1808 Comm
= Comment
[0].strip()
1812 Description
= PatternDesc
.findall(Comm
)
1814 Prompt
= PatternPrompt
.findall(Comm
)
1816 ValidFormt
= Comm
.lstrip('#')
1817 ValidFormt
= ValidFormt
.lstrip()
1818 if ValidFormt
[0:11] == '@ValidRange':
1819 ValidFormt
= ValidFormt
[11:]
1820 ValidFormt
= ValidFormt
.lstrip()
1822 ErrorCode
, Expression
= ValidFormt
.split('|', 1)
1825 Expression
= ValidFormt
1826 ErrorCode
, Expression
= ErrorCode
.strip(), Expression
.strip()
1828 if not eval(ErrorCodeValid
% ErrorCode
):
1829 EdkLogger
.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1831 EdkLogger
.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1832 if not PatternValidRng
.search(Expression
):
1833 EdkLogger
.warn('Parser', '@ValidRange Expression(%s) of PCD %s is incorrect format.' % (Expression
, TokenList
[0]))
1834 if ValidFormt
[0:10] == '@ValidList':
1835 ValidFormt
= ValidFormt
[10:]
1836 ValidFormt
= ValidFormt
.lstrip()
1838 ErrorCode
, Expression
= ValidFormt
.split('|', 1)
1841 Expression
= ValidFormt
1842 ErrorCode
, Expression
= ErrorCode
.strip(), Expression
.strip()
1844 if not eval(ErrorCodeValid
% ErrorCode
):
1845 EdkLogger
.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1847 EdkLogger
.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1848 Values
= Expression
.split(',')
1849 for Value
in Values
:
1850 Value
= Value
.strip()
1854 EdkLogger
.warn('Parser', '@ValidList Expression of PCD %s include a invalid value(%s).' % (TokenList
[0], Value
))
1856 if ValidFormt
[0:11] == '@Expression':
1857 ValidFormt
= ValidFormt
[11:]
1858 ValidFormt
= ValidFormt
.lstrip()
1860 ErrorCode
, Expression
= ValidFormt
.split('|', 1)
1863 Expression
= ValidFormt
1864 ErrorCode
, Expression
= ErrorCode
.strip(), Expression
.strip()
1866 if not eval(ErrorCodeValid
% ErrorCode
):
1867 EdkLogger
.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1869 EdkLogger
.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1871 EdkLogger
.warn('Parser', '@Expression Expression of PCD %s is incorrect format.' % TokenList
[0])
1873 EdkLogger
.warn('Parser', 'PCD %s Description information is not provided.' % TokenList
[0])
1875 EdkLogger
.warn('Parser', 'PCD %s Prompt information is not provided.' % TokenList
[0])
1876 # check Description, Prompt localization information
1878 self
._UniObj
.CheckPcdInfo(TokenList
[0])
1880 if ValueList
[0] in ['True', 'true', 'TRUE']:
1882 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1885 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
1888 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
1889 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
1890 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
1891 MODEL_EFI_GUID
: _GuidParser
,
1892 MODEL_EFI_PPI
: _GuidParser
,
1893 MODEL_EFI_PROTOCOL
: _GuidParser
,
1894 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1895 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1896 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1897 MODEL_PCD_DYNAMIC
: _PcdParser
,
1898 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
1899 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1900 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1906 # This class defined the structure used in Fdf object
1908 # @param Filename: Input value for Ffilename of Fdf file, default is None
1909 # @param WorkspaceDir: Input value for current workspace directory, default is None
1912 def __init__(self
, Filename
= None, IsToDatabase
= False, WorkspaceDir
= None, Database
= None):
1913 self
.WorkspaceDir
= WorkspaceDir
1914 self
.IsToDatabase
= IsToDatabase
1916 self
.Cur
= Database
.Cur
1917 self
.TblFile
= Database
.TblFile
1918 self
.TblFdf
= Database
.TblFdf
1923 # Load Fdf file if filename is not None
1925 if Filename
is not None:
1927 self
.LoadFdfFile(Filename
)
1932 # Insert a FDF file record into database
1934 def InsertFile(self
, Filename
):
1936 Filename
= NormPath(Filename
)
1937 if Filename
not in self
.FileList
:
1938 FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_FDF
)
1939 self
.FileList
[Filename
] = FileID
1941 return self
.FileList
[Filename
]
1946 # Load the file if it exists
1948 # @param Filename: Input value for filename of Fdf file
1950 def LoadFdfFile(self
, Filename
):
1955 Filename
= NormPath(Filename
)
1956 Fdf
= FdfParser(Filename
)
1960 # Insert inf file and pcd information
1962 if self
.IsToDatabase
:
1963 (Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
) = \
1964 (0, '', '', '', 'COMMON', 'COMMON', -1, -1, -1, -1, -1, -1, 0)
1965 for Index
in range(0, len(Fdf
.Profile
.PcdDict
)):
1967 for Key
in Fdf
.Profile
.PcdDict
.keys():
1971 FileName
= Fdf
.Profile
.PcdFileLineDict
[Key
][0]
1972 StartLine
= Fdf
.Profile
.PcdFileLineDict
[Key
][1]
1973 BelongsToFile
= self
.InsertFile(FileName
)
1974 self
.TblFdf
.Insert(Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
)
1975 for Index
in range(0, len(Fdf
.Profile
.InfList
)):
1976 Model
= MODEL_META_DATA_COMPONENT
1977 Value1
= Fdf
.Profile
.InfList
[Index
]
1979 FileName
= Fdf
.Profile
.InfFileLineList
[Index
][0]
1980 StartLine
= Fdf
.Profile
.InfFileLineList
[Index
][1]
1981 BelongsToFile
= self
.InsertFile(FileName
)
1982 self
.TblFdf
.Insert(Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
)
1984 class UniParser(object):
1985 # IsExtraUni defined the UNI file is Module UNI or extra Module UNI
1986 # IsModuleUni defined the UNI file is Module UNI or Package UNI
1987 def __init__(self
, FilePath
, IsExtraUni
=False, IsModuleUni
=True):
1988 self
.FilePath
= FilePath
1989 self
.FileName
= os
.path
.basename(FilePath
)
1990 self
.IsExtraUni
= IsExtraUni
1991 self
.IsModuleUni
= IsModuleUni
1998 self
.FileIn
= CodecOpenLongFilePath(self
.FilePath
, Mode
='rb', Encoding
='utf_8').read()
1999 except UnicodeError:
2000 self
.FileIn
= CodecOpenLongFilePath(self
.FilePath
, Mode
='rb', Encoding
='utf_16').read()
2001 except UnicodeError:
2002 self
.FileIn
= CodecOpenLongFilePath(self
.FilePath
, Mode
='rb', Encoding
='utf_16_le').read()
2007 if self
.IsModuleUni
:
2009 ModuleName
= self
.CheckKeyValid('STR_PROPERTIES_MODULE_NAME')
2010 self
.PrintLog('STR_PROPERTIES_MODULE_NAME', ModuleName
)
2012 ModuleAbstract
= self
.CheckKeyValid('STR_MODULE_ABSTRACT')
2013 self
.PrintLog('STR_MODULE_ABSTRACT', ModuleAbstract
)
2014 ModuleDescription
= self
.CheckKeyValid('STR_MODULE_DESCRIPTION')
2015 self
.PrintLog('STR_MODULE_DESCRIPTION', ModuleDescription
)
2018 PackageName
= self
.CheckKeyValid('STR_PROPERTIES_PACKAGE_NAME')
2019 self
.PrintLog('STR_PROPERTIES_PACKAGE_NAME', PackageName
)
2021 PackageAbstract
= self
.CheckKeyValid('STR_PACKAGE_ABSTRACT')
2022 self
.PrintLog('STR_PACKAGE_ABSTRACT', PackageAbstract
)
2023 PackageDescription
= self
.CheckKeyValid('STR_PACKAGE_DESCRIPTION')
2024 self
.PrintLog('STR_PACKAGE_DESCRIPTION', PackageDescription
)
2026 def CheckKeyValid(self
, Key
, Contents
=None):
2028 Contents
= self
.FileIn
2029 KeyPattern
= re
.compile('#string\s+%s\s+.*?#language.*?".*?"' % Key
, re
.S
)
2030 if KeyPattern
.search(Contents
):
2034 def CheckPcdInfo(self
, PcdCName
):
2035 PromptKey
= 'STR_%s_PROMPT' % PcdCName
.replace('.', '_')
2036 PcdPrompt
= self
.CheckKeyValid(PromptKey
)
2037 self
.PrintLog(PromptKey
, PcdPrompt
)
2038 HelpKey
= 'STR_%s_HELP' % PcdCName
.replace('.', '_')
2039 PcdHelp
= self
.CheckKeyValid(HelpKey
)
2040 self
.PrintLog(HelpKey
, PcdHelp
)
2042 def PrintLog(self
, Key
, Value
):
2043 if not Value
and Key
not in self
.Missing
:
2044 Msg
= '%s is missing in the %s file.' % (Key
, self
.FileName
)
2045 EdkLogger
.warn('Parser', Msg
)
2046 EccGlobalData
.gDb
.TblReport
.Insert(EccToolError
.ERROR_GENERAL_CHECK_UNI_HELP_INFO
, OtherMsg
=Msg
, BelongsToTable
='File', BelongsToItem
=-2)
2047 self
.Missing
.append(Key
)
2051 # This acts like the main() function for the script, unless it is 'import'ed into another
2054 if __name__
== '__main__':