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
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 .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', '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__':