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':
347 self
._Version
= int(Value
, 0)
349 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid version number",
350 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
352 if type(self
) == InfParser
and self
._Version
< 0x00010005:
353 # EDK module allows using defines as macros
354 self
._FileLocalMacros
[Name
] = Value
355 self
._Defines
[Name
] = Value
357 ## [BuildOptions] section parser
359 def _BuildOptionParser(self
):
360 self
._CurrentLine
= CleanString(self
._CurrentLine
, BuildOption
=True)
361 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
362 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
363 if len(TokenList2
) == 2:
364 self
._ValueList
[0] = TokenList2
[0] # toolchain family
365 self
._ValueList
[1] = TokenList2
[1] # keys
367 self
._ValueList
[1] = TokenList
[0]
368 if len(TokenList
) == 2 and type(self
) != DscParser
: # value
369 self
._ValueList
[2] = ReplaceMacro(TokenList
[1], self
._Macros
)
371 if self
._ValueList
[1].count('_') != 4:
375 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
376 ExtraData
=self
._CurrentLine
,
378 Line
=self
._LineIndex
+ 1
380 def GetValidExpression(self
, TokenSpaceGuid
, PcdCName
):
381 return self
._Table
.GetValidExpression(TokenSpaceGuid
, PcdCName
)
382 def _GetMacros(self
):
384 Macros
.update(self
._FileLocalMacros
)
385 Macros
.update(self
._GetApplicableSectionMacro
())
388 ## Construct section Macro dict
389 def _ConstructSectionMacroDict(self
, Name
, Value
):
390 ScopeKey
= [(Scope
[0], Scope
[1]) for Scope
in self
._Scope
]
391 ScopeKey
= tuple(ScopeKey
)
392 SectionDictKey
= self
._SectionType
, ScopeKey
394 # DecParser SectionType is a list, will contain more than one item only in Pcd Section
395 # As Pcd section macro usage is not alllowed, so here it is safe
397 if type(self
) == DecParser
:
398 SectionDictKey
= self
._SectionType
[0], ScopeKey
399 if SectionDictKey
not in self
._SectionsMacroDict
:
400 self
._SectionsMacroDict
[SectionDictKey
] = {}
401 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
402 SectionLocalMacros
[Name
] = Value
404 ## Get section Macros that are applicable to current line, which may come from other sections
405 ## that share the same name while scope is wider
406 def _GetApplicableSectionMacro(self
):
413 ActiveSectionType
= self
._SectionType
414 if type(self
) == DecParser
:
415 ActiveSectionType
= self
._SectionType
[0]
417 for (SectionType
, Scope
) in self
._SectionsMacroDict
:
418 if SectionType
!= ActiveSectionType
:
421 for ActiveScope
in self
._Scope
:
422 Scope0
, Scope1
= ActiveScope
[0], ActiveScope
[1]
423 if(Scope0
, Scope1
) not in Scope
:
426 SpeSpeMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
428 for ActiveScope
in self
._Scope
:
429 Scope0
, Scope1
= ActiveScope
[0], ActiveScope
[1]
430 if(Scope0
, Scope1
) not in Scope
and (Scope0
, "COMMON") not in Scope
and ("COMMON", Scope1
) not in Scope
:
433 ComSpeMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
435 if ("COMMON", "COMMON") in Scope
:
436 ComComMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
438 Macros
.update(ComComMacroDict
)
439 Macros
.update(ComSpeMacroDict
)
440 Macros
.update(SpeSpeMacroDict
)
445 Finished
= property(_GetFinished
, _SetFinished
)
446 _Macros
= property(_GetMacros
)
449 ## INF file parser class
451 # @param FilePath The path of platform description file
452 # @param FileType The raw data of DSC file
453 # @param Table Database used to retrieve module/package information
454 # @param Macros Macros used for replacement in file
456 class InfParser(MetaFileParser
):
457 # INF file supported data types (one type per section)
459 TAB_UNKNOWN
.upper() : MODEL_UNKNOWN
,
460 TAB_INF_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
461 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
462 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
463 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
464 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
465 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
466 TAB_PACKAGES
.upper() : MODEL_META_DATA_PACKAGE
,
467 TAB_NMAKE
.upper() : MODEL_META_DATA_NMAKE
,
468 TAB_INF_FIXED_PCD
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
469 TAB_INF_PATCH_PCD
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
470 TAB_INF_FEATURE_PCD
.upper() : MODEL_PCD_FEATURE_FLAG
,
471 TAB_INF_PCD_EX
.upper() : MODEL_PCD_DYNAMIC_EX
,
472 TAB_INF_PCD
.upper() : MODEL_PCD_DYNAMIC
,
473 TAB_SOURCES
.upper() : MODEL_EFI_SOURCE_FILE
,
474 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
475 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
476 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
477 TAB_DEPEX
.upper() : MODEL_EFI_DEPEX
,
478 TAB_BINARIES
.upper() : MODEL_EFI_BINARY_FILE
,
479 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
482 ## Constructor of InfParser
484 # Initialize object of InfParser
486 # @param FilePath The path of module description file
487 # @param FileType The raw data of DSC file
488 # @param Table Database used to retrieve module/package information
489 # @param Macros Macros used for replacement in file
491 def __init__(self
, FilePath
, FileType
, Table
):
492 # prevent re-initialization
493 if hasattr(self
, "_Table"):
495 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
503 Content
= open(str(self
.MetaFile
), 'r').readlines()
505 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
507 # parse the file line by line
508 IsFindBlockComment
= False
509 GetHeaderComment
= False
514 for Index
in range(0, len(Content
)):
515 # skip empty, commented, block commented lines
516 Line
, Comment
= CleanString2(Content
[Index
], AllowCppStyleComment
=True)
518 if Index
+ 1 < len(Content
):
519 NextLine
, NextComment
= CleanString2(Content
[Index
+ 1])
522 Comments
.append((Comment
, Index
+ 1))
523 elif GetHeaderComment
:
524 SectionComments
.extend(Comments
)
527 if Line
.find(DataType
.TAB_COMMENT_EDK_START
) > -1:
528 IsFindBlockComment
= True
530 if Line
.find(DataType
.TAB_COMMENT_EDK_END
) > -1:
531 IsFindBlockComment
= False
533 if IsFindBlockComment
:
536 self
._LineIndex
= Index
537 self
._CurrentLine
= Line
540 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
541 if not GetHeaderComment
:
542 for Cmt
, LNo
in Comments
:
543 self
._Store
(MODEL_META_DATA_HEADER_COMMENT
, Cmt
, '', '', 'COMMON',
544 'COMMON', self
._Owner
[-1], LNo
, -1, LNo
, -1, 0)
545 GetHeaderComment
= True
547 TailComments
.extend(SectionComments
+ Comments
)
549 self
._SectionHeaderParser
()
550 # Check invalid sections
551 if self
._Version
< 0x00010005:
552 if self
._SectionType
in [MODEL_META_DATA_BUILD_OPTION
,
553 MODEL_EFI_LIBRARY_CLASS
,
554 MODEL_META_DATA_PACKAGE
,
555 MODEL_PCD_FIXED_AT_BUILD
,
556 MODEL_PCD_PATCHABLE_IN_MODULE
,
557 MODEL_PCD_FEATURE_FLAG
,
558 MODEL_PCD_DYNAMIC_EX
,
563 MODEL_META_DATA_USER_EXTENSION
]:
564 EdkLogger
.error('Parser', FORMAT_INVALID
,
565 "Section [%s] is not allowed in inf file without version" % (self
._SectionName
),
566 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
567 elif self
._SectionType
in [MODEL_EFI_INCLUDE
,
568 MODEL_EFI_LIBRARY_INSTANCE
,
569 MODEL_META_DATA_NMAKE
]:
570 EdkLogger
.error('Parser', FORMAT_INVALID
,
571 "Section [%s] is not allowed in inf file with version 0x%08x" % (self
._SectionName
, self
._Version
),
572 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
574 # merge two lines specified by '\' in section NMAKE
575 elif self
._SectionType
== MODEL_META_DATA_NMAKE
:
578 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
581 if NextLine
[0] == TAB_SECTION_START
and NextLine
[-1] == TAB_SECTION_END
:
582 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
585 NmakeLine
= NmakeLine
+ ' ' + Line
[0:-1]
588 self
._CurrentLine
= NmakeLine
+ Line
592 self
._ValueList
= ['', '', '']
593 # parse current line, result will be put in self._ValueList
594 self
._SectionParser
[self
._SectionType
](self
)
595 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
600 Comments
.append((Comment
, Index
+ 1))
601 if GlobalData
.gOptions
and GlobalData
.gOptions
.CheckUsage
:
602 CheckInfComment(self
._SectionType
, Comments
, str(self
.MetaFile
), Index
+ 1, self
._ValueList
)
604 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
605 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
607 for Arch
, Platform
in self
._Scope
:
608 LastItem
= self
._Store
(self
._SectionType
,
621 for Comment
, LineNo
in Comments
:
622 self
._Store
(MODEL_META_DATA_COMMENT
, Comment
, '', '', Arch
, Platform
,
623 LastItem
, LineNo
, -1, LineNo
, -1, 0)
626 TailComments
.extend(SectionComments
+ Comments
)
627 if IsFindBlockComment
:
628 EdkLogger
.error("Parser", FORMAT_INVALID
, "Open block comments (starting with /*) are expected to end with */",
631 # If there are tail comments in INF file, save to database whatever the comments are
632 for Comment
in TailComments
:
633 self
._Store
(MODEL_META_DATA_TAIL_COMMENT
, Comment
[0], '', '', 'COMMON',
634 'COMMON', self
._Owner
[-1], -1, -1, -1, -1, 0)
637 ## Data parser for the format in which there's path
639 # Only path can have macro used. So we need to replace them before use.
641 def _IncludeParser(self
):
642 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
643 self
._ValueList
[0:len(TokenList
)] = TokenList
644 Macros
= self
._Macros
646 for Index
in range(0, len(self
._ValueList
)):
647 Value
= self
._ValueList
[Index
]
651 if Value
.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value
.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
652 Value
= '$(EDK_SOURCE)' + Value
[17:]
653 if Value
.find('$(EFI_SOURCE)') > -1 or Value
.find('$(EDK_SOURCE)') > -1:
655 elif Value
.startswith('.'):
657 elif Value
.startswith('$('):
660 Value
= '$(EFI_SOURCE)/' + Value
662 self
._ValueList
[Index
] = ReplaceMacro(Value
, Macros
)
664 ## Parse [Sources] section
666 # Only path can have macro used. So we need to replace them before use.
669 def _SourceFileParser(self
):
670 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
671 self
._ValueList
[0:len(TokenList
)] = TokenList
672 Macros
= self
._Macros
673 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
674 if 'COMPONENT_TYPE' in Macros
:
675 if self
._Defines
['COMPONENT_TYPE'].upper() == 'ACPITABLE':
676 self
._ValueList
[0] = GetSplitValueList(self
._ValueList
[0], ' ', 1)[0]
677 if self
._Defines
['BASE_NAME'] == 'Microcode':
679 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
681 ## Parse [Binaries] section
683 # Only path can have macro used. So we need to replace them before use.
686 def _BinaryFileParser(self
):
687 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 2)
688 if len(TokenList
) < 2:
689 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type or path specified",
690 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
691 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
693 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type specified",
694 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
695 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
697 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file path specified",
698 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
699 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
700 self
._ValueList
[0:len(TokenList
)] = TokenList
701 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
703 ## [nmake] section parser (Edk.x style only)
704 def _NmakeParser(self
):
705 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
706 self
._ValueList
[0:len(TokenList
)] = TokenList
708 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
709 # remove self-reference in macro setting
710 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
712 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
714 def _PcdParser(self
):
715 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
716 ValueList
= GetSplitValueList(TokenList
[0], TAB_SPLIT
)
717 if len(ValueList
) != 2:
718 EdkLogger
.error('Parser', FORMAT_INVALID
, "Illegal token space GUID and PCD name format",
719 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
720 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
721 self
._ValueList
[0:1] = ValueList
722 if len(TokenList
) > 1:
723 self
._ValueList
[2] = TokenList
[1]
724 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
725 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
726 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
727 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
729 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
730 if self
._ValueList
[2] != '':
731 InfPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
732 if InfPcdValueList
[0] in ['True', 'true', 'TRUE']:
733 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '1', 1);
734 elif InfPcdValueList
[0] in ['False', 'false', 'FALSE']:
735 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '0', 1);
736 if (self
._ValueList
[0], self
._ValueList
[1]) not in self
.PcdsDict
:
737 self
.PcdsDict
[self
._ValueList
[0], self
._ValueList
[1]] = self
._SectionType
738 elif self
.PcdsDict
[self
._ValueList
[0], self
._ValueList
[1]] != self
._SectionType
:
739 EdkLogger
.error('Parser', FORMAT_INVALID
, "It is not permissible to list a specified PCD in different PCD type sections.",
740 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
741 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
743 ## [depex] section parser
745 def _DepexParser(self
):
746 self
._ValueList
[0:1] = [self
._CurrentLine
]
749 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
750 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
751 MODEL_META_DATA_BUILD_OPTION
: MetaFileParser
._BuildOptionParser
,
752 MODEL_EFI_INCLUDE
: _IncludeParser
, # for Edk.x modules
753 MODEL_EFI_LIBRARY_INSTANCE
: MetaFileParser
._CommonParser
, # for Edk.x modules
754 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
755 MODEL_META_DATA_PACKAGE
: MetaFileParser
._PathParser
,
756 MODEL_META_DATA_NMAKE
: _NmakeParser
, # for Edk.x modules
757 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
758 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
759 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
760 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
761 MODEL_PCD_DYNAMIC
: _PcdParser
,
762 MODEL_EFI_SOURCE_FILE
: _SourceFileParser
,
763 MODEL_EFI_GUID
: MetaFileParser
._CommonParser
,
764 MODEL_EFI_PROTOCOL
: MetaFileParser
._CommonParser
,
765 MODEL_EFI_PPI
: MetaFileParser
._CommonParser
,
766 MODEL_EFI_DEPEX
: _DepexParser
,
767 MODEL_EFI_BINARY_FILE
: _BinaryFileParser
,
768 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
771 ## DSC file parser class
773 # @param FilePath The path of platform description file
774 # @param FileType The raw data of DSC file
775 # @param Table Database used to retrieve module/package information
776 # @param Macros Macros used for replacement in file
777 # @param Owner Owner ID (for sub-section parsing)
778 # @param From ID from which the data comes (for !INCLUDE directive)
780 class DscParser(MetaFileParser
):
781 # DSC file supported data types (one type per section)
783 TAB_SKUIDS
.upper() : MODEL_EFI_SKU_ID
,
784 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
785 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
786 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
787 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
788 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
789 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
790 TAB_PCDS_DYNAMIC_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_DEFAULT
,
791 TAB_PCDS_DYNAMIC_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_HII
,
792 TAB_PCDS_DYNAMIC_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_VPD
,
793 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT
,
794 TAB_PCDS_DYNAMIC_EX_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_HII
,
795 TAB_PCDS_DYNAMIC_EX_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_VPD
,
796 TAB_COMPONENTS
.upper() : MODEL_META_DATA_COMPONENT
,
797 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH
.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
,
798 TAB_DSC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
799 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
800 TAB_DSC_DEFINES_EDKGLOBAL
: MODEL_META_DATA_GLOBAL_DEFINE
,
801 TAB_INCLUDE
.upper() : MODEL_META_DATA_INCLUDE
,
802 TAB_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
803 TAB_IF_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
804 TAB_IF_N_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
,
805 TAB_ELSE_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
,
806 TAB_ELSE
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
807 TAB_END_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
,
808 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
,
811 # Valid names in define section
818 "PCD_INFO_GENERATION",
819 "PCD_VAR_CHECK_GENERATION",
820 "SUPPORTED_ARCHITECTURES",
829 "FIX_LOAD_TOP_MEMORY_ADDRESS"
832 SubSectionDefineKeywords
= [
836 SymbolPattern
= ValueExpression
.SymbolPattern
838 ## Constructor of DscParser
840 # Initialize object of DscParser
842 # @param FilePath The path of platform description file
843 # @param FileType The raw data of DSC file
844 # @param Table Database used to retrieve module/package information
845 # @param Macros Macros used for replacement in file
846 # @param Owner Owner ID (for sub-section parsing)
847 # @param From ID from which the data comes (for !INCLUDE directive)
849 def __init__(self
, FilePath
, FileType
, Table
, Owner
= -1, From
= -1):
850 # prevent re-initialization
851 if hasattr(self
, "_Table"):
853 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, Owner
, From
)
854 self
._Version
= 0x00010005 # Only EDK2 dsc file is supported
855 # to store conditional directive evaluation result
856 self
._DirectiveStack
= []
857 self
._DirectiveEvalStack
= []
861 # Specify whether current line is in uncertain condition
863 self
._InDirective
= -1
865 # Final valid replacable symbols
868 # Map the ID between the original table and new table to track
871 self
._IdMapping
= {-1:-1}
877 Content
= open(str(self
.MetaFile
), 'r').readlines()
879 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
882 for Index
in range(0, len(Content
)):
883 Line
= CleanString(Content
[Index
])
888 self
._CurrentLine
= Line
889 self
._LineIndex
= Index
890 if self
._InSubsection
and self
._Owner
[-1] == -1:
891 self
._Owner
.append(self
._LastItem
)
894 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
895 self
._SectionType
= MODEL_META_DATA_SECTION_HEADER
897 elif Line
[0] == '}' and self
._InSubsection
:
898 self
._InSubsection
= False
899 self
._SubsectionType
= MODEL_UNKNOWN
900 self
._SubsectionName
= ''
905 elif Line
[0] == TAB_OPTION_START
and Line
[-1] == TAB_OPTION_END
:
906 self
._SubsectionType
= MODEL_META_DATA_SUBSECTION_HEADER
909 self
._DirectiveParser
()
912 if self
._InSubsection
:
913 SectionType
= self
._SubsectionType
915 SectionType
= self
._SectionType
916 self
._ItemType
= SectionType
918 self
._ValueList
= ['', '', '']
919 self
._SectionParser
[SectionType
](self
)
920 if self
._ValueList
== None:
923 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
924 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
926 for Arch
, ModuleType
in self
._Scope
:
927 Owner
= self
._Owner
[-1]
928 if self
._SubsectionType
!= MODEL_UNKNOWN
:
929 Owner
= OwnerId
[Arch
]
930 self
._LastItem
= self
._Store
(
945 if self
._SubsectionType
== MODEL_UNKNOWN
and self
._InSubsection
:
946 OwnerId
[Arch
] = self
._LastItem
948 if self
._DirectiveStack
:
949 Type
, Line
, Text
= self
._DirectiveStack
[-1]
950 EdkLogger
.error('Parser', FORMAT_INVALID
, "No matching '!endif' found",
951 ExtraData
=Text
, File
=self
.MetaFile
, Line
=Line
)
954 ## <subsection_header> parser
955 def _SubsectionHeaderParser(self
):
956 self
._SubsectionName
= self
._CurrentLine
[1:-1].upper()
957 if self
._SubsectionName
in self
.DataType
:
958 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
960 self
._SubsectionType
= MODEL_UNKNOWN
961 EdkLogger
.warn("Parser", "Unrecognized sub-section", File
=self
.MetaFile
,
962 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
963 self
._ValueList
[0] = self
._SubsectionName
965 ## Directive statement parser
966 def _DirectiveParser(self
):
967 self
._ValueList
= ['', '', '']
968 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
969 self
._ValueList
[0:len(TokenList
)] = TokenList
972 DirectiveName
= self
._ValueList
[0].upper()
973 if DirectiveName
not in self
.DataType
:
974 EdkLogger
.error("Parser", FORMAT_INVALID
, "Unknown directive [%s]" % DirectiveName
,
975 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
977 if DirectiveName
in ['!IF', '!IFDEF', '!IFNDEF']:
978 self
._InDirective
+= 1
980 if DirectiveName
in ['!ENDIF']:
981 self
._InDirective
-= 1
983 if DirectiveName
in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self
._ValueList
[1] == '':
984 EdkLogger
.error("Parser", FORMAT_INVALID
, "Missing expression",
985 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
986 ExtraData
=self
._CurrentLine
)
988 ItemType
= self
.DataType
[DirectiveName
]
989 Scope
= [['COMMON', 'COMMON']]
990 if ItemType
== MODEL_META_DATA_INCLUDE
:
992 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
993 # Remove all directives between !if and !endif, including themselves
994 while self
._DirectiveStack
:
995 # Remove any !else or !elseif
996 DirectiveInfo
= self
._DirectiveStack
.pop()
997 if DirectiveInfo
[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
998 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
999 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1002 EdkLogger
.error("Parser", FORMAT_INVALID
, "Redundant '!endif'",
1003 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
1004 ExtraData
=self
._CurrentLine
)
1005 elif ItemType
!= MODEL_META_DATA_INCLUDE
:
1006 # Break if there's a !else is followed by a !elseif
1007 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
and \
1008 self
._DirectiveStack
and \
1009 self
._DirectiveStack
[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1010 EdkLogger
.error("Parser", FORMAT_INVALID
, "'!elseif' after '!else'",
1011 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
1012 ExtraData
=self
._CurrentLine
)
1013 self
._DirectiveStack
.append((ItemType
, self
._LineIndex
+ 1, self
._CurrentLine
))
1016 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
1017 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
1019 for Arch
, ModuleType
in Scope
:
1020 self
._LastItem
= self
._Store
(
1029 self
._LineIndex
+ 1,
1031 self
._LineIndex
+ 1,
1036 ## [defines] section parser
1038 def _DefineParser(self
):
1039 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1040 self
._ValueList
[1:len(TokenList
)] = TokenList
1043 if not self
._ValueList
[1]:
1044 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
1045 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1046 if not self
._ValueList
[2]:
1047 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
1048 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1049 if (not self
._ValueList
[1] in self
.DefineKeywords
and
1050 (self
._InSubsection
and self
._ValueList
[1] not in self
.SubSectionDefineKeywords
)):
1051 EdkLogger
.error('Parser', FORMAT_INVALID
,
1052 "Unknown keyword found: %s. "
1053 "If this is a macro you must "
1054 "add it as a DEFINE in the DSC" % self
._ValueList
[1],
1055 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1056 if not self
._InSubsection
:
1057 self
._Defines
[self
._ValueList
[1]] = self
._ValueList
[2]
1058 self
._ItemType
= self
.DataType
[TAB_DSC_DEFINES
.upper()]
1061 def _SkuIdParser(self
):
1062 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1063 if len(TokenList
) != 2:
1064 EdkLogger
.error('Parser', FORMAT_INVALID
, "Correct format is '<Integer>|<UiName>'",
1065 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1066 self
._ValueList
[0:len(TokenList
)] = TokenList
1068 ## Parse Edk style of library modules
1070 def _LibraryInstanceParser(self
):
1071 self
._ValueList
[0] = self
._CurrentLine
1073 ## PCD sections parser
1075 # [PcdsFixedAtBuild]
1076 # [PcdsPatchableInModule]
1079 # [PcdsDynamicExDefault]
1080 # [PcdsDynamicExVpd]
1081 # [PcdsDynamicExHii]
1083 # [PcdsDynamicDefault]
1088 def _PcdParser(self
):
1089 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1090 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1091 if len(TokenList
) == 2:
1092 self
._ValueList
[2] = TokenList
[1]
1093 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1094 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1095 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1096 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1097 if self
._ValueList
[2] == '':
1099 # The PCD values are optional for FIXEDATBUILD and PATCHABLEINMODULE
1101 if self
._SectionType
in (MODEL_PCD_FIXED_AT_BUILD
, MODEL_PCD_PATCHABLE_IN_MODULE
):
1103 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD value given",
1104 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1105 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1107 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD
1108 ValueList
= GetSplitValueList(self
._ValueList
[2])
1109 if len(ValueList
) > 1 and ValueList
[1] != TAB_VOID \
1110 and self
._ItemType
in [MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_EX_DEFAULT
]:
1111 EdkLogger
.error('Parser', FORMAT_INVALID
, "The datum type '%s' of PCD is wrong" % ValueList
[1],
1112 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1114 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1115 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
1116 if DscPcdValueList
[0] in ['True', 'true', 'TRUE']:
1117 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '1', 1);
1118 elif DscPcdValueList
[0] in ['False', 'false', 'FALSE']:
1119 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '0', 1);
1122 ## [components] section parser
1124 def _ComponentParser(self
):
1125 if self
._CurrentLine
[-1] == '{':
1126 self
._ValueList
[0] = self
._CurrentLine
[0:-1].strip()
1127 self
._InSubsection
= True
1129 self
._ValueList
[0] = self
._CurrentLine
1131 ## [LibraryClasses] section
1133 def _LibraryClassParser(self
):
1134 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1135 if len(TokenList
) < 2:
1136 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class or instance specified",
1137 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1138 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1139 if TokenList
[0] == '':
1140 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class specified",
1141 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1142 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1143 if TokenList
[1] == '':
1144 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library instance specified",
1145 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1146 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1148 self
._ValueList
[0:len(TokenList
)] = TokenList
1150 def _CompponentSourceOverridePathParser(self
):
1151 self
._ValueList
[0] = self
._CurrentLine
1153 ## [BuildOptions] section parser
1155 def _BuildOptionParser(self
):
1156 self
._CurrentLine
= CleanString(self
._CurrentLine
, BuildOption
=True)
1157 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1158 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
1159 if len(TokenList2
) == 2:
1160 self
._ValueList
[0] = TokenList2
[0] # toolchain family
1161 self
._ValueList
[1] = TokenList2
[1] # keys
1163 self
._ValueList
[1] = TokenList
[0]
1164 if len(TokenList
) == 2: # value
1165 self
._ValueList
[2] = TokenList
[1]
1167 if self
._ValueList
[1].count('_') != 4:
1171 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
1172 ExtraData
=self
._CurrentLine
,
1174 Line
=self
._LineIndex
+ 1
1177 ## Override parent's method since we'll do all macro replacements in parser
1178 def _GetMacros(self
):
1180 Macros
.update(self
._FileLocalMacros
)
1181 Macros
.update(self
._GetApplicableSectionMacro
())
1182 Macros
.update(GlobalData
.gEdkGlobal
)
1183 Macros
.update(GlobalData
.gPlatformDefines
)
1184 Macros
.update(GlobalData
.gCommandLineDefines
)
1185 # PCD cannot be referenced in macro definition
1186 if self
._ItemType
not in [MODEL_META_DATA_DEFINE
, MODEL_META_DATA_GLOBAL_DEFINE
]:
1187 Macros
.update(self
._Symbols
)
1190 def _PostProcess(self
):
1192 MODEL_META_DATA_SECTION_HEADER
: self
.__ProcessSectionHeader
,
1193 MODEL_META_DATA_SUBSECTION_HEADER
: self
.__ProcessSubsectionHeader
,
1194 MODEL_META_DATA_HEADER
: self
.__ProcessDefine
,
1195 MODEL_META_DATA_DEFINE
: self
.__ProcessDefine
,
1196 MODEL_META_DATA_GLOBAL_DEFINE
: self
.__ProcessDefine
,
1197 MODEL_META_DATA_INCLUDE
: self
.__ProcessDirective
,
1198 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
: self
.__ProcessDirective
,
1199 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
: self
.__ProcessDirective
,
1200 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
: self
.__ProcessDirective
,
1201 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
: self
.__ProcessDirective
,
1202 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
: self
.__ProcessDirective
,
1203 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
: self
.__ProcessDirective
,
1204 MODEL_EFI_SKU_ID
: self
.__ProcessSkuId
,
1205 MODEL_EFI_LIBRARY_INSTANCE
: self
.__ProcessLibraryInstance
,
1206 MODEL_EFI_LIBRARY_CLASS
: self
.__ProcessLibraryClass
,
1207 MODEL_PCD_FIXED_AT_BUILD
: self
.__ProcessPcd
,
1208 MODEL_PCD_PATCHABLE_IN_MODULE
: self
.__ProcessPcd
,
1209 MODEL_PCD_FEATURE_FLAG
: self
.__ProcessPcd
,
1210 MODEL_PCD_DYNAMIC_DEFAULT
: self
.__ProcessPcd
,
1211 MODEL_PCD_DYNAMIC_HII
: self
.__ProcessPcd
,
1212 MODEL_PCD_DYNAMIC_VPD
: self
.__ProcessPcd
,
1213 MODEL_PCD_DYNAMIC_EX_DEFAULT
: self
.__ProcessPcd
,
1214 MODEL_PCD_DYNAMIC_EX_HII
: self
.__ProcessPcd
,
1215 MODEL_PCD_DYNAMIC_EX_VPD
: self
.__ProcessPcd
,
1216 MODEL_META_DATA_COMPONENT
: self
.__ProcessComponent
,
1217 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: self
.__ProcessSourceOverridePath
,
1218 MODEL_META_DATA_BUILD_OPTION
: self
.__ProcessBuildOption
,
1219 MODEL_UNKNOWN
: self
._Skip
,
1220 MODEL_META_DATA_USER_EXTENSION
: self
._SkipUserExtension
,
1223 self
._Table
= MetaFileStorage(self
._RawTable
.Cur
, self
.MetaFile
, MODEL_FILE_DSC
, True)
1224 self
._Table
.Create()
1225 self
._DirectiveStack
= []
1226 self
._DirectiveEvalStack
= []
1227 self
._FileWithError
= self
.MetaFile
1228 self
._FileLocalMacros
= {}
1229 self
._SectionsMacroDict
= {}
1230 GlobalData
.gPlatformDefines
= {}
1232 # Get all macro and PCD which has straitforward value
1233 self
.__RetrievePcdValue
()
1234 self
._Content
= self
._RawTable
.GetAll()
1235 self
._ContentIndex
= 0
1236 self
._InSubsection
= False
1237 while self
._ContentIndex
< len(self
._Content
) :
1238 Id
, self
._ItemType
, V1
, V2
, V3
, S1
, S2
, Owner
, self
._From
, \
1239 LineStart
, ColStart
, LineEnd
, ColEnd
, Enabled
= self
._Content
[self
._ContentIndex
]
1242 self
._FileWithError
= self
.MetaFile
1244 self
._ContentIndex
+= 1
1246 self
._Scope
= [[S1
, S2
]]
1248 # For !include directive, handle it specially,
1249 # merge arch and module type in case of duplicate items
1251 while self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1252 if self
._ContentIndex
>= len(self
._Content
):
1254 Record
= self
._Content
[self
._ContentIndex
]
1255 if LineStart
== Record
[9] and LineEnd
== Record
[11]:
1256 if [Record
[5], Record
[6]] not in self
._Scope
:
1257 self
._Scope
.append([Record
[5], Record
[6]])
1258 self
._ContentIndex
+= 1
1262 self
._LineIndex
= LineStart
- 1
1263 self
._ValueList
= [V1
, V2
, V3
]
1265 if Owner
> 0 and Owner
in self
._IdMapping
:
1266 self
._InSubsection
= True
1268 self
._InSubsection
= False
1270 Processer
[self
._ItemType
]()
1271 except EvaluationException
, Excpt
:
1273 # Only catch expression evaluation error here. We need to report
1274 # the precise number of line on which the error occurred
1276 if hasattr(Excpt
, 'Pcd'):
1277 if Excpt
.Pcd
in GlobalData
.gPlatformOtherPcds
:
1278 Info
= GlobalData
.gPlatformOtherPcds
[Excpt
.Pcd
]
1279 EdkLogger
.error('Parser', FORMAT_INVALID
, "Cannot use this PCD (%s) in an expression as"
1280 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
1281 " of the DSC file, and it is currently defined in this section:"
1282 " %s, line #: %d." % (Excpt
.Pcd
, Info
[0], Info
[1]),
1283 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1284 Line
=self
._LineIndex
+ 1)
1286 EdkLogger
.error('Parser', FORMAT_INVALID
, "PCD (%s) is not defined in DSC file" % Excpt
.Pcd
,
1287 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1288 Line
=self
._LineIndex
+ 1)
1290 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid expression: %s" % str(Excpt
),
1291 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1292 Line
=self
._LineIndex
+ 1)
1293 except MacroException
, Excpt
:
1294 EdkLogger
.error('Parser', FORMAT_INVALID
, str(Excpt
),
1295 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1296 Line
=self
._LineIndex
+ 1)
1298 if self
._ValueList
== None:
1301 NewOwner
= self
._IdMapping
.get(Owner
, -1)
1302 self
._Enabled
= int((not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
))
1303 self
._LastItem
= self
._Store
(
1312 self
._LineIndex
+ 1,
1314 self
._LineIndex
+ 1,
1318 self
._IdMapping
[Id
] = self
._LastItem
1320 GlobalData
.gPlatformDefines
.update(self
._FileLocalMacros
)
1321 self
._PostProcessed
= True
1322 self
._Content
= None
1324 def __ProcessSectionHeader(self
):
1325 self
._SectionName
= self
._ValueList
[0]
1326 if self
._SectionName
in self
.DataType
:
1327 self
._SectionType
= self
.DataType
[self
._SectionName
]
1329 self
._SectionType
= MODEL_UNKNOWN
1331 def __ProcessSubsectionHeader(self
):
1332 self
._SubsectionName
= self
._ValueList
[0]
1333 if self
._SubsectionName
in self
.DataType
:
1334 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
1336 self
._SubsectionType
= MODEL_UNKNOWN
1338 def __RetrievePcdValue(self
):
1339 Content
= open(str(self
.MetaFile
), 'r').readlines()
1340 GlobalData
.gPlatformOtherPcds
['DSCFILE'] = str(self
.MetaFile
)
1341 for PcdType
in (MODEL_PCD_PATCHABLE_IN_MODULE
, MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_HII
,
1342 MODEL_PCD_DYNAMIC_VPD
, MODEL_PCD_DYNAMIC_EX_DEFAULT
, MODEL_PCD_DYNAMIC_EX_HII
,
1343 MODEL_PCD_DYNAMIC_EX_VPD
):
1344 Records
= self
._RawTable
.Query(PcdType
, BelongsToItem
= -1.0)
1345 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1346 Name
= TokenSpaceGuid
+ '.' + PcdName
1347 if Name
not in GlobalData
.gPlatformOtherPcds
:
1349 while not Content
[Line
- 1].lstrip().startswith(TAB_SECTION_START
):
1351 GlobalData
.gPlatformOtherPcds
[Name
] = (CleanString(Content
[Line
- 1]), PcdLine
, PcdType
)
1353 def __ProcessDefine(self
):
1354 if not self
._Enabled
:
1357 Type
, Name
, Value
= self
._ValueList
1358 Value
= ReplaceMacro(Value
, self
._Macros
, False)
1360 # If it is <Defines>, return
1362 if self
._InSubsection
:
1363 self
._ValueList
= [Type
, Name
, Value
]
1366 if self
._ItemType
== MODEL_META_DATA_DEFINE
:
1367 if self
._SectionType
== MODEL_META_DATA_HEADER
:
1368 self
._FileLocalMacros
[Name
] = Value
1370 self
._ConstructSectionMacroDict
(Name
, Value
)
1371 elif self
._ItemType
== MODEL_META_DATA_GLOBAL_DEFINE
:
1372 GlobalData
.gEdkGlobal
[Name
] = Value
1375 # Keyword in [Defines] section can be used as Macros
1377 if (self
._ItemType
== MODEL_META_DATA_HEADER
) and (self
._SectionType
== MODEL_META_DATA_HEADER
):
1378 self
._FileLocalMacros
[Name
] = Value
1380 self
._ValueList
= [Type
, Name
, Value
]
1382 def __ProcessDirective(self
):
1384 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1385 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
]:
1386 Macros
= self
._Macros
1387 Macros
.update(GlobalData
.gGlobalDefines
)
1389 Result
= ValueExpression(self
._ValueList
[1], Macros
)()
1390 except SymbolNotFound
, Exc
:
1391 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1393 except WrnExpression
, Excpt
:
1395 # Catch expression evaluation warning here. We need to report
1396 # the precise number of line and return the evaluation result
1398 EdkLogger
.warn('Parser', "Suspicious expression: %s" % str(Excpt
),
1399 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1400 Line
=self
._LineIndex
+ 1)
1401 Result
= Excpt
.result
1403 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1404 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1405 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1406 self
._DirectiveStack
.append(self
._ItemType
)
1407 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
:
1408 Result
= bool(Result
)
1410 Macro
= self
._ValueList
[1]
1411 Macro
= Macro
[2:-1] if (Macro
.startswith("$(") and Macro
.endswith(")")) else Macro
1412 Result
= Macro
in self
._Macros
1413 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
:
1415 self
._DirectiveEvalStack
.append(Result
)
1416 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
:
1417 self
._DirectiveStack
.append(self
._ItemType
)
1418 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1419 self
._DirectiveEvalStack
.append(bool(Result
))
1420 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1421 self
._DirectiveStack
.append(self
._ItemType
)
1422 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1423 self
._DirectiveEvalStack
.append(True)
1424 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1425 # Back to the nearest !if/!ifdef/!ifndef
1426 while self
._DirectiveStack
:
1427 self
._DirectiveEvalStack
.pop()
1428 Directive
= self
._DirectiveStack
.pop()
1429 if Directive
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1430 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1431 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1433 elif self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1434 # The included file must be relative to workspace or same directory as DSC file
1435 __IncludeMacros
= {}
1437 # Allow using system environment variables in path after !include
1439 __IncludeMacros
['WORKSPACE'] = GlobalData
.gGlobalDefines
['WORKSPACE']
1440 if "ECP_SOURCE" in GlobalData
.gGlobalDefines
.keys():
1441 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gGlobalDefines
['ECP_SOURCE']
1443 # During GenFds phase call DSC parser, will go into this branch.
1445 elif "ECP_SOURCE" in GlobalData
.gCommandLineDefines
.keys():
1446 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gCommandLineDefines
['ECP_SOURCE']
1448 __IncludeMacros
['EFI_SOURCE'] = GlobalData
.gGlobalDefines
['EFI_SOURCE']
1449 __IncludeMacros
['EDK_SOURCE'] = GlobalData
.gGlobalDefines
['EDK_SOURCE']
1451 # Allow using MACROs comes from [Defines] section to keep compatible.
1453 __IncludeMacros
.update(self
._Macros
)
1455 IncludedFile
= NormPath(ReplaceMacro(self
._ValueList
[1], __IncludeMacros
, RaiseError
=True))
1457 # First search the include file under the same directory as DSC file
1459 IncludedFile1
= PathClass(IncludedFile
, self
.MetaFile
.Dir
)
1460 ErrorCode
, ErrorInfo1
= IncludedFile1
.Validate()
1463 # Also search file under the WORKSPACE directory
1465 IncludedFile1
= PathClass(IncludedFile
, GlobalData
.gWorkspace
)
1466 ErrorCode
, ErrorInfo2
= IncludedFile1
.Validate()
1468 EdkLogger
.error('parser', ErrorCode
, File
=self
._FileWithError
,
1469 Line
=self
._LineIndex
+ 1, ExtraData
=ErrorInfo1
+ "\n" + ErrorInfo2
)
1471 self
._FileWithError
= IncludedFile1
1473 IncludedFileTable
= MetaFileStorage(self
._Table
.Cur
, IncludedFile1
, MODEL_FILE_DSC
, False)
1474 Owner
= self
._Content
[self
._ContentIndex
- 1][0]
1475 Parser
= DscParser(IncludedFile1
, self
._FileType
, IncludedFileTable
,
1476 Owner
=Owner
, From
=Owner
)
1478 # Does not allow lower level included file to include upper level included file
1479 if Parser
._From
!= Owner
and int(Owner
) > int (Parser
._From
):
1480 EdkLogger
.error('parser', FILE_ALREADY_EXIST
, File
=self
._FileWithError
,
1481 Line
=self
._LineIndex
+ 1, ExtraData
="{0} is already included at a higher level.".format(IncludedFile1
))
1484 # set the parser status with current status
1485 Parser
._SectionName
= self
._SectionName
1486 Parser
._SectionType
= self
._SectionType
1487 Parser
._Scope
= self
._Scope
1488 Parser
._Enabled
= self
._Enabled
1489 # Parse the included file
1492 # update current status with sub-parser's status
1493 self
._SectionName
= Parser
._SectionName
1494 self
._SectionType
= Parser
._SectionType
1495 self
._Scope
= Parser
._Scope
1496 self
._Enabled
= Parser
._Enabled
1498 # Insert all records in the table for the included file into dsc file table
1499 Records
= IncludedFileTable
.GetAll()
1501 self
._Content
[self
._ContentIndex
:self
._ContentIndex
] = Records
1502 self
._Content
.pop(self
._ContentIndex
- 1)
1503 self
._ValueList
= None
1504 self
._ContentIndex
-= 1
1506 def __ProcessSkuId(self
):
1507 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=True)
1508 for Value
in self
._ValueList
]
1510 def __ProcessLibraryInstance(self
):
1511 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
1513 def __ProcessLibraryClass(self
):
1514 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, RaiseError
=True)
1516 def __ProcessPcd(self
):
1517 if self
._ItemType
not in [MODEL_PCD_FEATURE_FLAG
, MODEL_PCD_FIXED_AT_BUILD
]:
1518 self
._ValueList
[2] = ReplaceMacro(self
._ValueList
[2], self
._Macros
, RaiseError
=True)
1521 ValList
, Valid
, Index
= AnalyzeDscPcd(self
._ValueList
[2], self
._ItemType
)
1523 EdkLogger
.error('build', FORMAT_INVALID
, "Pcd format incorrect.", File
=self
._FileWithError
, Line
=self
._LineIndex
+1,
1524 ExtraData
="%s.%s|%s" % (self
._ValueList
[0], self
._ValueList
[1], self
._ValueList
[2]))
1525 PcdValue
= ValList
[Index
]
1528 ValList
[Index
] = ValueExpression(PcdValue
, self
._Macros
)(True)
1529 except WrnExpression
, Value
:
1530 ValList
[Index
] = Value
.result
1532 if ValList
[Index
] == 'True':
1533 ValList
[Index
] = '1'
1534 if ValList
[Index
] == 'False':
1535 ValList
[Index
] = '0'
1537 if (not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
):
1538 GlobalData
.gPlatformPcds
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = PcdValue
1539 self
._Symbols
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = PcdValue
1540 self
._ValueList
[2] = '|'.join(ValList
)
1542 def __ProcessComponent(self
):
1543 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1545 def __ProcessSourceOverridePath(self
):
1546 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1548 def __ProcessBuildOption(self
):
1549 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=False)
1550 for Value
in self
._ValueList
]
1553 MODEL_META_DATA_HEADER
: _DefineParser
,
1554 MODEL_EFI_SKU_ID
: _SkuIdParser
,
1555 MODEL_EFI_LIBRARY_INSTANCE
: _LibraryInstanceParser
,
1556 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
1557 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1558 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1559 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1560 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
1561 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
1562 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
1563 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
1564 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
1565 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
1566 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
1567 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: _CompponentSourceOverridePathParser
,
1568 MODEL_META_DATA_BUILD_OPTION
: _BuildOptionParser
,
1569 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1570 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
1571 MODEL_META_DATA_SECTION_HEADER
: MetaFileParser
._SectionHeaderParser
,
1572 MODEL_META_DATA_SUBSECTION_HEADER
: _SubsectionHeaderParser
,
1575 _Macros
= property(_GetMacros
)
1577 ## DEC file parser class
1579 # @param FilePath The path of platform description file
1580 # @param FileType The raw data of DSC file
1581 # @param Table Database used to retrieve module/package information
1582 # @param Macros Macros used for replacement in file
1584 class DecParser(MetaFileParser
):
1585 # DEC file supported data types (one type per section)
1587 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1588 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
1589 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1590 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1591 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1592 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1593 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1594 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1595 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1596 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1597 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1598 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1599 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
,
1602 ## Constructor of DecParser
1604 # Initialize object of DecParser
1606 # @param FilePath The path of platform description file
1607 # @param FileType The raw data of DSC file
1608 # @param Table Database used to retrieve module/package information
1609 # @param Macros Macros used for replacement in file
1611 def __init__(self
, FilePath
, FileType
, Table
):
1612 # prevent re-initialization
1613 if hasattr(self
, "_Table"):
1615 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, -1)
1617 self
._Version
= 0x00010005 # Only EDK2 dec file is supported
1618 self
._AllPCDs
= [] # Only for check duplicate PCD
1624 Content
= open(str(self
.MetaFile
), 'r').readlines()
1626 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1628 for Index
in range(0, len(Content
)):
1629 Line
, Comment
= CleanString2(Content
[Index
])
1630 self
._CurrentLine
= Line
1631 self
._LineIndex
= Index
1633 # save comment for later use
1635 self
._Comments
.append((Comment
, self
._LineIndex
+ 1))
1641 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1642 self
._SectionHeaderParser
()
1645 elif len(self
._SectionType
) == 0:
1650 self
._ValueList
= ['', '', '']
1651 self
._SectionParser
[self
._SectionType
[0]](self
)
1652 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
1658 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1659 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1661 for Arch
, ModuleType
, Type
in self
._Scope
:
1662 self
._LastItem
= self
._Store
(
1670 self
._LineIndex
+ 1,
1672 self
._LineIndex
+ 1,
1676 for Comment
, LineNo
in self
._Comments
:
1678 MODEL_META_DATA_COMMENT
,
1695 ## Section header parser
1697 # The section header is always in following format:
1699 # [section_name.arch<.platform|module_type>]
1701 def _SectionHeaderParser(self
):
1703 self
._SectionName
= ''
1704 self
._SectionType
= []
1706 Line
= self
._CurrentLine
.replace("%s%s" % (TAB_COMMA_SPLIT
, TAB_SPACE_SPLIT
), TAB_COMMA_SPLIT
)
1707 for Item
in Line
[1:-1].split(TAB_COMMA_SPLIT
):
1709 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
,
1710 "section name can NOT be empty or incorrectly use separator comma",
1711 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1712 ItemList
= Item
.split(TAB_SPLIT
)
1714 # different types of PCD are permissible in one section
1715 self
._SectionName
= ItemList
[0].upper()
1716 if self
._SectionName
in self
.DataType
:
1717 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1718 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1720 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
1721 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1723 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1727 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1729 Line
=self
._LineIndex
+ 1,
1730 ExtraData
=self
._CurrentLine
1733 if len(ItemList
) > 1:
1734 S1
= ItemList
[1].upper()
1738 # S2 may be Platform or ModuleType
1739 if len(ItemList
) > 2:
1740 S2
= ItemList
[2].upper()
1743 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1744 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1746 # 'COMMON' must not be used with specific ARCHs at the same section
1747 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1748 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1749 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
1751 ## [guids], [ppis] and [protocols] section parser
1753 def _GuidParser(self
):
1754 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1755 if len(TokenList
) < 2:
1756 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1757 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1758 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1759 if TokenList
[0] == '':
1760 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1761 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1762 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1763 if TokenList
[1] == '':
1764 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1765 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1766 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1767 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1768 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1769 ExtraData
=self
._CurrentLine
+ \
1770 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1771 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1772 self
._ValueList
[0] = TokenList
[0]
1773 self
._ValueList
[1] = TokenList
[1]
1775 ## PCD sections parser
1777 # [PcdsFixedAtBuild]
1778 # [PcdsPatchableInModule]
1784 def _PcdParser(self
):
1785 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1786 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1787 ValueRe
= re
.compile(r
'^[a-zA-Z_][a-zA-Z0-9_]*')
1788 # check PCD information
1789 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1790 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1791 ExtraData
=self
._CurrentLine
+ \
1792 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1793 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1794 # check format of token space GUID CName
1795 if not ValueRe
.match(self
._ValueList
[0]):
1796 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_]*'",
1797 ExtraData
=self
._CurrentLine
+ \
1798 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1799 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1800 # check format of PCD CName
1801 if not ValueRe
.match(self
._ValueList
[1]):
1802 EdkLogger
.error('Parser', FORMAT_INVALID
, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
1803 ExtraData
=self
._CurrentLine
+ \
1804 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1805 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1806 # check PCD datum information
1807 if len(TokenList
) < 2 or TokenList
[1] == '':
1808 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1809 ExtraData
=self
._CurrentLine
+ \
1810 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1811 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1814 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1815 PtrValue
= ValueRe
.findall(TokenList
[1])
1817 # Has VOID* type string, may contain "|" character in the string.
1818 if len(PtrValue
) != 0:
1819 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1820 ValueList
= GetSplitValueList(ptrValueList
)
1821 ValueList
[0] = PtrValue
[0]
1823 ValueList
= GetSplitValueList(TokenList
[1])
1826 # check if there's enough datum information given
1827 if len(ValueList
) != 3:
1828 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1829 ExtraData
=self
._CurrentLine
+ \
1830 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1831 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1832 # check default value
1833 if ValueList
[0] == '':
1834 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1835 ExtraData
=self
._CurrentLine
+ \
1836 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1837 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1839 if ValueList
[1] == '':
1840 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1841 ExtraData
=self
._CurrentLine
+ \
1842 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1843 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1844 # check token of the PCD
1845 if ValueList
[2] == '':
1846 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1847 ExtraData
=self
._CurrentLine
+ \
1848 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1849 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1850 # check format of default value against the datum type
1851 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1853 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1854 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1856 if ValueList
[0] in ['True', 'true', 'TRUE']:
1858 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1861 # check for duplicate PCD definition
1862 if (self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]) in self
._AllPCDs
:
1863 EdkLogger
.error('Parser', FORMAT_INVALID
,
1864 "The same PCD name and GUID have been already defined",
1865 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1867 self
._AllPCDs
.append((self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]))
1869 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
1872 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
1873 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
1874 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
1875 MODEL_EFI_GUID
: _GuidParser
,
1876 MODEL_EFI_PPI
: _GuidParser
,
1877 MODEL_EFI_PROTOCOL
: _GuidParser
,
1878 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1879 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1880 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1881 MODEL_PCD_DYNAMIC
: _PcdParser
,
1882 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
1883 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1884 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
1889 # This acts like the main() function for the script, unless it is 'import'ed into another
1892 if __name__
== '__main__':