2 # This file is used to parse meta files
4 # Copyright (c) 2008 - 2015, 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"
837 SubSectionDefineKeywords
= [
841 SymbolPattern
= ValueExpression
.SymbolPattern
843 ## Constructor of DscParser
845 # Initialize object of DscParser
847 # @param FilePath The path of platform description file
848 # @param FileType The raw data of DSC file
849 # @param Table Database used to retrieve module/package information
850 # @param Macros Macros used for replacement in file
851 # @param Owner Owner ID (for sub-section parsing)
852 # @param From ID from which the data comes (for !INCLUDE directive)
854 def __init__(self
, FilePath
, FileType
, Table
, Owner
= -1, From
= -1):
855 # prevent re-initialization
856 if hasattr(self
, "_Table"):
858 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, Owner
, From
)
859 self
._Version
= 0x00010005 # Only EDK2 dsc file is supported
860 # to store conditional directive evaluation result
861 self
._DirectiveStack
= []
862 self
._DirectiveEvalStack
= []
866 # Specify whether current line is in uncertain condition
868 self
._InDirective
= -1
870 # Final valid replacable symbols
873 # Map the ID between the original table and new table to track
876 self
._IdMapping
= {-1:-1}
882 Content
= open(str(self
.MetaFile
), 'r').readlines()
884 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
887 for Index
in range(0, len(Content
)):
888 Line
= CleanString(Content
[Index
])
893 self
._CurrentLine
= Line
894 self
._LineIndex
= Index
895 if self
._InSubsection
and self
._Owner
[-1] == -1:
896 self
._Owner
.append(self
._LastItem
)
899 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
900 self
._SectionType
= MODEL_META_DATA_SECTION_HEADER
902 elif Line
[0] == '}' and self
._InSubsection
:
903 self
._InSubsection
= False
904 self
._SubsectionType
= MODEL_UNKNOWN
905 self
._SubsectionName
= ''
910 elif Line
[0] == TAB_OPTION_START
and Line
[-1] == TAB_OPTION_END
:
911 self
._SubsectionType
= MODEL_META_DATA_SUBSECTION_HEADER
914 self
._DirectiveParser
()
917 if self
._InSubsection
:
918 SectionType
= self
._SubsectionType
920 SectionType
= self
._SectionType
921 self
._ItemType
= SectionType
923 self
._ValueList
= ['', '', '']
924 self
._SectionParser
[SectionType
](self
)
925 if self
._ValueList
== None:
928 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
929 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
931 for Arch
, ModuleType
in self
._Scope
:
932 Owner
= self
._Owner
[-1]
933 if self
._SubsectionType
!= MODEL_UNKNOWN
:
934 Owner
= OwnerId
[Arch
]
935 self
._LastItem
= self
._Store
(
950 if self
._SubsectionType
== MODEL_UNKNOWN
and self
._InSubsection
:
951 OwnerId
[Arch
] = self
._LastItem
953 if self
._DirectiveStack
:
954 Type
, Line
, Text
= self
._DirectiveStack
[-1]
955 EdkLogger
.error('Parser', FORMAT_INVALID
, "No matching '!endif' found",
956 ExtraData
=Text
, File
=self
.MetaFile
, Line
=Line
)
959 ## <subsection_header> parser
960 def _SubsectionHeaderParser(self
):
961 self
._SubsectionName
= self
._CurrentLine
[1:-1].upper()
962 if self
._SubsectionName
in self
.DataType
:
963 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
965 self
._SubsectionType
= MODEL_UNKNOWN
966 EdkLogger
.warn("Parser", "Unrecognized sub-section", File
=self
.MetaFile
,
967 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
968 self
._ValueList
[0] = self
._SubsectionName
970 ## Directive statement parser
971 def _DirectiveParser(self
):
972 self
._ValueList
= ['', '', '']
973 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
974 self
._ValueList
[0:len(TokenList
)] = TokenList
977 DirectiveName
= self
._ValueList
[0].upper()
978 if DirectiveName
not in self
.DataType
:
979 EdkLogger
.error("Parser", FORMAT_INVALID
, "Unknown directive [%s]" % DirectiveName
,
980 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
982 if DirectiveName
in ['!IF', '!IFDEF', '!IFNDEF']:
983 self
._InDirective
+= 1
985 if DirectiveName
in ['!ENDIF']:
986 self
._InDirective
-= 1
988 if DirectiveName
in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self
._ValueList
[1] == '':
989 EdkLogger
.error("Parser", FORMAT_INVALID
, "Missing expression",
990 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
991 ExtraData
=self
._CurrentLine
)
993 ItemType
= self
.DataType
[DirectiveName
]
994 Scope
= [['COMMON', 'COMMON']]
995 if ItemType
== MODEL_META_DATA_INCLUDE
:
997 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
998 # Remove all directives between !if and !endif, including themselves
999 while self
._DirectiveStack
:
1000 # Remove any !else or !elseif
1001 DirectiveInfo
= self
._DirectiveStack
.pop()
1002 if DirectiveInfo
[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1003 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1004 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1007 EdkLogger
.error("Parser", FORMAT_INVALID
, "Redundant '!endif'",
1008 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
1009 ExtraData
=self
._CurrentLine
)
1010 elif ItemType
!= MODEL_META_DATA_INCLUDE
:
1011 # Break if there's a !else is followed by a !elseif
1012 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
and \
1013 self
._DirectiveStack
and \
1014 self
._DirectiveStack
[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1015 EdkLogger
.error("Parser", FORMAT_INVALID
, "'!elseif' after '!else'",
1016 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
1017 ExtraData
=self
._CurrentLine
)
1018 self
._DirectiveStack
.append((ItemType
, self
._LineIndex
+ 1, self
._CurrentLine
))
1021 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
1022 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
1024 for Arch
, ModuleType
in Scope
:
1025 self
._LastItem
= self
._Store
(
1034 self
._LineIndex
+ 1,
1036 self
._LineIndex
+ 1,
1041 ## [defines] section parser
1043 def _DefineParser(self
):
1044 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1045 self
._ValueList
[1:len(TokenList
)] = TokenList
1048 if not self
._ValueList
[1]:
1049 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
1050 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1051 if not self
._ValueList
[2]:
1052 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
1053 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1054 if (not self
._ValueList
[1] in self
.DefineKeywords
and
1055 (self
._InSubsection
and self
._ValueList
[1] not in self
.SubSectionDefineKeywords
)):
1056 EdkLogger
.error('Parser', FORMAT_INVALID
,
1057 "Unknown keyword found: %s. "
1058 "If this is a macro you must "
1059 "add it as a DEFINE in the DSC" % self
._ValueList
[1],
1060 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1061 if not self
._InSubsection
:
1062 self
._Defines
[self
._ValueList
[1]] = self
._ValueList
[2]
1063 self
._ItemType
= self
.DataType
[TAB_DSC_DEFINES
.upper()]
1066 def _SkuIdParser(self
):
1067 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1068 if len(TokenList
) != 2:
1069 EdkLogger
.error('Parser', FORMAT_INVALID
, "Correct format is '<Integer>|<UiName>'",
1070 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1071 self
._ValueList
[0:len(TokenList
)] = TokenList
1073 ## Parse Edk style of library modules
1075 def _LibraryInstanceParser(self
):
1076 self
._ValueList
[0] = self
._CurrentLine
1078 ## PCD sections parser
1080 # [PcdsFixedAtBuild]
1081 # [PcdsPatchableInModule]
1084 # [PcdsDynamicExDefault]
1085 # [PcdsDynamicExVpd]
1086 # [PcdsDynamicExHii]
1088 # [PcdsDynamicDefault]
1093 def _PcdParser(self
):
1094 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1095 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1096 if len(TokenList
) == 2:
1097 self
._ValueList
[2] = TokenList
[1]
1098 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1099 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1100 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1101 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1102 if self
._ValueList
[2] == '':
1104 # The PCD values are optional for FIXEDATBUILD and PATCHABLEINMODULE
1106 if self
._SectionType
in (MODEL_PCD_FIXED_AT_BUILD
, MODEL_PCD_PATCHABLE_IN_MODULE
):
1108 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD value given",
1109 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1110 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1112 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD
1113 ValueList
= GetSplitValueList(self
._ValueList
[2])
1114 if len(ValueList
) > 1 and ValueList
[1] != TAB_VOID \
1115 and self
._ItemType
in [MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_EX_DEFAULT
]:
1116 EdkLogger
.error('Parser', FORMAT_INVALID
, "The datum type '%s' of PCD is wrong" % ValueList
[1],
1117 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1119 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1120 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
1121 if DscPcdValueList
[0] in ['True', 'true', 'TRUE']:
1122 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '1', 1);
1123 elif DscPcdValueList
[0] in ['False', 'false', 'FALSE']:
1124 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '0', 1);
1127 ## [components] section parser
1129 def _ComponentParser(self
):
1130 if self
._CurrentLine
[-1] == '{':
1131 self
._ValueList
[0] = self
._CurrentLine
[0:-1].strip()
1132 self
._InSubsection
= True
1134 self
._ValueList
[0] = self
._CurrentLine
1136 ## [LibraryClasses] section
1138 def _LibraryClassParser(self
):
1139 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1140 if len(TokenList
) < 2:
1141 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class or instance specified",
1142 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1143 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1144 if TokenList
[0] == '':
1145 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class specified",
1146 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1147 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1148 if TokenList
[1] == '':
1149 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library instance specified",
1150 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1151 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1153 self
._ValueList
[0:len(TokenList
)] = TokenList
1155 def _CompponentSourceOverridePathParser(self
):
1156 self
._ValueList
[0] = self
._CurrentLine
1158 ## [BuildOptions] section parser
1160 def _BuildOptionParser(self
):
1161 self
._CurrentLine
= CleanString(self
._CurrentLine
, BuildOption
=True)
1162 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1163 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
1164 if len(TokenList2
) == 2:
1165 self
._ValueList
[0] = TokenList2
[0] # toolchain family
1166 self
._ValueList
[1] = TokenList2
[1] # keys
1168 self
._ValueList
[1] = TokenList
[0]
1169 if len(TokenList
) == 2: # value
1170 self
._ValueList
[2] = TokenList
[1]
1172 if self
._ValueList
[1].count('_') != 4:
1176 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
1177 ExtraData
=self
._CurrentLine
,
1179 Line
=self
._LineIndex
+ 1
1182 ## Override parent's method since we'll do all macro replacements in parser
1183 def _GetMacros(self
):
1185 Macros
.update(self
._FileLocalMacros
)
1186 Macros
.update(self
._GetApplicableSectionMacro
())
1187 Macros
.update(GlobalData
.gEdkGlobal
)
1188 Macros
.update(GlobalData
.gPlatformDefines
)
1189 Macros
.update(GlobalData
.gCommandLineDefines
)
1190 # PCD cannot be referenced in macro definition
1191 if self
._ItemType
not in [MODEL_META_DATA_DEFINE
, MODEL_META_DATA_GLOBAL_DEFINE
]:
1192 Macros
.update(self
._Symbols
)
1195 def _PostProcess(self
):
1197 MODEL_META_DATA_SECTION_HEADER
: self
.__ProcessSectionHeader
,
1198 MODEL_META_DATA_SUBSECTION_HEADER
: self
.__ProcessSubsectionHeader
,
1199 MODEL_META_DATA_HEADER
: self
.__ProcessDefine
,
1200 MODEL_META_DATA_DEFINE
: self
.__ProcessDefine
,
1201 MODEL_META_DATA_GLOBAL_DEFINE
: self
.__ProcessDefine
,
1202 MODEL_META_DATA_INCLUDE
: self
.__ProcessDirective
,
1203 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
: self
.__ProcessDirective
,
1204 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
: self
.__ProcessDirective
,
1205 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
: self
.__ProcessDirective
,
1206 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
: self
.__ProcessDirective
,
1207 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
: self
.__ProcessDirective
,
1208 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
: self
.__ProcessDirective
,
1209 MODEL_EFI_SKU_ID
: self
.__ProcessSkuId
,
1210 MODEL_EFI_LIBRARY_INSTANCE
: self
.__ProcessLibraryInstance
,
1211 MODEL_EFI_LIBRARY_CLASS
: self
.__ProcessLibraryClass
,
1212 MODEL_PCD_FIXED_AT_BUILD
: self
.__ProcessPcd
,
1213 MODEL_PCD_PATCHABLE_IN_MODULE
: self
.__ProcessPcd
,
1214 MODEL_PCD_FEATURE_FLAG
: self
.__ProcessPcd
,
1215 MODEL_PCD_DYNAMIC_DEFAULT
: self
.__ProcessPcd
,
1216 MODEL_PCD_DYNAMIC_HII
: self
.__ProcessPcd
,
1217 MODEL_PCD_DYNAMIC_VPD
: self
.__ProcessPcd
,
1218 MODEL_PCD_DYNAMIC_EX_DEFAULT
: self
.__ProcessPcd
,
1219 MODEL_PCD_DYNAMIC_EX_HII
: self
.__ProcessPcd
,
1220 MODEL_PCD_DYNAMIC_EX_VPD
: self
.__ProcessPcd
,
1221 MODEL_META_DATA_COMPONENT
: self
.__ProcessComponent
,
1222 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: self
.__ProcessSourceOverridePath
,
1223 MODEL_META_DATA_BUILD_OPTION
: self
.__ProcessBuildOption
,
1224 MODEL_UNKNOWN
: self
._Skip
,
1225 MODEL_META_DATA_USER_EXTENSION
: self
._SkipUserExtension
,
1228 self
._Table
= MetaFileStorage(self
._RawTable
.Cur
, self
.MetaFile
, MODEL_FILE_DSC
, True)
1229 self
._Table
.Create()
1230 self
._DirectiveStack
= []
1231 self
._DirectiveEvalStack
= []
1232 self
._FileWithError
= self
.MetaFile
1233 self
._FileLocalMacros
= {}
1234 self
._SectionsMacroDict
= {}
1235 GlobalData
.gPlatformDefines
= {}
1237 # Get all macro and PCD which has straitforward value
1238 self
.__RetrievePcdValue
()
1239 self
._Content
= self
._RawTable
.GetAll()
1240 self
._ContentIndex
= 0
1241 self
._InSubsection
= False
1242 while self
._ContentIndex
< len(self
._Content
) :
1243 Id
, self
._ItemType
, V1
, V2
, V3
, S1
, S2
, Owner
, self
._From
, \
1244 LineStart
, ColStart
, LineEnd
, ColEnd
, Enabled
= self
._Content
[self
._ContentIndex
]
1247 self
._FileWithError
= self
.MetaFile
1249 self
._ContentIndex
+= 1
1251 self
._Scope
= [[S1
, S2
]]
1253 # For !include directive, handle it specially,
1254 # merge arch and module type in case of duplicate items
1256 while self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1257 if self
._ContentIndex
>= len(self
._Content
):
1259 Record
= self
._Content
[self
._ContentIndex
]
1260 if LineStart
== Record
[9] and LineEnd
== Record
[11]:
1261 if [Record
[5], Record
[6]] not in self
._Scope
:
1262 self
._Scope
.append([Record
[5], Record
[6]])
1263 self
._ContentIndex
+= 1
1267 self
._LineIndex
= LineStart
- 1
1268 self
._ValueList
= [V1
, V2
, V3
]
1270 if Owner
> 0 and Owner
in self
._IdMapping
:
1271 self
._InSubsection
= True
1273 self
._InSubsection
= False
1275 Processer
[self
._ItemType
]()
1276 except EvaluationException
, Excpt
:
1278 # Only catch expression evaluation error here. We need to report
1279 # the precise number of line on which the error occurred
1281 if hasattr(Excpt
, 'Pcd'):
1282 if Excpt
.Pcd
in GlobalData
.gPlatformOtherPcds
:
1283 Info
= GlobalData
.gPlatformOtherPcds
[Excpt
.Pcd
]
1284 EdkLogger
.error('Parser', FORMAT_INVALID
, "Cannot use this PCD (%s) in an expression as"
1285 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
1286 " of the DSC file, and it is currently defined in this section:"
1287 " %s, line #: %d." % (Excpt
.Pcd
, Info
[0], Info
[1]),
1288 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1289 Line
=self
._LineIndex
+ 1)
1291 EdkLogger
.error('Parser', FORMAT_INVALID
, "PCD (%s) is not defined in DSC file" % Excpt
.Pcd
,
1292 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1293 Line
=self
._LineIndex
+ 1)
1295 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid expression: %s" % str(Excpt
),
1296 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1297 Line
=self
._LineIndex
+ 1)
1298 except MacroException
, Excpt
:
1299 EdkLogger
.error('Parser', FORMAT_INVALID
, str(Excpt
),
1300 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1301 Line
=self
._LineIndex
+ 1)
1303 if self
._ValueList
== None:
1306 NewOwner
= self
._IdMapping
.get(Owner
, -1)
1307 self
._Enabled
= int((not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
))
1308 self
._LastItem
= self
._Store
(
1317 self
._LineIndex
+ 1,
1319 self
._LineIndex
+ 1,
1323 self
._IdMapping
[Id
] = self
._LastItem
1325 GlobalData
.gPlatformDefines
.update(self
._FileLocalMacros
)
1326 self
._PostProcessed
= True
1327 self
._Content
= None
1329 def __ProcessSectionHeader(self
):
1330 self
._SectionName
= self
._ValueList
[0]
1331 if self
._SectionName
in self
.DataType
:
1332 self
._SectionType
= self
.DataType
[self
._SectionName
]
1334 self
._SectionType
= MODEL_UNKNOWN
1336 def __ProcessSubsectionHeader(self
):
1337 self
._SubsectionName
= self
._ValueList
[0]
1338 if self
._SubsectionName
in self
.DataType
:
1339 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
1341 self
._SubsectionType
= MODEL_UNKNOWN
1343 def __RetrievePcdValue(self
):
1344 Content
= open(str(self
.MetaFile
), 'r').readlines()
1345 GlobalData
.gPlatformOtherPcds
['DSCFILE'] = str(self
.MetaFile
)
1346 for PcdType
in (MODEL_PCD_PATCHABLE_IN_MODULE
, MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_HII
,
1347 MODEL_PCD_DYNAMIC_VPD
, MODEL_PCD_DYNAMIC_EX_DEFAULT
, MODEL_PCD_DYNAMIC_EX_HII
,
1348 MODEL_PCD_DYNAMIC_EX_VPD
):
1349 Records
= self
._RawTable
.Query(PcdType
, BelongsToItem
= -1.0)
1350 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1351 Name
= TokenSpaceGuid
+ '.' + PcdName
1352 if Name
not in GlobalData
.gPlatformOtherPcds
:
1354 while not Content
[Line
- 1].lstrip().startswith(TAB_SECTION_START
):
1356 GlobalData
.gPlatformOtherPcds
[Name
] = (CleanString(Content
[Line
- 1]), PcdLine
, PcdType
)
1358 def __ProcessDefine(self
):
1359 if not self
._Enabled
:
1362 Type
, Name
, Value
= self
._ValueList
1363 Value
= ReplaceMacro(Value
, self
._Macros
, False)
1365 # If it is <Defines>, return
1367 if self
._InSubsection
:
1368 self
._ValueList
= [Type
, Name
, Value
]
1371 if self
._ItemType
== MODEL_META_DATA_DEFINE
:
1372 if self
._SectionType
== MODEL_META_DATA_HEADER
:
1373 self
._FileLocalMacros
[Name
] = Value
1375 self
._ConstructSectionMacroDict
(Name
, Value
)
1376 elif self
._ItemType
== MODEL_META_DATA_GLOBAL_DEFINE
:
1377 GlobalData
.gEdkGlobal
[Name
] = Value
1380 # Keyword in [Defines] section can be used as Macros
1382 if (self
._ItemType
== MODEL_META_DATA_HEADER
) and (self
._SectionType
== MODEL_META_DATA_HEADER
):
1383 self
._FileLocalMacros
[Name
] = Value
1385 self
._ValueList
= [Type
, Name
, Value
]
1387 def __ProcessDirective(self
):
1389 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1390 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
]:
1391 Macros
= self
._Macros
1392 Macros
.update(GlobalData
.gGlobalDefines
)
1394 Result
= ValueExpression(self
._ValueList
[1], Macros
)()
1395 except SymbolNotFound
, Exc
:
1396 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1398 except WrnExpression
, Excpt
:
1400 # Catch expression evaluation warning here. We need to report
1401 # the precise number of line and return the evaluation result
1403 EdkLogger
.warn('Parser', "Suspicious expression: %s" % str(Excpt
),
1404 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1405 Line
=self
._LineIndex
+ 1)
1406 Result
= Excpt
.result
1408 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1409 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1410 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1411 self
._DirectiveStack
.append(self
._ItemType
)
1412 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
:
1413 Result
= bool(Result
)
1415 Macro
= self
._ValueList
[1]
1416 Macro
= Macro
[2:-1] if (Macro
.startswith("$(") and Macro
.endswith(")")) else Macro
1417 Result
= Macro
in self
._Macros
1418 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
:
1420 self
._DirectiveEvalStack
.append(Result
)
1421 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
:
1422 self
._DirectiveStack
.append(self
._ItemType
)
1423 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1424 self
._DirectiveEvalStack
.append(bool(Result
))
1425 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1426 self
._DirectiveStack
.append(self
._ItemType
)
1427 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1428 self
._DirectiveEvalStack
.append(True)
1429 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1430 # Back to the nearest !if/!ifdef/!ifndef
1431 while self
._DirectiveStack
:
1432 self
._DirectiveEvalStack
.pop()
1433 Directive
= self
._DirectiveStack
.pop()
1434 if Directive
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1435 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1436 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1438 elif self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1439 # The included file must be relative to workspace or same directory as DSC file
1440 __IncludeMacros
= {}
1442 # Allow using system environment variables in path after !include
1444 __IncludeMacros
['WORKSPACE'] = GlobalData
.gGlobalDefines
['WORKSPACE']
1445 if "ECP_SOURCE" in GlobalData
.gGlobalDefines
.keys():
1446 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gGlobalDefines
['ECP_SOURCE']
1448 # During GenFds phase call DSC parser, will go into this branch.
1450 elif "ECP_SOURCE" in GlobalData
.gCommandLineDefines
.keys():
1451 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gCommandLineDefines
['ECP_SOURCE']
1453 __IncludeMacros
['EFI_SOURCE'] = GlobalData
.gGlobalDefines
['EFI_SOURCE']
1454 __IncludeMacros
['EDK_SOURCE'] = GlobalData
.gGlobalDefines
['EDK_SOURCE']
1456 # Allow using MACROs comes from [Defines] section to keep compatible.
1458 __IncludeMacros
.update(self
._Macros
)
1460 IncludedFile
= NormPath(ReplaceMacro(self
._ValueList
[1], __IncludeMacros
, RaiseError
=True))
1462 # First search the include file under the same directory as DSC file
1464 IncludedFile1
= PathClass(IncludedFile
, self
.MetaFile
.Dir
)
1465 ErrorCode
, ErrorInfo1
= IncludedFile1
.Validate()
1468 # Also search file under the WORKSPACE directory
1470 IncludedFile1
= PathClass(IncludedFile
, GlobalData
.gWorkspace
)
1471 ErrorCode
, ErrorInfo2
= IncludedFile1
.Validate()
1473 EdkLogger
.error('parser', ErrorCode
, File
=self
._FileWithError
,
1474 Line
=self
._LineIndex
+ 1, ExtraData
=ErrorInfo1
+ "\n" + ErrorInfo2
)
1476 self
._FileWithError
= IncludedFile1
1478 IncludedFileTable
= MetaFileStorage(self
._Table
.Cur
, IncludedFile1
, MODEL_FILE_DSC
, False)
1479 Owner
= self
._Content
[self
._ContentIndex
- 1][0]
1480 Parser
= DscParser(IncludedFile1
, self
._FileType
, IncludedFileTable
,
1481 Owner
=Owner
, From
=Owner
)
1483 # Does not allow lower level included file to include upper level included file
1484 if Parser
._From
!= Owner
and int(Owner
) > int (Parser
._From
):
1485 EdkLogger
.error('parser', FILE_ALREADY_EXIST
, File
=self
._FileWithError
,
1486 Line
=self
._LineIndex
+ 1, ExtraData
="{0} is already included at a higher level.".format(IncludedFile1
))
1489 # set the parser status with current status
1490 Parser
._SectionName
= self
._SectionName
1491 Parser
._SectionType
= self
._SectionType
1492 Parser
._Scope
= self
._Scope
1493 Parser
._Enabled
= self
._Enabled
1494 # Parse the included file
1497 # update current status with sub-parser's status
1498 self
._SectionName
= Parser
._SectionName
1499 self
._SectionType
= Parser
._SectionType
1500 self
._Scope
= Parser
._Scope
1501 self
._Enabled
= Parser
._Enabled
1503 # Insert all records in the table for the included file into dsc file table
1504 Records
= IncludedFileTable
.GetAll()
1506 self
._Content
[self
._ContentIndex
:self
._ContentIndex
] = Records
1507 self
._Content
.pop(self
._ContentIndex
- 1)
1508 self
._ValueList
= None
1509 self
._ContentIndex
-= 1
1511 def __ProcessSkuId(self
):
1512 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=True)
1513 for Value
in self
._ValueList
]
1515 def __ProcessLibraryInstance(self
):
1516 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
1518 def __ProcessLibraryClass(self
):
1519 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, RaiseError
=True)
1521 def __ProcessPcd(self
):
1522 if self
._ItemType
not in [MODEL_PCD_FEATURE_FLAG
, MODEL_PCD_FIXED_AT_BUILD
]:
1523 self
._ValueList
[2] = ReplaceMacro(self
._ValueList
[2], self
._Macros
, RaiseError
=True)
1526 ValList
, Valid
, Index
= AnalyzeDscPcd(self
._ValueList
[2], self
._ItemType
)
1528 EdkLogger
.error('build', FORMAT_INVALID
, "Pcd format incorrect.", File
=self
._FileWithError
, Line
=self
._LineIndex
+1,
1529 ExtraData
="%s.%s|%s" % (self
._ValueList
[0], self
._ValueList
[1], self
._ValueList
[2]))
1530 PcdValue
= ValList
[Index
]
1533 ValList
[Index
] = ValueExpression(PcdValue
, self
._Macros
)(True)
1534 except WrnExpression
, Value
:
1535 ValList
[Index
] = Value
.result
1537 if ValList
[Index
] == 'True':
1538 ValList
[Index
] = '1'
1539 if ValList
[Index
] == 'False':
1540 ValList
[Index
] = '0'
1542 if (not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
):
1543 GlobalData
.gPlatformPcds
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = PcdValue
1544 self
._Symbols
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = PcdValue
1545 self
._ValueList
[2] = '|'.join(ValList
)
1547 def __ProcessComponent(self
):
1548 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1550 def __ProcessSourceOverridePath(self
):
1551 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1553 def __ProcessBuildOption(self
):
1554 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=False)
1555 for Value
in self
._ValueList
]
1558 MODEL_META_DATA_HEADER
: _DefineParser
,
1559 MODEL_EFI_SKU_ID
: _SkuIdParser
,
1560 MODEL_EFI_LIBRARY_INSTANCE
: _LibraryInstanceParser
,
1561 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
1562 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1563 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1564 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1565 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
1566 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
1567 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
1568 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
1569 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
1570 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
1571 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
1572 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: _CompponentSourceOverridePathParser
,
1573 MODEL_META_DATA_BUILD_OPTION
: _BuildOptionParser
,
1574 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1575 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
1576 MODEL_META_DATA_SECTION_HEADER
: MetaFileParser
._SectionHeaderParser
,
1577 MODEL_META_DATA_SUBSECTION_HEADER
: _SubsectionHeaderParser
,
1580 _Macros
= property(_GetMacros
)
1582 ## DEC file parser class
1584 # @param FilePath The path of platform description file
1585 # @param FileType The raw data of DSC file
1586 # @param Table Database used to retrieve module/package information
1587 # @param Macros Macros used for replacement in file
1589 class DecParser(MetaFileParser
):
1590 # DEC file supported data types (one type per section)
1592 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1593 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
1594 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1595 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1596 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1597 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1598 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1599 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1600 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1601 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1602 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1603 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1604 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
,
1607 ## Constructor of DecParser
1609 # Initialize object of DecParser
1611 # @param FilePath The path of platform description file
1612 # @param FileType The raw data of DSC file
1613 # @param Table Database used to retrieve module/package information
1614 # @param Macros Macros used for replacement in file
1616 def __init__(self
, FilePath
, FileType
, Table
):
1617 # prevent re-initialization
1618 if hasattr(self
, "_Table"):
1620 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, -1)
1622 self
._Version
= 0x00010005 # Only EDK2 dec file is supported
1623 self
._AllPCDs
= [] # Only for check duplicate PCD
1629 Content
= open(str(self
.MetaFile
), 'r').readlines()
1631 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1633 for Index
in range(0, len(Content
)):
1634 Line
, Comment
= CleanString2(Content
[Index
])
1635 self
._CurrentLine
= Line
1636 self
._LineIndex
= Index
1638 # save comment for later use
1640 self
._Comments
.append((Comment
, self
._LineIndex
+ 1))
1646 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1647 self
._SectionHeaderParser
()
1650 elif len(self
._SectionType
) == 0:
1655 self
._ValueList
= ['', '', '']
1656 self
._SectionParser
[self
._SectionType
[0]](self
)
1657 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
1663 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1664 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1666 for Arch
, ModuleType
, Type
in self
._Scope
:
1667 self
._LastItem
= self
._Store
(
1675 self
._LineIndex
+ 1,
1677 self
._LineIndex
+ 1,
1681 for Comment
, LineNo
in self
._Comments
:
1683 MODEL_META_DATA_COMMENT
,
1700 ## Section header parser
1702 # The section header is always in following format:
1704 # [section_name.arch<.platform|module_type>]
1706 def _SectionHeaderParser(self
):
1708 self
._SectionName
= ''
1709 self
._SectionType
= []
1711 Line
= self
._CurrentLine
.replace("%s%s" % (TAB_COMMA_SPLIT
, TAB_SPACE_SPLIT
), TAB_COMMA_SPLIT
)
1712 for Item
in Line
[1:-1].split(TAB_COMMA_SPLIT
):
1714 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
,
1715 "section name can NOT be empty or incorrectly use separator comma",
1716 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1717 ItemList
= Item
.split(TAB_SPLIT
)
1719 # different types of PCD are permissible in one section
1720 self
._SectionName
= ItemList
[0].upper()
1721 if self
._SectionName
in self
.DataType
:
1722 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1723 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1725 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
1726 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1728 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1732 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1734 Line
=self
._LineIndex
+ 1,
1735 ExtraData
=self
._CurrentLine
1738 if len(ItemList
) > 1:
1739 S1
= ItemList
[1].upper()
1743 # S2 may be Platform or ModuleType
1744 if len(ItemList
) > 2:
1745 S2
= ItemList
[2].upper()
1748 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1749 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1751 # 'COMMON' must not be used with specific ARCHs at the same section
1752 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1753 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1754 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
1756 ## [guids], [ppis] and [protocols] section parser
1758 def _GuidParser(self
):
1759 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1760 if len(TokenList
) < 2:
1761 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1762 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1763 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1764 if TokenList
[0] == '':
1765 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1766 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1767 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1768 if TokenList
[1] == '':
1769 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1770 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1771 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1772 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1773 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1774 ExtraData
=self
._CurrentLine
+ \
1775 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1776 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1777 self
._ValueList
[0] = TokenList
[0]
1778 self
._ValueList
[1] = TokenList
[1]
1780 ## PCD sections parser
1782 # [PcdsFixedAtBuild]
1783 # [PcdsPatchableInModule]
1789 def _PcdParser(self
):
1790 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1791 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1792 ValueRe
= re
.compile(r
'^[a-zA-Z_][a-zA-Z0-9_]*')
1793 # check PCD information
1794 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1795 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1796 ExtraData
=self
._CurrentLine
+ \
1797 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1798 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1799 # check format of token space GUID CName
1800 if not ValueRe
.match(self
._ValueList
[0]):
1801 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_]*'",
1802 ExtraData
=self
._CurrentLine
+ \
1803 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1804 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1805 # check format of PCD CName
1806 if not ValueRe
.match(self
._ValueList
[1]):
1807 EdkLogger
.error('Parser', FORMAT_INVALID
, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
1808 ExtraData
=self
._CurrentLine
+ \
1809 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1810 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1811 # check PCD datum information
1812 if len(TokenList
) < 2 or TokenList
[1] == '':
1813 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1814 ExtraData
=self
._CurrentLine
+ \
1815 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1816 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1819 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1820 PtrValue
= ValueRe
.findall(TokenList
[1])
1822 # Has VOID* type string, may contain "|" character in the string.
1823 if len(PtrValue
) != 0:
1824 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1825 ValueList
= GetSplitValueList(ptrValueList
)
1826 ValueList
[0] = PtrValue
[0]
1828 ValueList
= GetSplitValueList(TokenList
[1])
1831 # check if there's enough datum information given
1832 if len(ValueList
) != 3:
1833 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1834 ExtraData
=self
._CurrentLine
+ \
1835 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1836 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1837 # check default value
1838 if ValueList
[0] == '':
1839 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1840 ExtraData
=self
._CurrentLine
+ \
1841 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1842 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1844 if ValueList
[1] == '':
1845 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1846 ExtraData
=self
._CurrentLine
+ \
1847 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1848 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1849 # check token of the PCD
1850 if ValueList
[2] == '':
1851 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1852 ExtraData
=self
._CurrentLine
+ \
1853 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1854 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1855 # check format of default value against the datum type
1856 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1858 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1859 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1861 if ValueList
[0] in ['True', 'true', 'TRUE']:
1863 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1866 # check for duplicate PCD definition
1867 if (self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]) in self
._AllPCDs
:
1868 EdkLogger
.error('Parser', FORMAT_INVALID
,
1869 "The same PCD name and GUID have been already defined",
1870 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1872 self
._AllPCDs
.append((self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]))
1874 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
1877 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
1878 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
1879 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
1880 MODEL_EFI_GUID
: _GuidParser
,
1881 MODEL_EFI_PPI
: _GuidParser
,
1882 MODEL_EFI_PROTOCOL
: _GuidParser
,
1883 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1884 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1885 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1886 MODEL_PCD_DYNAMIC
: _PcdParser
,
1887 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
1888 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1889 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
1894 # This acts like the main() function for the script, unless it is 'import'ed into another
1897 if __name__
== '__main__':