2 # This file is used to parse meta files
4 # Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 import Common
.LongFilePathOs
as os
22 import Common
.EdkLogger
as EdkLogger
23 import Common
.GlobalData
as GlobalData
25 from CommonDataClass
.DataClass
import *
26 from Common
.DataType
import *
27 from Common
.String
import *
28 from Common
.Misc
import GuidStructureStringToGuidString
, CheckPcdDatum
, PathClass
, AnalyzePcdData
, AnalyzeDscPcd
29 from Common
.Expression
import *
30 from CommonDataClass
.Exceptions
import *
31 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
33 from MetaFileTable
import MetaFileStorage
34 from MetaFileCommentParser
import CheckInfComment
36 ## A decorator used to parse macro definition
37 def ParseMacro(Parser
):
38 def MacroParser(self
):
39 Match
= gMacroDefPattern
.match(self
._CurrentLine
)
41 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
45 TokenList
= GetSplitValueList(self
._CurrentLine
[Match
.end(1):], TAB_EQUAL_SPLIT
, 1)
48 EdkLogger
.error('Parser', FORMAT_INVALID
, "No macro name given",
49 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
50 if len(TokenList
) < 2:
54 Name
, Value
= TokenList
55 # Global macros can be only defined via environment variable
56 if Name
in GlobalData
.gGlobalDefines
:
57 EdkLogger
.error('Parser', FORMAT_INVALID
, "%s can only be defined via environment variable" % Name
,
58 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
59 # Only upper case letters, digit and '_' are allowed
60 if not gMacroNamePattern
.match(Name
):
61 EdkLogger
.error('Parser', FORMAT_INVALID
, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
62 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
64 Value
= ReplaceMacro(Value
, self
._Macros
)
65 if Type
in self
.DataType
:
66 self
._ItemType
= self
.DataType
[Type
]
68 self
._ItemType
= MODEL_META_DATA_DEFINE
69 # DEFINE defined macros
70 if Type
== TAB_DSC_DEFINES_DEFINE
:
72 # First judge whether this DEFINE is in conditional directive statements or not.
74 if type(self
) == DscParser
and self
._InDirective
> -1:
77 if type(self
) == DecParser
:
78 if MODEL_META_DATA_HEADER
in self
._SectionType
:
79 self
._FileLocalMacros
[Name
] = Value
81 self
._ConstructSectionMacroDict
(Name
, Value
)
82 elif self
._SectionType
== MODEL_META_DATA_HEADER
:
83 self
._FileLocalMacros
[Name
] = Value
85 self
._ConstructSectionMacroDict
(Name
, Value
)
87 # EDK_GLOBAL defined macros
88 elif type(self
) != DscParser
:
89 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used in .dsc file",
90 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
91 elif self
._SectionType
!= MODEL_META_DATA_HEADER
:
92 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used under [Defines] section",
93 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
94 elif (Name
in self
._FileLocalMacros
) and (self
._FileLocalMacros
[Name
] != Value
):
95 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
96 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
98 self
._ValueList
= [Type
, Name
, Value
]
102 ## Base class of parser
104 # This class is used for derivation purpose. The specific parser for one kind
105 # type file must derive this class and implement some public interfaces.
107 # @param FilePath The path of platform description file
108 # @param FileType The raw data of DSC file
109 # @param Table Database used to retrieve module/package information
110 # @param Macros Macros used for replacement in file
111 # @param Owner Owner ID (for sub-section parsing)
112 # @param From ID from which the data comes (for !INCLUDE directive)
114 class MetaFileParser(object):
115 # data type (file content) for specific file type
118 # Parser objects used to implement singleton
123 # One file, one parser object. This factory method makes sure that there's
124 # only one object constructed for one meta file.
126 # @param Class class object of real AutoGen class
127 # (InfParser, DecParser or DscParser)
128 # @param FilePath The path of meta file
129 # @param *args The specific class related parameters
130 # @param **kwargs The specific class related dict parameters
132 def __new__(Class
, FilePath
, *args
, **kwargs
):
133 if FilePath
in Class
.MetaFiles
:
134 return Class
.MetaFiles
[FilePath
]
136 ParserObject
= super(MetaFileParser
, Class
).__new
__(Class
)
137 Class
.MetaFiles
[FilePath
] = ParserObject
140 ## Constructor of MetaFileParser
142 # Initialize object of MetaFileParser
144 # @param FilePath The path of platform description file
145 # @param FileType The raw data of DSC file
146 # @param Table Database used to retrieve module/package information
147 # @param Macros Macros used for replacement in file
148 # @param Owner Owner ID (for sub-section parsing)
149 # @param From ID from which the data comes (for !INCLUDE directive)
151 def __init__(self
, FilePath
, FileType
, Table
, Owner
= -1, From
= -1):
153 self
._RawTable
= Table
154 self
._FileType
= FileType
155 self
.MetaFile
= FilePath
156 self
._FileDir
= self
.MetaFile
.Dir
158 self
._FileLocalMacros
= {}
159 self
._SectionsMacroDict
= {}
161 # for recursive parsing
162 self
._Owner
= [Owner
]
165 # parsr status for parsing
166 self
._ValueList
= ['', '', '', '', '']
169 self
._CurrentLine
= ''
170 self
._SectionType
= MODEL_UNKNOWN
171 self
._SectionName
= ''
172 self
._InSubsection
= False
173 self
._SubsectionType
= MODEL_UNKNOWN
174 self
._SubsectionName
= ''
175 self
._ItemType
= MODEL_UNKNOWN
178 self
._Finished
= False
179 self
._PostProcessed
= False
180 # Different version of meta-file has different way to parse.
183 ## Store the parsed data in table
184 def _Store(self
, *Args
):
185 return self
._Table
.Insert(*Args
)
187 ## Virtual method for starting parse
189 raise NotImplementedError
191 ## Notify a post-process is needed
192 def DoPostProcess(self
):
193 self
._PostProcessed
= False
195 ## Set parsing complete flag in both class and table
197 self
._Finished
= True
198 ## Do not set end flag when processing included files
200 self
._Table
.SetEndFlag()
202 def _PostProcess(self
):
203 self
._PostProcessed
= True
205 ## Get the parse complete flag
206 def _GetFinished(self
):
207 return self
._Finished
209 ## Set the complete flag
210 def _SetFinished(self
, Value
):
211 self
._Finished
= Value
213 ## Use [] style to query data in table, just for readability
215 # DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]
217 def __getitem__(self
, DataInfo
):
218 if type(DataInfo
) != type(()):
219 DataInfo
= (DataInfo
,)
221 # Parse the file first, if necessary
222 if not self
._Finished
:
223 if self
._RawTable
.IsIntegrity():
224 self
._Finished
= True
226 self
._Table
= self
._RawTable
227 self
._PostProcessed
= False
230 # No specific ARCH or Platform given, use raw data
231 if self
._RawTable
and (len(DataInfo
) == 1 or DataInfo
[1] == None):
232 return self
._RawTable
.Query(*DataInfo
)
234 # Do post-process if necessary
235 if not self
._PostProcessed
:
238 return self
._Table
.Query(*DataInfo
)
240 ## Data parser for the common format in different type of file
242 # The common format in the meatfile is like
247 def _CommonParser(self
):
248 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
249 self
._ValueList
[0:len(TokenList
)] = TokenList
251 ## Data parser for the format in which there's path
253 # Only path can have macro used. So we need to replace them before use.
256 def _PathParser(self
):
257 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
258 self
._ValueList
[0:len(TokenList
)] = TokenList
259 # Don't do macro replacement for dsc file at this point
260 if type(self
) != DscParser
:
261 Macros
= self
._Macros
262 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
264 ## Skip unsupported data
266 EdkLogger
.warn("Parser", "Unrecognized content", File
=self
.MetaFile
,
267 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
);
268 self
._ValueList
[0:1] = [self
._CurrentLine
]
270 ## Skip unsupported data for UserExtension Section
271 def _SkipUserExtension(self
):
272 self
._ValueList
[0:1] = [self
._CurrentLine
]
274 ## Section header parser
276 # The section header is always in following format:
278 # [section_name.arch<.platform|module_type>]
280 def _SectionHeaderParser(self
):
282 self
._SectionName
= ''
284 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
287 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
,2)
288 # different section should not mix in one section
289 if self
._SectionName
!= '' and self
._SectionName
!= ItemList
[0].upper():
290 EdkLogger
.error('Parser', FORMAT_INVALID
, "Different section names in the same section",
291 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
292 self
._SectionName
= ItemList
[0].upper()
293 if self
._SectionName
in self
.DataType
:
294 self
._SectionType
= self
.DataType
[self
._SectionName
]
295 # Check if the section name is valid
296 if self
._SectionName
not in SECTIONS_HAVE_ITEM_AFTER_ARCH
and len(ItemList
) > 3:
297 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
298 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
299 elif self
._Version
>= 0x00010005:
300 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
301 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
303 self
._SectionType
= MODEL_UNKNOWN
306 if len(ItemList
) > 1:
307 S1
= ItemList
[1].upper()
312 # S2 may be Platform or ModuleType
313 if len(ItemList
) > 2:
314 if self
._SectionName
.upper() in SECTIONS_HAVE_ITEM_PCD
:
317 S2
= ItemList
[2].upper()
320 self
._Scope
.append([S1
, S2
])
322 # 'COMMON' must not be used with specific ARCHs at the same section
323 if 'COMMON' in ArchList
and len(ArchList
) > 1:
324 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
325 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
326 # If the section information is needed later, it should be stored in database
327 self
._ValueList
[0] = self
._SectionName
329 ## [defines] section parser
331 def _DefineParser(self
):
332 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
333 self
._ValueList
[1:len(TokenList
)] = TokenList
334 if not self
._ValueList
[1]:
335 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
336 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
337 if not self
._ValueList
[2]:
338 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
339 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
341 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
342 Name
, Value
= self
._ValueList
[1], self
._ValueList
[2]
343 # Sometimes, we need to make differences between EDK and EDK2 modules
344 if Name
== 'INF_VERSION':
346 self
._Version
= int(Value
, 0)
348 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid version number",
349 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
351 if type(self
) == InfParser
and self
._Version
< 0x00010005:
352 # EDK module allows using defines as macros
353 self
._FileLocalMacros
[Name
] = Value
354 self
._Defines
[Name
] = Value
356 ## [BuildOptions] section parser
358 def _BuildOptionParser(self
):
359 self
._CurrentLine
= CleanString(self
._CurrentLine
, BuildOption
=True)
360 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
361 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
362 if len(TokenList2
) == 2:
363 self
._ValueList
[0] = TokenList2
[0] # toolchain family
364 self
._ValueList
[1] = TokenList2
[1] # keys
366 self
._ValueList
[1] = TokenList
[0]
367 if len(TokenList
) == 2 and type(self
) != DscParser
: # value
368 self
._ValueList
[2] = ReplaceMacro(TokenList
[1], self
._Macros
)
370 if self
._ValueList
[1].count('_') != 4:
374 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
375 ExtraData
=self
._CurrentLine
,
377 Line
=self
._LineIndex
+ 1
379 def GetValidExpression(self
, TokenSpaceGuid
, PcdCName
):
380 return self
._Table
.GetValidExpression(TokenSpaceGuid
, PcdCName
)
381 def _GetMacros(self
):
383 Macros
.update(self
._FileLocalMacros
)
384 Macros
.update(self
._GetApplicableSectionMacro
())
387 ## Construct section Macro dict
388 def _ConstructSectionMacroDict(self
, Name
, Value
):
389 ScopeKey
= [(Scope
[0], Scope
[1]) for Scope
in self
._Scope
]
390 ScopeKey
= tuple(ScopeKey
)
391 SectionDictKey
= self
._SectionType
, ScopeKey
393 # DecParser SectionType is a list, will contain more than one item only in Pcd Section
394 # As Pcd section macro usage is not alllowed, so here it is safe
396 if type(self
) == DecParser
:
397 SectionDictKey
= self
._SectionType
[0], ScopeKey
398 if SectionDictKey
not in self
._SectionsMacroDict
:
399 self
._SectionsMacroDict
[SectionDictKey
] = {}
400 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
401 SectionLocalMacros
[Name
] = Value
403 ## Get section Macros that are applicable to current line, which may come from other sections
404 ## that share the same name while scope is wider
405 def _GetApplicableSectionMacro(self
):
412 ActiveSectionType
= self
._SectionType
413 if type(self
) == DecParser
:
414 ActiveSectionType
= self
._SectionType
[0]
416 for (SectionType
, Scope
) in self
._SectionsMacroDict
:
417 if SectionType
!= ActiveSectionType
:
420 for ActiveScope
in self
._Scope
:
421 Scope0
, Scope1
= ActiveScope
[0], ActiveScope
[1]
422 if(Scope0
, Scope1
) not in Scope
:
425 SpeSpeMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
427 for ActiveScope
in self
._Scope
:
428 Scope0
, Scope1
= ActiveScope
[0], ActiveScope
[1]
429 if(Scope0
, Scope1
) not in Scope
and (Scope0
, "COMMON") not in Scope
and ("COMMON", Scope1
) not in Scope
:
432 ComSpeMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
434 if ("COMMON", "COMMON") in Scope
:
435 ComComMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
437 Macros
.update(ComComMacroDict
)
438 Macros
.update(ComSpeMacroDict
)
439 Macros
.update(SpeSpeMacroDict
)
444 Finished
= property(_GetFinished
, _SetFinished
)
445 _Macros
= property(_GetMacros
)
448 ## INF file parser class
450 # @param FilePath The path of platform description file
451 # @param FileType The raw data of DSC file
452 # @param Table Database used to retrieve module/package information
453 # @param Macros Macros used for replacement in file
455 class InfParser(MetaFileParser
):
456 # INF file supported data types (one type per section)
458 TAB_UNKNOWN
.upper() : MODEL_UNKNOWN
,
459 TAB_INF_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
460 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
461 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
462 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
463 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
464 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
465 TAB_PACKAGES
.upper() : MODEL_META_DATA_PACKAGE
,
466 TAB_NMAKE
.upper() : MODEL_META_DATA_NMAKE
,
467 TAB_INF_FIXED_PCD
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
468 TAB_INF_PATCH_PCD
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
469 TAB_INF_FEATURE_PCD
.upper() : MODEL_PCD_FEATURE_FLAG
,
470 TAB_INF_PCD_EX
.upper() : MODEL_PCD_DYNAMIC_EX
,
471 TAB_INF_PCD
.upper() : MODEL_PCD_DYNAMIC
,
472 TAB_SOURCES
.upper() : MODEL_EFI_SOURCE_FILE
,
473 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
474 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
475 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
476 TAB_DEPEX
.upper() : MODEL_EFI_DEPEX
,
477 TAB_BINARIES
.upper() : MODEL_EFI_BINARY_FILE
,
478 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
481 ## Constructor of InfParser
483 # Initialize object of InfParser
485 # @param FilePath The path of module description file
486 # @param FileType The raw data of DSC file
487 # @param Table Database used to retrieve module/package information
488 # @param Macros Macros used for replacement in file
490 def __init__(self
, FilePath
, FileType
, Table
):
491 # prevent re-initialization
492 if hasattr(self
, "_Table"):
494 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
502 Content
= open(str(self
.MetaFile
), 'r').readlines()
504 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
506 # parse the file line by line
507 IsFindBlockComment
= False
508 GetHeaderComment
= False
513 for Index
in range(0, len(Content
)):
514 # skip empty, commented, block commented lines
515 Line
, Comment
= CleanString2(Content
[Index
], AllowCppStyleComment
=True)
517 if Index
+ 1 < len(Content
):
518 NextLine
, NextComment
= CleanString2(Content
[Index
+ 1])
521 Comments
.append((Comment
, Index
+ 1))
522 elif GetHeaderComment
:
523 SectionComments
.extend(Comments
)
526 if Line
.find(DataType
.TAB_COMMENT_EDK_START
) > -1:
527 IsFindBlockComment
= True
529 if Line
.find(DataType
.TAB_COMMENT_EDK_END
) > -1:
530 IsFindBlockComment
= False
532 if IsFindBlockComment
:
535 self
._LineIndex
= Index
536 self
._CurrentLine
= Line
539 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
540 if not GetHeaderComment
:
541 for Cmt
, LNo
in Comments
:
542 self
._Store
(MODEL_META_DATA_HEADER_COMMENT
, Cmt
, '', '', 'COMMON',
543 'COMMON', self
._Owner
[-1], LNo
, -1, LNo
, -1, 0)
544 GetHeaderComment
= True
546 TailComments
.extend(SectionComments
+ Comments
)
548 self
._SectionHeaderParser
()
549 # Check invalid sections
550 if self
._Version
< 0x00010005:
551 if self
._SectionType
in [MODEL_META_DATA_BUILD_OPTION
,
552 MODEL_EFI_LIBRARY_CLASS
,
553 MODEL_META_DATA_PACKAGE
,
554 MODEL_PCD_FIXED_AT_BUILD
,
555 MODEL_PCD_PATCHABLE_IN_MODULE
,
556 MODEL_PCD_FEATURE_FLAG
,
557 MODEL_PCD_DYNAMIC_EX
,
562 MODEL_META_DATA_USER_EXTENSION
]:
563 EdkLogger
.error('Parser', FORMAT_INVALID
,
564 "Section [%s] is not allowed in inf file without version" % (self
._SectionName
),
565 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
566 elif self
._SectionType
in [MODEL_EFI_INCLUDE
,
567 MODEL_EFI_LIBRARY_INSTANCE
,
568 MODEL_META_DATA_NMAKE
]:
569 EdkLogger
.error('Parser', FORMAT_INVALID
,
570 "Section [%s] is not allowed in inf file with version 0x%08x" % (self
._SectionName
, self
._Version
),
571 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
573 # merge two lines specified by '\' in section NMAKE
574 elif self
._SectionType
== MODEL_META_DATA_NMAKE
:
577 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
580 if NextLine
[0] == TAB_SECTION_START
and NextLine
[-1] == TAB_SECTION_END
:
581 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
584 NmakeLine
= NmakeLine
+ ' ' + Line
[0:-1]
587 self
._CurrentLine
= NmakeLine
+ Line
591 self
._ValueList
= ['', '', '']
592 # parse current line, result will be put in self._ValueList
593 self
._SectionParser
[self
._SectionType
](self
)
594 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
599 Comments
.append((Comment
, Index
+ 1))
600 if GlobalData
.gOptions
and GlobalData
.gOptions
.CheckUsage
:
601 CheckInfComment(self
._SectionType
, Comments
, str(self
.MetaFile
), Index
+ 1, self
._ValueList
)
603 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
604 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
606 for Arch
, Platform
in self
._Scope
:
607 LastItem
= self
._Store
(self
._SectionType
,
620 for Comment
, LineNo
in Comments
:
621 self
._Store
(MODEL_META_DATA_COMMENT
, Comment
, '', '', Arch
, Platform
,
622 LastItem
, LineNo
, -1, LineNo
, -1, 0)
625 TailComments
.extend(SectionComments
+ Comments
)
626 if IsFindBlockComment
:
627 EdkLogger
.error("Parser", FORMAT_INVALID
, "Open block comments (starting with /*) are expected to end with */",
630 # If there are tail comments in INF file, save to database whatever the comments are
631 for Comment
in TailComments
:
632 self
._Store
(MODEL_META_DATA_TAIL_COMMENT
, Comment
[0], '', '', 'COMMON',
633 'COMMON', self
._Owner
[-1], -1, -1, -1, -1, 0)
636 ## Data parser for the format in which there's path
638 # Only path can have macro used. So we need to replace them before use.
640 def _IncludeParser(self
):
641 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
642 self
._ValueList
[0:len(TokenList
)] = TokenList
643 Macros
= self
._Macros
645 for Index
in range(0, len(self
._ValueList
)):
646 Value
= self
._ValueList
[Index
]
650 if Value
.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value
.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
651 Value
= '$(EDK_SOURCE)' + Value
[17:]
652 if Value
.find('$(EFI_SOURCE)') > -1 or Value
.find('$(EDK_SOURCE)') > -1:
654 elif Value
.startswith('.'):
656 elif Value
.startswith('$('):
659 Value
= '$(EFI_SOURCE)/' + Value
661 self
._ValueList
[Index
] = ReplaceMacro(Value
, Macros
)
663 ## Parse [Sources] section
665 # Only path can have macro used. So we need to replace them before use.
668 def _SourceFileParser(self
):
669 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
670 self
._ValueList
[0:len(TokenList
)] = TokenList
671 Macros
= self
._Macros
672 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
673 if 'COMPONENT_TYPE' in Macros
:
674 if self
._Defines
['COMPONENT_TYPE'].upper() == 'ACPITABLE':
675 self
._ValueList
[0] = GetSplitValueList(self
._ValueList
[0], ' ', 1)[0]
676 if self
._Defines
['BASE_NAME'] == 'Microcode':
678 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
680 ## Parse [Binaries] section
682 # Only path can have macro used. So we need to replace them before use.
685 def _BinaryFileParser(self
):
686 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 2)
687 if len(TokenList
) < 2:
688 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type or path specified",
689 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
690 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
692 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type specified",
693 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
694 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
696 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file path specified",
697 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
698 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
699 self
._ValueList
[0:len(TokenList
)] = TokenList
700 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
702 ## [nmake] section parser (Edk.x style only)
703 def _NmakeParser(self
):
704 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
705 self
._ValueList
[0:len(TokenList
)] = TokenList
707 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
708 # remove self-reference in macro setting
709 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
711 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
713 def _PcdParser(self
):
714 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
715 ValueList
= GetSplitValueList(TokenList
[0], TAB_SPLIT
)
716 if len(ValueList
) != 2:
717 EdkLogger
.error('Parser', FORMAT_INVALID
, "Illegal token space GUID and PCD name format",
718 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
719 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
720 self
._ValueList
[0:1] = ValueList
721 if len(TokenList
) > 1:
722 self
._ValueList
[2] = TokenList
[1]
723 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
724 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
725 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
726 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
728 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
729 if self
._ValueList
[2] != '':
730 InfPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
731 if InfPcdValueList
[0] in ['True', 'true', 'TRUE']:
732 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '1', 1);
733 elif InfPcdValueList
[0] in ['False', 'false', 'FALSE']:
734 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '0', 1);
735 if (self
._ValueList
[0], self
._ValueList
[1]) not in self
.PcdsDict
:
736 self
.PcdsDict
[self
._ValueList
[0], self
._ValueList
[1]] = self
._SectionType
737 elif self
.PcdsDict
[self
._ValueList
[0], self
._ValueList
[1]] != self
._SectionType
:
738 EdkLogger
.error('Parser', FORMAT_INVALID
, "It is not permissible to list a specified PCD in different PCD type sections.",
739 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
740 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
742 ## [depex] section parser
744 def _DepexParser(self
):
745 self
._ValueList
[0:1] = [self
._CurrentLine
]
748 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
749 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
750 MODEL_META_DATA_BUILD_OPTION
: MetaFileParser
._BuildOptionParser
,
751 MODEL_EFI_INCLUDE
: _IncludeParser
, # for Edk.x modules
752 MODEL_EFI_LIBRARY_INSTANCE
: MetaFileParser
._CommonParser
, # for Edk.x modules
753 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
754 MODEL_META_DATA_PACKAGE
: MetaFileParser
._PathParser
,
755 MODEL_META_DATA_NMAKE
: _NmakeParser
, # for Edk.x modules
756 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
757 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
758 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
759 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
760 MODEL_PCD_DYNAMIC
: _PcdParser
,
761 MODEL_EFI_SOURCE_FILE
: _SourceFileParser
,
762 MODEL_EFI_GUID
: MetaFileParser
._CommonParser
,
763 MODEL_EFI_PROTOCOL
: MetaFileParser
._CommonParser
,
764 MODEL_EFI_PPI
: MetaFileParser
._CommonParser
,
765 MODEL_EFI_DEPEX
: _DepexParser
,
766 MODEL_EFI_BINARY_FILE
: _BinaryFileParser
,
767 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
770 ## DSC file parser class
772 # @param FilePath The path of platform description file
773 # @param FileType The raw data of DSC file
774 # @param Table Database used to retrieve module/package information
775 # @param Macros Macros used for replacement in file
776 # @param Owner Owner ID (for sub-section parsing)
777 # @param From ID from which the data comes (for !INCLUDE directive)
779 class DscParser(MetaFileParser
):
780 # DSC file supported data types (one type per section)
782 TAB_SKUIDS
.upper() : MODEL_EFI_SKU_ID
,
783 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
784 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
785 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
786 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
787 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
788 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
789 TAB_PCDS_DYNAMIC_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_DEFAULT
,
790 TAB_PCDS_DYNAMIC_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_HII
,
791 TAB_PCDS_DYNAMIC_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_VPD
,
792 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT
,
793 TAB_PCDS_DYNAMIC_EX_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_HII
,
794 TAB_PCDS_DYNAMIC_EX_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_VPD
,
795 TAB_COMPONENTS
.upper() : MODEL_META_DATA_COMPONENT
,
796 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH
.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
,
797 TAB_DSC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
798 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
799 TAB_DSC_DEFINES_EDKGLOBAL
: MODEL_META_DATA_GLOBAL_DEFINE
,
800 TAB_INCLUDE
.upper() : MODEL_META_DATA_INCLUDE
,
801 TAB_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
802 TAB_IF_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
803 TAB_IF_N_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
,
804 TAB_ELSE_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
,
805 TAB_ELSE
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
806 TAB_END_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
,
807 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
,
810 # Valid names in define section
817 "PCD_INFO_GENERATION",
818 "PCD_VAR_CHECK_GENERATION",
819 "SUPPORTED_ARCHITECTURES",
828 "FIX_LOAD_TOP_MEMORY_ADDRESS"
831 SubSectionDefineKeywords
= [
835 SymbolPattern
= ValueExpression
.SymbolPattern
837 ## Constructor of DscParser
839 # Initialize object of DscParser
841 # @param FilePath The path of platform description file
842 # @param FileType The raw data of DSC file
843 # @param Table Database used to retrieve module/package information
844 # @param Macros Macros used for replacement in file
845 # @param Owner Owner ID (for sub-section parsing)
846 # @param From ID from which the data comes (for !INCLUDE directive)
848 def __init__(self
, FilePath
, FileType
, Table
, Owner
= -1, From
= -1):
849 # prevent re-initialization
850 if hasattr(self
, "_Table"):
852 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, Owner
, From
)
853 self
._Version
= 0x00010005 # Only EDK2 dsc file is supported
854 # to store conditional directive evaluation result
855 self
._DirectiveStack
= []
856 self
._DirectiveEvalStack
= []
860 # Specify whether current line is in uncertain condition
862 self
._InDirective
= -1
864 # Final valid replacable symbols
867 # Map the ID between the original table and new table to track
870 self
._IdMapping
= {-1:-1}
876 Content
= open(str(self
.MetaFile
), 'r').readlines()
878 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
881 for Index
in range(0, len(Content
)):
882 Line
= CleanString(Content
[Index
])
887 self
._CurrentLine
= Line
888 self
._LineIndex
= Index
889 if self
._InSubsection
and self
._Owner
[-1] == -1:
890 self
._Owner
.append(self
._LastItem
)
893 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
894 self
._SectionType
= MODEL_META_DATA_SECTION_HEADER
896 elif Line
[0] == '}' and self
._InSubsection
:
897 self
._InSubsection
= False
898 self
._SubsectionType
= MODEL_UNKNOWN
899 self
._SubsectionName
= ''
904 elif Line
[0] == TAB_OPTION_START
and Line
[-1] == TAB_OPTION_END
:
905 self
._SubsectionType
= MODEL_META_DATA_SUBSECTION_HEADER
908 self
._DirectiveParser
()
911 if self
._InSubsection
:
912 SectionType
= self
._SubsectionType
914 SectionType
= self
._SectionType
915 self
._ItemType
= SectionType
917 self
._ValueList
= ['', '', '']
918 self
._SectionParser
[SectionType
](self
)
919 if self
._ValueList
== None:
922 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
923 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
925 for Arch
, ModuleType
in self
._Scope
:
926 Owner
= self
._Owner
[-1]
927 if self
._SubsectionType
!= MODEL_UNKNOWN
:
928 Owner
= OwnerId
[Arch
]
929 self
._LastItem
= self
._Store
(
944 if self
._SubsectionType
== MODEL_UNKNOWN
and self
._InSubsection
:
945 OwnerId
[Arch
] = self
._LastItem
947 if self
._DirectiveStack
:
948 Type
, Line
, Text
= self
._DirectiveStack
[-1]
949 EdkLogger
.error('Parser', FORMAT_INVALID
, "No matching '!endif' found",
950 ExtraData
=Text
, File
=self
.MetaFile
, Line
=Line
)
953 ## <subsection_header> parser
954 def _SubsectionHeaderParser(self
):
955 self
._SubsectionName
= self
._CurrentLine
[1:-1].upper()
956 if self
._SubsectionName
in self
.DataType
:
957 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
959 self
._SubsectionType
= MODEL_UNKNOWN
960 EdkLogger
.warn("Parser", "Unrecognized sub-section", File
=self
.MetaFile
,
961 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
962 self
._ValueList
[0] = self
._SubsectionName
964 ## Directive statement parser
965 def _DirectiveParser(self
):
966 self
._ValueList
= ['', '', '']
967 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
968 self
._ValueList
[0:len(TokenList
)] = TokenList
971 DirectiveName
= self
._ValueList
[0].upper()
972 if DirectiveName
not in self
.DataType
:
973 EdkLogger
.error("Parser", FORMAT_INVALID
, "Unknown directive [%s]" % DirectiveName
,
974 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
976 if DirectiveName
in ['!IF', '!IFDEF', '!IFNDEF']:
977 self
._InDirective
+= 1
979 if DirectiveName
in ['!ENDIF']:
980 self
._InDirective
-= 1
982 if DirectiveName
in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self
._ValueList
[1] == '':
983 EdkLogger
.error("Parser", FORMAT_INVALID
, "Missing expression",
984 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
985 ExtraData
=self
._CurrentLine
)
987 ItemType
= self
.DataType
[DirectiveName
]
988 Scope
= [['COMMON', 'COMMON']]
989 if ItemType
== MODEL_META_DATA_INCLUDE
:
991 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
992 # Remove all directives between !if and !endif, including themselves
993 while self
._DirectiveStack
:
994 # Remove any !else or !elseif
995 DirectiveInfo
= self
._DirectiveStack
.pop()
996 if DirectiveInfo
[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
997 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
998 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1001 EdkLogger
.error("Parser", FORMAT_INVALID
, "Redundant '!endif'",
1002 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
1003 ExtraData
=self
._CurrentLine
)
1004 elif ItemType
!= MODEL_META_DATA_INCLUDE
:
1005 # Break if there's a !else is followed by a !elseif
1006 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
and \
1007 self
._DirectiveStack
and \
1008 self
._DirectiveStack
[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1009 EdkLogger
.error("Parser", FORMAT_INVALID
, "'!elseif' after '!else'",
1010 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
1011 ExtraData
=self
._CurrentLine
)
1012 self
._DirectiveStack
.append((ItemType
, self
._LineIndex
+ 1, self
._CurrentLine
))
1013 elif self
._From
> 0:
1014 EdkLogger
.error('Parser', FORMAT_INVALID
,
1015 "No '!include' allowed in included file",
1016 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
,
1017 Line
=self
._LineIndex
+ 1)
1020 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
1021 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
1023 for Arch
, ModuleType
in Scope
:
1024 self
._LastItem
= self
._Store
(
1033 self
._LineIndex
+ 1,
1035 self
._LineIndex
+ 1,
1040 ## [defines] section parser
1042 def _DefineParser(self
):
1043 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1044 self
._ValueList
[1:len(TokenList
)] = TokenList
1047 if not self
._ValueList
[1]:
1048 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
1049 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1050 if not self
._ValueList
[2]:
1051 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
1052 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1053 if (not self
._ValueList
[1] in self
.DefineKeywords
and
1054 (self
._InSubsection
and self
._ValueList
[1] not in self
.SubSectionDefineKeywords
)):
1055 EdkLogger
.error('Parser', FORMAT_INVALID
,
1056 "Unknown keyword found: %s. "
1057 "If this is a macro you must "
1058 "add it as a DEFINE in the DSC" % self
._ValueList
[1],
1059 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1060 if not self
._InSubsection
:
1061 self
._Defines
[self
._ValueList
[1]] = self
._ValueList
[2]
1062 self
._ItemType
= self
.DataType
[TAB_DSC_DEFINES
.upper()]
1065 def _SkuIdParser(self
):
1066 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1067 if len(TokenList
) != 2:
1068 EdkLogger
.error('Parser', FORMAT_INVALID
, "Correct format is '<Integer>|<UiName>'",
1069 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1070 self
._ValueList
[0:len(TokenList
)] = TokenList
1072 ## Parse Edk style of library modules
1074 def _LibraryInstanceParser(self
):
1075 self
._ValueList
[0] = self
._CurrentLine
1077 ## PCD sections parser
1079 # [PcdsFixedAtBuild]
1080 # [PcdsPatchableInModule]
1083 # [PcdsDynamicExDefault]
1084 # [PcdsDynamicExVpd]
1085 # [PcdsDynamicExHii]
1087 # [PcdsDynamicDefault]
1092 def _PcdParser(self
):
1093 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1094 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1095 if len(TokenList
) == 2:
1096 self
._ValueList
[2] = TokenList
[1]
1097 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1098 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1099 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1100 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1101 if self
._ValueList
[2] == '':
1103 # The PCD values are optional for FIXEDATBUILD and PATCHABLEINMODULE
1105 if self
._SectionType
in (MODEL_PCD_FIXED_AT_BUILD
, MODEL_PCD_PATCHABLE_IN_MODULE
):
1107 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD value given",
1108 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1109 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1111 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD
1112 ValueList
= GetSplitValueList(self
._ValueList
[2])
1113 if len(ValueList
) > 1 and ValueList
[1] != TAB_VOID \
1114 and self
._ItemType
in [MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_EX_DEFAULT
]:
1115 EdkLogger
.error('Parser', FORMAT_INVALID
, "The datum type '%s' of PCD is wrong" % ValueList
[1],
1116 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1118 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1119 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
1120 if DscPcdValueList
[0] in ['True', 'true', 'TRUE']:
1121 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '1', 1);
1122 elif DscPcdValueList
[0] in ['False', 'false', 'FALSE']:
1123 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '0', 1);
1126 ## [components] section parser
1128 def _ComponentParser(self
):
1129 if self
._CurrentLine
[-1] == '{':
1130 self
._ValueList
[0] = self
._CurrentLine
[0:-1].strip()
1131 self
._InSubsection
= True
1133 self
._ValueList
[0] = self
._CurrentLine
1135 ## [LibraryClasses] section
1137 def _LibraryClassParser(self
):
1138 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1139 if len(TokenList
) < 2:
1140 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class or instance specified",
1141 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1142 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1143 if TokenList
[0] == '':
1144 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class specified",
1145 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1146 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1147 if TokenList
[1] == '':
1148 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library instance specified",
1149 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1150 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1152 self
._ValueList
[0:len(TokenList
)] = TokenList
1154 def _CompponentSourceOverridePathParser(self
):
1155 self
._ValueList
[0] = self
._CurrentLine
1157 ## [BuildOptions] section parser
1159 def _BuildOptionParser(self
):
1160 self
._CurrentLine
= CleanString(self
._CurrentLine
, BuildOption
=True)
1161 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1162 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
1163 if len(TokenList2
) == 2:
1164 self
._ValueList
[0] = TokenList2
[0] # toolchain family
1165 self
._ValueList
[1] = TokenList2
[1] # keys
1167 self
._ValueList
[1] = TokenList
[0]
1168 if len(TokenList
) == 2: # value
1169 self
._ValueList
[2] = TokenList
[1]
1171 if self
._ValueList
[1].count('_') != 4:
1175 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
1176 ExtraData
=self
._CurrentLine
,
1178 Line
=self
._LineIndex
+ 1
1181 ## Override parent's method since we'll do all macro replacements in parser
1182 def _GetMacros(self
):
1184 Macros
.update(self
._FileLocalMacros
)
1185 Macros
.update(self
._GetApplicableSectionMacro
())
1186 Macros
.update(GlobalData
.gEdkGlobal
)
1187 Macros
.update(GlobalData
.gPlatformDefines
)
1188 Macros
.update(GlobalData
.gCommandLineDefines
)
1189 # PCD cannot be referenced in macro definition
1190 if self
._ItemType
not in [MODEL_META_DATA_DEFINE
, MODEL_META_DATA_GLOBAL_DEFINE
]:
1191 Macros
.update(self
._Symbols
)
1194 def _PostProcess(self
):
1196 MODEL_META_DATA_SECTION_HEADER
: self
.__ProcessSectionHeader
,
1197 MODEL_META_DATA_SUBSECTION_HEADER
: self
.__ProcessSubsectionHeader
,
1198 MODEL_META_DATA_HEADER
: self
.__ProcessDefine
,
1199 MODEL_META_DATA_DEFINE
: self
.__ProcessDefine
,
1200 MODEL_META_DATA_GLOBAL_DEFINE
: self
.__ProcessDefine
,
1201 MODEL_META_DATA_INCLUDE
: self
.__ProcessDirective
,
1202 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
: self
.__ProcessDirective
,
1203 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
: self
.__ProcessDirective
,
1204 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
: self
.__ProcessDirective
,
1205 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
: self
.__ProcessDirective
,
1206 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
: self
.__ProcessDirective
,
1207 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
: self
.__ProcessDirective
,
1208 MODEL_EFI_SKU_ID
: self
.__ProcessSkuId
,
1209 MODEL_EFI_LIBRARY_INSTANCE
: self
.__ProcessLibraryInstance
,
1210 MODEL_EFI_LIBRARY_CLASS
: self
.__ProcessLibraryClass
,
1211 MODEL_PCD_FIXED_AT_BUILD
: self
.__ProcessPcd
,
1212 MODEL_PCD_PATCHABLE_IN_MODULE
: self
.__ProcessPcd
,
1213 MODEL_PCD_FEATURE_FLAG
: self
.__ProcessPcd
,
1214 MODEL_PCD_DYNAMIC_DEFAULT
: self
.__ProcessPcd
,
1215 MODEL_PCD_DYNAMIC_HII
: self
.__ProcessPcd
,
1216 MODEL_PCD_DYNAMIC_VPD
: self
.__ProcessPcd
,
1217 MODEL_PCD_DYNAMIC_EX_DEFAULT
: self
.__ProcessPcd
,
1218 MODEL_PCD_DYNAMIC_EX_HII
: self
.__ProcessPcd
,
1219 MODEL_PCD_DYNAMIC_EX_VPD
: self
.__ProcessPcd
,
1220 MODEL_META_DATA_COMPONENT
: self
.__ProcessComponent
,
1221 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: self
.__ProcessSourceOverridePath
,
1222 MODEL_META_DATA_BUILD_OPTION
: self
.__ProcessBuildOption
,
1223 MODEL_UNKNOWN
: self
._Skip
,
1224 MODEL_META_DATA_USER_EXTENSION
: self
._SkipUserExtension
,
1227 self
._Table
= MetaFileStorage(self
._RawTable
.Cur
, self
.MetaFile
, MODEL_FILE_DSC
, True)
1228 self
._Table
.Create()
1229 self
._DirectiveStack
= []
1230 self
._DirectiveEvalStack
= []
1231 self
._FileWithError
= self
.MetaFile
1232 self
._FileLocalMacros
= {}
1233 self
._SectionsMacroDict
= {}
1234 GlobalData
.gPlatformDefines
= {}
1236 # Get all macro and PCD which has straitforward value
1237 self
.__RetrievePcdValue
()
1238 self
._Content
= self
._RawTable
.GetAll()
1239 self
._ContentIndex
= 0
1240 self
._InSubsection
= False
1241 while self
._ContentIndex
< len(self
._Content
) :
1242 Id
, self
._ItemType
, V1
, V2
, V3
, S1
, S2
, Owner
, self
._From
, \
1243 LineStart
, ColStart
, LineEnd
, ColEnd
, Enabled
= self
._Content
[self
._ContentIndex
]
1246 self
._FileWithError
= self
.MetaFile
1248 self
._ContentIndex
+= 1
1250 self
._Scope
= [[S1
, S2
]]
1252 # For !include directive, handle it specially,
1253 # merge arch and module type in case of duplicate items
1255 while self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1256 if self
._ContentIndex
>= len(self
._Content
):
1258 Record
= self
._Content
[self
._ContentIndex
]
1259 if LineStart
== Record
[9] and LineEnd
== Record
[11]:
1260 if [Record
[5], Record
[6]] not in self
._Scope
:
1261 self
._Scope
.append([Record
[5], Record
[6]])
1262 self
._ContentIndex
+= 1
1266 self
._LineIndex
= LineStart
- 1
1267 self
._ValueList
= [V1
, V2
, V3
]
1269 if Owner
> 0 and Owner
in self
._IdMapping
:
1270 self
._InSubsection
= True
1272 self
._InSubsection
= False
1274 Processer
[self
._ItemType
]()
1275 except EvaluationException
, Excpt
:
1277 # Only catch expression evaluation error here. We need to report
1278 # the precise number of line on which the error occurred
1280 if hasattr(Excpt
, 'Pcd'):
1281 if Excpt
.Pcd
in GlobalData
.gPlatformOtherPcds
:
1282 Info
= GlobalData
.gPlatformOtherPcds
[Excpt
.Pcd
]
1283 EdkLogger
.error('Parser', FORMAT_INVALID
, "Cannot use this PCD (%s) in an expression as"
1284 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
1285 " of the DSC file, and it is currently defined in this section:"
1286 " %s, line #: %d." % (Excpt
.Pcd
, Info
[0], Info
[1]),
1287 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1288 Line
=self
._LineIndex
+ 1)
1290 EdkLogger
.error('Parser', FORMAT_INVALID
, "PCD (%s) is not defined in DSC file" % Excpt
.Pcd
,
1291 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1292 Line
=self
._LineIndex
+ 1)
1294 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid expression: %s" % str(Excpt
),
1295 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1296 Line
=self
._LineIndex
+ 1)
1297 except MacroException
, Excpt
:
1298 EdkLogger
.error('Parser', FORMAT_INVALID
, str(Excpt
),
1299 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1300 Line
=self
._LineIndex
+ 1)
1302 if self
._ValueList
== None:
1305 NewOwner
= self
._IdMapping
.get(Owner
, -1)
1306 self
._Enabled
= int((not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
))
1307 self
._LastItem
= self
._Store
(
1316 self
._LineIndex
+ 1,
1318 self
._LineIndex
+ 1,
1322 self
._IdMapping
[Id
] = self
._LastItem
1324 GlobalData
.gPlatformDefines
.update(self
._FileLocalMacros
)
1325 self
._PostProcessed
= True
1326 self
._Content
= None
1328 def __ProcessSectionHeader(self
):
1329 self
._SectionName
= self
._ValueList
[0]
1330 if self
._SectionName
in self
.DataType
:
1331 self
._SectionType
= self
.DataType
[self
._SectionName
]
1333 self
._SectionType
= MODEL_UNKNOWN
1335 def __ProcessSubsectionHeader(self
):
1336 self
._SubsectionName
= self
._ValueList
[0]
1337 if self
._SubsectionName
in self
.DataType
:
1338 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
1340 self
._SubsectionType
= MODEL_UNKNOWN
1342 def __RetrievePcdValue(self
):
1343 Content
= open(str(self
.MetaFile
), 'r').readlines()
1344 GlobalData
.gPlatformOtherPcds
['DSCFILE'] = str(self
.MetaFile
)
1345 for PcdType
in (MODEL_PCD_PATCHABLE_IN_MODULE
, MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_HII
,
1346 MODEL_PCD_DYNAMIC_VPD
, MODEL_PCD_DYNAMIC_EX_DEFAULT
, MODEL_PCD_DYNAMIC_EX_HII
,
1347 MODEL_PCD_DYNAMIC_EX_VPD
):
1348 Records
= self
._RawTable
.Query(PcdType
, BelongsToItem
= -1.0)
1349 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1350 Name
= TokenSpaceGuid
+ '.' + PcdName
1351 if Name
not in GlobalData
.gPlatformOtherPcds
:
1353 while not Content
[Line
- 1].lstrip().startswith(TAB_SECTION_START
):
1355 GlobalData
.gPlatformOtherPcds
[Name
] = (CleanString(Content
[Line
- 1]), PcdLine
, PcdType
)
1357 def __ProcessDefine(self
):
1358 if not self
._Enabled
:
1361 Type
, Name
, Value
= self
._ValueList
1362 Value
= ReplaceMacro(Value
, self
._Macros
, False)
1364 # If it is <Defines>, return
1366 if self
._InSubsection
:
1367 self
._ValueList
= [Type
, Name
, Value
]
1370 if self
._ItemType
== MODEL_META_DATA_DEFINE
:
1371 if self
._SectionType
== MODEL_META_DATA_HEADER
:
1372 self
._FileLocalMacros
[Name
] = Value
1374 self
._ConstructSectionMacroDict
(Name
, Value
)
1375 elif self
._ItemType
== MODEL_META_DATA_GLOBAL_DEFINE
:
1376 GlobalData
.gEdkGlobal
[Name
] = Value
1379 # Keyword in [Defines] section can be used as Macros
1381 if (self
._ItemType
== MODEL_META_DATA_HEADER
) and (self
._SectionType
== MODEL_META_DATA_HEADER
):
1382 self
._FileLocalMacros
[Name
] = Value
1384 self
._ValueList
= [Type
, Name
, Value
]
1386 def __ProcessDirective(self
):
1388 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1389 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
]:
1390 Macros
= self
._Macros
1391 Macros
.update(GlobalData
.gGlobalDefines
)
1393 Result
= ValueExpression(self
._ValueList
[1], Macros
)()
1394 except SymbolNotFound
, Exc
:
1395 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1397 except WrnExpression
, Excpt
:
1399 # Catch expression evaluation warning here. We need to report
1400 # the precise number of line and return the evaluation result
1402 EdkLogger
.warn('Parser', "Suspicious expression: %s" % str(Excpt
),
1403 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1404 Line
=self
._LineIndex
+ 1)
1405 Result
= Excpt
.result
1407 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1408 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1409 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1410 self
._DirectiveStack
.append(self
._ItemType
)
1411 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
:
1412 Result
= bool(Result
)
1414 Macro
= self
._ValueList
[1]
1415 Macro
= Macro
[2:-1] if (Macro
.startswith("$(") and Macro
.endswith(")")) else Macro
1416 Result
= Macro
in self
._Macros
1417 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
:
1419 self
._DirectiveEvalStack
.append(Result
)
1420 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
:
1421 self
._DirectiveStack
.append(self
._ItemType
)
1422 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1423 self
._DirectiveEvalStack
.append(bool(Result
))
1424 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1425 self
._DirectiveStack
.append(self
._ItemType
)
1426 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1427 self
._DirectiveEvalStack
.append(True)
1428 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1429 # Back to the nearest !if/!ifdef/!ifndef
1430 while self
._DirectiveStack
:
1431 self
._DirectiveEvalStack
.pop()
1432 Directive
= self
._DirectiveStack
.pop()
1433 if Directive
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1434 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1435 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1437 elif self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1438 # The included file must be relative to workspace or same directory as DSC file
1439 __IncludeMacros
= {}
1441 # Allow using system environment variables in path after !include
1443 __IncludeMacros
['WORKSPACE'] = GlobalData
.gGlobalDefines
['WORKSPACE']
1444 if "ECP_SOURCE" in GlobalData
.gGlobalDefines
.keys():
1445 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gGlobalDefines
['ECP_SOURCE']
1447 # During GenFds phase call DSC parser, will go into this branch.
1449 elif "ECP_SOURCE" in GlobalData
.gCommandLineDefines
.keys():
1450 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gCommandLineDefines
['ECP_SOURCE']
1452 __IncludeMacros
['EFI_SOURCE'] = GlobalData
.gGlobalDefines
['EFI_SOURCE']
1453 __IncludeMacros
['EDK_SOURCE'] = GlobalData
.gGlobalDefines
['EDK_SOURCE']
1455 # Allow using MACROs comes from [Defines] section to keep compatible.
1457 __IncludeMacros
.update(self
._Macros
)
1459 IncludedFile
= NormPath(ReplaceMacro(self
._ValueList
[1], __IncludeMacros
, RaiseError
=True))
1461 # First search the include file under the same directory as DSC file
1463 IncludedFile1
= PathClass(IncludedFile
, self
.MetaFile
.Dir
)
1464 ErrorCode
, ErrorInfo1
= IncludedFile1
.Validate()
1467 # Also search file under the WORKSPACE directory
1469 IncludedFile1
= PathClass(IncludedFile
, GlobalData
.gWorkspace
)
1470 ErrorCode
, ErrorInfo2
= IncludedFile1
.Validate()
1472 EdkLogger
.error('parser', ErrorCode
, File
=self
._FileWithError
,
1473 Line
=self
._LineIndex
+ 1, ExtraData
=ErrorInfo1
+ "\n" + ErrorInfo2
)
1475 self
._FileWithError
= IncludedFile1
1477 IncludedFileTable
= MetaFileStorage(self
._Table
.Cur
, IncludedFile1
, MODEL_FILE_DSC
, False)
1478 Owner
= self
._Content
[self
._ContentIndex
- 1][0]
1479 Parser
= DscParser(IncludedFile1
, self
._FileType
, IncludedFileTable
,
1480 Owner
=Owner
, From
=Owner
)
1482 # set the parser status with current status
1483 Parser
._SectionName
= self
._SectionName
1484 Parser
._SectionType
= self
._SectionType
1485 Parser
._Scope
= self
._Scope
1486 Parser
._Enabled
= self
._Enabled
1487 # Parse the included file
1490 # update current status with sub-parser's status
1491 self
._SectionName
= Parser
._SectionName
1492 self
._SectionType
= Parser
._SectionType
1493 self
._Scope
= Parser
._Scope
1494 self
._Enabled
= Parser
._Enabled
1496 # Insert all records in the table for the included file into dsc file table
1497 Records
= IncludedFileTable
.GetAll()
1499 self
._Content
[self
._ContentIndex
:self
._ContentIndex
] = Records
1500 self
._Content
.pop(self
._ContentIndex
- 1)
1501 self
._ValueList
= None
1502 self
._ContentIndex
-= 1
1504 def __ProcessSkuId(self
):
1505 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=True)
1506 for Value
in self
._ValueList
]
1508 def __ProcessLibraryInstance(self
):
1509 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
1511 def __ProcessLibraryClass(self
):
1512 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, RaiseError
=True)
1514 def __ProcessPcd(self
):
1515 if self
._ItemType
not in [MODEL_PCD_FEATURE_FLAG
, MODEL_PCD_FIXED_AT_BUILD
]:
1516 self
._ValueList
[2] = ReplaceMacro(self
._ValueList
[2], self
._Macros
, RaiseError
=True)
1519 ValList
, Valid
, Index
= AnalyzeDscPcd(self
._ValueList
[2], self
._ItemType
)
1521 EdkLogger
.error('build', FORMAT_INVALID
, "Pcd format incorrect.", File
=self
._FileWithError
, Line
=self
._LineIndex
+1,
1522 ExtraData
="%s.%s|%s" % (self
._ValueList
[0], self
._ValueList
[1], self
._ValueList
[2]))
1523 PcdValue
= ValList
[Index
]
1526 ValList
[Index
] = ValueExpression(PcdValue
, self
._Macros
)(True)
1527 except WrnExpression
, Value
:
1528 ValList
[Index
] = Value
.result
1530 if ValList
[Index
] == 'True':
1531 ValList
[Index
] = '1'
1532 if ValList
[Index
] == 'False':
1533 ValList
[Index
] = '0'
1535 if (not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
):
1536 GlobalData
.gPlatformPcds
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = PcdValue
1537 self
._Symbols
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = PcdValue
1538 self
._ValueList
[2] = '|'.join(ValList
)
1540 def __ProcessComponent(self
):
1541 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1543 def __ProcessSourceOverridePath(self
):
1544 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1546 def __ProcessBuildOption(self
):
1547 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=False)
1548 for Value
in self
._ValueList
]
1551 MODEL_META_DATA_HEADER
: _DefineParser
,
1552 MODEL_EFI_SKU_ID
: _SkuIdParser
,
1553 MODEL_EFI_LIBRARY_INSTANCE
: _LibraryInstanceParser
,
1554 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
1555 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1556 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1557 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1558 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
1559 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
1560 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
1561 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
1562 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
1563 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
1564 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
1565 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: _CompponentSourceOverridePathParser
,
1566 MODEL_META_DATA_BUILD_OPTION
: _BuildOptionParser
,
1567 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1568 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
1569 MODEL_META_DATA_SECTION_HEADER
: MetaFileParser
._SectionHeaderParser
,
1570 MODEL_META_DATA_SUBSECTION_HEADER
: _SubsectionHeaderParser
,
1573 _Macros
= property(_GetMacros
)
1575 ## DEC file parser class
1577 # @param FilePath The path of platform description file
1578 # @param FileType The raw data of DSC file
1579 # @param Table Database used to retrieve module/package information
1580 # @param Macros Macros used for replacement in file
1582 class DecParser(MetaFileParser
):
1583 # DEC file supported data types (one type per section)
1585 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1586 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
1587 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1588 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1589 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1590 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1591 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1592 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1593 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1594 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1595 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1596 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1597 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
,
1600 ## Constructor of DecParser
1602 # Initialize object of DecParser
1604 # @param FilePath The path of platform description file
1605 # @param FileType The raw data of DSC file
1606 # @param Table Database used to retrieve module/package information
1607 # @param Macros Macros used for replacement in file
1609 def __init__(self
, FilePath
, FileType
, Table
):
1610 # prevent re-initialization
1611 if hasattr(self
, "_Table"):
1613 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, -1)
1615 self
._Version
= 0x00010005 # Only EDK2 dec file is supported
1616 self
._AllPCDs
= [] # Only for check duplicate PCD
1622 Content
= open(str(self
.MetaFile
), 'r').readlines()
1624 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1626 for Index
in range(0, len(Content
)):
1627 Line
, Comment
= CleanString2(Content
[Index
])
1628 self
._CurrentLine
= Line
1629 self
._LineIndex
= Index
1631 # save comment for later use
1633 self
._Comments
.append((Comment
, self
._LineIndex
+ 1))
1639 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1640 self
._SectionHeaderParser
()
1643 elif len(self
._SectionType
) == 0:
1648 self
._ValueList
= ['', '', '']
1649 self
._SectionParser
[self
._SectionType
[0]](self
)
1650 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
1656 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1657 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1659 for Arch
, ModuleType
, Type
in self
._Scope
:
1660 self
._LastItem
= self
._Store
(
1668 self
._LineIndex
+ 1,
1670 self
._LineIndex
+ 1,
1674 for Comment
, LineNo
in self
._Comments
:
1676 MODEL_META_DATA_COMMENT
,
1693 ## Section header parser
1695 # The section header is always in following format:
1697 # [section_name.arch<.platform|module_type>]
1699 def _SectionHeaderParser(self
):
1701 self
._SectionName
= ''
1702 self
._SectionType
= []
1704 Line
= self
._CurrentLine
.replace("%s%s" % (TAB_COMMA_SPLIT
, TAB_SPACE_SPLIT
), TAB_COMMA_SPLIT
)
1705 for Item
in Line
[1:-1].split(TAB_COMMA_SPLIT
):
1707 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
,
1708 "section name can NOT be empty or incorrectly use separator comma",
1709 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1710 ItemList
= Item
.split(TAB_SPLIT
)
1712 # different types of PCD are permissible in one section
1713 self
._SectionName
= ItemList
[0].upper()
1714 if self
._SectionName
in self
.DataType
:
1715 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1716 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1718 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
1719 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1721 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1725 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1727 Line
=self
._LineIndex
+ 1,
1728 ExtraData
=self
._CurrentLine
1731 if len(ItemList
) > 1:
1732 S1
= ItemList
[1].upper()
1736 # S2 may be Platform or ModuleType
1737 if len(ItemList
) > 2:
1738 S2
= ItemList
[2].upper()
1741 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1742 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1744 # 'COMMON' must not be used with specific ARCHs at the same section
1745 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1746 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1747 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
1749 ## [guids], [ppis] and [protocols] section parser
1751 def _GuidParser(self
):
1752 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1753 if len(TokenList
) < 2:
1754 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1755 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1756 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1757 if TokenList
[0] == '':
1758 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1759 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1760 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1761 if TokenList
[1] == '':
1762 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1763 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1764 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1765 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1766 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1767 ExtraData
=self
._CurrentLine
+ \
1768 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1769 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1770 self
._ValueList
[0] = TokenList
[0]
1771 self
._ValueList
[1] = TokenList
[1]
1773 ## PCD sections parser
1775 # [PcdsFixedAtBuild]
1776 # [PcdsPatchableInModule]
1782 def _PcdParser(self
):
1783 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1784 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1785 ValueRe
= re
.compile(r
'^[a-zA-Z_][a-zA-Z0-9_]*')
1786 # check PCD information
1787 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1788 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1789 ExtraData
=self
._CurrentLine
+ \
1790 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1791 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1792 # check format of token space GUID CName
1793 if not ValueRe
.match(self
._ValueList
[0]):
1794 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_]*'",
1795 ExtraData
=self
._CurrentLine
+ \
1796 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1797 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1798 # check format of PCD CName
1799 if not ValueRe
.match(self
._ValueList
[1]):
1800 EdkLogger
.error('Parser', FORMAT_INVALID
, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
1801 ExtraData
=self
._CurrentLine
+ \
1802 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1803 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1804 # check PCD datum information
1805 if len(TokenList
) < 2 or TokenList
[1] == '':
1806 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1807 ExtraData
=self
._CurrentLine
+ \
1808 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1809 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1812 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1813 PtrValue
= ValueRe
.findall(TokenList
[1])
1815 # Has VOID* type string, may contain "|" character in the string.
1816 if len(PtrValue
) != 0:
1817 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1818 ValueList
= GetSplitValueList(ptrValueList
)
1819 ValueList
[0] = PtrValue
[0]
1821 ValueList
= GetSplitValueList(TokenList
[1])
1824 # check if there's enough datum information given
1825 if len(ValueList
) != 3:
1826 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1827 ExtraData
=self
._CurrentLine
+ \
1828 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1829 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1830 # check default value
1831 if ValueList
[0] == '':
1832 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1833 ExtraData
=self
._CurrentLine
+ \
1834 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1835 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1837 if ValueList
[1] == '':
1838 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1839 ExtraData
=self
._CurrentLine
+ \
1840 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1841 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1842 # check token of the PCD
1843 if ValueList
[2] == '':
1844 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1845 ExtraData
=self
._CurrentLine
+ \
1846 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1847 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1848 # check format of default value against the datum type
1849 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1851 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1852 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1854 if ValueList
[0] in ['True', 'true', 'TRUE']:
1856 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1859 # check for duplicate PCD definition
1860 if (self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]) in self
._AllPCDs
:
1861 EdkLogger
.error('Parser', FORMAT_INVALID
,
1862 "The same PCD name and GUID have been already defined",
1863 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1865 self
._AllPCDs
.append((self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]))
1867 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
1870 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
1871 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
1872 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
1873 MODEL_EFI_GUID
: _GuidParser
,
1874 MODEL_EFI_PPI
: _GuidParser
,
1875 MODEL_EFI_PROTOCOL
: _GuidParser
,
1876 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1877 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1878 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1879 MODEL_PCD_DYNAMIC
: _PcdParser
,
1880 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
1881 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1882 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
1887 # This acts like the main() function for the script, unless it is 'import'ed into another
1890 if __name__
== '__main__':