2 # This file is used to parse meta files
4 # Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.<BR>
5 # Copyright (c) 2015, Hewlett Packard Enterprise Development, L.P.<BR>
6 # This program and the accompanying materials
7 # are licensed and made available under the terms and conditions of the BSD License
8 # which accompanies this distribution. The full text of the license may be found at
9 # http://opensource.org/licenses/bsd-license.php
11 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 import Common
.LongFilePathOs
as os
23 import Common
.EdkLogger
as EdkLogger
24 import Common
.GlobalData
as GlobalData
26 from CommonDataClass
.DataClass
import *
27 from Common
.DataType
import *
28 from Common
.String
import *
29 from Common
.Misc
import GuidStructureStringToGuidString
, CheckPcdDatum
, PathClass
, AnalyzePcdData
, AnalyzeDscPcd
30 from Common
.Expression
import *
31 from CommonDataClass
.Exceptions
import *
32 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
34 from MetaFileTable
import MetaFileStorage
35 from MetaFileCommentParser
import CheckInfComment
37 ## A decorator used to parse macro definition
38 def ParseMacro(Parser
):
39 def MacroParser(self
):
40 Match
= gMacroDefPattern
.match(self
._CurrentLine
)
42 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
46 TokenList
= GetSplitValueList(self
._CurrentLine
[Match
.end(1):], TAB_EQUAL_SPLIT
, 1)
49 EdkLogger
.error('Parser', FORMAT_INVALID
, "No macro name given",
50 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
51 if len(TokenList
) < 2:
55 Name
, Value
= TokenList
56 # Global macros can be only defined via environment variable
57 if Name
in GlobalData
.gGlobalDefines
:
58 EdkLogger
.error('Parser', FORMAT_INVALID
, "%s can only be defined via environment variable" % Name
,
59 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
60 # Only upper case letters, digit and '_' are allowed
61 if not gMacroNamePattern
.match(Name
):
62 EdkLogger
.error('Parser', FORMAT_INVALID
, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
63 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
65 Value
= ReplaceMacro(Value
, self
._Macros
)
66 if Type
in self
.DataType
:
67 self
._ItemType
= self
.DataType
[Type
]
69 self
._ItemType
= MODEL_META_DATA_DEFINE
70 # DEFINE defined macros
71 if Type
== TAB_DSC_DEFINES_DEFINE
:
73 # First judge whether this DEFINE is in conditional directive statements or not.
75 if type(self
) == DscParser
and self
._InDirective
> -1:
78 if type(self
) == DecParser
:
79 if MODEL_META_DATA_HEADER
in self
._SectionType
:
80 self
._FileLocalMacros
[Name
] = Value
82 self
._ConstructSectionMacroDict
(Name
, Value
)
83 elif self
._SectionType
== MODEL_META_DATA_HEADER
:
84 self
._FileLocalMacros
[Name
] = Value
86 self
._ConstructSectionMacroDict
(Name
, Value
)
88 # EDK_GLOBAL defined macros
89 elif type(self
) != DscParser
:
90 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used in .dsc file",
91 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
92 elif self
._SectionType
!= MODEL_META_DATA_HEADER
:
93 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used under [Defines] section",
94 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
95 elif (Name
in self
._FileLocalMacros
) and (self
._FileLocalMacros
[Name
] != Value
):
96 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
97 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
99 self
._ValueList
= [Type
, Name
, Value
]
103 ## Base class of parser
105 # This class is used for derivation purpose. The specific parser for one kind
106 # type file must derive this class and implement some public interfaces.
108 # @param FilePath The path of platform description file
109 # @param FileType The raw data of DSC file
110 # @param Table Database used to retrieve module/package information
111 # @param Macros Macros used for replacement in file
112 # @param Owner Owner ID (for sub-section parsing)
113 # @param From ID from which the data comes (for !INCLUDE directive)
115 class MetaFileParser(object):
116 # data type (file content) for specific file type
119 # Parser objects used to implement singleton
124 # One file, one parser object. This factory method makes sure that there's
125 # only one object constructed for one meta file.
127 # @param Class class object of real AutoGen class
128 # (InfParser, DecParser or DscParser)
129 # @param FilePath The path of meta file
130 # @param *args The specific class related parameters
131 # @param **kwargs The specific class related dict parameters
133 def __new__(Class
, FilePath
, *args
, **kwargs
):
134 if FilePath
in Class
.MetaFiles
:
135 return Class
.MetaFiles
[FilePath
]
137 ParserObject
= super(MetaFileParser
, Class
).__new
__(Class
)
138 Class
.MetaFiles
[FilePath
] = ParserObject
141 ## Constructor of MetaFileParser
143 # Initialize object of MetaFileParser
145 # @param FilePath The path of platform description file
146 # @param FileType The raw data of DSC file
147 # @param Table Database used to retrieve module/package information
148 # @param Macros Macros used for replacement in file
149 # @param Owner Owner ID (for sub-section parsing)
150 # @param From ID from which the data comes (for !INCLUDE directive)
152 def __init__(self
, FilePath
, FileType
, Table
, Owner
= -1, From
= -1):
154 self
._RawTable
= Table
155 self
._FileType
= FileType
156 self
.MetaFile
= FilePath
157 self
._FileDir
= self
.MetaFile
.Dir
159 self
._FileLocalMacros
= {}
160 self
._SectionsMacroDict
= {}
162 # for recursive parsing
163 self
._Owner
= [Owner
]
166 # parsr status for parsing
167 self
._ValueList
= ['', '', '', '', '']
170 self
._CurrentLine
= ''
171 self
._SectionType
= MODEL_UNKNOWN
172 self
._SectionName
= ''
173 self
._InSubsection
= False
174 self
._SubsectionType
= MODEL_UNKNOWN
175 self
._SubsectionName
= ''
176 self
._ItemType
= MODEL_UNKNOWN
179 self
._Finished
= False
180 self
._PostProcessed
= False
181 # Different version of meta-file has different way to parse.
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 type(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] == 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 type(self
) != DscParser
:
262 Macros
= self
._Macros
263 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
265 ## Skip unsupported data
267 EdkLogger
.warn("Parser", "Unrecognized content", File
=self
.MetaFile
,
268 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
);
269 self
._ValueList
[0:1] = [self
._CurrentLine
]
271 ## Skip unsupported data for UserExtension Section
272 def _SkipUserExtension(self
):
273 self
._ValueList
[0:1] = [self
._CurrentLine
]
275 ## Section header parser
277 # The section header is always in following format:
279 # [section_name.arch<.platform|module_type>]
281 def _SectionHeaderParser(self
):
283 self
._SectionName
= ''
285 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
288 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
,2)
289 # different section should not mix in one section
290 if self
._SectionName
!= '' and self
._SectionName
!= ItemList
[0].upper():
291 EdkLogger
.error('Parser', FORMAT_INVALID
, "Different section names in the same section",
292 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
293 self
._SectionName
= ItemList
[0].upper()
294 if self
._SectionName
in self
.DataType
:
295 self
._SectionType
= self
.DataType
[self
._SectionName
]
296 # Check if the section name is valid
297 if self
._SectionName
not in SECTIONS_HAVE_ITEM_AFTER_ARCH
and len(ItemList
) > 3:
298 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
299 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
300 elif self
._Version
>= 0x00010005:
301 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
302 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
304 self
._SectionType
= MODEL_UNKNOWN
307 if len(ItemList
) > 1:
308 S1
= ItemList
[1].upper()
313 # S2 may be Platform or ModuleType
314 if len(ItemList
) > 2:
315 if self
._SectionName
.upper() in SECTIONS_HAVE_ITEM_PCD
:
318 S2
= ItemList
[2].upper()
321 self
._Scope
.append([S1
, S2
])
323 # 'COMMON' must not be used with specific ARCHs at the same section
324 if 'COMMON' in ArchList
and len(ArchList
) > 1:
325 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
326 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
327 # If the section information is needed later, it should be stored in database
328 self
._ValueList
[0] = self
._SectionName
330 ## [defines] section parser
332 def _DefineParser(self
):
333 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
334 self
._ValueList
[1:len(TokenList
)] = TokenList
335 if not self
._ValueList
[1]:
336 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
337 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
338 if not self
._ValueList
[2]:
339 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
340 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
342 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
343 Name
, Value
= self
._ValueList
[1], self
._ValueList
[2]
344 # Sometimes, we need to make differences between EDK and EDK2 modules
345 if Name
== 'INF_VERSION':
346 if re
.match(r
'0[xX][\da-f-A-F]{5,8}', Value
):
347 self
._Version
= int(Value
, 0)
348 elif re
.match(r
'\d+\.\d+', Value
):
349 ValueList
= Value
.split('.')
350 Major
= '%04o' % int(ValueList
[0], 0)
351 Minor
= '%04o' % int(ValueList
[1], 0)
352 self
._Version
= int('0x' + Major
+ Minor
, 0)
354 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid version number",
355 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
357 if type(self
) == InfParser
and self
._Version
< 0x00010005:
358 # EDK module allows using defines as macros
359 self
._FileLocalMacros
[Name
] = Value
360 self
._Defines
[Name
] = Value
362 ## [BuildOptions] section parser
364 def _BuildOptionParser(self
):
365 self
._CurrentLine
= CleanString(self
._CurrentLine
, BuildOption
=True)
366 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
367 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
368 if len(TokenList2
) == 2:
369 self
._ValueList
[0] = TokenList2
[0] # toolchain family
370 self
._ValueList
[1] = TokenList2
[1] # keys
372 self
._ValueList
[1] = TokenList
[0]
373 if len(TokenList
) == 2 and type(self
) != DscParser
: # value
374 self
._ValueList
[2] = ReplaceMacro(TokenList
[1], self
._Macros
)
376 if self
._ValueList
[1].count('_') != 4:
380 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
381 ExtraData
=self
._CurrentLine
,
383 Line
=self
._LineIndex
+ 1
385 def GetValidExpression(self
, TokenSpaceGuid
, PcdCName
):
386 return self
._Table
.GetValidExpression(TokenSpaceGuid
, PcdCName
)
387 def _GetMacros(self
):
389 Macros
.update(self
._FileLocalMacros
)
390 Macros
.update(self
._GetApplicableSectionMacro
())
393 ## Construct section Macro dict
394 def _ConstructSectionMacroDict(self
, Name
, Value
):
395 ScopeKey
= [(Scope
[0], Scope
[1]) for Scope
in self
._Scope
]
396 ScopeKey
= tuple(ScopeKey
)
397 SectionDictKey
= self
._SectionType
, ScopeKey
399 # DecParser SectionType is a list, will contain more than one item only in Pcd Section
400 # As Pcd section macro usage is not alllowed, so here it is safe
402 if type(self
) == DecParser
:
403 SectionDictKey
= self
._SectionType
[0], ScopeKey
404 if SectionDictKey
not in self
._SectionsMacroDict
:
405 self
._SectionsMacroDict
[SectionDictKey
] = {}
406 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
407 SectionLocalMacros
[Name
] = Value
409 ## Get section Macros that are applicable to current line, which may come from other sections
410 ## that share the same name while scope is wider
411 def _GetApplicableSectionMacro(self
):
418 ActiveSectionType
= self
._SectionType
419 if type(self
) == DecParser
:
420 ActiveSectionType
= self
._SectionType
[0]
422 for (SectionType
, Scope
) in self
._SectionsMacroDict
:
423 if SectionType
!= ActiveSectionType
:
426 for ActiveScope
in self
._Scope
:
427 Scope0
, Scope1
= ActiveScope
[0], ActiveScope
[1]
428 if(Scope0
, Scope1
) not in Scope
:
431 SpeSpeMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
433 for ActiveScope
in self
._Scope
:
434 Scope0
, Scope1
= ActiveScope
[0], ActiveScope
[1]
435 if(Scope0
, Scope1
) not in Scope
and (Scope0
, "COMMON") not in Scope
and ("COMMON", Scope1
) not in Scope
:
438 ComSpeMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
440 if ("COMMON", "COMMON") in Scope
:
441 ComComMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
443 Macros
.update(ComComMacroDict
)
444 Macros
.update(ComSpeMacroDict
)
445 Macros
.update(SpeSpeMacroDict
)
450 Finished
= property(_GetFinished
, _SetFinished
)
451 _Macros
= property(_GetMacros
)
454 ## INF file parser class
456 # @param FilePath The path of platform description file
457 # @param FileType The raw data of DSC file
458 # @param Table Database used to retrieve module/package information
459 # @param Macros Macros used for replacement in file
461 class InfParser(MetaFileParser
):
462 # INF file supported data types (one type per section)
464 TAB_UNKNOWN
.upper() : MODEL_UNKNOWN
,
465 TAB_INF_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
466 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
467 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
468 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
469 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
470 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
471 TAB_PACKAGES
.upper() : MODEL_META_DATA_PACKAGE
,
472 TAB_NMAKE
.upper() : MODEL_META_DATA_NMAKE
,
473 TAB_INF_FIXED_PCD
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
474 TAB_INF_PATCH_PCD
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
475 TAB_INF_FEATURE_PCD
.upper() : MODEL_PCD_FEATURE_FLAG
,
476 TAB_INF_PCD_EX
.upper() : MODEL_PCD_DYNAMIC_EX
,
477 TAB_INF_PCD
.upper() : MODEL_PCD_DYNAMIC
,
478 TAB_SOURCES
.upper() : MODEL_EFI_SOURCE_FILE
,
479 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
480 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
481 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
482 TAB_DEPEX
.upper() : MODEL_EFI_DEPEX
,
483 TAB_BINARIES
.upper() : MODEL_EFI_BINARY_FILE
,
484 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
487 ## Constructor of InfParser
489 # Initialize object of InfParser
491 # @param FilePath The path of module description file
492 # @param FileType The raw data of DSC file
493 # @param Table Database used to retrieve module/package information
494 # @param Macros Macros used for replacement in file
496 def __init__(self
, FilePath
, FileType
, Table
):
497 # prevent re-initialization
498 if hasattr(self
, "_Table"):
500 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
508 Content
= open(str(self
.MetaFile
), 'r').readlines()
510 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
512 # parse the file line by line
513 IsFindBlockComment
= False
514 GetHeaderComment
= False
519 for Index
in range(0, len(Content
)):
520 # skip empty, commented, block commented lines
521 Line
, Comment
= CleanString2(Content
[Index
], AllowCppStyleComment
=True)
523 if Index
+ 1 < len(Content
):
524 NextLine
, NextComment
= CleanString2(Content
[Index
+ 1])
527 Comments
.append((Comment
, Index
+ 1))
528 elif GetHeaderComment
:
529 SectionComments
.extend(Comments
)
532 if Line
.find(DataType
.TAB_COMMENT_EDK_START
) > -1:
533 IsFindBlockComment
= True
535 if Line
.find(DataType
.TAB_COMMENT_EDK_END
) > -1:
536 IsFindBlockComment
= False
538 if IsFindBlockComment
:
541 self
._LineIndex
= Index
542 self
._CurrentLine
= Line
545 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
546 if not GetHeaderComment
:
547 for Cmt
, LNo
in Comments
:
548 self
._Store
(MODEL_META_DATA_HEADER_COMMENT
, Cmt
, '', '', 'COMMON',
549 'COMMON', self
._Owner
[-1], LNo
, -1, LNo
, -1, 0)
550 GetHeaderComment
= True
552 TailComments
.extend(SectionComments
+ Comments
)
554 self
._SectionHeaderParser
()
555 # Check invalid sections
556 if self
._Version
< 0x00010005:
557 if self
._SectionType
in [MODEL_META_DATA_BUILD_OPTION
,
558 MODEL_EFI_LIBRARY_CLASS
,
559 MODEL_META_DATA_PACKAGE
,
560 MODEL_PCD_FIXED_AT_BUILD
,
561 MODEL_PCD_PATCHABLE_IN_MODULE
,
562 MODEL_PCD_FEATURE_FLAG
,
563 MODEL_PCD_DYNAMIC_EX
,
568 MODEL_META_DATA_USER_EXTENSION
]:
569 EdkLogger
.error('Parser', FORMAT_INVALID
,
570 "Section [%s] is not allowed in inf file without version" % (self
._SectionName
),
571 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
572 elif self
._SectionType
in [MODEL_EFI_INCLUDE
,
573 MODEL_EFI_LIBRARY_INSTANCE
,
574 MODEL_META_DATA_NMAKE
]:
575 EdkLogger
.error('Parser', FORMAT_INVALID
,
576 "Section [%s] is not allowed in inf file with version 0x%08x" % (self
._SectionName
, self
._Version
),
577 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
579 # merge two lines specified by '\' in section NMAKE
580 elif self
._SectionType
== MODEL_META_DATA_NMAKE
:
583 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
586 if NextLine
[0] == TAB_SECTION_START
and NextLine
[-1] == TAB_SECTION_END
:
587 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
590 NmakeLine
= NmakeLine
+ ' ' + Line
[0:-1]
593 self
._CurrentLine
= NmakeLine
+ Line
597 self
._ValueList
= ['', '', '']
598 # parse current line, result will be put in self._ValueList
599 self
._SectionParser
[self
._SectionType
](self
)
600 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
605 Comments
.append((Comment
, Index
+ 1))
606 if GlobalData
.gOptions
and GlobalData
.gOptions
.CheckUsage
:
607 CheckInfComment(self
._SectionType
, Comments
, str(self
.MetaFile
), Index
+ 1, self
._ValueList
)
609 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
610 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
612 for Arch
, Platform
in self
._Scope
:
613 LastItem
= self
._Store
(self
._SectionType
,
626 for Comment
, LineNo
in Comments
:
627 self
._Store
(MODEL_META_DATA_COMMENT
, Comment
, '', '', Arch
, Platform
,
628 LastItem
, LineNo
, -1, LineNo
, -1, 0)
631 TailComments
.extend(SectionComments
+ Comments
)
632 if IsFindBlockComment
:
633 EdkLogger
.error("Parser", FORMAT_INVALID
, "Open block comments (starting with /*) are expected to end with */",
636 # If there are tail comments in INF file, save to database whatever the comments are
637 for Comment
in TailComments
:
638 self
._Store
(MODEL_META_DATA_TAIL_COMMENT
, Comment
[0], '', '', 'COMMON',
639 'COMMON', self
._Owner
[-1], -1, -1, -1, -1, 0)
642 ## Data parser for the format in which there's path
644 # Only path can have macro used. So we need to replace them before use.
646 def _IncludeParser(self
):
647 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
648 self
._ValueList
[0:len(TokenList
)] = TokenList
649 Macros
= self
._Macros
651 for Index
in range(0, len(self
._ValueList
)):
652 Value
= self
._ValueList
[Index
]
656 if Value
.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value
.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
657 Value
= '$(EDK_SOURCE)' + Value
[17:]
658 if Value
.find('$(EFI_SOURCE)') > -1 or Value
.find('$(EDK_SOURCE)') > -1:
660 elif Value
.startswith('.'):
662 elif Value
.startswith('$('):
665 Value
= '$(EFI_SOURCE)/' + Value
667 self
._ValueList
[Index
] = ReplaceMacro(Value
, Macros
)
669 ## Parse [Sources] section
671 # Only path can have macro used. So we need to replace them before use.
674 def _SourceFileParser(self
):
675 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
676 self
._ValueList
[0:len(TokenList
)] = TokenList
677 Macros
= self
._Macros
678 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
679 if 'COMPONENT_TYPE' in Macros
:
680 if self
._Defines
['COMPONENT_TYPE'].upper() == 'ACPITABLE':
681 self
._ValueList
[0] = GetSplitValueList(self
._ValueList
[0], ' ', 1)[0]
682 if self
._Defines
['BASE_NAME'] == 'Microcode':
684 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
686 ## Parse [Binaries] section
688 # Only path can have macro used. So we need to replace them before use.
691 def _BinaryFileParser(self
):
692 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 2)
693 if len(TokenList
) < 2:
694 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type or path specified",
695 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
696 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
698 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type specified",
699 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
700 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
702 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file path specified",
703 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
704 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
705 self
._ValueList
[0:len(TokenList
)] = TokenList
706 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
708 ## [nmake] section parser (Edk.x style only)
709 def _NmakeParser(self
):
710 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
711 self
._ValueList
[0:len(TokenList
)] = TokenList
713 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
714 # remove self-reference in macro setting
715 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
717 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
719 def _PcdParser(self
):
720 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
721 ValueList
= GetSplitValueList(TokenList
[0], TAB_SPLIT
)
722 if len(ValueList
) != 2:
723 EdkLogger
.error('Parser', FORMAT_INVALID
, "Illegal token space GUID and PCD name format",
724 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
725 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
726 self
._ValueList
[0:1] = ValueList
727 if len(TokenList
) > 1:
728 self
._ValueList
[2] = TokenList
[1]
729 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
730 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
731 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
732 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
734 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
735 if self
._ValueList
[2] != '':
736 InfPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
737 if InfPcdValueList
[0] in ['True', 'true', 'TRUE']:
738 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '1', 1);
739 elif InfPcdValueList
[0] in ['False', 'false', 'FALSE']:
740 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '0', 1);
741 if (self
._ValueList
[0], self
._ValueList
[1]) not in self
.PcdsDict
:
742 self
.PcdsDict
[self
._ValueList
[0], self
._ValueList
[1]] = self
._SectionType
743 elif self
.PcdsDict
[self
._ValueList
[0], self
._ValueList
[1]] != self
._SectionType
:
744 EdkLogger
.error('Parser', FORMAT_INVALID
, "It is not permissible to list a specified PCD in different PCD type sections.",
745 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
746 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
748 ## [depex] section parser
750 def _DepexParser(self
):
751 self
._ValueList
[0:1] = [self
._CurrentLine
]
754 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
755 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
756 MODEL_META_DATA_BUILD_OPTION
: MetaFileParser
._BuildOptionParser
,
757 MODEL_EFI_INCLUDE
: _IncludeParser
, # for Edk.x modules
758 MODEL_EFI_LIBRARY_INSTANCE
: MetaFileParser
._CommonParser
, # for Edk.x modules
759 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
760 MODEL_META_DATA_PACKAGE
: MetaFileParser
._PathParser
,
761 MODEL_META_DATA_NMAKE
: _NmakeParser
, # for Edk.x modules
762 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
763 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
764 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
765 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
766 MODEL_PCD_DYNAMIC
: _PcdParser
,
767 MODEL_EFI_SOURCE_FILE
: _SourceFileParser
,
768 MODEL_EFI_GUID
: MetaFileParser
._CommonParser
,
769 MODEL_EFI_PROTOCOL
: MetaFileParser
._CommonParser
,
770 MODEL_EFI_PPI
: MetaFileParser
._CommonParser
,
771 MODEL_EFI_DEPEX
: _DepexParser
,
772 MODEL_EFI_BINARY_FILE
: _BinaryFileParser
,
773 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
776 ## DSC file parser class
778 # @param FilePath The path of platform description file
779 # @param FileType The raw data of DSC file
780 # @param Table Database used to retrieve module/package information
781 # @param Macros Macros used for replacement in file
782 # @param Owner Owner ID (for sub-section parsing)
783 # @param From ID from which the data comes (for !INCLUDE directive)
785 class DscParser(MetaFileParser
):
786 # DSC file supported data types (one type per section)
788 TAB_SKUIDS
.upper() : MODEL_EFI_SKU_ID
,
789 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
790 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
791 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
792 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
793 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
794 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
795 TAB_PCDS_DYNAMIC_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_DEFAULT
,
796 TAB_PCDS_DYNAMIC_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_HII
,
797 TAB_PCDS_DYNAMIC_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_VPD
,
798 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT
,
799 TAB_PCDS_DYNAMIC_EX_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_HII
,
800 TAB_PCDS_DYNAMIC_EX_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_VPD
,
801 TAB_COMPONENTS
.upper() : MODEL_META_DATA_COMPONENT
,
802 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH
.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
,
803 TAB_DSC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
804 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
805 TAB_DSC_DEFINES_EDKGLOBAL
: MODEL_META_DATA_GLOBAL_DEFINE
,
806 TAB_INCLUDE
.upper() : MODEL_META_DATA_INCLUDE
,
807 TAB_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
808 TAB_IF_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
809 TAB_IF_N_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
,
810 TAB_ELSE_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
,
811 TAB_ELSE
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
812 TAB_END_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
,
813 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
,
816 # Valid names in define section
823 "PCD_INFO_GENERATION",
824 "PCD_VAR_CHECK_GENERATION",
825 "SUPPORTED_ARCHITECTURES",
834 "FIX_LOAD_TOP_MEMORY_ADDRESS",
839 SubSectionDefineKeywords
= [
843 SymbolPattern
= ValueExpression
.SymbolPattern
845 ## Constructor of DscParser
847 # Initialize object of DscParser
849 # @param FilePath The path of platform description file
850 # @param FileType The raw data of DSC file
851 # @param Table Database used to retrieve module/package information
852 # @param Macros Macros used for replacement in file
853 # @param Owner Owner ID (for sub-section parsing)
854 # @param From ID from which the data comes (for !INCLUDE directive)
856 def __init__(self
, FilePath
, FileType
, Table
, Owner
= -1, From
= -1):
857 # prevent re-initialization
858 if hasattr(self
, "_Table"):
860 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, Owner
, From
)
861 self
._Version
= 0x00010005 # Only EDK2 dsc file is supported
862 # to store conditional directive evaluation result
863 self
._DirectiveStack
= []
864 self
._DirectiveEvalStack
= []
868 # Specify whether current line is in uncertain condition
870 self
._InDirective
= -1
872 # Final valid replacable symbols
875 # Map the ID between the original table and new table to track
878 self
._IdMapping
= {-1:-1}
884 Content
= open(str(self
.MetaFile
), 'r').readlines()
886 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
889 for Index
in range(0, len(Content
)):
890 Line
= CleanString(Content
[Index
])
895 self
._CurrentLine
= Line
896 self
._LineIndex
= Index
897 if self
._InSubsection
and self
._Owner
[-1] == -1:
898 self
._Owner
.append(self
._LastItem
)
901 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
902 self
._SectionType
= MODEL_META_DATA_SECTION_HEADER
904 elif Line
[0] == '}' and self
._InSubsection
:
905 self
._InSubsection
= False
906 self
._SubsectionType
= MODEL_UNKNOWN
907 self
._SubsectionName
= ''
912 elif Line
[0] == TAB_OPTION_START
and Line
[-1] == TAB_OPTION_END
:
913 self
._SubsectionType
= MODEL_META_DATA_SUBSECTION_HEADER
916 self
._DirectiveParser
()
919 if self
._InSubsection
:
920 SectionType
= self
._SubsectionType
922 SectionType
= self
._SectionType
923 self
._ItemType
= SectionType
925 self
._ValueList
= ['', '', '']
926 self
._SectionParser
[SectionType
](self
)
927 if self
._ValueList
== None:
930 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
931 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
933 for Arch
, ModuleType
in self
._Scope
:
934 Owner
= self
._Owner
[-1]
935 if self
._SubsectionType
!= MODEL_UNKNOWN
:
936 Owner
= OwnerId
[Arch
]
937 self
._LastItem
= self
._Store
(
952 if self
._SubsectionType
== MODEL_UNKNOWN
and self
._InSubsection
:
953 OwnerId
[Arch
] = self
._LastItem
955 if self
._DirectiveStack
:
956 Type
, Line
, Text
= self
._DirectiveStack
[-1]
957 EdkLogger
.error('Parser', FORMAT_INVALID
, "No matching '!endif' found",
958 ExtraData
=Text
, File
=self
.MetaFile
, Line
=Line
)
961 ## <subsection_header> parser
962 def _SubsectionHeaderParser(self
):
963 self
._SubsectionName
= self
._CurrentLine
[1:-1].upper()
964 if self
._SubsectionName
in self
.DataType
:
965 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
967 self
._SubsectionType
= MODEL_UNKNOWN
968 EdkLogger
.warn("Parser", "Unrecognized sub-section", File
=self
.MetaFile
,
969 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
970 self
._ValueList
[0] = self
._SubsectionName
972 ## Directive statement parser
973 def _DirectiveParser(self
):
974 self
._ValueList
= ['', '', '']
975 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
976 self
._ValueList
[0:len(TokenList
)] = TokenList
979 DirectiveName
= self
._ValueList
[0].upper()
980 if DirectiveName
not in self
.DataType
:
981 EdkLogger
.error("Parser", FORMAT_INVALID
, "Unknown directive [%s]" % DirectiveName
,
982 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
984 if DirectiveName
in ['!IF', '!IFDEF', '!IFNDEF']:
985 self
._InDirective
+= 1
987 if DirectiveName
in ['!ENDIF']:
988 self
._InDirective
-= 1
990 if DirectiveName
in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self
._ValueList
[1] == '':
991 EdkLogger
.error("Parser", FORMAT_INVALID
, "Missing expression",
992 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
993 ExtraData
=self
._CurrentLine
)
995 ItemType
= self
.DataType
[DirectiveName
]
996 Scope
= [['COMMON', 'COMMON']]
997 if ItemType
== MODEL_META_DATA_INCLUDE
:
999 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1000 # Remove all directives between !if and !endif, including themselves
1001 while self
._DirectiveStack
:
1002 # Remove any !else or !elseif
1003 DirectiveInfo
= self
._DirectiveStack
.pop()
1004 if DirectiveInfo
[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1005 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1006 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1009 EdkLogger
.error("Parser", FORMAT_INVALID
, "Redundant '!endif'",
1010 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
1011 ExtraData
=self
._CurrentLine
)
1012 elif ItemType
!= MODEL_META_DATA_INCLUDE
:
1013 # Break if there's a !else is followed by a !elseif
1014 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
and \
1015 self
._DirectiveStack
and \
1016 self
._DirectiveStack
[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1017 EdkLogger
.error("Parser", FORMAT_INVALID
, "'!elseif' after '!else'",
1018 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
1019 ExtraData
=self
._CurrentLine
)
1020 self
._DirectiveStack
.append((ItemType
, self
._LineIndex
+ 1, self
._CurrentLine
))
1023 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
1024 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
1026 for Arch
, ModuleType
in Scope
:
1027 self
._LastItem
= self
._Store
(
1036 self
._LineIndex
+ 1,
1038 self
._LineIndex
+ 1,
1043 ## [defines] section parser
1045 def _DefineParser(self
):
1046 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1047 self
._ValueList
[1:len(TokenList
)] = TokenList
1050 if not self
._ValueList
[1]:
1051 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
1052 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1053 if not self
._ValueList
[2]:
1054 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
1055 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1056 if (not self
._ValueList
[1] in self
.DefineKeywords
and
1057 (self
._InSubsection
and self
._ValueList
[1] not in self
.SubSectionDefineKeywords
)):
1058 EdkLogger
.error('Parser', FORMAT_INVALID
,
1059 "Unknown keyword found: %s. "
1060 "If this is a macro you must "
1061 "add it as a DEFINE in the DSC" % self
._ValueList
[1],
1062 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1063 if not self
._InSubsection
:
1064 self
._Defines
[self
._ValueList
[1]] = self
._ValueList
[2]
1065 self
._ItemType
= self
.DataType
[TAB_DSC_DEFINES
.upper()]
1068 def _SkuIdParser(self
):
1069 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1070 if len(TokenList
) != 2:
1071 EdkLogger
.error('Parser', FORMAT_INVALID
, "Correct format is '<Integer>|<UiName>'",
1072 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1073 self
._ValueList
[0:len(TokenList
)] = TokenList
1075 ## Parse Edk style of library modules
1077 def _LibraryInstanceParser(self
):
1078 self
._ValueList
[0] = self
._CurrentLine
1080 ## PCD sections parser
1082 # [PcdsFixedAtBuild]
1083 # [PcdsPatchableInModule]
1086 # [PcdsDynamicExDefault]
1087 # [PcdsDynamicExVpd]
1088 # [PcdsDynamicExHii]
1090 # [PcdsDynamicDefault]
1095 def _PcdParser(self
):
1096 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1097 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1098 if len(TokenList
) == 2:
1099 self
._ValueList
[2] = TokenList
[1]
1100 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1101 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1102 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1103 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1104 if self
._ValueList
[2] == '':
1106 # The PCD values are optional for FIXEDATBUILD and PATCHABLEINMODULE
1108 if self
._SectionType
in (MODEL_PCD_FIXED_AT_BUILD
, MODEL_PCD_PATCHABLE_IN_MODULE
):
1110 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD value given",
1111 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1112 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1114 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD
1115 ValueList
= GetSplitValueList(self
._ValueList
[2])
1116 if len(ValueList
) > 1 and ValueList
[1] != TAB_VOID \
1117 and self
._ItemType
in [MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_EX_DEFAULT
]:
1118 EdkLogger
.error('Parser', FORMAT_INVALID
, "The datum type '%s' of PCD is wrong" % ValueList
[1],
1119 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1121 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1122 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
1123 if DscPcdValueList
[0] in ['True', 'true', 'TRUE']:
1124 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '1', 1);
1125 elif DscPcdValueList
[0] in ['False', 'false', 'FALSE']:
1126 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '0', 1);
1129 ## [components] section parser
1131 def _ComponentParser(self
):
1132 if self
._CurrentLine
[-1] == '{':
1133 self
._ValueList
[0] = self
._CurrentLine
[0:-1].strip()
1134 self
._InSubsection
= True
1136 self
._ValueList
[0] = self
._CurrentLine
1138 ## [LibraryClasses] section
1140 def _LibraryClassParser(self
):
1141 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1142 if len(TokenList
) < 2:
1143 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class or instance specified",
1144 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1145 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1146 if TokenList
[0] == '':
1147 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class specified",
1148 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1149 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1150 if TokenList
[1] == '':
1151 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library instance specified",
1152 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1153 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1155 self
._ValueList
[0:len(TokenList
)] = TokenList
1157 def _CompponentSourceOverridePathParser(self
):
1158 self
._ValueList
[0] = self
._CurrentLine
1160 ## [BuildOptions] section parser
1162 def _BuildOptionParser(self
):
1163 self
._CurrentLine
= CleanString(self
._CurrentLine
, BuildOption
=True)
1164 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1165 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
1166 if len(TokenList2
) == 2:
1167 self
._ValueList
[0] = TokenList2
[0] # toolchain family
1168 self
._ValueList
[1] = TokenList2
[1] # keys
1170 self
._ValueList
[1] = TokenList
[0]
1171 if len(TokenList
) == 2: # value
1172 self
._ValueList
[2] = TokenList
[1]
1174 if self
._ValueList
[1].count('_') != 4:
1178 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
1179 ExtraData
=self
._CurrentLine
,
1181 Line
=self
._LineIndex
+ 1
1184 ## Override parent's method since we'll do all macro replacements in parser
1185 def _GetMacros(self
):
1187 Macros
.update(self
._FileLocalMacros
)
1188 Macros
.update(self
._GetApplicableSectionMacro
())
1189 Macros
.update(GlobalData
.gEdkGlobal
)
1190 Macros
.update(GlobalData
.gPlatformDefines
)
1191 Macros
.update(GlobalData
.gCommandLineDefines
)
1192 # PCD cannot be referenced in macro definition
1193 if self
._ItemType
not in [MODEL_META_DATA_DEFINE
, MODEL_META_DATA_GLOBAL_DEFINE
]:
1194 Macros
.update(self
._Symbols
)
1197 def _PostProcess(self
):
1199 MODEL_META_DATA_SECTION_HEADER
: self
.__ProcessSectionHeader
,
1200 MODEL_META_DATA_SUBSECTION_HEADER
: self
.__ProcessSubsectionHeader
,
1201 MODEL_META_DATA_HEADER
: self
.__ProcessDefine
,
1202 MODEL_META_DATA_DEFINE
: self
.__ProcessDefine
,
1203 MODEL_META_DATA_GLOBAL_DEFINE
: self
.__ProcessDefine
,
1204 MODEL_META_DATA_INCLUDE
: self
.__ProcessDirective
,
1205 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
: self
.__ProcessDirective
,
1206 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
: self
.__ProcessDirective
,
1207 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
: self
.__ProcessDirective
,
1208 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
: self
.__ProcessDirective
,
1209 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
: self
.__ProcessDirective
,
1210 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
: self
.__ProcessDirective
,
1211 MODEL_EFI_SKU_ID
: self
.__ProcessSkuId
,
1212 MODEL_EFI_LIBRARY_INSTANCE
: self
.__ProcessLibraryInstance
,
1213 MODEL_EFI_LIBRARY_CLASS
: self
.__ProcessLibraryClass
,
1214 MODEL_PCD_FIXED_AT_BUILD
: self
.__ProcessPcd
,
1215 MODEL_PCD_PATCHABLE_IN_MODULE
: self
.__ProcessPcd
,
1216 MODEL_PCD_FEATURE_FLAG
: self
.__ProcessPcd
,
1217 MODEL_PCD_DYNAMIC_DEFAULT
: self
.__ProcessPcd
,
1218 MODEL_PCD_DYNAMIC_HII
: self
.__ProcessPcd
,
1219 MODEL_PCD_DYNAMIC_VPD
: self
.__ProcessPcd
,
1220 MODEL_PCD_DYNAMIC_EX_DEFAULT
: self
.__ProcessPcd
,
1221 MODEL_PCD_DYNAMIC_EX_HII
: self
.__ProcessPcd
,
1222 MODEL_PCD_DYNAMIC_EX_VPD
: self
.__ProcessPcd
,
1223 MODEL_META_DATA_COMPONENT
: self
.__ProcessComponent
,
1224 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: self
.__ProcessSourceOverridePath
,
1225 MODEL_META_DATA_BUILD_OPTION
: self
.__ProcessBuildOption
,
1226 MODEL_UNKNOWN
: self
._Skip
,
1227 MODEL_META_DATA_USER_EXTENSION
: self
._SkipUserExtension
,
1230 self
._Table
= MetaFileStorage(self
._RawTable
.Cur
, self
.MetaFile
, MODEL_FILE_DSC
, True)
1231 self
._Table
.Create()
1232 self
._DirectiveStack
= []
1233 self
._DirectiveEvalStack
= []
1234 self
._FileWithError
= self
.MetaFile
1235 self
._FileLocalMacros
= {}
1236 self
._SectionsMacroDict
= {}
1237 GlobalData
.gPlatformDefines
= {}
1239 # Get all macro and PCD which has straitforward value
1240 self
.__RetrievePcdValue
()
1241 self
._Content
= self
._RawTable
.GetAll()
1242 self
._ContentIndex
= 0
1243 self
._InSubsection
= False
1244 while self
._ContentIndex
< len(self
._Content
) :
1245 Id
, self
._ItemType
, V1
, V2
, V3
, S1
, S2
, Owner
, self
._From
, \
1246 LineStart
, ColStart
, LineEnd
, ColEnd
, Enabled
= self
._Content
[self
._ContentIndex
]
1249 self
._FileWithError
= self
.MetaFile
1251 self
._ContentIndex
+= 1
1253 self
._Scope
= [[S1
, S2
]]
1255 # For !include directive, handle it specially,
1256 # merge arch and module type in case of duplicate items
1258 while self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1259 if self
._ContentIndex
>= len(self
._Content
):
1261 Record
= self
._Content
[self
._ContentIndex
]
1262 if LineStart
== Record
[9] and LineEnd
== Record
[11]:
1263 if [Record
[5], Record
[6]] not in self
._Scope
:
1264 self
._Scope
.append([Record
[5], Record
[6]])
1265 self
._ContentIndex
+= 1
1269 self
._LineIndex
= LineStart
- 1
1270 self
._ValueList
= [V1
, V2
, V3
]
1272 if Owner
> 0 and Owner
in self
._IdMapping
:
1273 self
._InSubsection
= True
1275 self
._InSubsection
= False
1277 Processer
[self
._ItemType
]()
1278 except EvaluationException
, Excpt
:
1280 # Only catch expression evaluation error here. We need to report
1281 # the precise number of line on which the error occurred
1283 if hasattr(Excpt
, 'Pcd'):
1284 if Excpt
.Pcd
in GlobalData
.gPlatformOtherPcds
:
1285 Info
= GlobalData
.gPlatformOtherPcds
[Excpt
.Pcd
]
1286 EdkLogger
.error('Parser', FORMAT_INVALID
, "Cannot use this PCD (%s) in an expression as"
1287 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
1288 " of the DSC file, and it is currently defined in this section:"
1289 " %s, line #: %d." % (Excpt
.Pcd
, Info
[0], Info
[1]),
1290 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1291 Line
=self
._LineIndex
+ 1)
1293 EdkLogger
.error('Parser', FORMAT_INVALID
, "PCD (%s) is not defined in DSC file" % Excpt
.Pcd
,
1294 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1295 Line
=self
._LineIndex
+ 1)
1297 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid expression: %s" % str(Excpt
),
1298 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1299 Line
=self
._LineIndex
+ 1)
1300 except MacroException
, Excpt
:
1301 EdkLogger
.error('Parser', FORMAT_INVALID
, str(Excpt
),
1302 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1303 Line
=self
._LineIndex
+ 1)
1305 if self
._ValueList
== None:
1308 NewOwner
= self
._IdMapping
.get(Owner
, -1)
1309 self
._Enabled
= int((not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
))
1310 self
._LastItem
= self
._Store
(
1319 self
._LineIndex
+ 1,
1321 self
._LineIndex
+ 1,
1325 self
._IdMapping
[Id
] = self
._LastItem
1327 GlobalData
.gPlatformDefines
.update(self
._FileLocalMacros
)
1328 self
._PostProcessed
= True
1329 self
._Content
= None
1331 def __ProcessSectionHeader(self
):
1332 self
._SectionName
= self
._ValueList
[0]
1333 if self
._SectionName
in self
.DataType
:
1334 self
._SectionType
= self
.DataType
[self
._SectionName
]
1336 self
._SectionType
= MODEL_UNKNOWN
1338 def __ProcessSubsectionHeader(self
):
1339 self
._SubsectionName
= self
._ValueList
[0]
1340 if self
._SubsectionName
in self
.DataType
:
1341 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
1343 self
._SubsectionType
= MODEL_UNKNOWN
1345 def __RetrievePcdValue(self
):
1346 Content
= open(str(self
.MetaFile
), 'r').readlines()
1347 GlobalData
.gPlatformOtherPcds
['DSCFILE'] = str(self
.MetaFile
)
1348 for PcdType
in (MODEL_PCD_PATCHABLE_IN_MODULE
, MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_HII
,
1349 MODEL_PCD_DYNAMIC_VPD
, MODEL_PCD_DYNAMIC_EX_DEFAULT
, MODEL_PCD_DYNAMIC_EX_HII
,
1350 MODEL_PCD_DYNAMIC_EX_VPD
):
1351 Records
= self
._RawTable
.Query(PcdType
, BelongsToItem
= -1.0)
1352 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1353 Name
= TokenSpaceGuid
+ '.' + PcdName
1354 if Name
not in GlobalData
.gPlatformOtherPcds
:
1356 while not Content
[Line
- 1].lstrip().startswith(TAB_SECTION_START
):
1358 GlobalData
.gPlatformOtherPcds
[Name
] = (CleanString(Content
[Line
- 1]), PcdLine
, PcdType
)
1360 def __ProcessDefine(self
):
1361 if not self
._Enabled
:
1364 Type
, Name
, Value
= self
._ValueList
1365 Value
= ReplaceMacro(Value
, self
._Macros
, False)
1367 # If it is <Defines>, return
1369 if self
._InSubsection
:
1370 self
._ValueList
= [Type
, Name
, Value
]
1373 if self
._ItemType
== MODEL_META_DATA_DEFINE
:
1374 if self
._SectionType
== MODEL_META_DATA_HEADER
:
1375 self
._FileLocalMacros
[Name
] = Value
1377 self
._ConstructSectionMacroDict
(Name
, Value
)
1378 elif self
._ItemType
== MODEL_META_DATA_GLOBAL_DEFINE
:
1379 GlobalData
.gEdkGlobal
[Name
] = Value
1382 # Keyword in [Defines] section can be used as Macros
1384 if (self
._ItemType
== MODEL_META_DATA_HEADER
) and (self
._SectionType
== MODEL_META_DATA_HEADER
):
1385 self
._FileLocalMacros
[Name
] = Value
1387 self
._ValueList
= [Type
, Name
, Value
]
1389 def __ProcessDirective(self
):
1391 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1392 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
]:
1393 Macros
= self
._Macros
1394 Macros
.update(GlobalData
.gGlobalDefines
)
1396 Result
= ValueExpression(self
._ValueList
[1], Macros
)()
1397 except SymbolNotFound
, Exc
:
1398 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1400 except WrnExpression
, Excpt
:
1402 # Catch expression evaluation warning here. We need to report
1403 # the precise number of line and return the evaluation result
1405 EdkLogger
.warn('Parser', "Suspicious expression: %s" % str(Excpt
),
1406 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1407 Line
=self
._LineIndex
+ 1)
1408 Result
= Excpt
.result
1410 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1411 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1412 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1413 self
._DirectiveStack
.append(self
._ItemType
)
1414 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
:
1415 Result
= bool(Result
)
1417 Macro
= self
._ValueList
[1]
1418 Macro
= Macro
[2:-1] if (Macro
.startswith("$(") and Macro
.endswith(")")) else Macro
1419 Result
= Macro
in self
._Macros
1420 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
:
1422 self
._DirectiveEvalStack
.append(Result
)
1423 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
:
1424 self
._DirectiveStack
.append(self
._ItemType
)
1425 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1426 self
._DirectiveEvalStack
.append(bool(Result
))
1427 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1428 self
._DirectiveStack
.append(self
._ItemType
)
1429 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1430 self
._DirectiveEvalStack
.append(True)
1431 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1432 # Back to the nearest !if/!ifdef/!ifndef
1433 while self
._DirectiveStack
:
1434 self
._DirectiveEvalStack
.pop()
1435 Directive
= self
._DirectiveStack
.pop()
1436 if Directive
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1437 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1438 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1440 elif self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1441 # The included file must be relative to workspace or same directory as DSC file
1442 __IncludeMacros
= {}
1444 # Allow using system environment variables in path after !include
1446 __IncludeMacros
['WORKSPACE'] = GlobalData
.gGlobalDefines
['WORKSPACE']
1447 if "ECP_SOURCE" in GlobalData
.gGlobalDefines
.keys():
1448 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gGlobalDefines
['ECP_SOURCE']
1450 # During GenFds phase call DSC parser, will go into this branch.
1452 elif "ECP_SOURCE" in GlobalData
.gCommandLineDefines
.keys():
1453 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gCommandLineDefines
['ECP_SOURCE']
1455 __IncludeMacros
['EFI_SOURCE'] = GlobalData
.gGlobalDefines
['EFI_SOURCE']
1456 __IncludeMacros
['EDK_SOURCE'] = GlobalData
.gGlobalDefines
['EDK_SOURCE']
1458 # Allow using MACROs comes from [Defines] section to keep compatible.
1460 __IncludeMacros
.update(self
._Macros
)
1462 IncludedFile
= NormPath(ReplaceMacro(self
._ValueList
[1], __IncludeMacros
, RaiseError
=True))
1464 # First search the include file under the same directory as DSC file
1466 IncludedFile1
= PathClass(IncludedFile
, self
.MetaFile
.Dir
)
1467 ErrorCode
, ErrorInfo1
= IncludedFile1
.Validate()
1470 # Also search file under the WORKSPACE directory
1472 IncludedFile1
= PathClass(IncludedFile
, GlobalData
.gWorkspace
)
1473 ErrorCode
, ErrorInfo2
= IncludedFile1
.Validate()
1475 EdkLogger
.error('parser', ErrorCode
, File
=self
._FileWithError
,
1476 Line
=self
._LineIndex
+ 1, ExtraData
=ErrorInfo1
+ "\n" + ErrorInfo2
)
1478 self
._FileWithError
= IncludedFile1
1480 IncludedFileTable
= MetaFileStorage(self
._Table
.Cur
, IncludedFile1
, MODEL_FILE_DSC
, False)
1481 Owner
= self
._Content
[self
._ContentIndex
- 1][0]
1482 Parser
= DscParser(IncludedFile1
, self
._FileType
, IncludedFileTable
,
1483 Owner
=Owner
, From
=Owner
)
1485 # Does not allow lower level included file to include upper level included file
1486 if Parser
._From
!= Owner
and int(Owner
) > int (Parser
._From
):
1487 EdkLogger
.error('parser', FILE_ALREADY_EXIST
, File
=self
._FileWithError
,
1488 Line
=self
._LineIndex
+ 1, ExtraData
="{0} is already included at a higher level.".format(IncludedFile1
))
1491 # set the parser status with current status
1492 Parser
._SectionName
= self
._SectionName
1493 Parser
._SectionType
= self
._SectionType
1494 Parser
._Scope
= self
._Scope
1495 Parser
._Enabled
= self
._Enabled
1496 # Parse the included file
1499 # update current status with sub-parser's status
1500 self
._SectionName
= Parser
._SectionName
1501 self
._SectionType
= Parser
._SectionType
1502 self
._Scope
= Parser
._Scope
1503 self
._Enabled
= Parser
._Enabled
1505 # Insert all records in the table for the included file into dsc file table
1506 Records
= IncludedFileTable
.GetAll()
1508 self
._Content
[self
._ContentIndex
:self
._ContentIndex
] = Records
1509 self
._Content
.pop(self
._ContentIndex
- 1)
1510 self
._ValueList
= None
1511 self
._ContentIndex
-= 1
1513 def __ProcessSkuId(self
):
1514 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=True)
1515 for Value
in self
._ValueList
]
1517 def __ProcessLibraryInstance(self
):
1518 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
1520 def __ProcessLibraryClass(self
):
1521 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, RaiseError
=True)
1523 def __ProcessPcd(self
):
1524 if self
._ItemType
not in [MODEL_PCD_FEATURE_FLAG
, MODEL_PCD_FIXED_AT_BUILD
]:
1525 self
._ValueList
[2] = ReplaceMacro(self
._ValueList
[2], self
._Macros
, RaiseError
=True)
1528 ValList
, Valid
, Index
= AnalyzeDscPcd(self
._ValueList
[2], self
._ItemType
)
1530 EdkLogger
.error('build', FORMAT_INVALID
, "Pcd format incorrect.", File
=self
._FileWithError
, Line
=self
._LineIndex
+ 1,
1531 ExtraData
="%s.%s|%s" % (self
._ValueList
[0], self
._ValueList
[1], self
._ValueList
[2]))
1532 PcdValue
= ValList
[Index
]
1535 ValList
[Index
] = ValueExpression(PcdValue
, self
._Macros
)(True)
1536 except WrnExpression
, Value
:
1537 ValList
[Index
] = Value
.result
1539 if ValList
[Index
] == 'True':
1540 ValList
[Index
] = '1'
1541 if ValList
[Index
] == 'False':
1542 ValList
[Index
] = '0'
1544 if (not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
):
1545 GlobalData
.gPlatformPcds
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = PcdValue
1546 self
._Symbols
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = PcdValue
1547 self
._ValueList
[2] = '|'.join(ValList
)
1549 def __ProcessComponent(self
):
1550 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1552 def __ProcessSourceOverridePath(self
):
1553 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1555 def __ProcessBuildOption(self
):
1556 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=False)
1557 for Value
in self
._ValueList
]
1560 MODEL_META_DATA_HEADER
: _DefineParser
,
1561 MODEL_EFI_SKU_ID
: _SkuIdParser
,
1562 MODEL_EFI_LIBRARY_INSTANCE
: _LibraryInstanceParser
,
1563 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
1564 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1565 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1566 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1567 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
1568 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
1569 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
1570 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
1571 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
1572 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
1573 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
1574 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: _CompponentSourceOverridePathParser
,
1575 MODEL_META_DATA_BUILD_OPTION
: _BuildOptionParser
,
1576 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1577 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
1578 MODEL_META_DATA_SECTION_HEADER
: MetaFileParser
._SectionHeaderParser
,
1579 MODEL_META_DATA_SUBSECTION_HEADER
: _SubsectionHeaderParser
,
1582 _Macros
= property(_GetMacros
)
1584 ## DEC file parser class
1586 # @param FilePath The path of platform description file
1587 # @param FileType The raw data of DSC file
1588 # @param Table Database used to retrieve module/package information
1589 # @param Macros Macros used for replacement in file
1591 class DecParser(MetaFileParser
):
1592 # DEC file supported data types (one type per section)
1594 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1595 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
1596 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1597 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1598 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1599 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1600 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1601 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1602 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1603 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1604 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1605 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1606 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
,
1609 ## Constructor of DecParser
1611 # Initialize object of DecParser
1613 # @param FilePath The path of platform description file
1614 # @param FileType The raw data of DSC file
1615 # @param Table Database used to retrieve module/package information
1616 # @param Macros Macros used for replacement in file
1618 def __init__(self
, FilePath
, FileType
, Table
):
1619 # prevent re-initialization
1620 if hasattr(self
, "_Table"):
1622 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, -1)
1624 self
._Version
= 0x00010005 # Only EDK2 dec file is supported
1625 self
._AllPCDs
= [] # Only for check duplicate PCD
1631 Content
= open(str(self
.MetaFile
), 'r').readlines()
1633 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1635 for Index
in range(0, len(Content
)):
1636 Line
, Comment
= CleanString2(Content
[Index
])
1637 self
._CurrentLine
= Line
1638 self
._LineIndex
= Index
1640 # save comment for later use
1642 self
._Comments
.append((Comment
, self
._LineIndex
+ 1))
1648 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1649 self
._SectionHeaderParser
()
1652 elif len(self
._SectionType
) == 0:
1657 self
._ValueList
= ['', '', '']
1658 self
._SectionParser
[self
._SectionType
[0]](self
)
1659 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
1665 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1666 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1668 for Arch
, ModuleType
, Type
in self
._Scope
:
1669 self
._LastItem
= self
._Store
(
1677 self
._LineIndex
+ 1,
1679 self
._LineIndex
+ 1,
1683 for Comment
, LineNo
in self
._Comments
:
1685 MODEL_META_DATA_COMMENT
,
1702 ## Section header parser
1704 # The section header is always in following format:
1706 # [section_name.arch<.platform|module_type>]
1708 def _SectionHeaderParser(self
):
1710 self
._SectionName
= ''
1711 self
._SectionType
= []
1713 Line
= self
._CurrentLine
.replace("%s%s" % (TAB_COMMA_SPLIT
, TAB_SPACE_SPLIT
), TAB_COMMA_SPLIT
)
1714 for Item
in Line
[1:-1].split(TAB_COMMA_SPLIT
):
1716 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
,
1717 "section name can NOT be empty or incorrectly use separator comma",
1718 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1719 ItemList
= Item
.split(TAB_SPLIT
)
1721 # different types of PCD are permissible in one section
1722 self
._SectionName
= ItemList
[0].upper()
1723 if self
._SectionName
in self
.DataType
:
1724 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1725 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1727 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
1728 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1730 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1734 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1736 Line
=self
._LineIndex
+ 1,
1737 ExtraData
=self
._CurrentLine
1740 if len(ItemList
) > 1:
1741 S1
= ItemList
[1].upper()
1745 # S2 may be Platform or ModuleType
1746 if len(ItemList
) > 2:
1747 S2
= ItemList
[2].upper()
1750 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1751 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1753 # 'COMMON' must not be used with specific ARCHs at the same section
1754 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1755 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1756 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
1758 ## [guids], [ppis] and [protocols] section parser
1760 def _GuidParser(self
):
1761 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1762 if len(TokenList
) < 2:
1763 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1764 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1765 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1766 if TokenList
[0] == '':
1767 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1768 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1769 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1770 if TokenList
[1] == '':
1771 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1772 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1773 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1774 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1775 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1776 ExtraData
=self
._CurrentLine
+ \
1777 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1778 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1779 self
._ValueList
[0] = TokenList
[0]
1780 self
._ValueList
[1] = TokenList
[1]
1782 ## PCD sections parser
1784 # [PcdsFixedAtBuild]
1785 # [PcdsPatchableInModule]
1791 def _PcdParser(self
):
1792 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1793 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1794 ValueRe
= re
.compile(r
'^[a-zA-Z_][a-zA-Z0-9_]*')
1795 # check PCD information
1796 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1797 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1798 ExtraData
=self
._CurrentLine
+ \
1799 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1800 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1801 # check format of token space GUID CName
1802 if not ValueRe
.match(self
._ValueList
[0]):
1803 EdkLogger
.error('Parser', FORMAT_INVALID
, "The format of the token space GUID CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
1804 ExtraData
=self
._CurrentLine
+ \
1805 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1806 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1807 # check format of PCD CName
1808 if not ValueRe
.match(self
._ValueList
[1]):
1809 EdkLogger
.error('Parser', FORMAT_INVALID
, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
1810 ExtraData
=self
._CurrentLine
+ \
1811 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1812 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1813 # check PCD datum information
1814 if len(TokenList
) < 2 or TokenList
[1] == '':
1815 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1816 ExtraData
=self
._CurrentLine
+ \
1817 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1818 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1821 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1822 PtrValue
= ValueRe
.findall(TokenList
[1])
1824 # Has VOID* type string, may contain "|" character in the string.
1825 if len(PtrValue
) != 0:
1826 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1827 ValueList
= GetSplitValueList(ptrValueList
)
1828 ValueList
[0] = PtrValue
[0]
1830 ValueList
= GetSplitValueList(TokenList
[1])
1833 # check if there's enough datum information given
1834 if len(ValueList
) != 3:
1835 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1836 ExtraData
=self
._CurrentLine
+ \
1837 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1838 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1839 # check default value
1840 if ValueList
[0] == '':
1841 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1842 ExtraData
=self
._CurrentLine
+ \
1843 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1844 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1846 if ValueList
[1] == '':
1847 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1848 ExtraData
=self
._CurrentLine
+ \
1849 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1850 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1851 # check token of the PCD
1852 if ValueList
[2] == '':
1853 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1854 ExtraData
=self
._CurrentLine
+ \
1855 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1856 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1857 # check format of default value against the datum type
1858 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1860 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1861 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1863 if ValueList
[0] in ['True', 'true', 'TRUE']:
1865 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1868 # check for duplicate PCD definition
1869 if (self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]) in self
._AllPCDs
:
1870 EdkLogger
.error('Parser', FORMAT_INVALID
,
1871 "The same PCD name and GUID have been already defined",
1872 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1874 self
._AllPCDs
.append((self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]))
1876 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
1879 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
1880 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
1881 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
1882 MODEL_EFI_GUID
: _GuidParser
,
1883 MODEL_EFI_PPI
: _GuidParser
,
1884 MODEL_EFI_PROTOCOL
: _GuidParser
,
1885 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1886 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1887 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1888 MODEL_PCD_DYNAMIC
: _PcdParser
,
1889 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
1890 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1891 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
1896 # This acts like the main() function for the script, unless it is 'import'ed into another
1899 if __name__
== '__main__':