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
35 ## A decorator used to parse macro definition
36 def ParseMacro(Parser
):
37 def MacroParser(self
):
38 Match
= gMacroDefPattern
.match(self
._CurrentLine
)
40 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
44 TokenList
= GetSplitValueList(self
._CurrentLine
[Match
.end(1):], TAB_EQUAL_SPLIT
, 1)
47 EdkLogger
.error('Parser', FORMAT_INVALID
, "No macro name given",
48 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
49 if len(TokenList
) < 2:
53 Name
, Value
= TokenList
54 # Global macros can be only defined via environment variable
55 if Name
in GlobalData
.gGlobalDefines
:
56 EdkLogger
.error('Parser', FORMAT_INVALID
, "%s can only be defined via environment variable" % Name
,
57 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
58 # Only upper case letters, digit and '_' are allowed
59 if not gMacroNamePattern
.match(Name
):
60 EdkLogger
.error('Parser', FORMAT_INVALID
, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
61 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
63 Value
= ReplaceMacro(Value
, self
._Macros
)
64 if Type
in self
.DataType
:
65 self
._ItemType
= self
.DataType
[Type
]
67 self
._ItemType
= MODEL_META_DATA_DEFINE
68 # DEFINE defined macros
69 if Type
== TAB_DSC_DEFINES_DEFINE
:
71 # First judge whether this DEFINE is in conditional directive statements or not.
73 if type(self
) == DscParser
and self
._InDirective
> -1:
76 if type(self
) == DecParser
:
77 if MODEL_META_DATA_HEADER
in self
._SectionType
:
78 self
._FileLocalMacros
[Name
] = Value
80 self
._ConstructSectionMacroDict
(Name
, Value
)
81 elif self
._SectionType
== MODEL_META_DATA_HEADER
:
82 self
._FileLocalMacros
[Name
] = Value
84 self
._ConstructSectionMacroDict
(Name
, Value
)
86 # EDK_GLOBAL defined macros
87 elif type(self
) != DscParser
:
88 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used in .dsc file",
89 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
90 elif self
._SectionType
!= MODEL_META_DATA_HEADER
:
91 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used under [Defines] section",
92 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
93 elif (Name
in self
._FileLocalMacros
) and (self
._FileLocalMacros
[Name
] != Value
):
94 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
95 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
97 self
._ValueList
= [Type
, Name
, Value
]
101 ## Base class of parser
103 # This class is used for derivation purpose. The specific parser for one kind
104 # type file must derive this class and implement some public interfaces.
106 # @param FilePath The path of platform description file
107 # @param FileType The raw data of DSC file
108 # @param Table Database used to retrieve module/package information
109 # @param Macros Macros used for replacement in file
110 # @param Owner Owner ID (for sub-section parsing)
111 # @param From ID from which the data comes (for !INCLUDE directive)
113 class MetaFileParser(object):
114 # data type (file content) for specific file type
117 # Parser objects used to implement singleton
122 # One file, one parser object. This factory method makes sure that there's
123 # only one object constructed for one meta file.
125 # @param Class class object of real AutoGen class
126 # (InfParser, DecParser or DscParser)
127 # @param FilePath The path of meta file
128 # @param *args The specific class related parameters
129 # @param **kwargs The specific class related dict parameters
131 def __new__(Class
, FilePath
, *args
, **kwargs
):
132 if FilePath
in Class
.MetaFiles
:
133 return Class
.MetaFiles
[FilePath
]
135 ParserObject
= super(MetaFileParser
, Class
).__new
__(Class
)
136 Class
.MetaFiles
[FilePath
] = ParserObject
139 ## Constructor of MetaFileParser
141 # Initialize object of MetaFileParser
143 # @param FilePath The path of platform description file
144 # @param FileType The raw data of DSC file
145 # @param Table Database used to retrieve module/package information
146 # @param Macros Macros used for replacement in file
147 # @param Owner Owner ID (for sub-section parsing)
148 # @param From ID from which the data comes (for !INCLUDE directive)
150 def __init__(self
, FilePath
, FileType
, Table
, Owner
= -1, From
= -1):
152 self
._RawTable
= Table
153 self
._FileType
= FileType
154 self
.MetaFile
= FilePath
155 self
._FileDir
= self
.MetaFile
.Dir
157 self
._FileLocalMacros
= {}
158 self
._SectionsMacroDict
= {}
160 # for recursive parsing
161 self
._Owner
= [Owner
]
164 # parsr status for parsing
165 self
._ValueList
= ['', '', '', '', '']
168 self
._CurrentLine
= ''
169 self
._SectionType
= MODEL_UNKNOWN
170 self
._SectionName
= ''
171 self
._InSubsection
= False
172 self
._SubsectionType
= MODEL_UNKNOWN
173 self
._SubsectionName
= ''
174 self
._ItemType
= MODEL_UNKNOWN
177 self
._Finished
= False
178 self
._PostProcessed
= False
179 # Different version of meta-file has different way to parse.
182 ## Store the parsed data in table
183 def _Store(self
, *Args
):
184 return self
._Table
.Insert(*Args
)
186 ## Virtual method for starting parse
188 raise NotImplementedError
190 ## Notify a post-process is needed
191 def DoPostProcess(self
):
192 self
._PostProcessed
= False
194 ## Set parsing complete flag in both class and table
196 self
._Finished
= True
197 ## Do not set end flag when processing included files
199 self
._Table
.SetEndFlag()
201 def _PostProcess(self
):
202 self
._PostProcessed
= True
204 ## Get the parse complete flag
205 def _GetFinished(self
):
206 return self
._Finished
208 ## Set the complete flag
209 def _SetFinished(self
, Value
):
210 self
._Finished
= Value
212 ## Use [] style to query data in table, just for readability
214 # DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]
216 def __getitem__(self
, DataInfo
):
217 if type(DataInfo
) != type(()):
218 DataInfo
= (DataInfo
,)
220 # Parse the file first, if necessary
221 if not self
._Finished
:
222 if self
._RawTable
.IsIntegrity():
223 self
._Finished
= True
225 self
._Table
= self
._RawTable
226 self
._PostProcessed
= False
229 # No specific ARCH or Platform given, use raw data
230 if self
._RawTable
and (len(DataInfo
) == 1 or DataInfo
[1] == None):
231 return self
._RawTable
.Query(*DataInfo
)
233 # Do post-process if necessary
234 if not self
._PostProcessed
:
237 return self
._Table
.Query(*DataInfo
)
239 ## Data parser for the common format in different type of file
241 # The common format in the meatfile is like
246 def _CommonParser(self
):
247 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
248 self
._ValueList
[0:len(TokenList
)] = TokenList
250 ## Data parser for the format in which there's path
252 # Only path can have macro used. So we need to replace them before use.
255 def _PathParser(self
):
256 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
257 self
._ValueList
[0:len(TokenList
)] = TokenList
258 # Don't do macro replacement for dsc file at this point
259 if type(self
) != DscParser
:
260 Macros
= self
._Macros
261 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
263 ## Skip unsupported data
265 EdkLogger
.warn("Parser", "Unrecognized content", File
=self
.MetaFile
,
266 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
);
267 self
._ValueList
[0:1] = [self
._CurrentLine
]
269 ## Skip unsupported data for UserExtension Section
270 def _SkipUserExtension(self
):
271 self
._ValueList
[0:1] = [self
._CurrentLine
]
273 ## Section header parser
275 # The section header is always in following format:
277 # [section_name.arch<.platform|module_type>]
279 def _SectionHeaderParser(self
):
281 self
._SectionName
= ''
283 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
286 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
,2)
287 # different section should not mix in one section
288 if self
._SectionName
!= '' and self
._SectionName
!= ItemList
[0].upper():
289 EdkLogger
.error('Parser', FORMAT_INVALID
, "Different section names in the same section",
290 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
291 self
._SectionName
= ItemList
[0].upper()
292 if self
._SectionName
in self
.DataType
:
293 self
._SectionType
= self
.DataType
[self
._SectionName
]
294 # Check if the section name is valid
295 if self
._SectionName
not in SECTIONS_HAVE_ITEM_AFTER_ARCH
and len(ItemList
) > 3:
296 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
297 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
298 elif self
._Version
>= 0x00010005:
299 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
300 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
302 self
._SectionType
= MODEL_UNKNOWN
305 if len(ItemList
) > 1:
306 S1
= ItemList
[1].upper()
311 # S2 may be Platform or ModuleType
312 if len(ItemList
) > 2:
313 if self
._SectionName
.upper() in SECTIONS_HAVE_ITEM_PCD
:
316 S2
= ItemList
[2].upper()
319 self
._Scope
.append([S1
, S2
])
321 # 'COMMON' must not be used with specific ARCHs at the same section
322 if 'COMMON' in ArchList
and len(ArchList
) > 1:
323 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
324 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
325 # If the section information is needed later, it should be stored in database
326 self
._ValueList
[0] = self
._SectionName
328 ## [defines] section parser
330 def _DefineParser(self
):
331 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
332 self
._ValueList
[1:len(TokenList
)] = TokenList
333 if not self
._ValueList
[1]:
334 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
335 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
336 if not self
._ValueList
[2]:
337 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
338 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
340 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
341 Name
, Value
= self
._ValueList
[1], self
._ValueList
[2]
342 # Sometimes, we need to make differences between EDK and EDK2 modules
343 if Name
== 'INF_VERSION':
345 self
._Version
= int(Value
, 0)
347 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid version number",
348 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
350 if type(self
) == InfParser
and self
._Version
< 0x00010005:
351 # EDK module allows using defines as macros
352 self
._FileLocalMacros
[Name
] = Value
353 self
._Defines
[Name
] = Value
355 ## [BuildOptions] section parser
357 def _BuildOptionParser(self
):
358 self
._CurrentLine
= CleanString(self
._CurrentLine
, BuildOption
=True)
359 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
360 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
361 if len(TokenList2
) == 2:
362 self
._ValueList
[0] = TokenList2
[0] # toolchain family
363 self
._ValueList
[1] = TokenList2
[1] # keys
365 self
._ValueList
[1] = TokenList
[0]
366 if len(TokenList
) == 2 and type(self
) != DscParser
: # value
367 self
._ValueList
[2] = ReplaceMacro(TokenList
[1], self
._Macros
)
369 if self
._ValueList
[1].count('_') != 4:
373 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
374 ExtraData
=self
._CurrentLine
,
376 Line
=self
._LineIndex
+ 1
379 def _GetMacros(self
):
381 Macros
.update(self
._FileLocalMacros
)
382 Macros
.update(self
._GetApplicableSectionMacro
())
385 ## Construct section Macro dict
386 def _ConstructSectionMacroDict(self
, Name
, Value
):
387 ScopeKey
= [(Scope
[0], Scope
[1]) for Scope
in self
._Scope
]
388 ScopeKey
= tuple(ScopeKey
)
389 SectionDictKey
= self
._SectionType
, ScopeKey
391 # DecParser SectionType is a list, will contain more than one item only in Pcd Section
392 # As Pcd section macro usage is not alllowed, so here it is safe
394 if type(self
) == DecParser
:
395 SectionDictKey
= self
._SectionType
[0], ScopeKey
396 if SectionDictKey
not in self
._SectionsMacroDict
:
397 self
._SectionsMacroDict
[SectionDictKey
] = {}
398 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
399 SectionLocalMacros
[Name
] = Value
401 ## Get section Macros that are applicable to current line, which may come from other sections
402 ## that share the same name while scope is wider
403 def _GetApplicableSectionMacro(self
):
410 ActiveSectionType
= self
._SectionType
411 if type(self
) == DecParser
:
412 ActiveSectionType
= self
._SectionType
[0]
414 for (SectionType
, Scope
) in self
._SectionsMacroDict
:
415 if SectionType
!= ActiveSectionType
:
418 for ActiveScope
in self
._Scope
:
419 Scope0
, Scope1
= ActiveScope
[0], ActiveScope
[1]
420 if(Scope0
, Scope1
) not in Scope
:
423 SpeSpeMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
425 for ActiveScope
in self
._Scope
:
426 Scope0
, Scope1
= ActiveScope
[0], ActiveScope
[1]
427 if(Scope0
, Scope1
) not in Scope
and (Scope0
, "COMMON") not in Scope
and ("COMMON", Scope1
) not in Scope
:
430 ComSpeMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
432 if ("COMMON", "COMMON") in Scope
:
433 ComComMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
435 Macros
.update(ComComMacroDict
)
436 Macros
.update(ComSpeMacroDict
)
437 Macros
.update(SpeSpeMacroDict
)
442 Finished
= property(_GetFinished
, _SetFinished
)
443 _Macros
= property(_GetMacros
)
446 ## INF file parser class
448 # @param FilePath The path of platform description file
449 # @param FileType The raw data of DSC file
450 # @param Table Database used to retrieve module/package information
451 # @param Macros Macros used for replacement in file
453 class InfParser(MetaFileParser
):
454 # INF file supported data types (one type per section)
456 TAB_UNKNOWN
.upper() : MODEL_UNKNOWN
,
457 TAB_INF_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
458 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
459 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
460 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
461 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
462 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
463 TAB_PACKAGES
.upper() : MODEL_META_DATA_PACKAGE
,
464 TAB_NMAKE
.upper() : MODEL_META_DATA_NMAKE
,
465 TAB_INF_FIXED_PCD
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
466 TAB_INF_PATCH_PCD
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
467 TAB_INF_FEATURE_PCD
.upper() : MODEL_PCD_FEATURE_FLAG
,
468 TAB_INF_PCD_EX
.upper() : MODEL_PCD_DYNAMIC_EX
,
469 TAB_INF_PCD
.upper() : MODEL_PCD_DYNAMIC
,
470 TAB_SOURCES
.upper() : MODEL_EFI_SOURCE_FILE
,
471 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
472 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
473 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
474 TAB_DEPEX
.upper() : MODEL_EFI_DEPEX
,
475 TAB_BINARIES
.upper() : MODEL_EFI_BINARY_FILE
,
476 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
479 ## Constructor of InfParser
481 # Initialize object of InfParser
483 # @param FilePath The path of module description file
484 # @param FileType The raw data of DSC file
485 # @param Table Database used to retrieve module/package information
486 # @param Macros Macros used for replacement in file
488 def __init__(self
, FilePath
, FileType
, Table
):
489 # prevent re-initialization
490 if hasattr(self
, "_Table"):
492 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
500 Content
= open(str(self
.MetaFile
), 'r').readlines()
502 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
504 # parse the file line by line
505 IsFindBlockComment
= False
506 GetHeaderComment
= False
511 for Index
in range(0, len(Content
)):
512 # skip empty, commented, block commented lines
513 Line
, Comment
= CleanString2(Content
[Index
], AllowCppStyleComment
=True)
515 if Index
+ 1 < len(Content
):
516 NextLine
, NextComment
= CleanString2(Content
[Index
+ 1])
519 Comments
.append((Comment
, Index
+ 1))
520 elif GetHeaderComment
:
521 SectionComments
.extend(Comments
)
524 if Line
.find(DataType
.TAB_COMMENT_EDK_START
) > -1:
525 IsFindBlockComment
= True
527 if Line
.find(DataType
.TAB_COMMENT_EDK_END
) > -1:
528 IsFindBlockComment
= False
530 if IsFindBlockComment
:
533 self
._LineIndex
= Index
534 self
._CurrentLine
= Line
537 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
538 if not GetHeaderComment
:
539 for Cmt
, LNo
in Comments
:
540 self
._Store
(MODEL_META_DATA_HEADER_COMMENT
, Cmt
, '', '', 'COMMON',
541 'COMMON', self
._Owner
[-1], LNo
, -1, LNo
, -1, 0)
542 GetHeaderComment
= True
544 TailComments
.extend(SectionComments
+ Comments
)
546 self
._SectionHeaderParser
()
547 # Check invalid sections
548 if self
._Version
< 0x00010005:
549 if self
._SectionType
in [MODEL_META_DATA_BUILD_OPTION
,
550 MODEL_EFI_LIBRARY_CLASS
,
551 MODEL_META_DATA_PACKAGE
,
552 MODEL_PCD_FIXED_AT_BUILD
,
553 MODEL_PCD_PATCHABLE_IN_MODULE
,
554 MODEL_PCD_FEATURE_FLAG
,
555 MODEL_PCD_DYNAMIC_EX
,
560 MODEL_META_DATA_USER_EXTENSION
]:
561 EdkLogger
.error('Parser', FORMAT_INVALID
,
562 "Section [%s] is not allowed in inf file without version" % (self
._SectionName
),
563 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
564 elif self
._SectionType
in [MODEL_EFI_INCLUDE
,
565 MODEL_EFI_LIBRARY_INSTANCE
,
566 MODEL_META_DATA_NMAKE
]:
567 EdkLogger
.error('Parser', FORMAT_INVALID
,
568 "Section [%s] is not allowed in inf file with version 0x%08x" % (self
._SectionName
, self
._Version
),
569 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
571 # merge two lines specified by '\' in section NMAKE
572 elif self
._SectionType
== MODEL_META_DATA_NMAKE
:
575 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
578 if NextLine
[0] == TAB_SECTION_START
and NextLine
[-1] == TAB_SECTION_END
:
579 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
582 NmakeLine
= NmakeLine
+ ' ' + Line
[0:-1]
585 self
._CurrentLine
= NmakeLine
+ Line
589 self
._ValueList
= ['', '', '']
590 # parse current line, result will be put in self._ValueList
591 self
._SectionParser
[self
._SectionType
](self
)
592 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
597 Comments
.append((Comment
, Index
+ 1))
599 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
600 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
602 for Arch
, Platform
in self
._Scope
:
603 LastItem
= self
._Store
(self
._SectionType
,
616 for Comment
, LineNo
in Comments
:
617 self
._Store
(MODEL_META_DATA_COMMENT
, Comment
, '', '', Arch
, Platform
,
618 LastItem
, LineNo
, -1, LineNo
, -1, 0)
621 TailComments
.extend(SectionComments
+ Comments
)
622 if IsFindBlockComment
:
623 EdkLogger
.error("Parser", FORMAT_INVALID
, "Open block comments (starting with /*) are expected to end with */",
626 # If there are tail comments in INF file, save to database whatever the comments are
627 for Comment
in TailComments
:
628 self
._Store
(MODEL_META_DATA_TAIL_COMMENT
, Comment
[0], '', '', 'COMMON',
629 'COMMON', self
._Owner
[-1], -1, -1, -1, -1, 0)
632 ## Data parser for the format in which there's path
634 # Only path can have macro used. So we need to replace them before use.
636 def _IncludeParser(self
):
637 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
638 self
._ValueList
[0:len(TokenList
)] = TokenList
639 Macros
= self
._Macros
641 for Index
in range(0, len(self
._ValueList
)):
642 Value
= self
._ValueList
[Index
]
646 if Value
.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value
.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
647 Value
= '$(EDK_SOURCE)' + Value
[17:]
648 if Value
.find('$(EFI_SOURCE)') > -1 or Value
.find('$(EDK_SOURCE)') > -1:
650 elif Value
.startswith('.'):
652 elif Value
.startswith('$('):
655 Value
= '$(EFI_SOURCE)/' + Value
657 self
._ValueList
[Index
] = ReplaceMacro(Value
, Macros
)
659 ## Parse [Sources] section
661 # Only path can have macro used. So we need to replace them before use.
664 def _SourceFileParser(self
):
665 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
666 self
._ValueList
[0:len(TokenList
)] = TokenList
667 Macros
= self
._Macros
668 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
669 if 'COMPONENT_TYPE' in Macros
:
670 if self
._Defines
['COMPONENT_TYPE'].upper() == 'ACPITABLE':
671 self
._ValueList
[0] = GetSplitValueList(self
._ValueList
[0], ' ', 1)[0]
672 if self
._Defines
['BASE_NAME'] == 'Microcode':
674 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
676 ## Parse [Binaries] section
678 # Only path can have macro used. So we need to replace them before use.
681 def _BinaryFileParser(self
):
682 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 2)
683 if len(TokenList
) < 2:
684 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type or path specified",
685 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
686 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
688 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type specified",
689 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
690 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
692 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file path specified",
693 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
694 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
695 self
._ValueList
[0:len(TokenList
)] = TokenList
696 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
698 ## [nmake] section parser (Edk.x style only)
699 def _NmakeParser(self
):
700 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
701 self
._ValueList
[0:len(TokenList
)] = TokenList
703 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
704 # remove self-reference in macro setting
705 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
707 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
709 def _PcdParser(self
):
710 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
711 ValueList
= GetSplitValueList(TokenList
[0], TAB_SPLIT
)
712 if len(ValueList
) != 2:
713 EdkLogger
.error('Parser', FORMAT_INVALID
, "Illegal token space GUID and PCD name format",
714 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
715 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
716 self
._ValueList
[0:1] = ValueList
717 if len(TokenList
) > 1:
718 self
._ValueList
[2] = TokenList
[1]
719 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
720 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
721 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
722 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
724 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
725 if self
._ValueList
[2] != '':
726 InfPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
727 if InfPcdValueList
[0] in ['True', 'true', 'TRUE']:
728 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '1', 1);
729 elif InfPcdValueList
[0] in ['False', 'false', 'FALSE']:
730 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '0', 1);
731 if (self
._ValueList
[0], self
._ValueList
[1]) not in self
.PcdsDict
:
732 self
.PcdsDict
[self
._ValueList
[0], self
._ValueList
[1]] = self
._SectionType
733 elif self
.PcdsDict
[self
._ValueList
[0], self
._ValueList
[1]] != self
._SectionType
:
734 EdkLogger
.error('Parser', FORMAT_INVALID
, "It is not permissible to list a specified PCD in different PCD type sections.",
735 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
736 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
738 ## [depex] section parser
740 def _DepexParser(self
):
741 self
._ValueList
[0:1] = [self
._CurrentLine
]
744 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
745 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
746 MODEL_META_DATA_BUILD_OPTION
: MetaFileParser
._BuildOptionParser
,
747 MODEL_EFI_INCLUDE
: _IncludeParser
, # for Edk.x modules
748 MODEL_EFI_LIBRARY_INSTANCE
: MetaFileParser
._CommonParser
, # for Edk.x modules
749 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
750 MODEL_META_DATA_PACKAGE
: MetaFileParser
._PathParser
,
751 MODEL_META_DATA_NMAKE
: _NmakeParser
, # for Edk.x modules
752 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
753 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
754 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
755 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
756 MODEL_PCD_DYNAMIC
: _PcdParser
,
757 MODEL_EFI_SOURCE_FILE
: _SourceFileParser
,
758 MODEL_EFI_GUID
: MetaFileParser
._CommonParser
,
759 MODEL_EFI_PROTOCOL
: MetaFileParser
._CommonParser
,
760 MODEL_EFI_PPI
: MetaFileParser
._CommonParser
,
761 MODEL_EFI_DEPEX
: _DepexParser
,
762 MODEL_EFI_BINARY_FILE
: _BinaryFileParser
,
763 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
766 ## DSC file parser class
768 # @param FilePath The path of platform description file
769 # @param FileType The raw data of DSC file
770 # @param Table Database used to retrieve module/package information
771 # @param Macros Macros used for replacement in file
772 # @param Owner Owner ID (for sub-section parsing)
773 # @param From ID from which the data comes (for !INCLUDE directive)
775 class DscParser(MetaFileParser
):
776 # DSC file supported data types (one type per section)
778 TAB_SKUIDS
.upper() : MODEL_EFI_SKU_ID
,
779 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
780 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
781 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
782 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
783 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
784 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
785 TAB_PCDS_DYNAMIC_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_DEFAULT
,
786 TAB_PCDS_DYNAMIC_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_HII
,
787 TAB_PCDS_DYNAMIC_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_VPD
,
788 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT
,
789 TAB_PCDS_DYNAMIC_EX_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_HII
,
790 TAB_PCDS_DYNAMIC_EX_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_VPD
,
791 TAB_COMPONENTS
.upper() : MODEL_META_DATA_COMPONENT
,
792 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH
.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
,
793 TAB_DSC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
794 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
795 TAB_DSC_DEFINES_EDKGLOBAL
: MODEL_META_DATA_GLOBAL_DEFINE
,
796 TAB_INCLUDE
.upper() : MODEL_META_DATA_INCLUDE
,
797 TAB_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
798 TAB_IF_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
799 TAB_IF_N_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
,
800 TAB_ELSE_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
,
801 TAB_ELSE
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
802 TAB_END_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
,
803 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
,
806 # Valid names in define section
813 "PCD_INFO_GENERATION",
814 "SUPPORTED_ARCHITECTURES",
823 "FIX_LOAD_TOP_MEMORY_ADDRESS"
826 SymbolPattern
= ValueExpression
.SymbolPattern
828 ## Constructor of DscParser
830 # Initialize object of DscParser
832 # @param FilePath The path of platform description file
833 # @param FileType The raw data of DSC file
834 # @param Table Database used to retrieve module/package information
835 # @param Macros Macros used for replacement in file
836 # @param Owner Owner ID (for sub-section parsing)
837 # @param From ID from which the data comes (for !INCLUDE directive)
839 def __init__(self
, FilePath
, FileType
, Table
, Owner
= -1, From
= -1):
840 # prevent re-initialization
841 if hasattr(self
, "_Table"):
843 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, Owner
, From
)
844 self
._Version
= 0x00010005 # Only EDK2 dsc file is supported
845 # to store conditional directive evaluation result
846 self
._DirectiveStack
= []
847 self
._DirectiveEvalStack
= []
851 # Specify whether current line is in uncertain condition
853 self
._InDirective
= -1
855 # Final valid replacable symbols
858 # Map the ID between the original table and new table to track
861 self
._IdMapping
= {-1:-1}
867 Content
= open(str(self
.MetaFile
), 'r').readlines()
869 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
872 for Index
in range(0, len(Content
)):
873 Line
= CleanString(Content
[Index
])
878 self
._CurrentLine
= Line
879 self
._LineIndex
= Index
880 if self
._InSubsection
and self
._Owner
[-1] == -1:
881 self
._Owner
.append(self
._LastItem
)
884 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
885 self
._SectionType
= MODEL_META_DATA_SECTION_HEADER
887 elif Line
[0] == '}' and self
._InSubsection
:
888 self
._InSubsection
= False
889 self
._SubsectionType
= MODEL_UNKNOWN
890 self
._SubsectionName
= ''
895 elif Line
[0] == TAB_OPTION_START
and Line
[-1] == TAB_OPTION_END
:
896 self
._SubsectionType
= MODEL_META_DATA_SUBSECTION_HEADER
899 self
._DirectiveParser
()
902 if self
._InSubsection
:
903 SectionType
= self
._SubsectionType
905 SectionType
= self
._SectionType
906 self
._ItemType
= SectionType
908 self
._ValueList
= ['', '', '']
909 self
._SectionParser
[SectionType
](self
)
910 if self
._ValueList
== None:
913 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
914 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
916 for Arch
, ModuleType
in self
._Scope
:
917 Owner
= self
._Owner
[-1]
918 if self
._SubsectionType
!= MODEL_UNKNOWN
:
919 Owner
= OwnerId
[Arch
]
920 self
._LastItem
= self
._Store
(
935 if self
._SubsectionType
== MODEL_UNKNOWN
and self
._InSubsection
:
936 OwnerId
[Arch
] = self
._LastItem
938 if self
._DirectiveStack
:
939 Type
, Line
, Text
= self
._DirectiveStack
[-1]
940 EdkLogger
.error('Parser', FORMAT_INVALID
, "No matching '!endif' found",
941 ExtraData
=Text
, File
=self
.MetaFile
, Line
=Line
)
944 ## <subsection_header> parser
945 def _SubsectionHeaderParser(self
):
946 self
._SubsectionName
= self
._CurrentLine
[1:-1].upper()
947 if self
._SubsectionName
in self
.DataType
:
948 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
950 self
._SubsectionType
= MODEL_UNKNOWN
951 EdkLogger
.warn("Parser", "Unrecognized sub-section", File
=self
.MetaFile
,
952 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
953 self
._ValueList
[0] = self
._SubsectionName
955 ## Directive statement parser
956 def _DirectiveParser(self
):
957 self
._ValueList
= ['', '', '']
958 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
959 self
._ValueList
[0:len(TokenList
)] = TokenList
962 DirectiveName
= self
._ValueList
[0].upper()
963 if DirectiveName
not in self
.DataType
:
964 EdkLogger
.error("Parser", FORMAT_INVALID
, "Unknown directive [%s]" % DirectiveName
,
965 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
967 if DirectiveName
in ['!IF', '!IFDEF', '!IFNDEF']:
968 self
._InDirective
+= 1
970 if DirectiveName
in ['!ENDIF']:
971 self
._InDirective
-= 1
973 if DirectiveName
in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self
._ValueList
[1] == '':
974 EdkLogger
.error("Parser", FORMAT_INVALID
, "Missing expression",
975 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
976 ExtraData
=self
._CurrentLine
)
978 ItemType
= self
.DataType
[DirectiveName
]
979 Scope
= [['COMMON', 'COMMON']]
980 if ItemType
== MODEL_META_DATA_INCLUDE
:
982 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
983 # Remove all directives between !if and !endif, including themselves
984 while self
._DirectiveStack
:
985 # Remove any !else or !elseif
986 DirectiveInfo
= self
._DirectiveStack
.pop()
987 if DirectiveInfo
[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
988 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
989 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
992 EdkLogger
.error("Parser", FORMAT_INVALID
, "Redundant '!endif'",
993 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
994 ExtraData
=self
._CurrentLine
)
995 elif ItemType
!= MODEL_META_DATA_INCLUDE
:
996 # Break if there's a !else is followed by a !elseif
997 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
and \
998 self
._DirectiveStack
and \
999 self
._DirectiveStack
[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1000 EdkLogger
.error("Parser", FORMAT_INVALID
, "'!elseif' after '!else'",
1001 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
1002 ExtraData
=self
._CurrentLine
)
1003 self
._DirectiveStack
.append((ItemType
, self
._LineIndex
+ 1, self
._CurrentLine
))
1004 elif self
._From
> 0:
1005 EdkLogger
.error('Parser', FORMAT_INVALID
,
1006 "No '!include' allowed in included file",
1007 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
,
1008 Line
=self
._LineIndex
+ 1)
1011 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
1012 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
1014 for Arch
, ModuleType
in Scope
:
1015 self
._LastItem
= self
._Store
(
1024 self
._LineIndex
+ 1,
1026 self
._LineIndex
+ 1,
1031 ## [defines] section parser
1033 def _DefineParser(self
):
1034 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1035 self
._ValueList
[1:len(TokenList
)] = TokenList
1038 if not self
._ValueList
[1]:
1039 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
1040 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1041 if not self
._ValueList
[2]:
1042 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
1043 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1044 if not self
._ValueList
[1] in self
.DefineKeywords
:
1045 EdkLogger
.error('Parser', FORMAT_INVALID
,
1046 "Unknown keyword found: %s. "
1047 "If this is a macro you must "
1048 "add it as a DEFINE in the DSC" % self
._ValueList
[1],
1049 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1050 self
._Defines
[self
._ValueList
[1]] = self
._ValueList
[2]
1051 self
._ItemType
= self
.DataType
[TAB_DSC_DEFINES
.upper()]
1054 def _SkuIdParser(self
):
1055 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1056 if len(TokenList
) != 2:
1057 EdkLogger
.error('Parser', FORMAT_INVALID
, "Correct format is '<Integer>|<UiName>'",
1058 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1059 self
._ValueList
[0:len(TokenList
)] = TokenList
1061 ## Parse Edk style of library modules
1063 def _LibraryInstanceParser(self
):
1064 self
._ValueList
[0] = self
._CurrentLine
1066 ## PCD sections parser
1068 # [PcdsFixedAtBuild]
1069 # [PcdsPatchableInModule]
1072 # [PcdsDynamicExDefault]
1073 # [PcdsDynamicExVpd]
1074 # [PcdsDynamicExHii]
1076 # [PcdsDynamicDefault]
1081 def _PcdParser(self
):
1082 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1083 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1084 if len(TokenList
) == 2:
1085 self
._ValueList
[2] = TokenList
[1]
1086 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1087 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1088 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1089 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1090 if self
._ValueList
[2] == '':
1092 # The PCD values are optional for FIXEDATBUILD and PATCHABLEINMODULE
1094 if self
._SectionType
in (MODEL_PCD_FIXED_AT_BUILD
, MODEL_PCD_PATCHABLE_IN_MODULE
):
1096 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD value given",
1097 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1098 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1100 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD
1101 ValueList
= GetSplitValueList(self
._ValueList
[2])
1102 if len(ValueList
) > 1 and ValueList
[1] != TAB_VOID \
1103 and self
._ItemType
in [MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_EX_DEFAULT
]:
1104 EdkLogger
.error('Parser', FORMAT_INVALID
, "The datum type '%s' of PCD is wrong" % ValueList
[1],
1105 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1107 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1108 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
1109 if DscPcdValueList
[0] in ['True', 'true', 'TRUE']:
1110 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '1', 1);
1111 elif DscPcdValueList
[0] in ['False', 'false', 'FALSE']:
1112 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '0', 1);
1115 ## [components] section parser
1117 def _ComponentParser(self
):
1118 if self
._CurrentLine
[-1] == '{':
1119 self
._ValueList
[0] = self
._CurrentLine
[0:-1].strip()
1120 self
._InSubsection
= True
1122 self
._ValueList
[0] = self
._CurrentLine
1124 ## [LibraryClasses] section
1126 def _LibraryClassParser(self
):
1127 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1128 if len(TokenList
) < 2:
1129 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class or instance specified",
1130 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1131 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1132 if TokenList
[0] == '':
1133 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class specified",
1134 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1135 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1136 if TokenList
[1] == '':
1137 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library instance specified",
1138 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1139 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1141 self
._ValueList
[0:len(TokenList
)] = TokenList
1143 def _CompponentSourceOverridePathParser(self
):
1144 self
._ValueList
[0] = self
._CurrentLine
1146 ## [BuildOptions] section parser
1148 def _BuildOptionParser(self
):
1149 self
._CurrentLine
= CleanString(self
._CurrentLine
, BuildOption
=True)
1150 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1151 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
1152 if len(TokenList2
) == 2:
1153 self
._ValueList
[0] = TokenList2
[0] # toolchain family
1154 self
._ValueList
[1] = TokenList2
[1] # keys
1156 self
._ValueList
[1] = TokenList
[0]
1157 if len(TokenList
) == 2: # value
1158 self
._ValueList
[2] = TokenList
[1]
1160 if self
._ValueList
[1].count('_') != 4:
1164 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
1165 ExtraData
=self
._CurrentLine
,
1167 Line
=self
._LineIndex
+ 1
1170 ## Override parent's method since we'll do all macro replacements in parser
1171 def _GetMacros(self
):
1173 Macros
.update(self
._FileLocalMacros
)
1174 Macros
.update(self
._GetApplicableSectionMacro
())
1175 Macros
.update(GlobalData
.gEdkGlobal
)
1176 Macros
.update(GlobalData
.gPlatformDefines
)
1177 Macros
.update(GlobalData
.gCommandLineDefines
)
1178 # PCD cannot be referenced in macro definition
1179 if self
._ItemType
not in [MODEL_META_DATA_DEFINE
, MODEL_META_DATA_GLOBAL_DEFINE
]:
1180 Macros
.update(self
._Symbols
)
1183 def _PostProcess(self
):
1185 MODEL_META_DATA_SECTION_HEADER
: self
.__ProcessSectionHeader
,
1186 MODEL_META_DATA_SUBSECTION_HEADER
: self
.__ProcessSubsectionHeader
,
1187 MODEL_META_DATA_HEADER
: self
.__ProcessDefine
,
1188 MODEL_META_DATA_DEFINE
: self
.__ProcessDefine
,
1189 MODEL_META_DATA_GLOBAL_DEFINE
: self
.__ProcessDefine
,
1190 MODEL_META_DATA_INCLUDE
: self
.__ProcessDirective
,
1191 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
: self
.__ProcessDirective
,
1192 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
: self
.__ProcessDirective
,
1193 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
: self
.__ProcessDirective
,
1194 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
: self
.__ProcessDirective
,
1195 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
: self
.__ProcessDirective
,
1196 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
: self
.__ProcessDirective
,
1197 MODEL_EFI_SKU_ID
: self
.__ProcessSkuId
,
1198 MODEL_EFI_LIBRARY_INSTANCE
: self
.__ProcessLibraryInstance
,
1199 MODEL_EFI_LIBRARY_CLASS
: self
.__ProcessLibraryClass
,
1200 MODEL_PCD_FIXED_AT_BUILD
: self
.__ProcessPcd
,
1201 MODEL_PCD_PATCHABLE_IN_MODULE
: self
.__ProcessPcd
,
1202 MODEL_PCD_FEATURE_FLAG
: self
.__ProcessPcd
,
1203 MODEL_PCD_DYNAMIC_DEFAULT
: self
.__ProcessPcd
,
1204 MODEL_PCD_DYNAMIC_HII
: self
.__ProcessPcd
,
1205 MODEL_PCD_DYNAMIC_VPD
: self
.__ProcessPcd
,
1206 MODEL_PCD_DYNAMIC_EX_DEFAULT
: self
.__ProcessPcd
,
1207 MODEL_PCD_DYNAMIC_EX_HII
: self
.__ProcessPcd
,
1208 MODEL_PCD_DYNAMIC_EX_VPD
: self
.__ProcessPcd
,
1209 MODEL_META_DATA_COMPONENT
: self
.__ProcessComponent
,
1210 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: self
.__ProcessSourceOverridePath
,
1211 MODEL_META_DATA_BUILD_OPTION
: self
.__ProcessBuildOption
,
1212 MODEL_UNKNOWN
: self
._Skip
,
1213 MODEL_META_DATA_USER_EXTENSION
: self
._SkipUserExtension
,
1216 self
._Table
= MetaFileStorage(self
._RawTable
.Cur
, self
.MetaFile
, MODEL_FILE_DSC
, True)
1217 self
._Table
.Create()
1218 self
._DirectiveStack
= []
1219 self
._DirectiveEvalStack
= []
1220 self
._FileWithError
= self
.MetaFile
1221 self
._FileLocalMacros
= {}
1222 self
._SectionsMacroDict
= {}
1223 GlobalData
.gPlatformDefines
= {}
1225 # Get all macro and PCD which has straitforward value
1226 self
.__RetrievePcdValue
()
1227 self
._Content
= self
._RawTable
.GetAll()
1228 self
._ContentIndex
= 0
1229 while self
._ContentIndex
< len(self
._Content
) :
1230 Id
, self
._ItemType
, V1
, V2
, V3
, S1
, S2
, Owner
, self
._From
, \
1231 LineStart
, ColStart
, LineEnd
, ColEnd
, Enabled
= self
._Content
[self
._ContentIndex
]
1234 self
._FileWithError
= self
.MetaFile
1236 self
._ContentIndex
+= 1
1238 self
._Scope
= [[S1
, S2
]]
1240 # For !include directive, handle it specially,
1241 # merge arch and module type in case of duplicate items
1243 while self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1244 if self
._ContentIndex
>= len(self
._Content
):
1246 Record
= self
._Content
[self
._ContentIndex
]
1247 if LineStart
== Record
[9] and LineEnd
== Record
[11]:
1248 if [Record
[5], Record
[6]] not in self
._Scope
:
1249 self
._Scope
.append([Record
[5], Record
[6]])
1250 self
._ContentIndex
+= 1
1254 self
._LineIndex
= LineStart
- 1
1255 self
._ValueList
= [V1
, V2
, V3
]
1258 Processer
[self
._ItemType
]()
1259 except EvaluationException
, Excpt
:
1261 # Only catch expression evaluation error here. We need to report
1262 # the precise number of line on which the error occurred
1264 if hasattr(Excpt
, 'Pcd'):
1265 if Excpt
.Pcd
in GlobalData
.gPlatformOtherPcds
:
1266 Info
= GlobalData
.gPlatformOtherPcds
[Excpt
.Pcd
]
1267 EdkLogger
.error('Parser', FORMAT_INVALID
, "Cannot use this PCD (%s) in an expression as"
1268 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
1269 " of the DSC file, and it is currently defined in this section:"
1270 " %s, line #: %d." % (Excpt
.Pcd
, Info
[0], Info
[1]),
1271 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1272 Line
=self
._LineIndex
+ 1)
1274 EdkLogger
.error('Parser', FORMAT_INVALID
, "PCD (%s) is not defined in DSC file" % Excpt
.Pcd
,
1275 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1276 Line
=self
._LineIndex
+ 1)
1278 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid expression: %s" % str(Excpt
),
1279 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1280 Line
=self
._LineIndex
+ 1)
1281 except MacroException
, Excpt
:
1282 EdkLogger
.error('Parser', FORMAT_INVALID
, str(Excpt
),
1283 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1284 Line
=self
._LineIndex
+ 1)
1286 if self
._ValueList
== None:
1289 NewOwner
= self
._IdMapping
.get(Owner
, -1)
1290 self
._Enabled
= int((not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
))
1291 self
._LastItem
= self
._Store
(
1300 self
._LineIndex
+ 1,
1302 self
._LineIndex
+ 1,
1306 self
._IdMapping
[Id
] = self
._LastItem
1308 GlobalData
.gPlatformDefines
.update(self
._FileLocalMacros
)
1309 self
._PostProcessed
= True
1310 self
._Content
= None
1312 def __ProcessSectionHeader(self
):
1313 self
._SectionName
= self
._ValueList
[0]
1314 if self
._SectionName
in self
.DataType
:
1315 self
._SectionType
= self
.DataType
[self
._SectionName
]
1317 self
._SectionType
= MODEL_UNKNOWN
1319 def __ProcessSubsectionHeader(self
):
1320 self
._SubsectionName
= self
._ValueList
[0]
1321 if self
._SubsectionName
in self
.DataType
:
1322 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
1324 self
._SubsectionType
= MODEL_UNKNOWN
1326 def __RetrievePcdValue(self
):
1327 Records
= self
._RawTable
.Query(MODEL_PCD_FEATURE_FLAG
, BelongsToItem
= -1.0)
1328 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1329 Name
= TokenSpaceGuid
+ '.' + PcdName
1330 ValList
, Valid
, Index
= AnalyzeDscPcd(Value
, MODEL_PCD_FEATURE_FLAG
)
1331 self
._Symbols
[Name
] = ValList
[Index
]
1333 Records
= self
._RawTable
.Query(MODEL_PCD_FIXED_AT_BUILD
, BelongsToItem
= -1.0)
1334 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1335 Name
= TokenSpaceGuid
+ '.' + PcdName
1336 ValList
, Valid
, Index
= AnalyzeDscPcd(Value
, MODEL_PCD_FIXED_AT_BUILD
)
1337 self
._Symbols
[Name
] = ValList
[Index
]
1339 Content
= open(str(self
.MetaFile
), 'r').readlines()
1340 GlobalData
.gPlatformOtherPcds
['DSCFILE'] = str(self
.MetaFile
)
1341 for PcdType
in (MODEL_PCD_PATCHABLE_IN_MODULE
, MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_HII
,
1342 MODEL_PCD_DYNAMIC_VPD
, MODEL_PCD_DYNAMIC_EX_DEFAULT
, MODEL_PCD_DYNAMIC_EX_HII
,
1343 MODEL_PCD_DYNAMIC_EX_VPD
):
1344 Records
= self
._RawTable
.Query(PcdType
, BelongsToItem
= -1.0)
1345 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1346 Name
= TokenSpaceGuid
+ '.' + PcdName
1347 if Name
not in GlobalData
.gPlatformOtherPcds
:
1349 while not Content
[Line
- 1].lstrip().startswith(TAB_SECTION_START
):
1351 GlobalData
.gPlatformOtherPcds
[Name
] = (CleanString(Content
[Line
- 1]), PcdLine
, PcdType
)
1353 def __ProcessDefine(self
):
1354 if not self
._Enabled
:
1357 Type
, Name
, Value
= self
._ValueList
1358 Value
= ReplaceMacro(Value
, self
._Macros
, False)
1359 if self
._ItemType
== MODEL_META_DATA_DEFINE
:
1360 if self
._SectionType
== MODEL_META_DATA_HEADER
:
1361 self
._FileLocalMacros
[Name
] = Value
1363 self
._ConstructSectionMacroDict
(Name
, Value
)
1364 elif self
._ItemType
== MODEL_META_DATA_GLOBAL_DEFINE
:
1365 GlobalData
.gEdkGlobal
[Name
] = Value
1368 # Keyword in [Defines] section can be used as Macros
1370 if (self
._ItemType
== MODEL_META_DATA_HEADER
) and (self
._SectionType
== MODEL_META_DATA_HEADER
):
1371 self
._FileLocalMacros
[Name
] = Value
1373 self
._ValueList
= [Type
, Name
, Value
]
1375 def __ProcessDirective(self
):
1377 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1378 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
]:
1379 Macros
= self
._Macros
1380 Macros
.update(GlobalData
.gGlobalDefines
)
1382 Result
= ValueExpression(self
._ValueList
[1], Macros
)()
1383 except SymbolNotFound
, Exc
:
1384 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1386 except WrnExpression
, Excpt
:
1388 # Catch expression evaluation warning here. We need to report
1389 # the precise number of line and return the evaluation result
1391 EdkLogger
.warn('Parser', "Suspicious expression: %s" % str(Excpt
),
1392 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1393 Line
=self
._LineIndex
+ 1)
1394 Result
= Excpt
.result
1396 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1397 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1398 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1399 self
._DirectiveStack
.append(self
._ItemType
)
1400 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
:
1401 Result
= bool(Result
)
1403 Macro
= self
._ValueList
[1]
1404 Macro
= Macro
[2:-1] if (Macro
.startswith("$(") and Macro
.endswith(")")) else Macro
1405 Result
= Macro
in self
._Macros
1406 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
:
1408 self
._DirectiveEvalStack
.append(Result
)
1409 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
:
1410 self
._DirectiveStack
.append(self
._ItemType
)
1411 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1412 self
._DirectiveEvalStack
.append(bool(Result
))
1413 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1414 self
._DirectiveStack
.append(self
._ItemType
)
1415 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1416 self
._DirectiveEvalStack
.append(True)
1417 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1418 # Back to the nearest !if/!ifdef/!ifndef
1419 while self
._DirectiveStack
:
1420 self
._DirectiveEvalStack
.pop()
1421 Directive
= self
._DirectiveStack
.pop()
1422 if Directive
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1423 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1424 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1426 elif self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1427 # The included file must be relative to workspace or same directory as DSC file
1428 __IncludeMacros
= {}
1430 # Allow using system environment variables in path after !include
1432 __IncludeMacros
['WORKSPACE'] = GlobalData
.gGlobalDefines
['WORKSPACE']
1433 if "ECP_SOURCE" in GlobalData
.gGlobalDefines
.keys():
1434 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gGlobalDefines
['ECP_SOURCE']
1436 # During GenFds phase call DSC parser, will go into this branch.
1438 elif "ECP_SOURCE" in GlobalData
.gCommandLineDefines
.keys():
1439 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gCommandLineDefines
['ECP_SOURCE']
1441 __IncludeMacros
['EFI_SOURCE'] = GlobalData
.gGlobalDefines
['EFI_SOURCE']
1442 __IncludeMacros
['EDK_SOURCE'] = GlobalData
.gGlobalDefines
['EDK_SOURCE']
1444 # Allow using MACROs comes from [Defines] section to keep compatible.
1446 __IncludeMacros
.update(self
._Macros
)
1448 IncludedFile
= NormPath(ReplaceMacro(self
._ValueList
[1], __IncludeMacros
, RaiseError
=True))
1450 # First search the include file under the same directory as DSC file
1452 IncludedFile1
= PathClass(IncludedFile
, self
.MetaFile
.Dir
)
1453 ErrorCode
, ErrorInfo1
= IncludedFile1
.Validate()
1456 # Also search file under the WORKSPACE directory
1458 IncludedFile1
= PathClass(IncludedFile
, GlobalData
.gWorkspace
)
1459 ErrorCode
, ErrorInfo2
= IncludedFile1
.Validate()
1461 EdkLogger
.error('parser', ErrorCode
, File
=self
._FileWithError
,
1462 Line
=self
._LineIndex
+ 1, ExtraData
=ErrorInfo1
+ "\n" + ErrorInfo2
)
1464 self
._FileWithError
= IncludedFile1
1466 IncludedFileTable
= MetaFileStorage(self
._Table
.Cur
, IncludedFile1
, MODEL_FILE_DSC
, False)
1467 Owner
= self
._Content
[self
._ContentIndex
- 1][0]
1468 Parser
= DscParser(IncludedFile1
, self
._FileType
, IncludedFileTable
,
1469 Owner
=Owner
, From
=Owner
)
1471 # set the parser status with current status
1472 Parser
._SectionName
= self
._SectionName
1473 Parser
._SectionType
= self
._SectionType
1474 Parser
._Scope
= self
._Scope
1475 Parser
._Enabled
= self
._Enabled
1476 # Parse the included file
1479 # update current status with sub-parser's status
1480 self
._SectionName
= Parser
._SectionName
1481 self
._SectionType
= Parser
._SectionType
1482 self
._Scope
= Parser
._Scope
1483 self
._Enabled
= Parser
._Enabled
1485 # Insert all records in the table for the included file into dsc file table
1486 Records
= IncludedFileTable
.GetAll()
1488 self
._Content
[self
._ContentIndex
:self
._ContentIndex
] = Records
1489 self
._Content
.pop(self
._ContentIndex
- 1)
1490 self
._ValueList
= None
1491 self
._ContentIndex
-= 1
1493 def __ProcessSkuId(self
):
1494 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=True)
1495 for Value
in self
._ValueList
]
1497 def __ProcessLibraryInstance(self
):
1498 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
1500 def __ProcessLibraryClass(self
):
1501 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, RaiseError
=True)
1503 def __ProcessPcd(self
):
1504 if self
._ItemType
not in [MODEL_PCD_FEATURE_FLAG
, MODEL_PCD_FIXED_AT_BUILD
]:
1505 self
._ValueList
[2] = ReplaceMacro(self
._ValueList
[2], self
._Macros
, RaiseError
=True)
1508 ValList
, Valid
, Index
= AnalyzeDscPcd(self
._ValueList
[2], self
._ItemType
)
1510 EdkLogger
.error('build', FORMAT_INVALID
, "Pcd format incorrect.", File
=self
._FileWithError
, Line
=self
._LineIndex
+1,
1511 ExtraData
="%s.%s|%s" % (self
._ValueList
[0], self
._ValueList
[1], self
._ValueList
[2]))
1512 PcdValue
= ValList
[Index
]
1515 ValList
[Index
] = ValueExpression(PcdValue
, self
._Macros
)(True)
1516 except WrnExpression
, Value
:
1517 ValList
[Index
] = Value
.result
1519 if ValList
[Index
] == 'True':
1520 ValList
[Index
] = '1'
1521 if ValList
[Index
] == 'False':
1522 ValList
[Index
] = '0'
1524 GlobalData
.gPlatformPcds
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = PcdValue
1525 self
._ValueList
[2] = '|'.join(ValList
)
1527 def __ProcessComponent(self
):
1528 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1530 def __ProcessSourceOverridePath(self
):
1531 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1533 def __ProcessBuildOption(self
):
1534 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=False)
1535 for Value
in self
._ValueList
]
1538 MODEL_META_DATA_HEADER
: _DefineParser
,
1539 MODEL_EFI_SKU_ID
: _SkuIdParser
,
1540 MODEL_EFI_LIBRARY_INSTANCE
: _LibraryInstanceParser
,
1541 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
1542 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1543 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1544 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1545 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
1546 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
1547 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
1548 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
1549 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
1550 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
1551 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
1552 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: _CompponentSourceOverridePathParser
,
1553 MODEL_META_DATA_BUILD_OPTION
: _BuildOptionParser
,
1554 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1555 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
1556 MODEL_META_DATA_SECTION_HEADER
: MetaFileParser
._SectionHeaderParser
,
1557 MODEL_META_DATA_SUBSECTION_HEADER
: _SubsectionHeaderParser
,
1560 _Macros
= property(_GetMacros
)
1562 ## DEC file parser class
1564 # @param FilePath The path of platform description file
1565 # @param FileType The raw data of DSC file
1566 # @param Table Database used to retrieve module/package information
1567 # @param Macros Macros used for replacement in file
1569 class DecParser(MetaFileParser
):
1570 # DEC file supported data types (one type per section)
1572 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1573 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
1574 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1575 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1576 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1577 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1578 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1579 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1580 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1581 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1582 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1583 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1584 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
,
1587 ## Constructor of DecParser
1589 # Initialize object of DecParser
1591 # @param FilePath The path of platform description file
1592 # @param FileType The raw data of DSC file
1593 # @param Table Database used to retrieve module/package information
1594 # @param Macros Macros used for replacement in file
1596 def __init__(self
, FilePath
, FileType
, Table
):
1597 # prevent re-initialization
1598 if hasattr(self
, "_Table"):
1600 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, -1)
1602 self
._Version
= 0x00010005 # Only EDK2 dec file is supported
1603 self
._AllPCDs
= [] # Only for check duplicate PCD
1609 Content
= open(str(self
.MetaFile
), 'r').readlines()
1611 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1613 for Index
in range(0, len(Content
)):
1614 Line
, Comment
= CleanString2(Content
[Index
])
1615 self
._CurrentLine
= Line
1616 self
._LineIndex
= Index
1618 # save comment for later use
1620 self
._Comments
.append((Comment
, self
._LineIndex
+ 1))
1626 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1627 self
._SectionHeaderParser
()
1630 elif len(self
._SectionType
) == 0:
1635 self
._ValueList
= ['', '', '']
1636 self
._SectionParser
[self
._SectionType
[0]](self
)
1637 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
1643 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1644 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1646 for Arch
, ModuleType
, Type
in self
._Scope
:
1647 self
._LastItem
= self
._Store
(
1655 self
._LineIndex
+ 1,
1657 self
._LineIndex
+ 1,
1661 for Comment
, LineNo
in self
._Comments
:
1663 MODEL_META_DATA_COMMENT
,
1680 ## Section header parser
1682 # The section header is always in following format:
1684 # [section_name.arch<.platform|module_type>]
1686 def _SectionHeaderParser(self
):
1688 self
._SectionName
= ''
1689 self
._SectionType
= []
1691 Line
= self
._CurrentLine
.replace("%s%s" % (TAB_COMMA_SPLIT
, TAB_SPACE_SPLIT
), TAB_COMMA_SPLIT
)
1692 for Item
in Line
[1:-1].split(TAB_COMMA_SPLIT
):
1694 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
,
1695 "section name can NOT be empty or incorrectly use separator comma",
1696 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1697 ItemList
= Item
.split(TAB_SPLIT
)
1699 # different types of PCD are permissible in one section
1700 self
._SectionName
= ItemList
[0].upper()
1701 if self
._SectionName
in self
.DataType
:
1702 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1703 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1705 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
1706 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1708 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1712 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1714 Line
=self
._LineIndex
+ 1,
1715 ExtraData
=self
._CurrentLine
1718 if len(ItemList
) > 1:
1719 S1
= ItemList
[1].upper()
1723 # S2 may be Platform or ModuleType
1724 if len(ItemList
) > 2:
1725 S2
= ItemList
[2].upper()
1728 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1729 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1731 # 'COMMON' must not be used with specific ARCHs at the same section
1732 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1733 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1734 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
1736 ## [guids], [ppis] and [protocols] section parser
1738 def _GuidParser(self
):
1739 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1740 if len(TokenList
) < 2:
1741 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1742 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1743 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1744 if TokenList
[0] == '':
1745 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1746 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1747 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1748 if TokenList
[1] == '':
1749 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1750 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1751 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1752 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1753 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1754 ExtraData
=self
._CurrentLine
+ \
1755 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1756 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1757 self
._ValueList
[0] = TokenList
[0]
1758 self
._ValueList
[1] = TokenList
[1]
1760 ## PCD sections parser
1762 # [PcdsFixedAtBuild]
1763 # [PcdsPatchableInModule]
1769 def _PcdParser(self
):
1770 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1771 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1772 ValueRe
= re
.compile(r
'^[a-zA-Z_][a-zA-Z0-9_]*')
1773 # check PCD information
1774 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1775 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1776 ExtraData
=self
._CurrentLine
+ \
1777 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1778 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1779 # check format of token space GUID CName
1780 if not ValueRe
.match(self
._ValueList
[0]):
1781 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_]*'",
1782 ExtraData
=self
._CurrentLine
+ \
1783 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1784 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1785 # check format of PCD CName
1786 if not ValueRe
.match(self
._ValueList
[1]):
1787 EdkLogger
.error('Parser', FORMAT_INVALID
, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
1788 ExtraData
=self
._CurrentLine
+ \
1789 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1790 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1791 # check PCD datum information
1792 if len(TokenList
) < 2 or TokenList
[1] == '':
1793 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1794 ExtraData
=self
._CurrentLine
+ \
1795 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1796 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1799 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1800 PtrValue
= ValueRe
.findall(TokenList
[1])
1802 # Has VOID* type string, may contain "|" character in the string.
1803 if len(PtrValue
) != 0:
1804 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1805 ValueList
= GetSplitValueList(ptrValueList
)
1806 ValueList
[0] = PtrValue
[0]
1808 ValueList
= GetSplitValueList(TokenList
[1])
1811 # check if there's enough datum information given
1812 if len(ValueList
) != 3:
1813 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1814 ExtraData
=self
._CurrentLine
+ \
1815 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1816 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1817 # check default value
1818 if ValueList
[0] == '':
1819 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1820 ExtraData
=self
._CurrentLine
+ \
1821 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1822 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1824 if ValueList
[1] == '':
1825 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1826 ExtraData
=self
._CurrentLine
+ \
1827 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1828 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1829 # check token of the PCD
1830 if ValueList
[2] == '':
1831 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1832 ExtraData
=self
._CurrentLine
+ \
1833 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1834 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1835 # check format of default value against the datum type
1836 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1838 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1839 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1841 if ValueList
[0] in ['True', 'true', 'TRUE']:
1843 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1846 # check for duplicate PCD definition
1847 if (self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]) in self
._AllPCDs
:
1848 EdkLogger
.error('Parser', FORMAT_INVALID
,
1849 "The same PCD name and GUID have been already defined",
1850 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1852 self
._AllPCDs
.append((self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]))
1854 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
1857 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
1858 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
1859 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
1860 MODEL_EFI_GUID
: _GuidParser
,
1861 MODEL_EFI_PPI
: _GuidParser
,
1862 MODEL_EFI_PROTOCOL
: _GuidParser
,
1863 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1864 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1865 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1866 MODEL_PCD_DYNAMIC
: _PcdParser
,
1867 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
1868 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1869 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
1874 # This acts like the main() function for the script, unless it is 'import'ed into another
1877 if __name__
== '__main__':