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 ## Section header parser
271 # The section header is always in following format:
273 # [section_name.arch<.platform|module_type>]
275 def _SectionHeaderParser(self
):
277 self
._SectionName
= ''
279 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
282 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
,2)
283 # different section should not mix in one section
284 if self
._SectionName
!= '' and self
._SectionName
!= ItemList
[0].upper():
285 EdkLogger
.error('Parser', FORMAT_INVALID
, "Different section names in the same section",
286 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
287 self
._SectionName
= ItemList
[0].upper()
288 if self
._SectionName
in self
.DataType
:
289 self
._SectionType
= self
.DataType
[self
._SectionName
]
290 # Check if the section name is valid
291 if self
._SectionName
not in SECTIONS_HAVE_ITEM_AFTER_ARCH
and len(ItemList
) > 3:
292 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
293 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
294 elif self
._Version
>= 0x00010005:
295 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
296 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
298 self
._SectionType
= MODEL_UNKNOWN
301 if len(ItemList
) > 1:
302 S1
= ItemList
[1].upper()
307 # S2 may be Platform or ModuleType
308 if len(ItemList
) > 2:
309 if self
._SectionName
.upper() in SECTIONS_HAVE_ITEM_PCD
:
312 S2
= ItemList
[2].upper()
315 self
._Scope
.append([S1
, S2
])
317 # 'COMMON' must not be used with specific ARCHs at the same section
318 if 'COMMON' in ArchList
and len(ArchList
) > 1:
319 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
320 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
321 # If the section information is needed later, it should be stored in database
322 self
._ValueList
[0] = self
._SectionName
324 ## [defines] section parser
326 def _DefineParser(self
):
327 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
328 self
._ValueList
[1:len(TokenList
)] = TokenList
329 if not self
._ValueList
[1]:
330 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
331 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
332 if not self
._ValueList
[2]:
333 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
334 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
336 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
337 Name
, Value
= self
._ValueList
[1], self
._ValueList
[2]
338 # Sometimes, we need to make differences between EDK and EDK2 modules
339 if Name
== 'INF_VERSION':
341 self
._Version
= int(Value
, 0)
343 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid version number",
344 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
346 if type(self
) == InfParser
and self
._Version
< 0x00010005:
347 # EDK module allows using defines as macros
348 self
._FileLocalMacros
[Name
] = Value
349 self
._Defines
[Name
] = Value
351 ## [BuildOptions] section parser
353 def _BuildOptionParser(self
):
354 self
._CurrentLine
= CleanString(self
._CurrentLine
, BuildOption
=True)
355 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
356 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
357 if len(TokenList2
) == 2:
358 self
._ValueList
[0] = TokenList2
[0] # toolchain family
359 self
._ValueList
[1] = TokenList2
[1] # keys
361 self
._ValueList
[1] = TokenList
[0]
362 if len(TokenList
) == 2 and type(self
) != DscParser
: # value
363 self
._ValueList
[2] = ReplaceMacro(TokenList
[1], self
._Macros
)
365 if self
._ValueList
[1].count('_') != 4:
369 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
370 ExtraData
=self
._CurrentLine
,
372 Line
=self
._LineIndex
+ 1
375 def _GetMacros(self
):
377 Macros
.update(self
._FileLocalMacros
)
378 Macros
.update(self
._GetApplicableSectionMacro
())
381 ## Construct section Macro dict
382 def _ConstructSectionMacroDict(self
, Name
, Value
):
383 ScopeKey
= [(Scope
[0], Scope
[1]) for Scope
in self
._Scope
]
384 ScopeKey
= tuple(ScopeKey
)
385 SectionDictKey
= self
._SectionType
, ScopeKey
387 # DecParser SectionType is a list, will contain more than one item only in Pcd Section
388 # As Pcd section macro usage is not alllowed, so here it is safe
390 if type(self
) == DecParser
:
391 SectionDictKey
= self
._SectionType
[0], ScopeKey
392 if SectionDictKey
not in self
._SectionsMacroDict
:
393 self
._SectionsMacroDict
[SectionDictKey
] = {}
394 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
395 SectionLocalMacros
[Name
] = Value
397 ## Get section Macros that are applicable to current line, which may come from other sections
398 ## that share the same name while scope is wider
399 def _GetApplicableSectionMacro(self
):
406 ActiveSectionType
= self
._SectionType
407 if type(self
) == DecParser
:
408 ActiveSectionType
= self
._SectionType
[0]
410 for (SectionType
, Scope
) in self
._SectionsMacroDict
:
411 if SectionType
!= ActiveSectionType
:
414 for ActiveScope
in self
._Scope
:
415 Scope0
, Scope1
= ActiveScope
[0], ActiveScope
[1]
416 if(Scope0
, Scope1
) not in Scope
:
419 SpeSpeMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
421 for ActiveScope
in self
._Scope
:
422 Scope0
, Scope1
= ActiveScope
[0], ActiveScope
[1]
423 if(Scope0
, Scope1
) not in Scope
and (Scope0
, "COMMON") not in Scope
and ("COMMON", Scope1
) not in Scope
:
426 ComSpeMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
428 if ("COMMON", "COMMON") in Scope
:
429 ComComMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
431 Macros
.update(ComComMacroDict
)
432 Macros
.update(ComSpeMacroDict
)
433 Macros
.update(SpeSpeMacroDict
)
438 Finished
= property(_GetFinished
, _SetFinished
)
439 _Macros
= property(_GetMacros
)
442 ## INF file parser class
444 # @param FilePath The path of platform description file
445 # @param FileType The raw data of DSC file
446 # @param Table Database used to retrieve module/package information
447 # @param Macros Macros used for replacement in file
449 class InfParser(MetaFileParser
):
450 # INF file supported data types (one type per section)
452 TAB_UNKNOWN
.upper() : MODEL_UNKNOWN
,
453 TAB_INF_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
454 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
455 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
456 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
457 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
458 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
459 TAB_PACKAGES
.upper() : MODEL_META_DATA_PACKAGE
,
460 TAB_NMAKE
.upper() : MODEL_META_DATA_NMAKE
,
461 TAB_INF_FIXED_PCD
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
462 TAB_INF_PATCH_PCD
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
463 TAB_INF_FEATURE_PCD
.upper() : MODEL_PCD_FEATURE_FLAG
,
464 TAB_INF_PCD_EX
.upper() : MODEL_PCD_DYNAMIC_EX
,
465 TAB_INF_PCD
.upper() : MODEL_PCD_DYNAMIC
,
466 TAB_SOURCES
.upper() : MODEL_EFI_SOURCE_FILE
,
467 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
468 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
469 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
470 TAB_DEPEX
.upper() : MODEL_EFI_DEPEX
,
471 TAB_BINARIES
.upper() : MODEL_EFI_BINARY_FILE
,
472 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
475 ## Constructor of InfParser
477 # Initialize object of InfParser
479 # @param FilePath The path of module description file
480 # @param FileType The raw data of DSC file
481 # @param Table Database used to retrieve module/package information
482 # @param Macros Macros used for replacement in file
484 def __init__(self
, FilePath
, FileType
, Table
):
485 # prevent re-initialization
486 if hasattr(self
, "_Table"):
488 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
496 Content
= open(str(self
.MetaFile
), 'r').readlines()
498 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
500 # parse the file line by line
501 IsFindBlockComment
= False
502 GetHeaderComment
= False
507 for Index
in range(0, len(Content
)):
508 # skip empty, commented, block commented lines
509 Line
, Comment
= CleanString2(Content
[Index
], AllowCppStyleComment
=True)
511 if Index
+ 1 < len(Content
):
512 NextLine
, NextComment
= CleanString2(Content
[Index
+ 1])
515 Comments
.append((Comment
, Index
+ 1))
516 elif GetHeaderComment
:
517 SectionComments
.extend(Comments
)
520 if Line
.find(DataType
.TAB_COMMENT_EDK_START
) > -1:
521 IsFindBlockComment
= True
523 if Line
.find(DataType
.TAB_COMMENT_EDK_END
) > -1:
524 IsFindBlockComment
= False
526 if IsFindBlockComment
:
529 self
._LineIndex
= Index
530 self
._CurrentLine
= Line
533 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
534 if not GetHeaderComment
:
535 for Cmt
, LNo
in Comments
:
536 self
._Store
(MODEL_META_DATA_HEADER_COMMENT
, Cmt
, '', '', 'COMMON',
537 'COMMON', self
._Owner
[-1], LNo
, -1, LNo
, -1, 0)
538 GetHeaderComment
= True
540 TailComments
.extend(SectionComments
+ Comments
)
542 self
._SectionHeaderParser
()
543 # Check invalid sections
544 if self
._Version
< 0x00010005:
545 if self
._SectionType
in [MODEL_META_DATA_BUILD_OPTION
,
546 MODEL_EFI_LIBRARY_CLASS
,
547 MODEL_META_DATA_PACKAGE
,
548 MODEL_PCD_FIXED_AT_BUILD
,
549 MODEL_PCD_PATCHABLE_IN_MODULE
,
550 MODEL_PCD_FEATURE_FLAG
,
551 MODEL_PCD_DYNAMIC_EX
,
556 MODEL_META_DATA_USER_EXTENSION
]:
557 EdkLogger
.error('Parser', FORMAT_INVALID
,
558 "Section [%s] is not allowed in inf file without version" % (self
._SectionName
),
559 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
560 elif self
._SectionType
in [MODEL_EFI_INCLUDE
,
561 MODEL_EFI_LIBRARY_INSTANCE
,
562 MODEL_META_DATA_NMAKE
]:
563 EdkLogger
.error('Parser', FORMAT_INVALID
,
564 "Section [%s] is not allowed in inf file with version 0x%08x" % (self
._SectionName
, self
._Version
),
565 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
567 # merge two lines specified by '\' in section NMAKE
568 elif self
._SectionType
== MODEL_META_DATA_NMAKE
:
571 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
574 if NextLine
[0] == TAB_SECTION_START
and NextLine
[-1] == TAB_SECTION_END
:
575 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
578 NmakeLine
= NmakeLine
+ ' ' + Line
[0:-1]
581 self
._CurrentLine
= NmakeLine
+ Line
585 self
._ValueList
= ['', '', '']
586 # parse current line, result will be put in self._ValueList
587 self
._SectionParser
[self
._SectionType
](self
)
588 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
593 Comments
.append((Comment
, Index
+ 1))
595 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
596 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
598 for Arch
, Platform
in self
._Scope
:
599 LastItem
= self
._Store
(self
._SectionType
,
612 for Comment
, LineNo
in Comments
:
613 self
._Store
(MODEL_META_DATA_COMMENT
, Comment
, '', '', Arch
, Platform
,
614 LastItem
, LineNo
, -1, LineNo
, -1, 0)
617 TailComments
.extend(SectionComments
+ Comments
)
618 if IsFindBlockComment
:
619 EdkLogger
.error("Parser", FORMAT_INVALID
, "Open block comments (starting with /*) are expected to end with */",
622 # If there are tail comments in INF file, save to database whatever the comments are
623 for Comment
in TailComments
:
624 self
._Store
(MODEL_META_DATA_TAIL_COMMENT
, Comment
[0], '', '', 'COMMON',
625 'COMMON', self
._Owner
[-1], -1, -1, -1, -1, 0)
628 ## Data parser for the format in which there's path
630 # Only path can have macro used. So we need to replace them before use.
632 def _IncludeParser(self
):
633 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
634 self
._ValueList
[0:len(TokenList
)] = TokenList
635 Macros
= self
._Macros
637 for Index
in range(0, len(self
._ValueList
)):
638 Value
= self
._ValueList
[Index
]
642 if Value
.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value
.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
643 Value
= '$(EDK_SOURCE)' + Value
[17:]
644 if Value
.find('$(EFI_SOURCE)') > -1 or Value
.find('$(EDK_SOURCE)') > -1:
646 elif Value
.startswith('.'):
648 elif Value
.startswith('$('):
651 Value
= '$(EFI_SOURCE)/' + Value
653 self
._ValueList
[Index
] = ReplaceMacro(Value
, Macros
)
655 ## Parse [Sources] section
657 # Only path can have macro used. So we need to replace them before use.
660 def _SourceFileParser(self
):
661 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
662 self
._ValueList
[0:len(TokenList
)] = TokenList
663 Macros
= self
._Macros
664 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
665 if 'COMPONENT_TYPE' in Macros
:
666 if self
._Defines
['COMPONENT_TYPE'].upper() == 'ACPITABLE':
667 self
._ValueList
[0] = GetSplitValueList(self
._ValueList
[0], ' ', 1)[0]
668 if self
._Defines
['BASE_NAME'] == 'Microcode':
670 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
672 ## Parse [Binaries] section
674 # Only path can have macro used. So we need to replace them before use.
677 def _BinaryFileParser(self
):
678 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 2)
679 if len(TokenList
) < 2:
680 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type or path specified",
681 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
682 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
684 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type specified",
685 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
686 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
688 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file path specified",
689 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
690 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
691 self
._ValueList
[0:len(TokenList
)] = TokenList
692 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
694 ## [nmake] section parser (Edk.x style only)
695 def _NmakeParser(self
):
696 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
697 self
._ValueList
[0:len(TokenList
)] = TokenList
699 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
700 # remove self-reference in macro setting
701 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
703 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
705 def _PcdParser(self
):
706 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
707 ValueList
= GetSplitValueList(TokenList
[0], TAB_SPLIT
)
708 if len(ValueList
) != 2:
709 EdkLogger
.error('Parser', FORMAT_INVALID
, "Illegal token space GUID and PCD name format",
710 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
711 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
712 self
._ValueList
[0:1] = ValueList
713 if len(TokenList
) > 1:
714 self
._ValueList
[2] = TokenList
[1]
715 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
716 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
717 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
718 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
720 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
721 if self
._ValueList
[2] != '':
722 InfPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
723 if InfPcdValueList
[0] in ['True', 'true', 'TRUE']:
724 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '1', 1);
725 elif InfPcdValueList
[0] in ['False', 'false', 'FALSE']:
726 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '0', 1);
727 if (self
._ValueList
[0], self
._ValueList
[1]) not in self
.PcdsDict
:
728 self
.PcdsDict
[self
._ValueList
[0], self
._ValueList
[1]] = self
._SectionType
729 elif self
.PcdsDict
[self
._ValueList
[0], self
._ValueList
[1]] != self
._SectionType
:
730 EdkLogger
.error('Parser', FORMAT_INVALID
, "It is not permissible to list a specified PCD in different PCD type sections.",
731 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
732 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
734 ## [depex] section parser
736 def _DepexParser(self
):
737 self
._ValueList
[0:1] = [self
._CurrentLine
]
740 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
741 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
742 MODEL_META_DATA_BUILD_OPTION
: MetaFileParser
._BuildOptionParser
,
743 MODEL_EFI_INCLUDE
: _IncludeParser
, # for Edk.x modules
744 MODEL_EFI_LIBRARY_INSTANCE
: MetaFileParser
._CommonParser
, # for Edk.x modules
745 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
746 MODEL_META_DATA_PACKAGE
: MetaFileParser
._PathParser
,
747 MODEL_META_DATA_NMAKE
: _NmakeParser
, # for Edk.x modules
748 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
749 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
750 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
751 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
752 MODEL_PCD_DYNAMIC
: _PcdParser
,
753 MODEL_EFI_SOURCE_FILE
: _SourceFileParser
,
754 MODEL_EFI_GUID
: MetaFileParser
._CommonParser
,
755 MODEL_EFI_PROTOCOL
: MetaFileParser
._CommonParser
,
756 MODEL_EFI_PPI
: MetaFileParser
._CommonParser
,
757 MODEL_EFI_DEPEX
: _DepexParser
,
758 MODEL_EFI_BINARY_FILE
: _BinaryFileParser
,
759 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
762 ## DSC file parser class
764 # @param FilePath The path of platform description file
765 # @param FileType The raw data of DSC file
766 # @param Table Database used to retrieve module/package information
767 # @param Macros Macros used for replacement in file
768 # @param Owner Owner ID (for sub-section parsing)
769 # @param From ID from which the data comes (for !INCLUDE directive)
771 class DscParser(MetaFileParser
):
772 # DSC file supported data types (one type per section)
774 TAB_SKUIDS
.upper() : MODEL_EFI_SKU_ID
,
775 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
776 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
777 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
778 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
779 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
780 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
781 TAB_PCDS_DYNAMIC_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_DEFAULT
,
782 TAB_PCDS_DYNAMIC_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_HII
,
783 TAB_PCDS_DYNAMIC_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_VPD
,
784 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT
,
785 TAB_PCDS_DYNAMIC_EX_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_HII
,
786 TAB_PCDS_DYNAMIC_EX_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_VPD
,
787 TAB_COMPONENTS
.upper() : MODEL_META_DATA_COMPONENT
,
788 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH
.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
,
789 TAB_DSC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
790 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
791 TAB_DSC_DEFINES_EDKGLOBAL
: MODEL_META_DATA_GLOBAL_DEFINE
,
792 TAB_INCLUDE
.upper() : MODEL_META_DATA_INCLUDE
,
793 TAB_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
794 TAB_IF_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
795 TAB_IF_N_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
,
796 TAB_ELSE_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
,
797 TAB_ELSE
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
798 TAB_END_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
,
801 # Valid names in define section
808 "PCD_INFO_GENERATION",
809 "SUPPORTED_ARCHITECTURES",
818 "FIX_LOAD_TOP_MEMORY_ADDRESS"
821 SymbolPattern
= ValueExpression
.SymbolPattern
823 ## Constructor of DscParser
825 # Initialize object of DscParser
827 # @param FilePath The path of platform description file
828 # @param FileType The raw data of DSC file
829 # @param Table Database used to retrieve module/package information
830 # @param Macros Macros used for replacement in file
831 # @param Owner Owner ID (for sub-section parsing)
832 # @param From ID from which the data comes (for !INCLUDE directive)
834 def __init__(self
, FilePath
, FileType
, Table
, Owner
= -1, From
= -1):
835 # prevent re-initialization
836 if hasattr(self
, "_Table"):
838 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, Owner
, From
)
839 self
._Version
= 0x00010005 # Only EDK2 dsc file is supported
840 # to store conditional directive evaluation result
841 self
._DirectiveStack
= []
842 self
._DirectiveEvalStack
= []
846 # Specify whether current line is in uncertain condition
848 self
._InDirective
= -1
850 # Final valid replacable symbols
853 # Map the ID between the original table and new table to track
856 self
._IdMapping
= {-1:-1}
862 Content
= open(str(self
.MetaFile
), 'r').readlines()
864 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
867 for Index
in range(0, len(Content
)):
868 Line
= CleanString(Content
[Index
])
873 self
._CurrentLine
= Line
874 self
._LineIndex
= Index
875 if self
._InSubsection
and self
._Owner
[-1] == -1:
876 self
._Owner
.append(self
._LastItem
)
879 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
880 self
._SectionType
= MODEL_META_DATA_SECTION_HEADER
882 elif Line
[0] == '}' and self
._InSubsection
:
883 self
._InSubsection
= False
884 self
._SubsectionType
= MODEL_UNKNOWN
885 self
._SubsectionName
= ''
890 elif Line
[0] == TAB_OPTION_START
and Line
[-1] == TAB_OPTION_END
:
891 self
._SubsectionType
= MODEL_META_DATA_SUBSECTION_HEADER
894 self
._DirectiveParser
()
897 if self
._InSubsection
:
898 SectionType
= self
._SubsectionType
900 SectionType
= self
._SectionType
901 self
._ItemType
= SectionType
903 self
._ValueList
= ['', '', '']
904 self
._SectionParser
[SectionType
](self
)
905 if self
._ValueList
== None:
908 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
909 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
911 for Arch
, ModuleType
in self
._Scope
:
912 Owner
= self
._Owner
[-1]
913 if self
._SubsectionType
!= MODEL_UNKNOWN
:
914 Owner
= OwnerId
[Arch
]
915 self
._LastItem
= self
._Store
(
930 if self
._SubsectionType
== MODEL_UNKNOWN
and self
._InSubsection
:
931 OwnerId
[Arch
] = self
._LastItem
933 if self
._DirectiveStack
:
934 Type
, Line
, Text
= self
._DirectiveStack
[-1]
935 EdkLogger
.error('Parser', FORMAT_INVALID
, "No matching '!endif' found",
936 ExtraData
=Text
, File
=self
.MetaFile
, Line
=Line
)
939 ## <subsection_header> parser
940 def _SubsectionHeaderParser(self
):
941 self
._SubsectionName
= self
._CurrentLine
[1:-1].upper()
942 if self
._SubsectionName
in self
.DataType
:
943 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
945 self
._SubsectionType
= MODEL_UNKNOWN
946 EdkLogger
.warn("Parser", "Unrecognized sub-section", File
=self
.MetaFile
,
947 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
948 self
._ValueList
[0] = self
._SubsectionName
950 ## Directive statement parser
951 def _DirectiveParser(self
):
952 self
._ValueList
= ['', '', '']
953 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
954 self
._ValueList
[0:len(TokenList
)] = TokenList
957 DirectiveName
= self
._ValueList
[0].upper()
958 if DirectiveName
not in self
.DataType
:
959 EdkLogger
.error("Parser", FORMAT_INVALID
, "Unknown directive [%s]" % DirectiveName
,
960 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
962 if DirectiveName
in ['!IF', '!IFDEF', '!IFNDEF']:
963 self
._InDirective
+= 1
965 if DirectiveName
in ['!ENDIF']:
966 self
._InDirective
-= 1
968 if DirectiveName
in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self
._ValueList
[1] == '':
969 EdkLogger
.error("Parser", FORMAT_INVALID
, "Missing expression",
970 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
971 ExtraData
=self
._CurrentLine
)
973 ItemType
= self
.DataType
[DirectiveName
]
974 Scope
= [['COMMON', 'COMMON']]
975 if ItemType
== MODEL_META_DATA_INCLUDE
:
977 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
978 # Remove all directives between !if and !endif, including themselves
979 while self
._DirectiveStack
:
980 # Remove any !else or !elseif
981 DirectiveInfo
= self
._DirectiveStack
.pop()
982 if DirectiveInfo
[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
983 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
984 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
987 EdkLogger
.error("Parser", FORMAT_INVALID
, "Redundant '!endif'",
988 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
989 ExtraData
=self
._CurrentLine
)
990 elif ItemType
!= MODEL_META_DATA_INCLUDE
:
991 # Break if there's a !else is followed by a !elseif
992 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
and \
993 self
._DirectiveStack
and \
994 self
._DirectiveStack
[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
995 EdkLogger
.error("Parser", FORMAT_INVALID
, "'!elseif' after '!else'",
996 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
997 ExtraData
=self
._CurrentLine
)
998 self
._DirectiveStack
.append((ItemType
, self
._LineIndex
+ 1, self
._CurrentLine
))
1000 EdkLogger
.error('Parser', FORMAT_INVALID
,
1001 "No '!include' allowed in included file",
1002 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
,
1003 Line
=self
._LineIndex
+ 1)
1006 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
1007 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
1009 for Arch
, ModuleType
in Scope
:
1010 self
._LastItem
= self
._Store
(
1019 self
._LineIndex
+ 1,
1021 self
._LineIndex
+ 1,
1026 ## [defines] section parser
1028 def _DefineParser(self
):
1029 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1030 self
._ValueList
[1:len(TokenList
)] = TokenList
1033 if not self
._ValueList
[1]:
1034 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
1035 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1036 if not self
._ValueList
[2]:
1037 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
1038 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1039 if not self
._ValueList
[1] in self
.DefineKeywords
:
1040 EdkLogger
.error('Parser', FORMAT_INVALID
,
1041 "Unknown keyword found: %s. "
1042 "If this is a macro you must "
1043 "add it as a DEFINE in the DSC" % self
._ValueList
[1],
1044 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1045 self
._Defines
[self
._ValueList
[1]] = self
._ValueList
[2]
1046 self
._ItemType
= self
.DataType
[TAB_DSC_DEFINES
.upper()]
1049 def _SkuIdParser(self
):
1050 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1051 if len(TokenList
) != 2:
1052 EdkLogger
.error('Parser', FORMAT_INVALID
, "Correct format is '<Integer>|<UiName>'",
1053 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1054 self
._ValueList
[0:len(TokenList
)] = TokenList
1056 ## Parse Edk style of library modules
1058 def _LibraryInstanceParser(self
):
1059 self
._ValueList
[0] = self
._CurrentLine
1061 ## PCD sections parser
1063 # [PcdsFixedAtBuild]
1064 # [PcdsPatchableInModule]
1067 # [PcdsDynamicExDefault]
1068 # [PcdsDynamicExVpd]
1069 # [PcdsDynamicExHii]
1071 # [PcdsDynamicDefault]
1076 def _PcdParser(self
):
1077 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1078 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1079 if len(TokenList
) == 2:
1080 self
._ValueList
[2] = TokenList
[1]
1081 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1082 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1083 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1084 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1085 if self
._ValueList
[2] == '':
1087 # The PCD values are optional for FIXEDATBUILD and PATCHABLEINMODULE
1089 if self
._SectionType
in (MODEL_PCD_FIXED_AT_BUILD
, MODEL_PCD_PATCHABLE_IN_MODULE
):
1091 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD value given",
1092 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1093 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1095 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD
1096 ValueList
= GetSplitValueList(self
._ValueList
[2])
1097 if len(ValueList
) > 1 and ValueList
[1] != TAB_VOID \
1098 and self
._ItemType
in [MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_EX_DEFAULT
]:
1099 EdkLogger
.error('Parser', FORMAT_INVALID
, "The datum type '%s' of PCD is wrong" % ValueList
[1],
1100 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1102 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1103 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
1104 if DscPcdValueList
[0] in ['True', 'true', 'TRUE']:
1105 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '1', 1);
1106 elif DscPcdValueList
[0] in ['False', 'false', 'FALSE']:
1107 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '0', 1);
1110 ## [components] section parser
1112 def _ComponentParser(self
):
1113 if self
._CurrentLine
[-1] == '{':
1114 self
._ValueList
[0] = self
._CurrentLine
[0:-1].strip()
1115 self
._InSubsection
= True
1117 self
._ValueList
[0] = self
._CurrentLine
1119 ## [LibraryClasses] section
1121 def _LibraryClassParser(self
):
1122 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1123 if len(TokenList
) < 2:
1124 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class or instance specified",
1125 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1126 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1127 if TokenList
[0] == '':
1128 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class specified",
1129 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1130 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1131 if TokenList
[1] == '':
1132 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library instance specified",
1133 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1134 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1136 self
._ValueList
[0:len(TokenList
)] = TokenList
1138 def _CompponentSourceOverridePathParser(self
):
1139 self
._ValueList
[0] = self
._CurrentLine
1141 ## [BuildOptions] section parser
1143 def _BuildOptionParser(self
):
1144 self
._CurrentLine
= CleanString(self
._CurrentLine
, BuildOption
=True)
1145 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1146 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
1147 if len(TokenList2
) == 2:
1148 self
._ValueList
[0] = TokenList2
[0] # toolchain family
1149 self
._ValueList
[1] = TokenList2
[1] # keys
1151 self
._ValueList
[1] = TokenList
[0]
1152 if len(TokenList
) == 2: # value
1153 self
._ValueList
[2] = TokenList
[1]
1155 if self
._ValueList
[1].count('_') != 4:
1159 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
1160 ExtraData
=self
._CurrentLine
,
1162 Line
=self
._LineIndex
+ 1
1165 ## Override parent's method since we'll do all macro replacements in parser
1166 def _GetMacros(self
):
1168 Macros
.update(self
._FileLocalMacros
)
1169 Macros
.update(self
._GetApplicableSectionMacro
())
1170 Macros
.update(GlobalData
.gEdkGlobal
)
1171 Macros
.update(GlobalData
.gPlatformDefines
)
1172 Macros
.update(GlobalData
.gCommandLineDefines
)
1173 # PCD cannot be referenced in macro definition
1174 if self
._ItemType
not in [MODEL_META_DATA_DEFINE
, MODEL_META_DATA_GLOBAL_DEFINE
]:
1175 Macros
.update(self
._Symbols
)
1178 def _PostProcess(self
):
1180 MODEL_META_DATA_SECTION_HEADER
: self
.__ProcessSectionHeader
,
1181 MODEL_META_DATA_SUBSECTION_HEADER
: self
.__ProcessSubsectionHeader
,
1182 MODEL_META_DATA_HEADER
: self
.__ProcessDefine
,
1183 MODEL_META_DATA_DEFINE
: self
.__ProcessDefine
,
1184 MODEL_META_DATA_GLOBAL_DEFINE
: self
.__ProcessDefine
,
1185 MODEL_META_DATA_INCLUDE
: self
.__ProcessDirective
,
1186 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
: self
.__ProcessDirective
,
1187 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
: self
.__ProcessDirective
,
1188 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
: self
.__ProcessDirective
,
1189 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
: self
.__ProcessDirective
,
1190 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
: self
.__ProcessDirective
,
1191 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
: self
.__ProcessDirective
,
1192 MODEL_EFI_SKU_ID
: self
.__ProcessSkuId
,
1193 MODEL_EFI_LIBRARY_INSTANCE
: self
.__ProcessLibraryInstance
,
1194 MODEL_EFI_LIBRARY_CLASS
: self
.__ProcessLibraryClass
,
1195 MODEL_PCD_FIXED_AT_BUILD
: self
.__ProcessPcd
,
1196 MODEL_PCD_PATCHABLE_IN_MODULE
: self
.__ProcessPcd
,
1197 MODEL_PCD_FEATURE_FLAG
: self
.__ProcessPcd
,
1198 MODEL_PCD_DYNAMIC_DEFAULT
: self
.__ProcessPcd
,
1199 MODEL_PCD_DYNAMIC_HII
: self
.__ProcessPcd
,
1200 MODEL_PCD_DYNAMIC_VPD
: self
.__ProcessPcd
,
1201 MODEL_PCD_DYNAMIC_EX_DEFAULT
: self
.__ProcessPcd
,
1202 MODEL_PCD_DYNAMIC_EX_HII
: self
.__ProcessPcd
,
1203 MODEL_PCD_DYNAMIC_EX_VPD
: self
.__ProcessPcd
,
1204 MODEL_META_DATA_COMPONENT
: self
.__ProcessComponent
,
1205 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: self
.__ProcessSourceOverridePath
,
1206 MODEL_META_DATA_BUILD_OPTION
: self
.__ProcessBuildOption
,
1207 MODEL_UNKNOWN
: self
._Skip
,
1208 MODEL_META_DATA_USER_EXTENSION
: self
._Skip
,
1211 self
._Table
= MetaFileStorage(self
._RawTable
.Cur
, self
.MetaFile
, MODEL_FILE_DSC
, True)
1212 self
._Table
.Create()
1213 self
._DirectiveStack
= []
1214 self
._DirectiveEvalStack
= []
1215 self
._FileWithError
= self
.MetaFile
1216 self
._FileLocalMacros
= {}
1217 self
._SectionsMacroDict
= {}
1218 GlobalData
.gPlatformDefines
= {}
1220 # Get all macro and PCD which has straitforward value
1221 self
.__RetrievePcdValue
()
1222 self
._Content
= self
._RawTable
.GetAll()
1223 self
._ContentIndex
= 0
1224 while self
._ContentIndex
< len(self
._Content
) :
1225 Id
, self
._ItemType
, V1
, V2
, V3
, S1
, S2
, Owner
, self
._From
, \
1226 LineStart
, ColStart
, LineEnd
, ColEnd
, Enabled
= self
._Content
[self
._ContentIndex
]
1229 self
._FileWithError
= self
.MetaFile
1231 self
._ContentIndex
+= 1
1233 self
._Scope
= [[S1
, S2
]]
1235 # For !include directive, handle it specially,
1236 # merge arch and module type in case of duplicate items
1238 while self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1239 if self
._ContentIndex
>= len(self
._Content
):
1241 Record
= self
._Content
[self
._ContentIndex
]
1242 if LineStart
== Record
[9] and LineEnd
== Record
[11]:
1243 if [Record
[5], Record
[6]] not in self
._Scope
:
1244 self
._Scope
.append([Record
[5], Record
[6]])
1245 self
._ContentIndex
+= 1
1249 self
._LineIndex
= LineStart
- 1
1250 self
._ValueList
= [V1
, V2
, V3
]
1253 Processer
[self
._ItemType
]()
1254 except EvaluationException
, Excpt
:
1256 # Only catch expression evaluation error here. We need to report
1257 # the precise number of line on which the error occurred
1259 if hasattr(Excpt
, 'Pcd'):
1260 if Excpt
.Pcd
in GlobalData
.gPlatformOtherPcds
:
1261 Info
= GlobalData
.gPlatformOtherPcds
[Excpt
.Pcd
]
1262 EdkLogger
.error('Parser', FORMAT_INVALID
, "Cannot use this PCD (%s) in an expression as"
1263 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
1264 " of the DSC file, and it is currently defined in this section:"
1265 " %s, line #: %d." % (Excpt
.Pcd
, Info
[0], Info
[1]),
1266 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1267 Line
=self
._LineIndex
+ 1)
1269 EdkLogger
.error('Parser', FORMAT_INVALID
, "PCD (%s) is not defined in DSC file" % Excpt
.Pcd
,
1270 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1271 Line
=self
._LineIndex
+ 1)
1273 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid expression: %s" % str(Excpt
),
1274 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1275 Line
=self
._LineIndex
+ 1)
1276 except MacroException
, Excpt
:
1277 EdkLogger
.error('Parser', FORMAT_INVALID
, str(Excpt
),
1278 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1279 Line
=self
._LineIndex
+ 1)
1281 if self
._ValueList
== None:
1284 NewOwner
= self
._IdMapping
.get(Owner
, -1)
1285 self
._Enabled
= int((not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
))
1286 self
._LastItem
= self
._Store
(
1295 self
._LineIndex
+ 1,
1297 self
._LineIndex
+ 1,
1301 self
._IdMapping
[Id
] = self
._LastItem
1303 GlobalData
.gPlatformDefines
.update(self
._FileLocalMacros
)
1304 self
._PostProcessed
= True
1305 self
._Content
= None
1307 def __ProcessSectionHeader(self
):
1308 self
._SectionName
= self
._ValueList
[0]
1309 if self
._SectionName
in self
.DataType
:
1310 self
._SectionType
= self
.DataType
[self
._SectionName
]
1312 self
._SectionType
= MODEL_UNKNOWN
1314 def __ProcessSubsectionHeader(self
):
1315 self
._SubsectionName
= self
._ValueList
[0]
1316 if self
._SubsectionName
in self
.DataType
:
1317 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
1319 self
._SubsectionType
= MODEL_UNKNOWN
1321 def __RetrievePcdValue(self
):
1322 Records
= self
._RawTable
.Query(MODEL_PCD_FEATURE_FLAG
, BelongsToItem
= -1.0)
1323 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1324 Name
= TokenSpaceGuid
+ '.' + PcdName
1325 ValList
, Valid
, Index
= AnalyzeDscPcd(Value
, MODEL_PCD_FEATURE_FLAG
)
1326 self
._Symbols
[Name
] = ValList
[Index
]
1328 Records
= self
._RawTable
.Query(MODEL_PCD_FIXED_AT_BUILD
, BelongsToItem
= -1.0)
1329 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1330 Name
= TokenSpaceGuid
+ '.' + PcdName
1331 ValList
, Valid
, Index
= AnalyzeDscPcd(Value
, MODEL_PCD_FIXED_AT_BUILD
)
1332 self
._Symbols
[Name
] = ValList
[Index
]
1334 Content
= open(str(self
.MetaFile
), 'r').readlines()
1335 GlobalData
.gPlatformOtherPcds
['DSCFILE'] = str(self
.MetaFile
)
1336 for PcdType
in (MODEL_PCD_PATCHABLE_IN_MODULE
, MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_HII
,
1337 MODEL_PCD_DYNAMIC_VPD
, MODEL_PCD_DYNAMIC_EX_DEFAULT
, MODEL_PCD_DYNAMIC_EX_HII
,
1338 MODEL_PCD_DYNAMIC_EX_VPD
):
1339 Records
= self
._RawTable
.Query(PcdType
, BelongsToItem
= -1.0)
1340 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1341 Name
= TokenSpaceGuid
+ '.' + PcdName
1342 if Name
not in GlobalData
.gPlatformOtherPcds
:
1344 while not Content
[Line
- 1].lstrip().startswith(TAB_SECTION_START
):
1346 GlobalData
.gPlatformOtherPcds
[Name
] = (CleanString(Content
[Line
- 1]), PcdLine
, PcdType
)
1348 def __ProcessDefine(self
):
1349 if not self
._Enabled
:
1352 Type
, Name
, Value
= self
._ValueList
1353 Value
= ReplaceMacro(Value
, self
._Macros
, False)
1354 if self
._ItemType
== MODEL_META_DATA_DEFINE
:
1355 if self
._SectionType
== MODEL_META_DATA_HEADER
:
1356 self
._FileLocalMacros
[Name
] = Value
1358 self
._ConstructSectionMacroDict
(Name
, Value
)
1359 elif self
._ItemType
== MODEL_META_DATA_GLOBAL_DEFINE
:
1360 GlobalData
.gEdkGlobal
[Name
] = Value
1363 # Keyword in [Defines] section can be used as Macros
1365 if (self
._ItemType
== MODEL_META_DATA_HEADER
) and (self
._SectionType
== MODEL_META_DATA_HEADER
):
1366 self
._FileLocalMacros
[Name
] = Value
1368 self
._ValueList
= [Type
, Name
, Value
]
1370 def __ProcessDirective(self
):
1372 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1373 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
]:
1374 Macros
= self
._Macros
1375 Macros
.update(GlobalData
.gGlobalDefines
)
1377 Result
= ValueExpression(self
._ValueList
[1], Macros
)()
1378 except SymbolNotFound
, Exc
:
1379 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1381 except WrnExpression
, Excpt
:
1383 # Catch expression evaluation warning here. We need to report
1384 # the precise number of line and return the evaluation result
1386 EdkLogger
.warn('Parser', "Suspicious expression: %s" % str(Excpt
),
1387 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1388 Line
=self
._LineIndex
+ 1)
1389 Result
= Excpt
.result
1391 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1392 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1393 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1394 self
._DirectiveStack
.append(self
._ItemType
)
1395 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
:
1396 Result
= bool(Result
)
1398 Macro
= self
._ValueList
[1]
1399 Macro
= Macro
[2:-1] if (Macro
.startswith("$(") and Macro
.endswith(")")) else Macro
1400 Result
= Macro
in self
._Macros
1401 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
:
1403 self
._DirectiveEvalStack
.append(Result
)
1404 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
:
1405 self
._DirectiveStack
.append(self
._ItemType
)
1406 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1407 self
._DirectiveEvalStack
.append(bool(Result
))
1408 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1409 self
._DirectiveStack
.append(self
._ItemType
)
1410 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1411 self
._DirectiveEvalStack
.append(True)
1412 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1413 # Back to the nearest !if/!ifdef/!ifndef
1414 while self
._DirectiveStack
:
1415 self
._DirectiveEvalStack
.pop()
1416 Directive
= self
._DirectiveStack
.pop()
1417 if Directive
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1418 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1419 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1421 elif self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1422 # The included file must be relative to workspace or same directory as DSC file
1423 __IncludeMacros
= {}
1425 # Allow using system environment variables in path after !include
1427 __IncludeMacros
['WORKSPACE'] = GlobalData
.gGlobalDefines
['WORKSPACE']
1428 if "ECP_SOURCE" in GlobalData
.gGlobalDefines
.keys():
1429 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gGlobalDefines
['ECP_SOURCE']
1431 # During GenFds phase call DSC parser, will go into this branch.
1433 elif "ECP_SOURCE" in GlobalData
.gCommandLineDefines
.keys():
1434 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gCommandLineDefines
['ECP_SOURCE']
1436 __IncludeMacros
['EFI_SOURCE'] = GlobalData
.gGlobalDefines
['EFI_SOURCE']
1437 __IncludeMacros
['EDK_SOURCE'] = GlobalData
.gGlobalDefines
['EDK_SOURCE']
1439 # Allow using MACROs comes from [Defines] section to keep compatible.
1441 __IncludeMacros
.update(self
._Macros
)
1443 IncludedFile
= NormPath(ReplaceMacro(self
._ValueList
[1], __IncludeMacros
, RaiseError
=True))
1445 # First search the include file under the same directory as DSC file
1447 IncludedFile1
= PathClass(IncludedFile
, self
.MetaFile
.Dir
)
1448 ErrorCode
, ErrorInfo1
= IncludedFile1
.Validate()
1451 # Also search file under the WORKSPACE directory
1453 IncludedFile1
= PathClass(IncludedFile
, GlobalData
.gWorkspace
)
1454 ErrorCode
, ErrorInfo2
= IncludedFile1
.Validate()
1456 EdkLogger
.error('parser', ErrorCode
, File
=self
._FileWithError
,
1457 Line
=self
._LineIndex
+ 1, ExtraData
=ErrorInfo1
+ "\n" + ErrorInfo2
)
1459 self
._FileWithError
= IncludedFile1
1461 IncludedFileTable
= MetaFileStorage(self
._Table
.Cur
, IncludedFile1
, MODEL_FILE_DSC
, False)
1462 Owner
= self
._Content
[self
._ContentIndex
- 1][0]
1463 Parser
= DscParser(IncludedFile1
, self
._FileType
, IncludedFileTable
,
1464 Owner
=Owner
, From
=Owner
)
1466 # set the parser status with current status
1467 Parser
._SectionName
= self
._SectionName
1468 Parser
._SectionType
= self
._SectionType
1469 Parser
._Scope
= self
._Scope
1470 Parser
._Enabled
= self
._Enabled
1471 # Parse the included file
1474 # update current status with sub-parser's status
1475 self
._SectionName
= Parser
._SectionName
1476 self
._SectionType
= Parser
._SectionType
1477 self
._Scope
= Parser
._Scope
1478 self
._Enabled
= Parser
._Enabled
1480 # Insert all records in the table for the included file into dsc file table
1481 Records
= IncludedFileTable
.GetAll()
1483 self
._Content
[self
._ContentIndex
:self
._ContentIndex
] = Records
1484 self
._Content
.pop(self
._ContentIndex
- 1)
1485 self
._ValueList
= None
1486 self
._ContentIndex
-= 1
1488 def __ProcessSkuId(self
):
1489 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=True)
1490 for Value
in self
._ValueList
]
1492 def __ProcessLibraryInstance(self
):
1493 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
1495 def __ProcessLibraryClass(self
):
1496 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, RaiseError
=True)
1498 def __ProcessPcd(self
):
1499 if self
._ItemType
not in [MODEL_PCD_FEATURE_FLAG
, MODEL_PCD_FIXED_AT_BUILD
]:
1500 self
._ValueList
[2] = ReplaceMacro(self
._ValueList
[2], self
._Macros
, RaiseError
=True)
1503 ValList
, Valid
, Index
= AnalyzeDscPcd(self
._ValueList
[2], self
._ItemType
)
1505 EdkLogger
.error('build', FORMAT_INVALID
, "Pcd format incorrect.", File
=self
._FileWithError
, Line
=self
._LineIndex
+1,
1506 ExtraData
="%s.%s|%s" % (self
._ValueList
[0], self
._ValueList
[1], self
._ValueList
[2]))
1507 PcdValue
= ValList
[Index
]
1510 ValList
[Index
] = ValueExpression(PcdValue
, self
._Macros
)(True)
1511 except WrnExpression
, Value
:
1512 ValList
[Index
] = Value
.result
1514 if ValList
[Index
] == 'True':
1515 ValList
[Index
] = '1'
1516 if ValList
[Index
] == 'False':
1517 ValList
[Index
] = '0'
1519 GlobalData
.gPlatformPcds
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = PcdValue
1520 self
._ValueList
[2] = '|'.join(ValList
)
1522 def __ProcessComponent(self
):
1523 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1525 def __ProcessSourceOverridePath(self
):
1526 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1528 def __ProcessBuildOption(self
):
1529 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=False)
1530 for Value
in self
._ValueList
]
1533 MODEL_META_DATA_HEADER
: _DefineParser
,
1534 MODEL_EFI_SKU_ID
: _SkuIdParser
,
1535 MODEL_EFI_LIBRARY_INSTANCE
: _LibraryInstanceParser
,
1536 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
1537 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1538 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1539 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1540 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
1541 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
1542 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
1543 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
1544 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
1545 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
1546 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
1547 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: _CompponentSourceOverridePathParser
,
1548 MODEL_META_DATA_BUILD_OPTION
: _BuildOptionParser
,
1549 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1550 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1551 MODEL_META_DATA_SECTION_HEADER
: MetaFileParser
._SectionHeaderParser
,
1552 MODEL_META_DATA_SUBSECTION_HEADER
: _SubsectionHeaderParser
,
1555 _Macros
= property(_GetMacros
)
1557 ## DEC file parser class
1559 # @param FilePath The path of platform description file
1560 # @param FileType The raw data of DSC file
1561 # @param Table Database used to retrieve module/package information
1562 # @param Macros Macros used for replacement in file
1564 class DecParser(MetaFileParser
):
1565 # DEC file supported data types (one type per section)
1567 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1568 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
1569 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1570 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1571 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1572 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1573 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1574 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1575 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1576 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1577 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1578 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1581 ## Constructor of DecParser
1583 # Initialize object of DecParser
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 def __init__(self
, FilePath
, FileType
, Table
):
1591 # prevent re-initialization
1592 if hasattr(self
, "_Table"):
1594 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, -1)
1596 self
._Version
= 0x00010005 # Only EDK2 dec file is supported
1597 self
._AllPCDs
= [] # Only for check duplicate PCD
1603 Content
= open(str(self
.MetaFile
), 'r').readlines()
1605 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1607 for Index
in range(0, len(Content
)):
1608 Line
, Comment
= CleanString2(Content
[Index
])
1609 self
._CurrentLine
= Line
1610 self
._LineIndex
= Index
1612 # save comment for later use
1614 self
._Comments
.append((Comment
, self
._LineIndex
+ 1))
1620 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1621 self
._SectionHeaderParser
()
1624 elif len(self
._SectionType
) == 0:
1629 self
._ValueList
= ['', '', '']
1630 self
._SectionParser
[self
._SectionType
[0]](self
)
1631 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
1637 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1638 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1640 for Arch
, ModuleType
, Type
in self
._Scope
:
1641 self
._LastItem
= self
._Store
(
1649 self
._LineIndex
+ 1,
1651 self
._LineIndex
+ 1,
1655 for Comment
, LineNo
in self
._Comments
:
1657 MODEL_META_DATA_COMMENT
,
1674 ## Section header parser
1676 # The section header is always in following format:
1678 # [section_name.arch<.platform|module_type>]
1680 def _SectionHeaderParser(self
):
1682 self
._SectionName
= ''
1683 self
._SectionType
= []
1685 Line
= self
._CurrentLine
.replace("%s%s" % (TAB_COMMA_SPLIT
, TAB_SPACE_SPLIT
), TAB_COMMA_SPLIT
)
1686 for Item
in Line
[1:-1].split(TAB_COMMA_SPLIT
):
1688 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
,
1689 "section name can NOT be empty or incorrectly use separator comma",
1690 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1691 ItemList
= Item
.split(TAB_SPLIT
)
1693 # different types of PCD are permissible in one section
1694 self
._SectionName
= ItemList
[0].upper()
1695 if self
._SectionName
in self
.DataType
:
1696 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1697 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1699 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
1700 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1702 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1706 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1708 Line
=self
._LineIndex
+ 1,
1709 ExtraData
=self
._CurrentLine
1712 if len(ItemList
) > 1:
1713 S1
= ItemList
[1].upper()
1717 # S2 may be Platform or ModuleType
1718 if len(ItemList
) > 2:
1719 S2
= ItemList
[2].upper()
1722 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1723 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1725 # 'COMMON' must not be used with specific ARCHs at the same section
1726 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1727 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1728 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
1730 ## [guids], [ppis] and [protocols] section parser
1732 def _GuidParser(self
):
1733 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1734 if len(TokenList
) < 2:
1735 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1736 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1737 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1738 if TokenList
[0] == '':
1739 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1740 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1741 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1742 if TokenList
[1] == '':
1743 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1744 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1745 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1746 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1747 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1748 ExtraData
=self
._CurrentLine
+ \
1749 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1750 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1751 self
._ValueList
[0] = TokenList
[0]
1752 self
._ValueList
[1] = TokenList
[1]
1754 ## PCD sections parser
1756 # [PcdsFixedAtBuild]
1757 # [PcdsPatchableInModule]
1763 def _PcdParser(self
):
1764 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1765 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1766 ValueRe
= re
.compile(r
'^[a-zA-Z_][a-zA-Z0-9_]*')
1767 # check PCD information
1768 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1769 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1770 ExtraData
=self
._CurrentLine
+ \
1771 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1772 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1773 # check format of token space GUID CName
1774 if not ValueRe
.match(self
._ValueList
[0]):
1775 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_]*'",
1776 ExtraData
=self
._CurrentLine
+ \
1777 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1778 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1779 # check format of PCD CName
1780 if not ValueRe
.match(self
._ValueList
[1]):
1781 EdkLogger
.error('Parser', FORMAT_INVALID
, "The format of the PCD 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 PCD datum information
1786 if len(TokenList
) < 2 or TokenList
[1] == '':
1787 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1788 ExtraData
=self
._CurrentLine
+ \
1789 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1790 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1793 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1794 PtrValue
= ValueRe
.findall(TokenList
[1])
1796 # Has VOID* type string, may contain "|" character in the string.
1797 if len(PtrValue
) != 0:
1798 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1799 ValueList
= GetSplitValueList(ptrValueList
)
1800 ValueList
[0] = PtrValue
[0]
1802 ValueList
= GetSplitValueList(TokenList
[1])
1805 # check if there's enough datum information given
1806 if len(ValueList
) != 3:
1807 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1808 ExtraData
=self
._CurrentLine
+ \
1809 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1810 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1811 # check default value
1812 if ValueList
[0] == '':
1813 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1814 ExtraData
=self
._CurrentLine
+ \
1815 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1816 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1818 if ValueList
[1] == '':
1819 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1820 ExtraData
=self
._CurrentLine
+ \
1821 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1822 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1823 # check token of the PCD
1824 if ValueList
[2] == '':
1825 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1826 ExtraData
=self
._CurrentLine
+ \
1827 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1828 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1829 # check format of default value against the datum type
1830 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1832 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1833 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1835 if ValueList
[0] in ['True', 'true', 'TRUE']:
1837 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1840 # check for duplicate PCD definition
1841 if (self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]) in self
._AllPCDs
:
1842 EdkLogger
.error('Parser', FORMAT_INVALID
,
1843 "The same PCD name and GUID have been already defined",
1844 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1846 self
._AllPCDs
.append((self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]))
1848 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
1851 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
1852 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
1853 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
1854 MODEL_EFI_GUID
: _GuidParser
,
1855 MODEL_EFI_PPI
: _GuidParser
,
1856 MODEL_EFI_PROTOCOL
: _GuidParser
,
1857 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1858 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1859 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1860 MODEL_PCD_DYNAMIC
: _PcdParser
,
1861 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
1862 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1863 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1868 # This acts like the main() function for the script, unless it is 'import'ed into another
1871 if __name__
== '__main__':