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
380 def _GetMacros(self
):
382 Macros
.update(self
._FileLocalMacros
)
383 Macros
.update(self
._GetApplicableSectionMacro
())
386 ## Construct section Macro dict
387 def _ConstructSectionMacroDict(self
, Name
, Value
):
388 ScopeKey
= [(Scope
[0], Scope
[1]) for Scope
in self
._Scope
]
389 ScopeKey
= tuple(ScopeKey
)
390 SectionDictKey
= self
._SectionType
, ScopeKey
392 # DecParser SectionType is a list, will contain more than one item only in Pcd Section
393 # As Pcd section macro usage is not alllowed, so here it is safe
395 if type(self
) == DecParser
:
396 SectionDictKey
= self
._SectionType
[0], ScopeKey
397 if SectionDictKey
not in self
._SectionsMacroDict
:
398 self
._SectionsMacroDict
[SectionDictKey
] = {}
399 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
400 SectionLocalMacros
[Name
] = Value
402 ## Get section Macros that are applicable to current line, which may come from other sections
403 ## that share the same name while scope is wider
404 def _GetApplicableSectionMacro(self
):
411 ActiveSectionType
= self
._SectionType
412 if type(self
) == DecParser
:
413 ActiveSectionType
= self
._SectionType
[0]
415 for (SectionType
, Scope
) in self
._SectionsMacroDict
:
416 if SectionType
!= ActiveSectionType
:
419 for ActiveScope
in self
._Scope
:
420 Scope0
, Scope1
= ActiveScope
[0], ActiveScope
[1]
421 if(Scope0
, Scope1
) not in Scope
:
424 SpeSpeMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
426 for ActiveScope
in self
._Scope
:
427 Scope0
, Scope1
= ActiveScope
[0], ActiveScope
[1]
428 if(Scope0
, Scope1
) not in Scope
and (Scope0
, "COMMON") not in Scope
and ("COMMON", Scope1
) not in Scope
:
431 ComSpeMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
433 if ("COMMON", "COMMON") in Scope
:
434 ComComMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
436 Macros
.update(ComComMacroDict
)
437 Macros
.update(ComSpeMacroDict
)
438 Macros
.update(SpeSpeMacroDict
)
443 Finished
= property(_GetFinished
, _SetFinished
)
444 _Macros
= property(_GetMacros
)
447 ## INF file parser class
449 # @param FilePath The path of platform description file
450 # @param FileType The raw data of DSC file
451 # @param Table Database used to retrieve module/package information
452 # @param Macros Macros used for replacement in file
454 class InfParser(MetaFileParser
):
455 # INF file supported data types (one type per section)
457 TAB_UNKNOWN
.upper() : MODEL_UNKNOWN
,
458 TAB_INF_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
459 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
460 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
461 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
462 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
463 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
464 TAB_PACKAGES
.upper() : MODEL_META_DATA_PACKAGE
,
465 TAB_NMAKE
.upper() : MODEL_META_DATA_NMAKE
,
466 TAB_INF_FIXED_PCD
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
467 TAB_INF_PATCH_PCD
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
468 TAB_INF_FEATURE_PCD
.upper() : MODEL_PCD_FEATURE_FLAG
,
469 TAB_INF_PCD_EX
.upper() : MODEL_PCD_DYNAMIC_EX
,
470 TAB_INF_PCD
.upper() : MODEL_PCD_DYNAMIC
,
471 TAB_SOURCES
.upper() : MODEL_EFI_SOURCE_FILE
,
472 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
473 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
474 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
475 TAB_DEPEX
.upper() : MODEL_EFI_DEPEX
,
476 TAB_BINARIES
.upper() : MODEL_EFI_BINARY_FILE
,
477 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
480 ## Constructor of InfParser
482 # Initialize object of InfParser
484 # @param FilePath The path of module description file
485 # @param FileType The raw data of DSC file
486 # @param Table Database used to retrieve module/package information
487 # @param Macros Macros used for replacement in file
489 def __init__(self
, FilePath
, FileType
, Table
):
490 # prevent re-initialization
491 if hasattr(self
, "_Table"):
493 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
501 Content
= open(str(self
.MetaFile
), 'r').readlines()
503 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
505 # parse the file line by line
506 IsFindBlockComment
= False
507 GetHeaderComment
= False
512 for Index
in range(0, len(Content
)):
513 # skip empty, commented, block commented lines
514 Line
, Comment
= CleanString2(Content
[Index
], AllowCppStyleComment
=True)
516 if Index
+ 1 < len(Content
):
517 NextLine
, NextComment
= CleanString2(Content
[Index
+ 1])
520 Comments
.append((Comment
, Index
+ 1))
521 elif GetHeaderComment
:
522 SectionComments
.extend(Comments
)
525 if Line
.find(DataType
.TAB_COMMENT_EDK_START
) > -1:
526 IsFindBlockComment
= True
528 if Line
.find(DataType
.TAB_COMMENT_EDK_END
) > -1:
529 IsFindBlockComment
= False
531 if IsFindBlockComment
:
534 self
._LineIndex
= Index
535 self
._CurrentLine
= Line
538 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
539 if not GetHeaderComment
:
540 for Cmt
, LNo
in Comments
:
541 self
._Store
(MODEL_META_DATA_HEADER_COMMENT
, Cmt
, '', '', 'COMMON',
542 'COMMON', self
._Owner
[-1], LNo
, -1, LNo
, -1, 0)
543 GetHeaderComment
= True
545 TailComments
.extend(SectionComments
+ Comments
)
547 self
._SectionHeaderParser
()
548 # Check invalid sections
549 if self
._Version
< 0x00010005:
550 if self
._SectionType
in [MODEL_META_DATA_BUILD_OPTION
,
551 MODEL_EFI_LIBRARY_CLASS
,
552 MODEL_META_DATA_PACKAGE
,
553 MODEL_PCD_FIXED_AT_BUILD
,
554 MODEL_PCD_PATCHABLE_IN_MODULE
,
555 MODEL_PCD_FEATURE_FLAG
,
556 MODEL_PCD_DYNAMIC_EX
,
561 MODEL_META_DATA_USER_EXTENSION
]:
562 EdkLogger
.error('Parser', FORMAT_INVALID
,
563 "Section [%s] is not allowed in inf file without version" % (self
._SectionName
),
564 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
565 elif self
._SectionType
in [MODEL_EFI_INCLUDE
,
566 MODEL_EFI_LIBRARY_INSTANCE
,
567 MODEL_META_DATA_NMAKE
]:
568 EdkLogger
.error('Parser', FORMAT_INVALID
,
569 "Section [%s] is not allowed in inf file with version 0x%08x" % (self
._SectionName
, self
._Version
),
570 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
572 # merge two lines specified by '\' in section NMAKE
573 elif self
._SectionType
== MODEL_META_DATA_NMAKE
:
576 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
579 if NextLine
[0] == TAB_SECTION_START
and NextLine
[-1] == TAB_SECTION_END
:
580 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
583 NmakeLine
= NmakeLine
+ ' ' + Line
[0:-1]
586 self
._CurrentLine
= NmakeLine
+ Line
590 self
._ValueList
= ['', '', '']
591 # parse current line, result will be put in self._ValueList
592 self
._SectionParser
[self
._SectionType
](self
)
593 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
598 Comments
.append((Comment
, Index
+ 1))
599 if GlobalData
.gOptions
and GlobalData
.gOptions
.CheckUsage
:
600 CheckInfComment(self
._SectionType
, Comments
, str(self
.MetaFile
), Index
+ 1, self
._ValueList
)
602 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
603 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
605 for Arch
, Platform
in self
._Scope
:
606 LastItem
= self
._Store
(self
._SectionType
,
619 for Comment
, LineNo
in Comments
:
620 self
._Store
(MODEL_META_DATA_COMMENT
, Comment
, '', '', Arch
, Platform
,
621 LastItem
, LineNo
, -1, LineNo
, -1, 0)
624 TailComments
.extend(SectionComments
+ Comments
)
625 if IsFindBlockComment
:
626 EdkLogger
.error("Parser", FORMAT_INVALID
, "Open block comments (starting with /*) are expected to end with */",
629 # If there are tail comments in INF file, save to database whatever the comments are
630 for Comment
in TailComments
:
631 self
._Store
(MODEL_META_DATA_TAIL_COMMENT
, Comment
[0], '', '', 'COMMON',
632 'COMMON', self
._Owner
[-1], -1, -1, -1, -1, 0)
635 ## Data parser for the format in which there's path
637 # Only path can have macro used. So we need to replace them before use.
639 def _IncludeParser(self
):
640 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
641 self
._ValueList
[0:len(TokenList
)] = TokenList
642 Macros
= self
._Macros
644 for Index
in range(0, len(self
._ValueList
)):
645 Value
= self
._ValueList
[Index
]
649 if Value
.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value
.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
650 Value
= '$(EDK_SOURCE)' + Value
[17:]
651 if Value
.find('$(EFI_SOURCE)') > -1 or Value
.find('$(EDK_SOURCE)') > -1:
653 elif Value
.startswith('.'):
655 elif Value
.startswith('$('):
658 Value
= '$(EFI_SOURCE)/' + Value
660 self
._ValueList
[Index
] = ReplaceMacro(Value
, Macros
)
662 ## Parse [Sources] section
664 # Only path can have macro used. So we need to replace them before use.
667 def _SourceFileParser(self
):
668 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
669 self
._ValueList
[0:len(TokenList
)] = TokenList
670 Macros
= self
._Macros
671 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
672 if 'COMPONENT_TYPE' in Macros
:
673 if self
._Defines
['COMPONENT_TYPE'].upper() == 'ACPITABLE':
674 self
._ValueList
[0] = GetSplitValueList(self
._ValueList
[0], ' ', 1)[0]
675 if self
._Defines
['BASE_NAME'] == 'Microcode':
677 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
679 ## Parse [Binaries] section
681 # Only path can have macro used. So we need to replace them before use.
684 def _BinaryFileParser(self
):
685 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 2)
686 if len(TokenList
) < 2:
687 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type or path specified",
688 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
689 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
691 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type specified",
692 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
693 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
695 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file path specified",
696 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
697 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
698 self
._ValueList
[0:len(TokenList
)] = TokenList
699 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
701 ## [nmake] section parser (Edk.x style only)
702 def _NmakeParser(self
):
703 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
704 self
._ValueList
[0:len(TokenList
)] = TokenList
706 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
707 # remove self-reference in macro setting
708 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
710 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
712 def _PcdParser(self
):
713 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
714 ValueList
= GetSplitValueList(TokenList
[0], TAB_SPLIT
)
715 if len(ValueList
) != 2:
716 EdkLogger
.error('Parser', FORMAT_INVALID
, "Illegal token space GUID and PCD name format",
717 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
718 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
719 self
._ValueList
[0:1] = ValueList
720 if len(TokenList
) > 1:
721 self
._ValueList
[2] = TokenList
[1]
722 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
723 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
724 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
725 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
727 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
728 if self
._ValueList
[2] != '':
729 InfPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
730 if InfPcdValueList
[0] in ['True', 'true', 'TRUE']:
731 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '1', 1);
732 elif InfPcdValueList
[0] in ['False', 'false', 'FALSE']:
733 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '0', 1);
734 if (self
._ValueList
[0], self
._ValueList
[1]) not in self
.PcdsDict
:
735 self
.PcdsDict
[self
._ValueList
[0], self
._ValueList
[1]] = self
._SectionType
736 elif self
.PcdsDict
[self
._ValueList
[0], self
._ValueList
[1]] != self
._SectionType
:
737 EdkLogger
.error('Parser', FORMAT_INVALID
, "It is not permissible to list a specified PCD in different PCD type sections.",
738 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
739 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
741 ## [depex] section parser
743 def _DepexParser(self
):
744 self
._ValueList
[0:1] = [self
._CurrentLine
]
747 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
748 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
749 MODEL_META_DATA_BUILD_OPTION
: MetaFileParser
._BuildOptionParser
,
750 MODEL_EFI_INCLUDE
: _IncludeParser
, # for Edk.x modules
751 MODEL_EFI_LIBRARY_INSTANCE
: MetaFileParser
._CommonParser
, # for Edk.x modules
752 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
753 MODEL_META_DATA_PACKAGE
: MetaFileParser
._PathParser
,
754 MODEL_META_DATA_NMAKE
: _NmakeParser
, # for Edk.x modules
755 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
756 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
757 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
758 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
759 MODEL_PCD_DYNAMIC
: _PcdParser
,
760 MODEL_EFI_SOURCE_FILE
: _SourceFileParser
,
761 MODEL_EFI_GUID
: MetaFileParser
._CommonParser
,
762 MODEL_EFI_PROTOCOL
: MetaFileParser
._CommonParser
,
763 MODEL_EFI_PPI
: MetaFileParser
._CommonParser
,
764 MODEL_EFI_DEPEX
: _DepexParser
,
765 MODEL_EFI_BINARY_FILE
: _BinaryFileParser
,
766 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
769 ## DSC file parser class
771 # @param FilePath The path of platform description file
772 # @param FileType The raw data of DSC file
773 # @param Table Database used to retrieve module/package information
774 # @param Macros Macros used for replacement in file
775 # @param Owner Owner ID (for sub-section parsing)
776 # @param From ID from which the data comes (for !INCLUDE directive)
778 class DscParser(MetaFileParser
):
779 # DSC file supported data types (one type per section)
781 TAB_SKUIDS
.upper() : MODEL_EFI_SKU_ID
,
782 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
783 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
784 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
785 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
786 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
787 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
788 TAB_PCDS_DYNAMIC_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_DEFAULT
,
789 TAB_PCDS_DYNAMIC_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_HII
,
790 TAB_PCDS_DYNAMIC_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_VPD
,
791 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT
,
792 TAB_PCDS_DYNAMIC_EX_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_HII
,
793 TAB_PCDS_DYNAMIC_EX_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_VPD
,
794 TAB_COMPONENTS
.upper() : MODEL_META_DATA_COMPONENT
,
795 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH
.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
,
796 TAB_DSC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
797 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
798 TAB_DSC_DEFINES_EDKGLOBAL
: MODEL_META_DATA_GLOBAL_DEFINE
,
799 TAB_INCLUDE
.upper() : MODEL_META_DATA_INCLUDE
,
800 TAB_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
801 TAB_IF_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
802 TAB_IF_N_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
,
803 TAB_ELSE_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
,
804 TAB_ELSE
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
805 TAB_END_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
,
806 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
,
809 # Valid names in define section
816 "PCD_INFO_GENERATION",
817 "SUPPORTED_ARCHITECTURES",
826 "FIX_LOAD_TOP_MEMORY_ADDRESS"
829 SubSectionDefineKeywords
= [
833 SymbolPattern
= ValueExpression
.SymbolPattern
835 ## Constructor of DscParser
837 # Initialize object of DscParser
839 # @param FilePath The path of platform description file
840 # @param FileType The raw data of DSC file
841 # @param Table Database used to retrieve module/package information
842 # @param Macros Macros used for replacement in file
843 # @param Owner Owner ID (for sub-section parsing)
844 # @param From ID from which the data comes (for !INCLUDE directive)
846 def __init__(self
, FilePath
, FileType
, Table
, Owner
= -1, From
= -1):
847 # prevent re-initialization
848 if hasattr(self
, "_Table"):
850 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, Owner
, From
)
851 self
._Version
= 0x00010005 # Only EDK2 dsc file is supported
852 # to store conditional directive evaluation result
853 self
._DirectiveStack
= []
854 self
._DirectiveEvalStack
= []
858 # Specify whether current line is in uncertain condition
860 self
._InDirective
= -1
862 # Final valid replacable symbols
865 # Map the ID between the original table and new table to track
868 self
._IdMapping
= {-1:-1}
874 Content
= open(str(self
.MetaFile
), 'r').readlines()
876 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
879 for Index
in range(0, len(Content
)):
880 Line
= CleanString(Content
[Index
])
885 self
._CurrentLine
= Line
886 self
._LineIndex
= Index
887 if self
._InSubsection
and self
._Owner
[-1] == -1:
888 self
._Owner
.append(self
._LastItem
)
891 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
892 self
._SectionType
= MODEL_META_DATA_SECTION_HEADER
894 elif Line
[0] == '}' and self
._InSubsection
:
895 self
._InSubsection
= False
896 self
._SubsectionType
= MODEL_UNKNOWN
897 self
._SubsectionName
= ''
902 elif Line
[0] == TAB_OPTION_START
and Line
[-1] == TAB_OPTION_END
:
903 self
._SubsectionType
= MODEL_META_DATA_SUBSECTION_HEADER
906 self
._DirectiveParser
()
909 if self
._InSubsection
:
910 SectionType
= self
._SubsectionType
912 SectionType
= self
._SectionType
913 self
._ItemType
= SectionType
915 self
._ValueList
= ['', '', '']
916 self
._SectionParser
[SectionType
](self
)
917 if self
._ValueList
== None:
920 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
921 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
923 for Arch
, ModuleType
in self
._Scope
:
924 Owner
= self
._Owner
[-1]
925 if self
._SubsectionType
!= MODEL_UNKNOWN
:
926 Owner
= OwnerId
[Arch
]
927 self
._LastItem
= self
._Store
(
942 if self
._SubsectionType
== MODEL_UNKNOWN
and self
._InSubsection
:
943 OwnerId
[Arch
] = self
._LastItem
945 if self
._DirectiveStack
:
946 Type
, Line
, Text
= self
._DirectiveStack
[-1]
947 EdkLogger
.error('Parser', FORMAT_INVALID
, "No matching '!endif' found",
948 ExtraData
=Text
, File
=self
.MetaFile
, Line
=Line
)
951 ## <subsection_header> parser
952 def _SubsectionHeaderParser(self
):
953 self
._SubsectionName
= self
._CurrentLine
[1:-1].upper()
954 if self
._SubsectionName
in self
.DataType
:
955 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
957 self
._SubsectionType
= MODEL_UNKNOWN
958 EdkLogger
.warn("Parser", "Unrecognized sub-section", File
=self
.MetaFile
,
959 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
960 self
._ValueList
[0] = self
._SubsectionName
962 ## Directive statement parser
963 def _DirectiveParser(self
):
964 self
._ValueList
= ['', '', '']
965 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
966 self
._ValueList
[0:len(TokenList
)] = TokenList
969 DirectiveName
= self
._ValueList
[0].upper()
970 if DirectiveName
not in self
.DataType
:
971 EdkLogger
.error("Parser", FORMAT_INVALID
, "Unknown directive [%s]" % DirectiveName
,
972 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
974 if DirectiveName
in ['!IF', '!IFDEF', '!IFNDEF']:
975 self
._InDirective
+= 1
977 if DirectiveName
in ['!ENDIF']:
978 self
._InDirective
-= 1
980 if DirectiveName
in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self
._ValueList
[1] == '':
981 EdkLogger
.error("Parser", FORMAT_INVALID
, "Missing expression",
982 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
983 ExtraData
=self
._CurrentLine
)
985 ItemType
= self
.DataType
[DirectiveName
]
986 Scope
= [['COMMON', 'COMMON']]
987 if ItemType
== MODEL_META_DATA_INCLUDE
:
989 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
990 # Remove all directives between !if and !endif, including themselves
991 while self
._DirectiveStack
:
992 # Remove any !else or !elseif
993 DirectiveInfo
= self
._DirectiveStack
.pop()
994 if DirectiveInfo
[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
995 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
996 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
999 EdkLogger
.error("Parser", FORMAT_INVALID
, "Redundant '!endif'",
1000 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
1001 ExtraData
=self
._CurrentLine
)
1002 elif ItemType
!= MODEL_META_DATA_INCLUDE
:
1003 # Break if there's a !else is followed by a !elseif
1004 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
and \
1005 self
._DirectiveStack
and \
1006 self
._DirectiveStack
[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1007 EdkLogger
.error("Parser", FORMAT_INVALID
, "'!elseif' after '!else'",
1008 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
1009 ExtraData
=self
._CurrentLine
)
1010 self
._DirectiveStack
.append((ItemType
, self
._LineIndex
+ 1, self
._CurrentLine
))
1011 elif self
._From
> 0:
1012 EdkLogger
.error('Parser', FORMAT_INVALID
,
1013 "No '!include' allowed in included file",
1014 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
,
1015 Line
=self
._LineIndex
+ 1)
1018 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
1019 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
1021 for Arch
, ModuleType
in Scope
:
1022 self
._LastItem
= self
._Store
(
1031 self
._LineIndex
+ 1,
1033 self
._LineIndex
+ 1,
1038 ## [defines] section parser
1040 def _DefineParser(self
):
1041 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1042 self
._ValueList
[1:len(TokenList
)] = TokenList
1045 if not self
._ValueList
[1]:
1046 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
1047 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1048 if not self
._ValueList
[2]:
1049 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
1050 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1051 if (not self
._ValueList
[1] in self
.DefineKeywords
and
1052 (self
._InSubsection
and self
._ValueList
[1] not in self
.SubSectionDefineKeywords
)):
1053 EdkLogger
.error('Parser', FORMAT_INVALID
,
1054 "Unknown keyword found: %s. "
1055 "If this is a macro you must "
1056 "add it as a DEFINE in the DSC" % self
._ValueList
[1],
1057 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1058 if not self
._InSubsection
:
1059 self
._Defines
[self
._ValueList
[1]] = self
._ValueList
[2]
1060 self
._ItemType
= self
.DataType
[TAB_DSC_DEFINES
.upper()]
1063 def _SkuIdParser(self
):
1064 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1065 if len(TokenList
) != 2:
1066 EdkLogger
.error('Parser', FORMAT_INVALID
, "Correct format is '<Integer>|<UiName>'",
1067 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1068 self
._ValueList
[0:len(TokenList
)] = TokenList
1070 ## Parse Edk style of library modules
1072 def _LibraryInstanceParser(self
):
1073 self
._ValueList
[0] = self
._CurrentLine
1075 ## PCD sections parser
1077 # [PcdsFixedAtBuild]
1078 # [PcdsPatchableInModule]
1081 # [PcdsDynamicExDefault]
1082 # [PcdsDynamicExVpd]
1083 # [PcdsDynamicExHii]
1085 # [PcdsDynamicDefault]
1090 def _PcdParser(self
):
1091 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1092 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1093 if len(TokenList
) == 2:
1094 self
._ValueList
[2] = TokenList
[1]
1095 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1096 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1097 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1098 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1099 if self
._ValueList
[2] == '':
1101 # The PCD values are optional for FIXEDATBUILD and PATCHABLEINMODULE
1103 if self
._SectionType
in (MODEL_PCD_FIXED_AT_BUILD
, MODEL_PCD_PATCHABLE_IN_MODULE
):
1105 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD value given",
1106 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1107 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1109 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD
1110 ValueList
= GetSplitValueList(self
._ValueList
[2])
1111 if len(ValueList
) > 1 and ValueList
[1] != TAB_VOID \
1112 and self
._ItemType
in [MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_EX_DEFAULT
]:
1113 EdkLogger
.error('Parser', FORMAT_INVALID
, "The datum type '%s' of PCD is wrong" % ValueList
[1],
1114 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1116 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1117 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
1118 if DscPcdValueList
[0] in ['True', 'true', 'TRUE']:
1119 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '1', 1);
1120 elif DscPcdValueList
[0] in ['False', 'false', 'FALSE']:
1121 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '0', 1);
1124 ## [components] section parser
1126 def _ComponentParser(self
):
1127 if self
._CurrentLine
[-1] == '{':
1128 self
._ValueList
[0] = self
._CurrentLine
[0:-1].strip()
1129 self
._InSubsection
= True
1131 self
._ValueList
[0] = self
._CurrentLine
1133 ## [LibraryClasses] section
1135 def _LibraryClassParser(self
):
1136 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1137 if len(TokenList
) < 2:
1138 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class or instance specified",
1139 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1140 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1141 if TokenList
[0] == '':
1142 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class specified",
1143 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1144 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1145 if TokenList
[1] == '':
1146 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library instance specified",
1147 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1148 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1150 self
._ValueList
[0:len(TokenList
)] = TokenList
1152 def _CompponentSourceOverridePathParser(self
):
1153 self
._ValueList
[0] = self
._CurrentLine
1155 ## [BuildOptions] section parser
1157 def _BuildOptionParser(self
):
1158 self
._CurrentLine
= CleanString(self
._CurrentLine
, BuildOption
=True)
1159 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1160 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
1161 if len(TokenList2
) == 2:
1162 self
._ValueList
[0] = TokenList2
[0] # toolchain family
1163 self
._ValueList
[1] = TokenList2
[1] # keys
1165 self
._ValueList
[1] = TokenList
[0]
1166 if len(TokenList
) == 2: # value
1167 self
._ValueList
[2] = TokenList
[1]
1169 if self
._ValueList
[1].count('_') != 4:
1173 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
1174 ExtraData
=self
._CurrentLine
,
1176 Line
=self
._LineIndex
+ 1
1179 ## Override parent's method since we'll do all macro replacements in parser
1180 def _GetMacros(self
):
1182 Macros
.update(self
._FileLocalMacros
)
1183 Macros
.update(self
._GetApplicableSectionMacro
())
1184 Macros
.update(GlobalData
.gEdkGlobal
)
1185 Macros
.update(GlobalData
.gPlatformDefines
)
1186 Macros
.update(GlobalData
.gCommandLineDefines
)
1187 # PCD cannot be referenced in macro definition
1188 if self
._ItemType
not in [MODEL_META_DATA_DEFINE
, MODEL_META_DATA_GLOBAL_DEFINE
]:
1189 Macros
.update(self
._Symbols
)
1192 def _PostProcess(self
):
1194 MODEL_META_DATA_SECTION_HEADER
: self
.__ProcessSectionHeader
,
1195 MODEL_META_DATA_SUBSECTION_HEADER
: self
.__ProcessSubsectionHeader
,
1196 MODEL_META_DATA_HEADER
: self
.__ProcessDefine
,
1197 MODEL_META_DATA_DEFINE
: self
.__ProcessDefine
,
1198 MODEL_META_DATA_GLOBAL_DEFINE
: self
.__ProcessDefine
,
1199 MODEL_META_DATA_INCLUDE
: self
.__ProcessDirective
,
1200 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
: self
.__ProcessDirective
,
1201 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
: self
.__ProcessDirective
,
1202 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
: self
.__ProcessDirective
,
1203 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
: self
.__ProcessDirective
,
1204 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
: self
.__ProcessDirective
,
1205 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
: self
.__ProcessDirective
,
1206 MODEL_EFI_SKU_ID
: self
.__ProcessSkuId
,
1207 MODEL_EFI_LIBRARY_INSTANCE
: self
.__ProcessLibraryInstance
,
1208 MODEL_EFI_LIBRARY_CLASS
: self
.__ProcessLibraryClass
,
1209 MODEL_PCD_FIXED_AT_BUILD
: self
.__ProcessPcd
,
1210 MODEL_PCD_PATCHABLE_IN_MODULE
: self
.__ProcessPcd
,
1211 MODEL_PCD_FEATURE_FLAG
: self
.__ProcessPcd
,
1212 MODEL_PCD_DYNAMIC_DEFAULT
: self
.__ProcessPcd
,
1213 MODEL_PCD_DYNAMIC_HII
: self
.__ProcessPcd
,
1214 MODEL_PCD_DYNAMIC_VPD
: self
.__ProcessPcd
,
1215 MODEL_PCD_DYNAMIC_EX_DEFAULT
: self
.__ProcessPcd
,
1216 MODEL_PCD_DYNAMIC_EX_HII
: self
.__ProcessPcd
,
1217 MODEL_PCD_DYNAMIC_EX_VPD
: self
.__ProcessPcd
,
1218 MODEL_META_DATA_COMPONENT
: self
.__ProcessComponent
,
1219 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: self
.__ProcessSourceOverridePath
,
1220 MODEL_META_DATA_BUILD_OPTION
: self
.__ProcessBuildOption
,
1221 MODEL_UNKNOWN
: self
._Skip
,
1222 MODEL_META_DATA_USER_EXTENSION
: self
._SkipUserExtension
,
1225 self
._Table
= MetaFileStorage(self
._RawTable
.Cur
, self
.MetaFile
, MODEL_FILE_DSC
, True)
1226 self
._Table
.Create()
1227 self
._DirectiveStack
= []
1228 self
._DirectiveEvalStack
= []
1229 self
._FileWithError
= self
.MetaFile
1230 self
._FileLocalMacros
= {}
1231 self
._SectionsMacroDict
= {}
1232 GlobalData
.gPlatformDefines
= {}
1234 # Get all macro and PCD which has straitforward value
1235 self
.__RetrievePcdValue
()
1236 self
._Content
= self
._RawTable
.GetAll()
1237 self
._ContentIndex
= 0
1238 self
._InSubsection
= False
1239 while self
._ContentIndex
< len(self
._Content
) :
1240 Id
, self
._ItemType
, V1
, V2
, V3
, S1
, S2
, Owner
, self
._From
, \
1241 LineStart
, ColStart
, LineEnd
, ColEnd
, Enabled
= self
._Content
[self
._ContentIndex
]
1244 self
._FileWithError
= self
.MetaFile
1246 self
._ContentIndex
+= 1
1248 self
._Scope
= [[S1
, S2
]]
1250 # For !include directive, handle it specially,
1251 # merge arch and module type in case of duplicate items
1253 while self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1254 if self
._ContentIndex
>= len(self
._Content
):
1256 Record
= self
._Content
[self
._ContentIndex
]
1257 if LineStart
== Record
[9] and LineEnd
== Record
[11]:
1258 if [Record
[5], Record
[6]] not in self
._Scope
:
1259 self
._Scope
.append([Record
[5], Record
[6]])
1260 self
._ContentIndex
+= 1
1264 self
._LineIndex
= LineStart
- 1
1265 self
._ValueList
= [V1
, V2
, V3
]
1267 if Owner
> 0 and Owner
in self
._IdMapping
:
1268 self
._InSubsection
= True
1270 self
._InSubsection
= False
1272 Processer
[self
._ItemType
]()
1273 except EvaluationException
, Excpt
:
1275 # Only catch expression evaluation error here. We need to report
1276 # the precise number of line on which the error occurred
1278 if hasattr(Excpt
, 'Pcd'):
1279 if Excpt
.Pcd
in GlobalData
.gPlatformOtherPcds
:
1280 Info
= GlobalData
.gPlatformOtherPcds
[Excpt
.Pcd
]
1281 EdkLogger
.error('Parser', FORMAT_INVALID
, "Cannot use this PCD (%s) in an expression as"
1282 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
1283 " of the DSC file, and it is currently defined in this section:"
1284 " %s, line #: %d." % (Excpt
.Pcd
, Info
[0], Info
[1]),
1285 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1286 Line
=self
._LineIndex
+ 1)
1288 EdkLogger
.error('Parser', FORMAT_INVALID
, "PCD (%s) is not defined in DSC file" % Excpt
.Pcd
,
1289 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1290 Line
=self
._LineIndex
+ 1)
1292 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid expression: %s" % str(Excpt
),
1293 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1294 Line
=self
._LineIndex
+ 1)
1295 except MacroException
, Excpt
:
1296 EdkLogger
.error('Parser', FORMAT_INVALID
, str(Excpt
),
1297 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1298 Line
=self
._LineIndex
+ 1)
1300 if self
._ValueList
== None:
1303 NewOwner
= self
._IdMapping
.get(Owner
, -1)
1304 self
._Enabled
= int((not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
))
1305 self
._LastItem
= self
._Store
(
1314 self
._LineIndex
+ 1,
1316 self
._LineIndex
+ 1,
1320 self
._IdMapping
[Id
] = self
._LastItem
1322 GlobalData
.gPlatformDefines
.update(self
._FileLocalMacros
)
1323 self
._PostProcessed
= True
1324 self
._Content
= None
1326 def __ProcessSectionHeader(self
):
1327 self
._SectionName
= self
._ValueList
[0]
1328 if self
._SectionName
in self
.DataType
:
1329 self
._SectionType
= self
.DataType
[self
._SectionName
]
1331 self
._SectionType
= MODEL_UNKNOWN
1333 def __ProcessSubsectionHeader(self
):
1334 self
._SubsectionName
= self
._ValueList
[0]
1335 if self
._SubsectionName
in self
.DataType
:
1336 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
1338 self
._SubsectionType
= MODEL_UNKNOWN
1340 def __RetrievePcdValue(self
):
1341 Content
= open(str(self
.MetaFile
), 'r').readlines()
1342 GlobalData
.gPlatformOtherPcds
['DSCFILE'] = str(self
.MetaFile
)
1343 for PcdType
in (MODEL_PCD_PATCHABLE_IN_MODULE
, MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_HII
,
1344 MODEL_PCD_DYNAMIC_VPD
, MODEL_PCD_DYNAMIC_EX_DEFAULT
, MODEL_PCD_DYNAMIC_EX_HII
,
1345 MODEL_PCD_DYNAMIC_EX_VPD
):
1346 Records
= self
._RawTable
.Query(PcdType
, BelongsToItem
= -1.0)
1347 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1348 Name
= TokenSpaceGuid
+ '.' + PcdName
1349 if Name
not in GlobalData
.gPlatformOtherPcds
:
1351 while not Content
[Line
- 1].lstrip().startswith(TAB_SECTION_START
):
1353 GlobalData
.gPlatformOtherPcds
[Name
] = (CleanString(Content
[Line
- 1]), PcdLine
, PcdType
)
1355 def __ProcessDefine(self
):
1356 if not self
._Enabled
:
1359 Type
, Name
, Value
= self
._ValueList
1360 Value
= ReplaceMacro(Value
, self
._Macros
, False)
1362 # If it is <Defines>, return
1364 if self
._InSubsection
:
1365 self
._ValueList
= [Type
, Name
, Value
]
1368 if self
._ItemType
== MODEL_META_DATA_DEFINE
:
1369 if self
._SectionType
== MODEL_META_DATA_HEADER
:
1370 self
._FileLocalMacros
[Name
] = Value
1372 self
._ConstructSectionMacroDict
(Name
, Value
)
1373 elif self
._ItemType
== MODEL_META_DATA_GLOBAL_DEFINE
:
1374 GlobalData
.gEdkGlobal
[Name
] = Value
1377 # Keyword in [Defines] section can be used as Macros
1379 if (self
._ItemType
== MODEL_META_DATA_HEADER
) and (self
._SectionType
== MODEL_META_DATA_HEADER
):
1380 self
._FileLocalMacros
[Name
] = Value
1382 self
._ValueList
= [Type
, Name
, Value
]
1384 def __ProcessDirective(self
):
1386 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1387 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
]:
1388 Macros
= self
._Macros
1389 Macros
.update(GlobalData
.gGlobalDefines
)
1391 Result
= ValueExpression(self
._ValueList
[1], Macros
)()
1392 except SymbolNotFound
, Exc
:
1393 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1395 except WrnExpression
, Excpt
:
1397 # Catch expression evaluation warning here. We need to report
1398 # the precise number of line and return the evaluation result
1400 EdkLogger
.warn('Parser', "Suspicious expression: %s" % str(Excpt
),
1401 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1402 Line
=self
._LineIndex
+ 1)
1403 Result
= Excpt
.result
1405 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1406 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1407 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1408 self
._DirectiveStack
.append(self
._ItemType
)
1409 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
:
1410 Result
= bool(Result
)
1412 Macro
= self
._ValueList
[1]
1413 Macro
= Macro
[2:-1] if (Macro
.startswith("$(") and Macro
.endswith(")")) else Macro
1414 Result
= Macro
in self
._Macros
1415 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
:
1417 self
._DirectiveEvalStack
.append(Result
)
1418 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
:
1419 self
._DirectiveStack
.append(self
._ItemType
)
1420 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1421 self
._DirectiveEvalStack
.append(bool(Result
))
1422 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1423 self
._DirectiveStack
.append(self
._ItemType
)
1424 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1425 self
._DirectiveEvalStack
.append(True)
1426 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1427 # Back to the nearest !if/!ifdef/!ifndef
1428 while self
._DirectiveStack
:
1429 self
._DirectiveEvalStack
.pop()
1430 Directive
= self
._DirectiveStack
.pop()
1431 if Directive
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1432 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1433 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1435 elif self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1436 # The included file must be relative to workspace or same directory as DSC file
1437 __IncludeMacros
= {}
1439 # Allow using system environment variables in path after !include
1441 __IncludeMacros
['WORKSPACE'] = GlobalData
.gGlobalDefines
['WORKSPACE']
1442 if "ECP_SOURCE" in GlobalData
.gGlobalDefines
.keys():
1443 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gGlobalDefines
['ECP_SOURCE']
1445 # During GenFds phase call DSC parser, will go into this branch.
1447 elif "ECP_SOURCE" in GlobalData
.gCommandLineDefines
.keys():
1448 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gCommandLineDefines
['ECP_SOURCE']
1450 __IncludeMacros
['EFI_SOURCE'] = GlobalData
.gGlobalDefines
['EFI_SOURCE']
1451 __IncludeMacros
['EDK_SOURCE'] = GlobalData
.gGlobalDefines
['EDK_SOURCE']
1453 # Allow using MACROs comes from [Defines] section to keep compatible.
1455 __IncludeMacros
.update(self
._Macros
)
1457 IncludedFile
= NormPath(ReplaceMacro(self
._ValueList
[1], __IncludeMacros
, RaiseError
=True))
1459 # First search the include file under the same directory as DSC file
1461 IncludedFile1
= PathClass(IncludedFile
, self
.MetaFile
.Dir
)
1462 ErrorCode
, ErrorInfo1
= IncludedFile1
.Validate()
1465 # Also search file under the WORKSPACE directory
1467 IncludedFile1
= PathClass(IncludedFile
, GlobalData
.gWorkspace
)
1468 ErrorCode
, ErrorInfo2
= IncludedFile1
.Validate()
1470 EdkLogger
.error('parser', ErrorCode
, File
=self
._FileWithError
,
1471 Line
=self
._LineIndex
+ 1, ExtraData
=ErrorInfo1
+ "\n" + ErrorInfo2
)
1473 self
._FileWithError
= IncludedFile1
1475 IncludedFileTable
= MetaFileStorage(self
._Table
.Cur
, IncludedFile1
, MODEL_FILE_DSC
, False)
1476 Owner
= self
._Content
[self
._ContentIndex
- 1][0]
1477 Parser
= DscParser(IncludedFile1
, self
._FileType
, IncludedFileTable
,
1478 Owner
=Owner
, From
=Owner
)
1480 # set the parser status with current status
1481 Parser
._SectionName
= self
._SectionName
1482 Parser
._SectionType
= self
._SectionType
1483 Parser
._Scope
= self
._Scope
1484 Parser
._Enabled
= self
._Enabled
1485 # Parse the included file
1488 # update current status with sub-parser's status
1489 self
._SectionName
= Parser
._SectionName
1490 self
._SectionType
= Parser
._SectionType
1491 self
._Scope
= Parser
._Scope
1492 self
._Enabled
= Parser
._Enabled
1494 # Insert all records in the table for the included file into dsc file table
1495 Records
= IncludedFileTable
.GetAll()
1497 self
._Content
[self
._ContentIndex
:self
._ContentIndex
] = Records
1498 self
._Content
.pop(self
._ContentIndex
- 1)
1499 self
._ValueList
= None
1500 self
._ContentIndex
-= 1
1502 def __ProcessSkuId(self
):
1503 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=True)
1504 for Value
in self
._ValueList
]
1506 def __ProcessLibraryInstance(self
):
1507 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
1509 def __ProcessLibraryClass(self
):
1510 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, RaiseError
=True)
1512 def __ProcessPcd(self
):
1513 if self
._ItemType
not in [MODEL_PCD_FEATURE_FLAG
, MODEL_PCD_FIXED_AT_BUILD
]:
1514 self
._ValueList
[2] = ReplaceMacro(self
._ValueList
[2], self
._Macros
, RaiseError
=True)
1517 ValList
, Valid
, Index
= AnalyzeDscPcd(self
._ValueList
[2], self
._ItemType
)
1519 EdkLogger
.error('build', FORMAT_INVALID
, "Pcd format incorrect.", File
=self
._FileWithError
, Line
=self
._LineIndex
+1,
1520 ExtraData
="%s.%s|%s" % (self
._ValueList
[0], self
._ValueList
[1], self
._ValueList
[2]))
1521 PcdValue
= ValList
[Index
]
1524 ValList
[Index
] = ValueExpression(PcdValue
, self
._Macros
)(True)
1525 except WrnExpression
, Value
:
1526 ValList
[Index
] = Value
.result
1528 if ValList
[Index
] == 'True':
1529 ValList
[Index
] = '1'
1530 if ValList
[Index
] == 'False':
1531 ValList
[Index
] = '0'
1533 if (not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
):
1534 GlobalData
.gPlatformPcds
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = PcdValue
1535 self
._Symbols
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = PcdValue
1536 self
._ValueList
[2] = '|'.join(ValList
)
1538 def __ProcessComponent(self
):
1539 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1541 def __ProcessSourceOverridePath(self
):
1542 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1544 def __ProcessBuildOption(self
):
1545 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=False)
1546 for Value
in self
._ValueList
]
1549 MODEL_META_DATA_HEADER
: _DefineParser
,
1550 MODEL_EFI_SKU_ID
: _SkuIdParser
,
1551 MODEL_EFI_LIBRARY_INSTANCE
: _LibraryInstanceParser
,
1552 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
1553 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1554 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1555 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1556 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
1557 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
1558 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
1559 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
1560 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
1561 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
1562 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
1563 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: _CompponentSourceOverridePathParser
,
1564 MODEL_META_DATA_BUILD_OPTION
: _BuildOptionParser
,
1565 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1566 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
1567 MODEL_META_DATA_SECTION_HEADER
: MetaFileParser
._SectionHeaderParser
,
1568 MODEL_META_DATA_SUBSECTION_HEADER
: _SubsectionHeaderParser
,
1571 _Macros
= property(_GetMacros
)
1573 ## DEC file parser class
1575 # @param FilePath The path of platform description file
1576 # @param FileType The raw data of DSC file
1577 # @param Table Database used to retrieve module/package information
1578 # @param Macros Macros used for replacement in file
1580 class DecParser(MetaFileParser
):
1581 # DEC file supported data types (one type per section)
1583 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1584 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
1585 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1586 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1587 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1588 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1589 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1590 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1591 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1592 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1593 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1594 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1595 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
,
1598 ## Constructor of DecParser
1600 # Initialize object of DecParser
1602 # @param FilePath The path of platform description file
1603 # @param FileType The raw data of DSC file
1604 # @param Table Database used to retrieve module/package information
1605 # @param Macros Macros used for replacement in file
1607 def __init__(self
, FilePath
, FileType
, Table
):
1608 # prevent re-initialization
1609 if hasattr(self
, "_Table"):
1611 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, -1)
1613 self
._Version
= 0x00010005 # Only EDK2 dec file is supported
1614 self
._AllPCDs
= [] # Only for check duplicate PCD
1620 Content
= open(str(self
.MetaFile
), 'r').readlines()
1622 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1624 for Index
in range(0, len(Content
)):
1625 Line
, Comment
= CleanString2(Content
[Index
])
1626 self
._CurrentLine
= Line
1627 self
._LineIndex
= Index
1629 # save comment for later use
1631 self
._Comments
.append((Comment
, self
._LineIndex
+ 1))
1637 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1638 self
._SectionHeaderParser
()
1641 elif len(self
._SectionType
) == 0:
1646 self
._ValueList
= ['', '', '']
1647 self
._SectionParser
[self
._SectionType
[0]](self
)
1648 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
1654 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1655 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1657 for Arch
, ModuleType
, Type
in self
._Scope
:
1658 self
._LastItem
= self
._Store
(
1666 self
._LineIndex
+ 1,
1668 self
._LineIndex
+ 1,
1672 for Comment
, LineNo
in self
._Comments
:
1674 MODEL_META_DATA_COMMENT
,
1691 ## Section header parser
1693 # The section header is always in following format:
1695 # [section_name.arch<.platform|module_type>]
1697 def _SectionHeaderParser(self
):
1699 self
._SectionName
= ''
1700 self
._SectionType
= []
1702 Line
= self
._CurrentLine
.replace("%s%s" % (TAB_COMMA_SPLIT
, TAB_SPACE_SPLIT
), TAB_COMMA_SPLIT
)
1703 for Item
in Line
[1:-1].split(TAB_COMMA_SPLIT
):
1705 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
,
1706 "section name can NOT be empty or incorrectly use separator comma",
1707 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1708 ItemList
= Item
.split(TAB_SPLIT
)
1710 # different types of PCD are permissible in one section
1711 self
._SectionName
= ItemList
[0].upper()
1712 if self
._SectionName
in self
.DataType
:
1713 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1714 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1716 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
1717 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1719 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1723 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1725 Line
=self
._LineIndex
+ 1,
1726 ExtraData
=self
._CurrentLine
1729 if len(ItemList
) > 1:
1730 S1
= ItemList
[1].upper()
1734 # S2 may be Platform or ModuleType
1735 if len(ItemList
) > 2:
1736 S2
= ItemList
[2].upper()
1739 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1740 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1742 # 'COMMON' must not be used with specific ARCHs at the same section
1743 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1744 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1745 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
1747 ## [guids], [ppis] and [protocols] section parser
1749 def _GuidParser(self
):
1750 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1751 if len(TokenList
) < 2:
1752 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1753 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1754 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1755 if TokenList
[0] == '':
1756 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1757 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1758 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1759 if TokenList
[1] == '':
1760 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1761 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1762 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1763 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1764 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1765 ExtraData
=self
._CurrentLine
+ \
1766 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1767 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1768 self
._ValueList
[0] = TokenList
[0]
1769 self
._ValueList
[1] = TokenList
[1]
1771 ## PCD sections parser
1773 # [PcdsFixedAtBuild]
1774 # [PcdsPatchableInModule]
1780 def _PcdParser(self
):
1781 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1782 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1783 ValueRe
= re
.compile(r
'^[a-zA-Z_][a-zA-Z0-9_]*')
1784 # check PCD information
1785 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1786 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1787 ExtraData
=self
._CurrentLine
+ \
1788 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1789 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1790 # check format of token space GUID CName
1791 if not ValueRe
.match(self
._ValueList
[0]):
1792 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_]*'",
1793 ExtraData
=self
._CurrentLine
+ \
1794 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1795 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1796 # check format of PCD CName
1797 if not ValueRe
.match(self
._ValueList
[1]):
1798 EdkLogger
.error('Parser', FORMAT_INVALID
, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
1799 ExtraData
=self
._CurrentLine
+ \
1800 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1801 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1802 # check PCD datum information
1803 if len(TokenList
) < 2 or TokenList
[1] == '':
1804 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1805 ExtraData
=self
._CurrentLine
+ \
1806 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1807 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1810 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1811 PtrValue
= ValueRe
.findall(TokenList
[1])
1813 # Has VOID* type string, may contain "|" character in the string.
1814 if len(PtrValue
) != 0:
1815 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1816 ValueList
= GetSplitValueList(ptrValueList
)
1817 ValueList
[0] = PtrValue
[0]
1819 ValueList
= GetSplitValueList(TokenList
[1])
1822 # check if there's enough datum information given
1823 if len(ValueList
) != 3:
1824 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1825 ExtraData
=self
._CurrentLine
+ \
1826 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1827 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1828 # check default value
1829 if ValueList
[0] == '':
1830 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1831 ExtraData
=self
._CurrentLine
+ \
1832 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1833 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1835 if ValueList
[1] == '':
1836 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1837 ExtraData
=self
._CurrentLine
+ \
1838 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1839 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1840 # check token of the PCD
1841 if ValueList
[2] == '':
1842 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1843 ExtraData
=self
._CurrentLine
+ \
1844 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1845 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1846 # check format of default value against the datum type
1847 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1849 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1850 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1852 if ValueList
[0] in ['True', 'true', 'TRUE']:
1854 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1857 # check for duplicate PCD definition
1858 if (self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]) in self
._AllPCDs
:
1859 EdkLogger
.error('Parser', FORMAT_INVALID
,
1860 "The same PCD name and GUID have been already defined",
1861 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1863 self
._AllPCDs
.append((self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]))
1865 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
1868 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
1869 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
1870 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
1871 MODEL_EFI_GUID
: _GuidParser
,
1872 MODEL_EFI_PPI
: _GuidParser
,
1873 MODEL_EFI_PROTOCOL
: _GuidParser
,
1874 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1875 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1876 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1877 MODEL_PCD_DYNAMIC
: _PcdParser
,
1878 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
1879 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1880 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
1885 # This acts like the main() function for the script, unless it is 'import'ed into another
1888 if __name__
== '__main__':