2 # This file is used to parse meta files
4 # Copyright (c) 2008 - 2014, 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 Records
= self
._RawTable
.Query(MODEL_PCD_FEATURE_FLAG
, BelongsToItem
= -1.0)
1342 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1343 Name
= TokenSpaceGuid
+ '.' + PcdName
1344 ValList
, Valid
, Index
= AnalyzeDscPcd(Value
, MODEL_PCD_FEATURE_FLAG
)
1345 self
._Symbols
[Name
] = ValList
[Index
]
1347 Records
= self
._RawTable
.Query(MODEL_PCD_FIXED_AT_BUILD
, BelongsToItem
= -1.0)
1348 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1349 Name
= TokenSpaceGuid
+ '.' + PcdName
1350 ValList
, Valid
, Index
= AnalyzeDscPcd(Value
, MODEL_PCD_FIXED_AT_BUILD
)
1351 self
._Symbols
[Name
] = ValList
[Index
]
1353 Content
= open(str(self
.MetaFile
), 'r').readlines()
1354 GlobalData
.gPlatformOtherPcds
['DSCFILE'] = str(self
.MetaFile
)
1355 for PcdType
in (MODEL_PCD_PATCHABLE_IN_MODULE
, MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_HII
,
1356 MODEL_PCD_DYNAMIC_VPD
, MODEL_PCD_DYNAMIC_EX_DEFAULT
, MODEL_PCD_DYNAMIC_EX_HII
,
1357 MODEL_PCD_DYNAMIC_EX_VPD
):
1358 Records
= self
._RawTable
.Query(PcdType
, BelongsToItem
= -1.0)
1359 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1360 Name
= TokenSpaceGuid
+ '.' + PcdName
1361 if Name
not in GlobalData
.gPlatformOtherPcds
:
1363 while not Content
[Line
- 1].lstrip().startswith(TAB_SECTION_START
):
1365 GlobalData
.gPlatformOtherPcds
[Name
] = (CleanString(Content
[Line
- 1]), PcdLine
, PcdType
)
1367 def __ProcessDefine(self
):
1368 if not self
._Enabled
:
1371 Type
, Name
, Value
= self
._ValueList
1372 Value
= ReplaceMacro(Value
, self
._Macros
, False)
1374 # If it is <Defines>, return
1376 if self
._InSubsection
:
1377 self
._ValueList
= [Type
, Name
, Value
]
1380 if self
._ItemType
== MODEL_META_DATA_DEFINE
:
1381 if self
._SectionType
== MODEL_META_DATA_HEADER
:
1382 self
._FileLocalMacros
[Name
] = Value
1384 self
._ConstructSectionMacroDict
(Name
, Value
)
1385 elif self
._ItemType
== MODEL_META_DATA_GLOBAL_DEFINE
:
1386 GlobalData
.gEdkGlobal
[Name
] = Value
1389 # Keyword in [Defines] section can be used as Macros
1391 if (self
._ItemType
== MODEL_META_DATA_HEADER
) and (self
._SectionType
== MODEL_META_DATA_HEADER
):
1392 self
._FileLocalMacros
[Name
] = Value
1394 self
._ValueList
= [Type
, Name
, Value
]
1396 def __ProcessDirective(self
):
1398 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1399 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
]:
1400 Macros
= self
._Macros
1401 Macros
.update(GlobalData
.gGlobalDefines
)
1403 Result
= ValueExpression(self
._ValueList
[1], Macros
)()
1404 except SymbolNotFound
, Exc
:
1405 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1407 except WrnExpression
, Excpt
:
1409 # Catch expression evaluation warning here. We need to report
1410 # the precise number of line and return the evaluation result
1412 EdkLogger
.warn('Parser', "Suspicious expression: %s" % str(Excpt
),
1413 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1414 Line
=self
._LineIndex
+ 1)
1415 Result
= Excpt
.result
1417 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1418 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1419 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1420 self
._DirectiveStack
.append(self
._ItemType
)
1421 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
:
1422 Result
= bool(Result
)
1424 Macro
= self
._ValueList
[1]
1425 Macro
= Macro
[2:-1] if (Macro
.startswith("$(") and Macro
.endswith(")")) else Macro
1426 Result
= Macro
in self
._Macros
1427 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
:
1429 self
._DirectiveEvalStack
.append(Result
)
1430 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
:
1431 self
._DirectiveStack
.append(self
._ItemType
)
1432 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1433 self
._DirectiveEvalStack
.append(bool(Result
))
1434 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1435 self
._DirectiveStack
.append(self
._ItemType
)
1436 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1437 self
._DirectiveEvalStack
.append(True)
1438 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1439 # Back to the nearest !if/!ifdef/!ifndef
1440 while self
._DirectiveStack
:
1441 self
._DirectiveEvalStack
.pop()
1442 Directive
= self
._DirectiveStack
.pop()
1443 if Directive
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1444 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1445 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1447 elif self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1448 # The included file must be relative to workspace or same directory as DSC file
1449 __IncludeMacros
= {}
1451 # Allow using system environment variables in path after !include
1453 __IncludeMacros
['WORKSPACE'] = GlobalData
.gGlobalDefines
['WORKSPACE']
1454 if "ECP_SOURCE" in GlobalData
.gGlobalDefines
.keys():
1455 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gGlobalDefines
['ECP_SOURCE']
1457 # During GenFds phase call DSC parser, will go into this branch.
1459 elif "ECP_SOURCE" in GlobalData
.gCommandLineDefines
.keys():
1460 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gCommandLineDefines
['ECP_SOURCE']
1462 __IncludeMacros
['EFI_SOURCE'] = GlobalData
.gGlobalDefines
['EFI_SOURCE']
1463 __IncludeMacros
['EDK_SOURCE'] = GlobalData
.gGlobalDefines
['EDK_SOURCE']
1465 # Allow using MACROs comes from [Defines] section to keep compatible.
1467 __IncludeMacros
.update(self
._Macros
)
1469 IncludedFile
= NormPath(ReplaceMacro(self
._ValueList
[1], __IncludeMacros
, RaiseError
=True))
1471 # First search the include file under the same directory as DSC file
1473 IncludedFile1
= PathClass(IncludedFile
, self
.MetaFile
.Dir
)
1474 ErrorCode
, ErrorInfo1
= IncludedFile1
.Validate()
1477 # Also search file under the WORKSPACE directory
1479 IncludedFile1
= PathClass(IncludedFile
, GlobalData
.gWorkspace
)
1480 ErrorCode
, ErrorInfo2
= IncludedFile1
.Validate()
1482 EdkLogger
.error('parser', ErrorCode
, File
=self
._FileWithError
,
1483 Line
=self
._LineIndex
+ 1, ExtraData
=ErrorInfo1
+ "\n" + ErrorInfo2
)
1485 self
._FileWithError
= IncludedFile1
1487 IncludedFileTable
= MetaFileStorage(self
._Table
.Cur
, IncludedFile1
, MODEL_FILE_DSC
, False)
1488 Owner
= self
._Content
[self
._ContentIndex
- 1][0]
1489 Parser
= DscParser(IncludedFile1
, self
._FileType
, IncludedFileTable
,
1490 Owner
=Owner
, From
=Owner
)
1492 # set the parser status with current status
1493 Parser
._SectionName
= self
._SectionName
1494 Parser
._SectionType
= self
._SectionType
1495 Parser
._Scope
= self
._Scope
1496 Parser
._Enabled
= self
._Enabled
1497 # Parse the included file
1500 # update current status with sub-parser's status
1501 self
._SectionName
= Parser
._SectionName
1502 self
._SectionType
= Parser
._SectionType
1503 self
._Scope
= Parser
._Scope
1504 self
._Enabled
= Parser
._Enabled
1506 # Insert all records in the table for the included file into dsc file table
1507 Records
= IncludedFileTable
.GetAll()
1509 self
._Content
[self
._ContentIndex
:self
._ContentIndex
] = Records
1510 self
._Content
.pop(self
._ContentIndex
- 1)
1511 self
._ValueList
= None
1512 self
._ContentIndex
-= 1
1514 def __ProcessSkuId(self
):
1515 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=True)
1516 for Value
in self
._ValueList
]
1518 def __ProcessLibraryInstance(self
):
1519 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
1521 def __ProcessLibraryClass(self
):
1522 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, RaiseError
=True)
1524 def __ProcessPcd(self
):
1525 if self
._ItemType
not in [MODEL_PCD_FEATURE_FLAG
, MODEL_PCD_FIXED_AT_BUILD
]:
1526 self
._ValueList
[2] = ReplaceMacro(self
._ValueList
[2], self
._Macros
, RaiseError
=True)
1529 ValList
, Valid
, Index
= AnalyzeDscPcd(self
._ValueList
[2], self
._ItemType
)
1531 EdkLogger
.error('build', FORMAT_INVALID
, "Pcd format incorrect.", File
=self
._FileWithError
, Line
=self
._LineIndex
+1,
1532 ExtraData
="%s.%s|%s" % (self
._ValueList
[0], self
._ValueList
[1], self
._ValueList
[2]))
1533 PcdValue
= ValList
[Index
]
1536 ValList
[Index
] = ValueExpression(PcdValue
, self
._Macros
)(True)
1537 except WrnExpression
, Value
:
1538 ValList
[Index
] = Value
.result
1540 if ValList
[Index
] == 'True':
1541 ValList
[Index
] = '1'
1542 if ValList
[Index
] == 'False':
1543 ValList
[Index
] = '0'
1545 GlobalData
.gPlatformPcds
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = PcdValue
1546 self
._ValueList
[2] = '|'.join(ValList
)
1548 def __ProcessComponent(self
):
1549 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1551 def __ProcessSourceOverridePath(self
):
1552 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1554 def __ProcessBuildOption(self
):
1555 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=False)
1556 for Value
in self
._ValueList
]
1559 MODEL_META_DATA_HEADER
: _DefineParser
,
1560 MODEL_EFI_SKU_ID
: _SkuIdParser
,
1561 MODEL_EFI_LIBRARY_INSTANCE
: _LibraryInstanceParser
,
1562 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
1563 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1564 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1565 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1566 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
1567 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
1568 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
1569 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
1570 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
1571 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
1572 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
1573 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: _CompponentSourceOverridePathParser
,
1574 MODEL_META_DATA_BUILD_OPTION
: _BuildOptionParser
,
1575 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1576 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
1577 MODEL_META_DATA_SECTION_HEADER
: MetaFileParser
._SectionHeaderParser
,
1578 MODEL_META_DATA_SUBSECTION_HEADER
: _SubsectionHeaderParser
,
1581 _Macros
= property(_GetMacros
)
1583 ## DEC file parser class
1585 # @param FilePath The path of platform description file
1586 # @param FileType The raw data of DSC file
1587 # @param Table Database used to retrieve module/package information
1588 # @param Macros Macros used for replacement in file
1590 class DecParser(MetaFileParser
):
1591 # DEC file supported data types (one type per section)
1593 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1594 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
1595 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1596 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1597 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1598 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1599 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1600 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1601 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1602 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1603 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1604 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1605 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
,
1608 ## Constructor of DecParser
1610 # Initialize object of DecParser
1612 # @param FilePath The path of platform description file
1613 # @param FileType The raw data of DSC file
1614 # @param Table Database used to retrieve module/package information
1615 # @param Macros Macros used for replacement in file
1617 def __init__(self
, FilePath
, FileType
, Table
):
1618 # prevent re-initialization
1619 if hasattr(self
, "_Table"):
1621 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, -1)
1623 self
._Version
= 0x00010005 # Only EDK2 dec file is supported
1624 self
._AllPCDs
= [] # Only for check duplicate PCD
1630 Content
= open(str(self
.MetaFile
), 'r').readlines()
1632 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1634 for Index
in range(0, len(Content
)):
1635 Line
, Comment
= CleanString2(Content
[Index
])
1636 self
._CurrentLine
= Line
1637 self
._LineIndex
= Index
1639 # save comment for later use
1641 self
._Comments
.append((Comment
, self
._LineIndex
+ 1))
1647 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1648 self
._SectionHeaderParser
()
1651 elif len(self
._SectionType
) == 0:
1656 self
._ValueList
= ['', '', '']
1657 self
._SectionParser
[self
._SectionType
[0]](self
)
1658 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
1664 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1665 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1667 for Arch
, ModuleType
, Type
in self
._Scope
:
1668 self
._LastItem
= self
._Store
(
1676 self
._LineIndex
+ 1,
1678 self
._LineIndex
+ 1,
1682 for Comment
, LineNo
in self
._Comments
:
1684 MODEL_META_DATA_COMMENT
,
1701 ## Section header parser
1703 # The section header is always in following format:
1705 # [section_name.arch<.platform|module_type>]
1707 def _SectionHeaderParser(self
):
1709 self
._SectionName
= ''
1710 self
._SectionType
= []
1712 Line
= self
._CurrentLine
.replace("%s%s" % (TAB_COMMA_SPLIT
, TAB_SPACE_SPLIT
), TAB_COMMA_SPLIT
)
1713 for Item
in Line
[1:-1].split(TAB_COMMA_SPLIT
):
1715 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
,
1716 "section name can NOT be empty or incorrectly use separator comma",
1717 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1718 ItemList
= Item
.split(TAB_SPLIT
)
1720 # different types of PCD are permissible in one section
1721 self
._SectionName
= ItemList
[0].upper()
1722 if self
._SectionName
in self
.DataType
:
1723 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1724 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1726 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
1727 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1729 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1733 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1735 Line
=self
._LineIndex
+ 1,
1736 ExtraData
=self
._CurrentLine
1739 if len(ItemList
) > 1:
1740 S1
= ItemList
[1].upper()
1744 # S2 may be Platform or ModuleType
1745 if len(ItemList
) > 2:
1746 S2
= ItemList
[2].upper()
1749 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1750 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1752 # 'COMMON' must not be used with specific ARCHs at the same section
1753 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1754 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1755 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
1757 ## [guids], [ppis] and [protocols] section parser
1759 def _GuidParser(self
):
1760 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1761 if len(TokenList
) < 2:
1762 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1763 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1764 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1765 if TokenList
[0] == '':
1766 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1767 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1768 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1769 if TokenList
[1] == '':
1770 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1771 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1772 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1773 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1774 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1775 ExtraData
=self
._CurrentLine
+ \
1776 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1777 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1778 self
._ValueList
[0] = TokenList
[0]
1779 self
._ValueList
[1] = TokenList
[1]
1781 ## PCD sections parser
1783 # [PcdsFixedAtBuild]
1784 # [PcdsPatchableInModule]
1790 def _PcdParser(self
):
1791 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1792 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1793 ValueRe
= re
.compile(r
'^[a-zA-Z_][a-zA-Z0-9_]*')
1794 # check PCD information
1795 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1796 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1797 ExtraData
=self
._CurrentLine
+ \
1798 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1799 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1800 # check format of token space GUID CName
1801 if not ValueRe
.match(self
._ValueList
[0]):
1802 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_]*'",
1803 ExtraData
=self
._CurrentLine
+ \
1804 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1805 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1806 # check format of PCD CName
1807 if not ValueRe
.match(self
._ValueList
[1]):
1808 EdkLogger
.error('Parser', FORMAT_INVALID
, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
1809 ExtraData
=self
._CurrentLine
+ \
1810 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1811 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1812 # check PCD datum information
1813 if len(TokenList
) < 2 or TokenList
[1] == '':
1814 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1815 ExtraData
=self
._CurrentLine
+ \
1816 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1817 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1820 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1821 PtrValue
= ValueRe
.findall(TokenList
[1])
1823 # Has VOID* type string, may contain "|" character in the string.
1824 if len(PtrValue
) != 0:
1825 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1826 ValueList
= GetSplitValueList(ptrValueList
)
1827 ValueList
[0] = PtrValue
[0]
1829 ValueList
= GetSplitValueList(TokenList
[1])
1832 # check if there's enough datum information given
1833 if len(ValueList
) != 3:
1834 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1835 ExtraData
=self
._CurrentLine
+ \
1836 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1837 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1838 # check default value
1839 if ValueList
[0] == '':
1840 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1841 ExtraData
=self
._CurrentLine
+ \
1842 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1843 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1845 if ValueList
[1] == '':
1846 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1847 ExtraData
=self
._CurrentLine
+ \
1848 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1849 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1850 # check token of the PCD
1851 if ValueList
[2] == '':
1852 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1853 ExtraData
=self
._CurrentLine
+ \
1854 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1855 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1856 # check format of default value against the datum type
1857 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1859 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1860 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1862 if ValueList
[0] in ['True', 'true', 'TRUE']:
1864 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1867 # check for duplicate PCD definition
1868 if (self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]) in self
._AllPCDs
:
1869 EdkLogger
.error('Parser', FORMAT_INVALID
,
1870 "The same PCD name and GUID have been already defined",
1871 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1873 self
._AllPCDs
.append((self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]))
1875 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
1878 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
1879 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
1880 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
1881 MODEL_EFI_GUID
: _GuidParser
,
1882 MODEL_EFI_PPI
: _GuidParser
,
1883 MODEL_EFI_PROTOCOL
: _GuidParser
,
1884 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1885 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1886 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1887 MODEL_PCD_DYNAMIC
: _PcdParser
,
1888 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
1889 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1890 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
1895 # This acts like the main() function for the script, unless it is 'import'ed into another
1898 if __name__
== '__main__':