2 # This file is used to parse meta files
4 # Copyright (c) 2008 - 2017, Intel Corporation. All rights reserved.<BR>
5 # (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
6 # This program and the accompanying materials
7 # are licensed and made available under the terms and conditions of the BSD License
8 # which accompanies this distribution. The full text of the license may be found at
9 # http://opensource.org/licenses/bsd-license.php
11 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 import Common
.LongFilePathOs
as os
24 import Common
.EdkLogger
as EdkLogger
25 import Common
.GlobalData
as GlobalData
27 from CommonDataClass
.DataClass
import *
28 from Common
.DataType
import *
29 from Common
.String
import *
30 from Common
.Misc
import GuidStructureStringToGuidString
, CheckPcdDatum
, PathClass
, AnalyzePcdData
, AnalyzeDscPcd
, AnalyzePcdExpression
31 from Common
.Expression
import *
32 from CommonDataClass
.Exceptions
import *
33 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
35 from MetaFileTable
import MetaFileStorage
36 from MetaFileCommentParser
import CheckInfComment
38 ## A decorator used to parse macro definition
39 def ParseMacro(Parser
):
40 def MacroParser(self
):
41 Match
= gMacroDefPattern
.match(self
._CurrentLine
)
43 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
47 TokenList
= GetSplitValueList(self
._CurrentLine
[Match
.end(1):], TAB_EQUAL_SPLIT
, 1)
50 EdkLogger
.error('Parser', FORMAT_INVALID
, "No macro name given",
51 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
52 if len(TokenList
) < 2:
56 Name
, Value
= TokenList
57 # Global macros can be only defined via environment variable
58 if Name
in GlobalData
.gGlobalDefines
:
59 EdkLogger
.error('Parser', FORMAT_INVALID
, "%s can only be defined via environment variable" % Name
,
60 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
61 # Only upper case letters, digit and '_' are allowed
62 if not gMacroNamePattern
.match(Name
):
63 EdkLogger
.error('Parser', FORMAT_INVALID
, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
64 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
66 Value
= ReplaceMacro(Value
, self
._Macros
)
67 if Type
in self
.DataType
:
68 self
._ItemType
= self
.DataType
[Type
]
70 self
._ItemType
= MODEL_META_DATA_DEFINE
71 # DEFINE defined macros
72 if Type
== TAB_DSC_DEFINES_DEFINE
:
74 # First judge whether this DEFINE is in conditional directive statements or not.
76 if type(self
) == DscParser
and self
._InDirective
> -1:
79 if type(self
) == DecParser
:
80 if MODEL_META_DATA_HEADER
in self
._SectionType
:
81 self
._FileLocalMacros
[Name
] = Value
83 self
._ConstructSectionMacroDict
(Name
, Value
)
84 elif self
._SectionType
== MODEL_META_DATA_HEADER
:
85 self
._FileLocalMacros
[Name
] = Value
87 self
._ConstructSectionMacroDict
(Name
, Value
)
89 # EDK_GLOBAL defined macros
90 elif type(self
) != DscParser
:
91 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used in .dsc file",
92 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
93 elif self
._SectionType
!= MODEL_META_DATA_HEADER
:
94 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used under [Defines] section",
95 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
96 elif (Name
in self
._FileLocalMacros
) and (self
._FileLocalMacros
[Name
] != Value
):
97 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
98 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
100 self
._ValueList
= [Type
, Name
, Value
]
104 ## Base class of parser
106 # This class is used for derivation purpose. The specific parser for one kind
107 # type file must derive this class and implement some public interfaces.
109 # @param FilePath The path of platform description file
110 # @param FileType The raw data of DSC file
111 # @param Table Database used to retrieve module/package information
112 # @param Macros Macros used for replacement in file
113 # @param Owner Owner ID (for sub-section parsing)
114 # @param From ID from which the data comes (for !INCLUDE directive)
116 class MetaFileParser(object):
117 # data type (file content) for specific file type
120 # Parser objects used to implement singleton
125 # One file, one parser object. This factory method makes sure that there's
126 # only one object constructed for one meta file.
128 # @param Class class object of real AutoGen class
129 # (InfParser, DecParser or DscParser)
130 # @param FilePath The path of meta file
131 # @param *args The specific class related parameters
132 # @param **kwargs The specific class related dict parameters
134 def __new__(Class
, FilePath
, *args
, **kwargs
):
135 if FilePath
in Class
.MetaFiles
:
136 return Class
.MetaFiles
[FilePath
]
138 ParserObject
= super(MetaFileParser
, Class
).__new
__(Class
)
139 Class
.MetaFiles
[FilePath
] = ParserObject
142 ## Constructor of MetaFileParser
144 # Initialize object of MetaFileParser
146 # @param FilePath The path of platform description file
147 # @param FileType The raw data of DSC file
148 # @param Arch Default Arch value for filtering sections
149 # @param Table Database used to retrieve module/package information
150 # @param Owner Owner ID (for sub-section parsing)
151 # @param From ID from which the data comes (for !INCLUDE directive)
153 def __init__(self
, FilePath
, FileType
, Arch
, Table
, Owner
= -1, From
= -1):
155 self
._RawTable
= Table
157 self
._FileType
= FileType
158 self
.MetaFile
= FilePath
159 self
._FileDir
= self
.MetaFile
.Dir
161 self
._FileLocalMacros
= {}
162 self
._SectionsMacroDict
= {}
164 # for recursive parsing
165 self
._Owner
= [Owner
]
168 # parsr status for parsing
169 self
._ValueList
= ['', '', '', '', '']
172 self
._CurrentLine
= ''
173 self
._SectionType
= MODEL_UNKNOWN
174 self
._SectionName
= ''
175 self
._InSubsection
= False
176 self
._SubsectionType
= MODEL_UNKNOWN
177 self
._SubsectionName
= ''
178 self
._ItemType
= MODEL_UNKNOWN
181 self
._Finished
= False
182 self
._PostProcessed
= False
183 # Different version of meta-file has different way to parse.
186 ## Store the parsed data in table
187 def _Store(self
, *Args
):
188 return self
._Table
.Insert(*Args
)
190 ## Virtual method for starting parse
192 raise NotImplementedError
194 ## Notify a post-process is needed
195 def DoPostProcess(self
):
196 self
._PostProcessed
= False
198 ## Set parsing complete flag in both class and table
200 self
._Finished
= True
201 ## Do not set end flag when processing included files
203 self
._Table
.SetEndFlag()
205 def _PostProcess(self
):
206 self
._PostProcessed
= True
208 ## Get the parse complete flag
209 def _GetFinished(self
):
210 return self
._Finished
212 ## Set the complete flag
213 def _SetFinished(self
, Value
):
214 self
._Finished
= Value
216 ## Remove records that do not match given Filter Arch
217 def _FilterRecordList(self
, RecordList
, FilterArch
):
219 for Record
in RecordList
:
221 if Arch
== 'COMMON' or Arch
== FilterArch
:
222 NewRecordList
.append(Record
)
225 ## Use [] style to query data in table, just for readability
227 # DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]
229 def __getitem__(self
, DataInfo
):
230 if type(DataInfo
) != type(()):
231 DataInfo
= (DataInfo
,)
233 # Parse the file first, if necessary
234 if not self
._Finished
:
235 if self
._RawTable
.IsIntegrity():
236 self
._Finished
= True
238 self
._Table
= self
._RawTable
239 self
._PostProcessed
= False
242 # No specific ARCH or Platform given, use raw data
243 if self
._RawTable
and (len(DataInfo
) == 1 or DataInfo
[1] == None):
244 return self
._FilterRecordList
(self
._RawTable
.Query(*DataInfo
), self
._Arch
)
246 # Do post-process if necessary
247 if not self
._PostProcessed
:
250 return self
._FilterRecordList
(self
._Table
.Query(*DataInfo
), DataInfo
[1])
252 ## Data parser for the common format in different type of file
254 # The common format in the meatfile is like
259 def _CommonParser(self
):
260 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
261 self
._ValueList
[0:len(TokenList
)] = TokenList
263 ## Data parser for the format in which there's path
265 # Only path can have macro used. So we need to replace them before use.
268 def _PathParser(self
):
269 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
270 self
._ValueList
[0:len(TokenList
)] = TokenList
271 # Don't do macro replacement for dsc file at this point
272 if type(self
) != DscParser
:
273 Macros
= self
._Macros
274 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
276 ## Skip unsupported data
278 EdkLogger
.warn("Parser", "Unrecognized content", File
=self
.MetaFile
,
279 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
);
280 self
._ValueList
[0:1] = [self
._CurrentLine
]
282 ## Skip unsupported data for UserExtension Section
283 def _SkipUserExtension(self
):
284 self
._ValueList
[0:1] = [self
._CurrentLine
]
286 ## Section header parser
288 # The section header is always in following format:
290 # [section_name.arch<.platform|module_type>]
292 def _SectionHeaderParser(self
):
294 self
._SectionName
= ''
296 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
299 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
,2)
300 # different section should not mix in one section
301 if self
._SectionName
!= '' and self
._SectionName
!= ItemList
[0].upper():
302 EdkLogger
.error('Parser', FORMAT_INVALID
, "Different section names in the same section",
303 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
304 self
._SectionName
= ItemList
[0].upper()
305 if self
._SectionName
in self
.DataType
:
306 self
._SectionType
= self
.DataType
[self
._SectionName
]
307 # Check if the section name is valid
308 if self
._SectionName
not in SECTIONS_HAVE_ITEM_AFTER_ARCH
and len(ItemList
) > 3:
309 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
310 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
311 elif self
._Version
>= 0x00010005:
312 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
313 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
315 self
._SectionType
= MODEL_UNKNOWN
318 if len(ItemList
) > 1:
319 S1
= ItemList
[1].upper()
324 # S2 may be Platform or ModuleType
325 if len(ItemList
) > 2:
326 if self
._SectionName
.upper() in SECTIONS_HAVE_ITEM_PCD
:
329 S2
= ItemList
[2].upper()
332 self
._Scope
.append([S1
, S2
])
334 # 'COMMON' must not be used with specific ARCHs at the same section
335 if 'COMMON' in ArchList
and len(ArchList
) > 1:
336 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
337 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
338 # If the section information is needed later, it should be stored in database
339 self
._ValueList
[0] = self
._SectionName
341 ## [defines] section parser
343 def _DefineParser(self
):
344 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
345 self
._ValueList
[1:len(TokenList
)] = TokenList
346 if not self
._ValueList
[1]:
347 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
348 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
349 if not self
._ValueList
[2]:
350 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
351 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
353 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
354 Name
, Value
= self
._ValueList
[1], self
._ValueList
[2]
355 MacroUsed
= GlobalData
.gMacroRefPattern
.findall(Value
)
356 if len(MacroUsed
) != 0:
357 for Macro
in MacroUsed
:
358 if Macro
in GlobalData
.gGlobalDefines
:
359 EdkLogger
.error("Parser", FORMAT_INVALID
, "Global macro %s is not permitted." % (Macro
), ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
361 EdkLogger
.error("Parser", FORMAT_INVALID
, "%s not defined" % (Macro
), ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
362 # Sometimes, we need to make differences between EDK and EDK2 modules
363 if Name
== 'INF_VERSION':
364 if re
.match(r
'0[xX][\da-f-A-F]{5,8}', Value
):
365 self
._Version
= int(Value
, 0)
366 elif re
.match(r
'\d+\.\d+', Value
):
367 ValueList
= Value
.split('.')
368 Major
= '%04o' % int(ValueList
[0], 0)
369 Minor
= '%04o' % int(ValueList
[1], 0)
370 self
._Version
= int('0x' + Major
+ Minor
, 0)
372 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid version number",
373 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
375 if type(self
) == InfParser
and self
._Version
< 0x00010005:
376 # EDK module allows using defines as macros
377 self
._FileLocalMacros
[Name
] = Value
378 self
._Defines
[Name
] = Value
380 ## [BuildOptions] section parser
382 def _BuildOptionParser(self
):
383 self
._CurrentLine
= CleanString(self
._CurrentLine
, BuildOption
=True)
384 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
385 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
386 if len(TokenList2
) == 2:
387 self
._ValueList
[0] = TokenList2
[0] # toolchain family
388 self
._ValueList
[1] = TokenList2
[1] # keys
390 self
._ValueList
[1] = TokenList
[0]
391 if len(TokenList
) == 2 and type(self
) != DscParser
: # value
392 self
._ValueList
[2] = ReplaceMacro(TokenList
[1], self
._Macros
)
394 if self
._ValueList
[1].count('_') != 4:
398 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
399 ExtraData
=self
._CurrentLine
,
401 Line
=self
._LineIndex
+ 1
403 def GetValidExpression(self
, TokenSpaceGuid
, PcdCName
):
404 return self
._Table
.GetValidExpression(TokenSpaceGuid
, PcdCName
)
405 def _GetMacros(self
):
407 Macros
.update(self
._FileLocalMacros
)
408 Macros
.update(self
._GetApplicableSectionMacro
())
411 ## Construct section Macro dict
412 def _ConstructSectionMacroDict(self
, Name
, Value
):
413 ScopeKey
= [(Scope
[0], Scope
[1]) for Scope
in self
._Scope
]
414 ScopeKey
= tuple(ScopeKey
)
415 SectionDictKey
= self
._SectionType
, ScopeKey
417 # DecParser SectionType is a list, will contain more than one item only in Pcd Section
418 # As Pcd section macro usage is not alllowed, so here it is safe
420 if type(self
) == DecParser
:
421 SectionDictKey
= self
._SectionType
[0], ScopeKey
422 if SectionDictKey
not in self
._SectionsMacroDict
:
423 self
._SectionsMacroDict
[SectionDictKey
] = {}
424 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
425 SectionLocalMacros
[Name
] = Value
427 ## Get section Macros that are applicable to current line, which may come from other sections
428 ## that share the same name while scope is wider
429 def _GetApplicableSectionMacro(self
):
436 ActiveSectionType
= self
._SectionType
437 if type(self
) == DecParser
:
438 ActiveSectionType
= self
._SectionType
[0]
440 for (SectionType
, Scope
) in self
._SectionsMacroDict
:
441 if SectionType
!= ActiveSectionType
:
444 for ActiveScope
in self
._Scope
:
445 Scope0
, Scope1
= ActiveScope
[0], ActiveScope
[1]
446 if(Scope0
, Scope1
) not in Scope
:
449 SpeSpeMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
451 for ActiveScope
in self
._Scope
:
452 Scope0
, Scope1
= ActiveScope
[0], ActiveScope
[1]
453 if(Scope0
, Scope1
) not in Scope
and (Scope0
, "COMMON") not in Scope
and ("COMMON", Scope1
) not in Scope
:
456 ComSpeMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
458 if ("COMMON", "COMMON") in Scope
:
459 ComComMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
461 Macros
.update(ComComMacroDict
)
462 Macros
.update(ComSpeMacroDict
)
463 Macros
.update(SpeSpeMacroDict
)
468 Finished
= property(_GetFinished
, _SetFinished
)
469 _Macros
= property(_GetMacros
)
472 ## INF file parser class
474 # @param FilePath The path of platform description file
475 # @param FileType The raw data of DSC file
476 # @param Table Database used to retrieve module/package information
477 # @param Macros Macros used for replacement in file
479 class InfParser(MetaFileParser
):
480 # INF file supported data types (one type per section)
482 TAB_UNKNOWN
.upper() : MODEL_UNKNOWN
,
483 TAB_INF_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
484 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
485 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
486 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
487 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
488 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
489 TAB_PACKAGES
.upper() : MODEL_META_DATA_PACKAGE
,
490 TAB_NMAKE
.upper() : MODEL_META_DATA_NMAKE
,
491 TAB_INF_FIXED_PCD
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
492 TAB_INF_PATCH_PCD
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
493 TAB_INF_FEATURE_PCD
.upper() : MODEL_PCD_FEATURE_FLAG
,
494 TAB_INF_PCD_EX
.upper() : MODEL_PCD_DYNAMIC_EX
,
495 TAB_INF_PCD
.upper() : MODEL_PCD_DYNAMIC
,
496 TAB_SOURCES
.upper() : MODEL_EFI_SOURCE_FILE
,
497 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
498 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
499 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
500 TAB_DEPEX
.upper() : MODEL_EFI_DEPEX
,
501 TAB_BINARIES
.upper() : MODEL_EFI_BINARY_FILE
,
502 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
505 ## Constructor of InfParser
507 # Initialize object of InfParser
509 # @param FilePath The path of module description file
510 # @param FileType The raw data of DSC file
511 # @param Arch Default Arch value for filtering sections
512 # @param Table Database used to retrieve module/package information
514 def __init__(self
, FilePath
, FileType
, Arch
, Table
):
515 # prevent re-initialization
516 if hasattr(self
, "_Table"):
518 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Arch
, Table
)
526 Content
= open(str(self
.MetaFile
), 'r').readlines()
528 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
530 # parse the file line by line
531 IsFindBlockComment
= False
532 GetHeaderComment
= False
537 for Index
in range(0, len(Content
)):
538 # skip empty, commented, block commented lines
539 Line
, Comment
= CleanString2(Content
[Index
], AllowCppStyleComment
=True)
541 if Index
+ 1 < len(Content
):
542 NextLine
, NextComment
= CleanString2(Content
[Index
+ 1])
545 Comments
.append((Comment
, Index
+ 1))
546 elif GetHeaderComment
:
547 SectionComments
.extend(Comments
)
550 if Line
.find(DataType
.TAB_COMMENT_EDK_START
) > -1:
551 IsFindBlockComment
= True
553 if Line
.find(DataType
.TAB_COMMENT_EDK_END
) > -1:
554 IsFindBlockComment
= False
556 if IsFindBlockComment
:
559 self
._LineIndex
= Index
560 self
._CurrentLine
= Line
563 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
564 if not GetHeaderComment
:
565 for Cmt
, LNo
in Comments
:
566 self
._Store
(MODEL_META_DATA_HEADER_COMMENT
, Cmt
, '', '', 'COMMON',
567 'COMMON', self
._Owner
[-1], LNo
, -1, LNo
, -1, 0)
568 GetHeaderComment
= True
570 TailComments
.extend(SectionComments
+ Comments
)
572 self
._SectionHeaderParser
()
573 # Check invalid sections
574 if self
._Version
< 0x00010005:
575 if self
._SectionType
in [MODEL_META_DATA_BUILD_OPTION
,
576 MODEL_EFI_LIBRARY_CLASS
,
577 MODEL_META_DATA_PACKAGE
,
578 MODEL_PCD_FIXED_AT_BUILD
,
579 MODEL_PCD_PATCHABLE_IN_MODULE
,
580 MODEL_PCD_FEATURE_FLAG
,
581 MODEL_PCD_DYNAMIC_EX
,
586 MODEL_META_DATA_USER_EXTENSION
]:
587 EdkLogger
.error('Parser', FORMAT_INVALID
,
588 "Section [%s] is not allowed in inf file without version" % (self
._SectionName
),
589 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
590 elif self
._SectionType
in [MODEL_EFI_INCLUDE
,
591 MODEL_EFI_LIBRARY_INSTANCE
,
592 MODEL_META_DATA_NMAKE
]:
593 EdkLogger
.error('Parser', FORMAT_INVALID
,
594 "Section [%s] is not allowed in inf file with version 0x%08x" % (self
._SectionName
, self
._Version
),
595 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
597 # merge two lines specified by '\' in section NMAKE
598 elif self
._SectionType
== MODEL_META_DATA_NMAKE
:
601 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
604 if NextLine
[0] == TAB_SECTION_START
and NextLine
[-1] == TAB_SECTION_END
:
605 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
608 NmakeLine
= NmakeLine
+ ' ' + Line
[0:-1]
611 self
._CurrentLine
= NmakeLine
+ Line
615 self
._ValueList
= ['', '', '']
616 # parse current line, result will be put in self._ValueList
617 self
._SectionParser
[self
._SectionType
](self
)
618 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
623 Comments
.append((Comment
, Index
+ 1))
624 if GlobalData
.gOptions
and GlobalData
.gOptions
.CheckUsage
:
625 CheckInfComment(self
._SectionType
, Comments
, str(self
.MetaFile
), Index
+ 1, self
._ValueList
)
627 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
628 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
630 for Arch
, Platform
in self
._Scope
:
631 LastItem
= self
._Store
(self
._SectionType
,
644 for Comment
, LineNo
in Comments
:
645 self
._Store
(MODEL_META_DATA_COMMENT
, Comment
, '', '', Arch
, Platform
,
646 LastItem
, LineNo
, -1, LineNo
, -1, 0)
649 TailComments
.extend(SectionComments
+ Comments
)
650 if IsFindBlockComment
:
651 EdkLogger
.error("Parser", FORMAT_INVALID
, "Open block comments (starting with /*) are expected to end with */",
654 # If there are tail comments in INF file, save to database whatever the comments are
655 for Comment
in TailComments
:
656 self
._Store
(MODEL_META_DATA_TAIL_COMMENT
, Comment
[0], '', '', 'COMMON',
657 'COMMON', self
._Owner
[-1], -1, -1, -1, -1, 0)
660 ## Data parser for the format in which there's path
662 # Only path can have macro used. So we need to replace them before use.
664 def _IncludeParser(self
):
665 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
666 self
._ValueList
[0:len(TokenList
)] = TokenList
667 Macros
= self
._Macros
669 for Index
in range(0, len(self
._ValueList
)):
670 Value
= self
._ValueList
[Index
]
674 if Value
.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value
.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
675 Value
= '$(EDK_SOURCE)' + Value
[17:]
676 if Value
.find('$(EFI_SOURCE)') > -1 or Value
.find('$(EDK_SOURCE)') > -1:
678 elif Value
.startswith('.'):
680 elif Value
.startswith('$('):
683 Value
= '$(EFI_SOURCE)/' + Value
685 self
._ValueList
[Index
] = ReplaceMacro(Value
, Macros
)
687 ## Parse [Sources] section
689 # Only path can have macro used. So we need to replace them before use.
692 def _SourceFileParser(self
):
693 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
694 self
._ValueList
[0:len(TokenList
)] = TokenList
695 Macros
= self
._Macros
696 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
697 if 'COMPONENT_TYPE' in Macros
:
698 if self
._Defines
['COMPONENT_TYPE'].upper() == 'ACPITABLE':
699 self
._ValueList
[0] = GetSplitValueList(self
._ValueList
[0], ' ', 1)[0]
700 if self
._Defines
['BASE_NAME'] == 'Microcode':
702 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
704 ## Parse [Binaries] section
706 # Only path can have macro used. So we need to replace them before use.
709 def _BinaryFileParser(self
):
710 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 2)
711 if len(TokenList
) < 2:
712 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type or path specified",
713 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
714 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
716 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type specified",
717 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
718 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
720 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file path specified",
721 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
722 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
723 self
._ValueList
[0:len(TokenList
)] = TokenList
724 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
726 ## [nmake] section parser (Edk.x style only)
727 def _NmakeParser(self
):
728 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
729 self
._ValueList
[0:len(TokenList
)] = TokenList
731 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
732 # remove self-reference in macro setting
733 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
735 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
737 def _PcdParser(self
):
738 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
739 ValueList
= GetSplitValueList(TokenList
[0], TAB_SPLIT
)
740 if len(ValueList
) != 2:
741 EdkLogger
.error('Parser', FORMAT_INVALID
, "Illegal token space GUID and PCD name format",
742 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
743 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
744 self
._ValueList
[0:1] = ValueList
745 if len(TokenList
) > 1:
746 self
._ValueList
[2] = TokenList
[1]
747 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
748 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
749 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
750 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
752 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
753 if self
._ValueList
[2] != '':
754 InfPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
755 if InfPcdValueList
[0] in ['True', 'true', 'TRUE']:
756 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '1', 1);
757 elif InfPcdValueList
[0] in ['False', 'false', 'FALSE']:
758 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '0', 1);
759 if (self
._ValueList
[0], self
._ValueList
[1]) not in self
.PcdsDict
:
760 self
.PcdsDict
[self
._ValueList
[0], self
._ValueList
[1]] = self
._SectionType
761 elif self
.PcdsDict
[self
._ValueList
[0], self
._ValueList
[1]] != self
._SectionType
:
762 EdkLogger
.error('Parser', FORMAT_INVALID
, "It is not permissible to list a specified PCD in different PCD type sections.",
763 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
764 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
766 ## [depex] section parser
768 def _DepexParser(self
):
769 self
._ValueList
[0:1] = [self
._CurrentLine
]
772 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
773 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
774 MODEL_META_DATA_BUILD_OPTION
: MetaFileParser
._BuildOptionParser
,
775 MODEL_EFI_INCLUDE
: _IncludeParser
, # for Edk.x modules
776 MODEL_EFI_LIBRARY_INSTANCE
: MetaFileParser
._CommonParser
, # for Edk.x modules
777 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
778 MODEL_META_DATA_PACKAGE
: MetaFileParser
._PathParser
,
779 MODEL_META_DATA_NMAKE
: _NmakeParser
, # for Edk.x modules
780 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
781 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
782 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
783 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
784 MODEL_PCD_DYNAMIC
: _PcdParser
,
785 MODEL_EFI_SOURCE_FILE
: _SourceFileParser
,
786 MODEL_EFI_GUID
: MetaFileParser
._CommonParser
,
787 MODEL_EFI_PROTOCOL
: MetaFileParser
._CommonParser
,
788 MODEL_EFI_PPI
: MetaFileParser
._CommonParser
,
789 MODEL_EFI_DEPEX
: _DepexParser
,
790 MODEL_EFI_BINARY_FILE
: _BinaryFileParser
,
791 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
794 ## DSC file parser class
796 # @param FilePath The path of platform description file
797 # @param FileType The raw data of DSC file
798 # @param Table Database used to retrieve module/package information
799 # @param Macros Macros used for replacement in file
800 # @param Owner Owner ID (for sub-section parsing)
801 # @param From ID from which the data comes (for !INCLUDE directive)
803 class DscParser(MetaFileParser
):
804 # DSC file supported data types (one type per section)
806 TAB_SKUIDS
.upper() : MODEL_EFI_SKU_ID
,
807 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
808 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
809 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
810 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
811 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
812 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
813 TAB_PCDS_DYNAMIC_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_DEFAULT
,
814 TAB_PCDS_DYNAMIC_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_HII
,
815 TAB_PCDS_DYNAMIC_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_VPD
,
816 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT
,
817 TAB_PCDS_DYNAMIC_EX_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_HII
,
818 TAB_PCDS_DYNAMIC_EX_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_VPD
,
819 TAB_COMPONENTS
.upper() : MODEL_META_DATA_COMPONENT
,
820 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH
.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
,
821 TAB_DSC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
822 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
823 TAB_DSC_DEFINES_EDKGLOBAL
: MODEL_META_DATA_GLOBAL_DEFINE
,
824 TAB_INCLUDE
.upper() : MODEL_META_DATA_INCLUDE
,
825 TAB_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
826 TAB_IF_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
827 TAB_IF_N_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
,
828 TAB_ELSE_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
,
829 TAB_ELSE
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
830 TAB_END_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
,
831 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
,
834 # Valid names in define section
841 "PCD_INFO_GENERATION",
842 "PCD_VAR_CHECK_GENERATION",
843 "SUPPORTED_ARCHITECTURES",
852 "FIX_LOAD_TOP_MEMORY_ADDRESS",
857 SubSectionDefineKeywords
= [
861 SymbolPattern
= ValueExpression
.SymbolPattern
863 IncludedFiles
= set()
865 ## Constructor of DscParser
867 # Initialize object of DscParser
869 # @param FilePath The path of platform description file
870 # @param FileType The raw data of DSC file
871 # @param Arch Default Arch value for filtering sections
872 # @param Table Database used to retrieve module/package information
873 # @param Owner Owner ID (for sub-section parsing)
874 # @param From ID from which the data comes (for !INCLUDE directive)
876 def __init__(self
, FilePath
, FileType
, Arch
, Table
, Owner
= -1, From
= -1):
877 # prevent re-initialization
878 if hasattr(self
, "_Table"):
880 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Arch
, Table
, Owner
, From
)
881 self
._Version
= 0x00010005 # Only EDK2 dsc file is supported
882 # to store conditional directive evaluation result
883 self
._DirectiveStack
= []
884 self
._DirectiveEvalStack
= []
888 # Specify whether current line is in uncertain condition
890 self
._InDirective
= -1
892 # Final valid replacable symbols
895 # Map the ID between the original table and new table to track
898 self
._IdMapping
= {-1:-1}
904 Content
= open(str(self
.MetaFile
), 'r').readlines()
906 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
909 for Index
in range(0, len(Content
)):
910 Line
= CleanString(Content
[Index
])
915 self
._CurrentLine
= Line
916 self
._LineIndex
= Index
917 if self
._InSubsection
and self
._Owner
[-1] == -1:
918 self
._Owner
.append(self
._LastItem
)
921 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
922 self
._SectionType
= MODEL_META_DATA_SECTION_HEADER
924 elif Line
[0] == '}' and self
._InSubsection
:
925 self
._InSubsection
= False
926 self
._SubsectionType
= MODEL_UNKNOWN
927 self
._SubsectionName
= ''
932 elif Line
[0] == TAB_OPTION_START
and Line
[-1] == TAB_OPTION_END
:
933 self
._SubsectionType
= MODEL_META_DATA_SUBSECTION_HEADER
936 self
._DirectiveParser
()
938 if Line
[0] == TAB_OPTION_START
and not self
._InSubsection
:
939 EdkLogger
.error("Parser", FILE_READ_FAILURE
, "Missing the '{' before %s in Line %s" % (Line
, Index
+1),ExtraData
=self
.MetaFile
)
941 if self
._InSubsection
:
942 SectionType
= self
._SubsectionType
944 SectionType
= self
._SectionType
945 self
._ItemType
= SectionType
947 self
._ValueList
= ['', '', '']
948 self
._SectionParser
[SectionType
](self
)
949 if self
._ValueList
== None:
952 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
953 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
955 for Arch
, ModuleType
in self
._Scope
:
956 Owner
= self
._Owner
[-1]
957 if self
._SubsectionType
!= MODEL_UNKNOWN
:
958 Owner
= OwnerId
[Arch
]
959 self
._LastItem
= self
._Store
(
974 if self
._SubsectionType
== MODEL_UNKNOWN
and self
._InSubsection
:
975 OwnerId
[Arch
] = self
._LastItem
977 if self
._DirectiveStack
:
978 Type
, Line
, Text
= self
._DirectiveStack
[-1]
979 EdkLogger
.error('Parser', FORMAT_INVALID
, "No matching '!endif' found",
980 ExtraData
=Text
, File
=self
.MetaFile
, Line
=Line
)
983 ## <subsection_header> parser
984 def _SubsectionHeaderParser(self
):
985 self
._SubsectionName
= self
._CurrentLine
[1:-1].upper()
986 if self
._SubsectionName
in self
.DataType
:
987 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
989 self
._SubsectionType
= MODEL_UNKNOWN
990 EdkLogger
.warn("Parser", "Unrecognized sub-section", File
=self
.MetaFile
,
991 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
992 self
._ValueList
[0] = self
._SubsectionName
994 ## Directive statement parser
995 def _DirectiveParser(self
):
996 self
._ValueList
= ['', '', '']
997 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
998 self
._ValueList
[0:len(TokenList
)] = TokenList
1001 DirectiveName
= self
._ValueList
[0].upper()
1002 if DirectiveName
not in self
.DataType
:
1003 EdkLogger
.error("Parser", FORMAT_INVALID
, "Unknown directive [%s]" % DirectiveName
,
1004 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1006 if DirectiveName
in ['!IF', '!IFDEF', '!IFNDEF']:
1007 self
._InDirective
+= 1
1009 if DirectiveName
in ['!ENDIF']:
1010 self
._InDirective
-= 1
1012 if DirectiveName
in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self
._ValueList
[1] == '':
1013 EdkLogger
.error("Parser", FORMAT_INVALID
, "Missing expression",
1014 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
1015 ExtraData
=self
._CurrentLine
)
1017 ItemType
= self
.DataType
[DirectiveName
]
1018 Scope
= [['COMMON', 'COMMON']]
1019 if ItemType
== MODEL_META_DATA_INCLUDE
:
1021 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1022 # Remove all directives between !if and !endif, including themselves
1023 while self
._DirectiveStack
:
1024 # Remove any !else or !elseif
1025 DirectiveInfo
= self
._DirectiveStack
.pop()
1026 if DirectiveInfo
[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1027 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1028 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1031 EdkLogger
.error("Parser", FORMAT_INVALID
, "Redundant '!endif'",
1032 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
1033 ExtraData
=self
._CurrentLine
)
1034 elif ItemType
!= MODEL_META_DATA_INCLUDE
:
1035 # Break if there's a !else is followed by a !elseif
1036 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
and \
1037 self
._DirectiveStack
and \
1038 self
._DirectiveStack
[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1039 EdkLogger
.error("Parser", FORMAT_INVALID
, "'!elseif' after '!else'",
1040 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
1041 ExtraData
=self
._CurrentLine
)
1042 self
._DirectiveStack
.append((ItemType
, self
._LineIndex
+ 1, self
._CurrentLine
))
1045 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
1046 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
1048 for Arch
, ModuleType
in Scope
:
1049 self
._LastItem
= self
._Store
(
1058 self
._LineIndex
+ 1,
1060 self
._LineIndex
+ 1,
1065 ## [defines] section parser
1067 def _DefineParser(self
):
1068 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1069 self
._ValueList
[1:len(TokenList
)] = TokenList
1072 if not self
._ValueList
[1]:
1073 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
1074 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1075 if not self
._ValueList
[2]:
1076 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
1077 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1078 if (not self
._ValueList
[1] in self
.DefineKeywords
and
1079 (self
._InSubsection
and self
._ValueList
[1] not in self
.SubSectionDefineKeywords
)):
1080 EdkLogger
.error('Parser', FORMAT_INVALID
,
1081 "Unknown keyword found: %s. "
1082 "If this is a macro you must "
1083 "add it as a DEFINE in the DSC" % self
._ValueList
[1],
1084 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1085 if not self
._InSubsection
:
1086 self
._Defines
[self
._ValueList
[1]] = self
._ValueList
[2]
1087 self
._ItemType
= self
.DataType
[TAB_DSC_DEFINES
.upper()]
1090 def _SkuIdParser(self
):
1091 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1092 if len(TokenList
) != 2:
1093 EdkLogger
.error('Parser', FORMAT_INVALID
, "Correct format is '<Integer>|<UiName>'",
1094 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1095 self
._ValueList
[0:len(TokenList
)] = TokenList
1097 ## Parse Edk style of library modules
1099 def _LibraryInstanceParser(self
):
1100 self
._ValueList
[0] = self
._CurrentLine
1102 ## PCD sections parser
1104 # [PcdsFixedAtBuild]
1105 # [PcdsPatchableInModule]
1108 # [PcdsDynamicExDefault]
1109 # [PcdsDynamicExVpd]
1110 # [PcdsDynamicExHii]
1112 # [PcdsDynamicDefault]
1117 def _PcdParser(self
):
1118 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1119 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1120 PcdNameTockens
= GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1121 if len(PcdNameTockens
) == 2:
1122 self
._ValueList
[0], self
._ValueList
[1] = PcdNameTockens
[0], PcdNameTockens
[1]
1123 elif len(PcdNameTockens
) == 3:
1124 self
._ValueList
[0], self
._ValueList
[1] = ".".join((PcdNameTockens
[0], PcdNameTockens
[1])), PcdNameTockens
[2]
1125 if len(TokenList
) == 2:
1126 self
._ValueList
[2] = TokenList
[1]
1127 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1128 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1129 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1130 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1131 if self
._ValueList
[2] == '':
1133 # The PCD values are optional for FIXEDATBUILD and PATCHABLEINMODULE
1135 if self
._SectionType
in (MODEL_PCD_FIXED_AT_BUILD
, MODEL_PCD_PATCHABLE_IN_MODULE
):
1137 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD value given",
1138 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1139 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1141 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD
1142 ValueList
= GetSplitValueList(self
._ValueList
[2])
1143 if len(ValueList
) > 1 and ValueList
[1] in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
] \
1144 and self
._ItemType
in [MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_EX_DEFAULT
]:
1145 EdkLogger
.error('Parser', FORMAT_INVALID
, "The datum type '%s' of PCD is wrong" % ValueList
[1],
1146 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1148 # Validate the VariableName of DynamicHii and DynamicExHii for PCD Entry must not be an empty string
1149 if self
._ItemType
in [MODEL_PCD_DYNAMIC_HII
, MODEL_PCD_DYNAMIC_EX_HII
]:
1150 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
1151 if len(DscPcdValueList
[0].replace('L','').replace('"','').strip()) == 0:
1152 EdkLogger
.error('Parser', FORMAT_INVALID
, "The VariableName field in the HII format PCD entry must not be an empty string",
1153 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1155 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1156 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
1157 if DscPcdValueList
[0] in ['True', 'true', 'TRUE']:
1158 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '1', 1);
1159 elif DscPcdValueList
[0] in ['False', 'false', 'FALSE']:
1160 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '0', 1);
1163 ## [components] section parser
1165 def _ComponentParser(self
):
1166 if self
._CurrentLine
[-1] == '{':
1167 self
._ValueList
[0] = self
._CurrentLine
[0:-1].strip()
1168 self
._InSubsection
= True
1170 self
._ValueList
[0] = self
._CurrentLine
1172 ## [LibraryClasses] section
1174 def _LibraryClassParser(self
):
1175 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1176 if len(TokenList
) < 2:
1177 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class or instance specified",
1178 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1179 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1180 if TokenList
[0] == '':
1181 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class specified",
1182 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1183 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1184 if TokenList
[1] == '':
1185 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library instance specified",
1186 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1187 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1189 self
._ValueList
[0:len(TokenList
)] = TokenList
1191 def _CompponentSourceOverridePathParser(self
):
1192 self
._ValueList
[0] = self
._CurrentLine
1194 ## [BuildOptions] section parser
1196 def _BuildOptionParser(self
):
1197 self
._CurrentLine
= CleanString(self
._CurrentLine
, BuildOption
=True)
1198 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1199 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
1200 if len(TokenList2
) == 2:
1201 self
._ValueList
[0] = TokenList2
[0] # toolchain family
1202 self
._ValueList
[1] = TokenList2
[1] # keys
1204 self
._ValueList
[1] = TokenList
[0]
1205 if len(TokenList
) == 2: # value
1206 self
._ValueList
[2] = TokenList
[1]
1208 if self
._ValueList
[1].count('_') != 4:
1212 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
1213 ExtraData
=self
._CurrentLine
,
1215 Line
=self
._LineIndex
+ 1
1218 ## Override parent's method since we'll do all macro replacements in parser
1219 def _GetMacros(self
):
1221 Macros
.update(self
._FileLocalMacros
)
1222 Macros
.update(self
._GetApplicableSectionMacro
())
1223 Macros
.update(GlobalData
.gEdkGlobal
)
1224 Macros
.update(GlobalData
.gPlatformDefines
)
1225 Macros
.update(GlobalData
.gCommandLineDefines
)
1226 # PCD cannot be referenced in macro definition
1227 if self
._ItemType
not in [MODEL_META_DATA_DEFINE
, MODEL_META_DATA_GLOBAL_DEFINE
]:
1228 Macros
.update(self
._Symbols
)
1231 def _PostProcess(self
):
1233 MODEL_META_DATA_SECTION_HEADER
: self
.__ProcessSectionHeader
,
1234 MODEL_META_DATA_SUBSECTION_HEADER
: self
.__ProcessSubsectionHeader
,
1235 MODEL_META_DATA_HEADER
: self
.__ProcessDefine
,
1236 MODEL_META_DATA_DEFINE
: self
.__ProcessDefine
,
1237 MODEL_META_DATA_GLOBAL_DEFINE
: self
.__ProcessDefine
,
1238 MODEL_META_DATA_INCLUDE
: self
.__ProcessDirective
,
1239 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
: self
.__ProcessDirective
,
1240 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
: self
.__ProcessDirective
,
1241 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
: self
.__ProcessDirective
,
1242 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
: self
.__ProcessDirective
,
1243 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
: self
.__ProcessDirective
,
1244 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
: self
.__ProcessDirective
,
1245 MODEL_EFI_SKU_ID
: self
.__ProcessSkuId
,
1246 MODEL_EFI_LIBRARY_INSTANCE
: self
.__ProcessLibraryInstance
,
1247 MODEL_EFI_LIBRARY_CLASS
: self
.__ProcessLibraryClass
,
1248 MODEL_PCD_FIXED_AT_BUILD
: self
.__ProcessPcd
,
1249 MODEL_PCD_PATCHABLE_IN_MODULE
: self
.__ProcessPcd
,
1250 MODEL_PCD_FEATURE_FLAG
: self
.__ProcessPcd
,
1251 MODEL_PCD_DYNAMIC_DEFAULT
: self
.__ProcessPcd
,
1252 MODEL_PCD_DYNAMIC_HII
: self
.__ProcessPcd
,
1253 MODEL_PCD_DYNAMIC_VPD
: self
.__ProcessPcd
,
1254 MODEL_PCD_DYNAMIC_EX_DEFAULT
: self
.__ProcessPcd
,
1255 MODEL_PCD_DYNAMIC_EX_HII
: self
.__ProcessPcd
,
1256 MODEL_PCD_DYNAMIC_EX_VPD
: self
.__ProcessPcd
,
1257 MODEL_META_DATA_COMPONENT
: self
.__ProcessComponent
,
1258 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: self
.__ProcessSourceOverridePath
,
1259 MODEL_META_DATA_BUILD_OPTION
: self
.__ProcessBuildOption
,
1260 MODEL_UNKNOWN
: self
._Skip
,
1261 MODEL_META_DATA_USER_EXTENSION
: self
._SkipUserExtension
,
1264 self
._Table
= MetaFileStorage(self
._RawTable
.Cur
, self
.MetaFile
, MODEL_FILE_DSC
, True)
1265 self
._Table
.Create()
1266 self
._DirectiveStack
= []
1267 self
._DirectiveEvalStack
= []
1268 self
._FileWithError
= self
.MetaFile
1269 self
._FileLocalMacros
= {}
1270 self
._SectionsMacroDict
= {}
1271 GlobalData
.gPlatformDefines
= {}
1273 # Get all macro and PCD which has straitforward value
1274 self
.__RetrievePcdValue
()
1275 self
._Content
= self
._RawTable
.GetAll()
1276 self
._ContentIndex
= 0
1277 self
._InSubsection
= False
1278 while self
._ContentIndex
< len(self
._Content
) :
1279 Id
, self
._ItemType
, V1
, V2
, V3
, S1
, S2
, Owner
, self
._From
, \
1280 LineStart
, ColStart
, LineEnd
, ColEnd
, Enabled
= self
._Content
[self
._ContentIndex
]
1283 self
._FileWithError
= self
.MetaFile
1285 self
._ContentIndex
+= 1
1287 self
._Scope
= [[S1
, S2
]]
1289 # For !include directive, handle it specially,
1290 # merge arch and module type in case of duplicate items
1292 while self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1293 if self
._ContentIndex
>= len(self
._Content
):
1295 Record
= self
._Content
[self
._ContentIndex
]
1296 if LineStart
== Record
[9] and LineEnd
== Record
[11]:
1297 if [Record
[5], Record
[6]] not in self
._Scope
:
1298 self
._Scope
.append([Record
[5], Record
[6]])
1299 self
._ContentIndex
+= 1
1303 self
._LineIndex
= LineStart
- 1
1304 self
._ValueList
= [V1
, V2
, V3
]
1306 if Owner
> 0 and Owner
in self
._IdMapping
:
1307 self
._InSubsection
= True
1309 self
._InSubsection
= False
1311 Processer
[self
._ItemType
]()
1312 except EvaluationException
, Excpt
:
1314 # Only catch expression evaluation error here. We need to report
1315 # the precise number of line on which the error occurred
1317 if hasattr(Excpt
, 'Pcd'):
1318 if Excpt
.Pcd
in GlobalData
.gPlatformOtherPcds
:
1319 Info
= GlobalData
.gPlatformOtherPcds
[Excpt
.Pcd
]
1320 EdkLogger
.error('Parser', FORMAT_INVALID
, "Cannot use this PCD (%s) in an expression as"
1321 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
1322 " of the DSC file, and it is currently defined in this section:"
1323 " %s, line #: %d." % (Excpt
.Pcd
, Info
[0], Info
[1]),
1324 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1325 Line
=self
._LineIndex
+ 1)
1327 EdkLogger
.error('Parser', FORMAT_INVALID
, "PCD (%s) is not defined in DSC file" % Excpt
.Pcd
,
1328 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1329 Line
=self
._LineIndex
+ 1)
1331 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid expression: %s" % str(Excpt
),
1332 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1333 Line
=self
._LineIndex
+ 1)
1334 except MacroException
, Excpt
:
1335 EdkLogger
.error('Parser', FORMAT_INVALID
, str(Excpt
),
1336 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1337 Line
=self
._LineIndex
+ 1)
1339 if self
._ValueList
== None:
1342 NewOwner
= self
._IdMapping
.get(Owner
, -1)
1343 self
._Enabled
= int((not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
))
1344 self
._LastItem
= self
._Store
(
1353 self
._LineIndex
+ 1,
1355 self
._LineIndex
+ 1,
1359 self
._IdMapping
[Id
] = self
._LastItem
1361 GlobalData
.gPlatformDefines
.update(self
._FileLocalMacros
)
1362 self
._PostProcessed
= True
1363 self
._Content
= None
1365 def __ProcessSectionHeader(self
):
1366 self
._SectionName
= self
._ValueList
[0]
1367 if self
._SectionName
in self
.DataType
:
1368 self
._SectionType
= self
.DataType
[self
._SectionName
]
1370 self
._SectionType
= MODEL_UNKNOWN
1372 def __ProcessSubsectionHeader(self
):
1373 self
._SubsectionName
= self
._ValueList
[0]
1374 if self
._SubsectionName
in self
.DataType
:
1375 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
1377 self
._SubsectionType
= MODEL_UNKNOWN
1379 def __RetrievePcdValue(self
):
1380 Content
= open(str(self
.MetaFile
), 'r').readlines()
1381 GlobalData
.gPlatformOtherPcds
['DSCFILE'] = str(self
.MetaFile
)
1382 for PcdType
in (MODEL_PCD_PATCHABLE_IN_MODULE
, MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_HII
,
1383 MODEL_PCD_DYNAMIC_VPD
, MODEL_PCD_DYNAMIC_EX_DEFAULT
, MODEL_PCD_DYNAMIC_EX_HII
,
1384 MODEL_PCD_DYNAMIC_EX_VPD
):
1385 Records
= self
._RawTable
.Query(PcdType
, BelongsToItem
= -1.0)
1386 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1387 Name
= TokenSpaceGuid
+ '.' + PcdName
1388 if Name
not in GlobalData
.gPlatformOtherPcds
:
1390 while not Content
[Line
- 1].lstrip().startswith(TAB_SECTION_START
):
1392 GlobalData
.gPlatformOtherPcds
[Name
] = (CleanString(Content
[Line
- 1]), PcdLine
, PcdType
)
1394 def __ProcessDefine(self
):
1395 if not self
._Enabled
:
1398 Type
, Name
, Value
= self
._ValueList
1399 Value
= ReplaceMacro(Value
, self
._Macros
, False)
1401 # If it is <Defines>, return
1403 if self
._InSubsection
:
1404 self
._ValueList
= [Type
, Name
, Value
]
1407 if self
._ItemType
== MODEL_META_DATA_DEFINE
:
1408 if self
._SectionType
== MODEL_META_DATA_HEADER
:
1409 self
._FileLocalMacros
[Name
] = Value
1411 self
._ConstructSectionMacroDict
(Name
, Value
)
1412 elif self
._ItemType
== MODEL_META_DATA_GLOBAL_DEFINE
:
1413 GlobalData
.gEdkGlobal
[Name
] = Value
1416 # Keyword in [Defines] section can be used as Macros
1418 if (self
._ItemType
== MODEL_META_DATA_HEADER
) and (self
._SectionType
== MODEL_META_DATA_HEADER
):
1419 self
._FileLocalMacros
[Name
] = Value
1421 self
._ValueList
= [Type
, Name
, Value
]
1423 def __ProcessDirective(self
):
1425 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1426 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
]:
1427 Macros
= self
._Macros
1428 Macros
.update(GlobalData
.gGlobalDefines
)
1430 Result
= ValueExpression(self
._ValueList
[1], Macros
)()
1431 except SymbolNotFound
, Exc
:
1432 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1434 except WrnExpression
, Excpt
:
1436 # Catch expression evaluation warning here. We need to report
1437 # the precise number of line and return the evaluation result
1439 EdkLogger
.warn('Parser', "Suspicious expression: %s" % str(Excpt
),
1440 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1441 Line
=self
._LineIndex
+ 1)
1442 Result
= Excpt
.result
1444 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1445 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1446 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1447 self
._DirectiveStack
.append(self
._ItemType
)
1448 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
:
1449 Result
= bool(Result
)
1451 Macro
= self
._ValueList
[1]
1452 Macro
= Macro
[2:-1] if (Macro
.startswith("$(") and Macro
.endswith(")")) else Macro
1453 Result
= Macro
in self
._Macros
1454 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
:
1456 self
._DirectiveEvalStack
.append(Result
)
1457 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
:
1458 self
._DirectiveStack
.append(self
._ItemType
)
1459 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1460 self
._DirectiveEvalStack
.append(bool(Result
))
1461 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1462 self
._DirectiveStack
.append(self
._ItemType
)
1463 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1464 self
._DirectiveEvalStack
.append(True)
1465 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1466 # Back to the nearest !if/!ifdef/!ifndef
1467 while self
._DirectiveStack
:
1468 self
._DirectiveEvalStack
.pop()
1469 Directive
= self
._DirectiveStack
.pop()
1470 if Directive
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1471 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1472 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1474 elif self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1475 # The included file must be relative to workspace or same directory as DSC file
1476 __IncludeMacros
= {}
1478 # Allow using system environment variables in path after !include
1480 __IncludeMacros
['WORKSPACE'] = GlobalData
.gGlobalDefines
['WORKSPACE']
1481 if "ECP_SOURCE" in GlobalData
.gGlobalDefines
.keys():
1482 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gGlobalDefines
['ECP_SOURCE']
1484 # During GenFds phase call DSC parser, will go into this branch.
1486 elif "ECP_SOURCE" in GlobalData
.gCommandLineDefines
.keys():
1487 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gCommandLineDefines
['ECP_SOURCE']
1489 __IncludeMacros
['EFI_SOURCE'] = GlobalData
.gGlobalDefines
['EFI_SOURCE']
1490 __IncludeMacros
['EDK_SOURCE'] = GlobalData
.gGlobalDefines
['EDK_SOURCE']
1492 # Allow using MACROs comes from [Defines] section to keep compatible.
1494 __IncludeMacros
.update(self
._Macros
)
1496 IncludedFile
= NormPath(ReplaceMacro(self
._ValueList
[1], __IncludeMacros
, RaiseError
=True))
1498 # First search the include file under the same directory as DSC file
1500 IncludedFile1
= PathClass(IncludedFile
, self
.MetaFile
.Dir
)
1501 ErrorCode
, ErrorInfo1
= IncludedFile1
.Validate()
1504 # Also search file under the WORKSPACE directory
1506 IncludedFile1
= PathClass(IncludedFile
, GlobalData
.gWorkspace
)
1507 ErrorCode
, ErrorInfo2
= IncludedFile1
.Validate()
1509 EdkLogger
.error('parser', ErrorCode
, File
=self
._FileWithError
,
1510 Line
=self
._LineIndex
+ 1, ExtraData
=ErrorInfo1
+ "\n" + ErrorInfo2
)
1512 self
._FileWithError
= IncludedFile1
1514 IncludedFileTable
= MetaFileStorage(self
._Table
.Cur
, IncludedFile1
, MODEL_FILE_DSC
, False)
1515 Owner
= self
._Content
[self
._ContentIndex
- 1][0]
1516 Parser
= DscParser(IncludedFile1
, self
._FileType
, self
._Arch
, IncludedFileTable
,
1517 Owner
=Owner
, From
=Owner
)
1519 self
.IncludedFiles
.add (IncludedFile1
)
1521 # Does not allow lower level included file to include upper level included file
1522 if Parser
._From
!= Owner
and int(Owner
) > int (Parser
._From
):
1523 EdkLogger
.error('parser', FILE_ALREADY_EXIST
, File
=self
._FileWithError
,
1524 Line
=self
._LineIndex
+ 1, ExtraData
="{0} is already included at a higher level.".format(IncludedFile1
))
1527 # set the parser status with current status
1528 Parser
._SectionName
= self
._SectionName
1529 Parser
._SectionType
= self
._SectionType
1530 Parser
._Scope
= self
._Scope
1531 Parser
._Enabled
= self
._Enabled
1532 # Parse the included file
1535 # update current status with sub-parser's status
1536 self
._SectionName
= Parser
._SectionName
1537 self
._SectionType
= Parser
._SectionType
1538 self
._Scope
= Parser
._Scope
1539 self
._Enabled
= Parser
._Enabled
1541 # Insert all records in the table for the included file into dsc file table
1542 Records
= IncludedFileTable
.GetAll()
1544 self
._Content
[self
._ContentIndex
:self
._ContentIndex
] = Records
1545 self
._Content
.pop(self
._ContentIndex
- 1)
1546 self
._ValueList
= None
1547 self
._ContentIndex
-= 1
1549 def __ProcessSkuId(self
):
1550 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=True)
1551 for Value
in self
._ValueList
]
1553 def __ProcessLibraryInstance(self
):
1554 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
1556 def __ProcessLibraryClass(self
):
1557 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, RaiseError
=True)
1559 def __ProcessPcd(self
):
1560 if self
._ItemType
not in [MODEL_PCD_FEATURE_FLAG
, MODEL_PCD_FIXED_AT_BUILD
]:
1561 self
._ValueList
[2] = ReplaceMacro(self
._ValueList
[2], self
._Macros
, RaiseError
=True)
1564 ValList
, Valid
, Index
= AnalyzeDscPcd(self
._ValueList
[2], self
._ItemType
)
1566 EdkLogger
.error('build', FORMAT_INVALID
, "Pcd format incorrect.", File
=self
._FileWithError
, Line
=self
._LineIndex
+ 1,
1567 ExtraData
="%s.%s|%s" % (self
._ValueList
[0], self
._ValueList
[1], self
._ValueList
[2]))
1568 PcdValue
= ValList
[Index
]
1569 if PcdValue
and "." not in self
._ValueList
[0]:
1571 ValList
[Index
] = ValueExpression(PcdValue
, self
._Macros
)(True)
1572 except WrnExpression
, Value
:
1573 ValList
[Index
] = Value
.result
1575 if ValList
[Index
] == 'True':
1576 ValList
[Index
] = '1'
1577 if ValList
[Index
] == 'False':
1578 ValList
[Index
] = '0'
1580 if (not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
):
1581 GlobalData
.gPlatformPcds
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = PcdValue
1582 self
._Symbols
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = PcdValue
1584 self
._ValueList
[2] = '|'.join(ValList
)
1588 def __ProcessComponent(self
):
1589 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1591 def __ProcessSourceOverridePath(self
):
1592 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1594 def __ProcessBuildOption(self
):
1595 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=False)
1596 for Value
in self
._ValueList
]
1599 MODEL_META_DATA_HEADER
: _DefineParser
,
1600 MODEL_EFI_SKU_ID
: _SkuIdParser
,
1601 MODEL_EFI_LIBRARY_INSTANCE
: _LibraryInstanceParser
,
1602 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
1603 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1604 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1605 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1606 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
1607 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
1608 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
1609 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
1610 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
1611 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
1612 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
1613 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: _CompponentSourceOverridePathParser
,
1614 MODEL_META_DATA_BUILD_OPTION
: _BuildOptionParser
,
1615 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1616 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
1617 MODEL_META_DATA_SECTION_HEADER
: MetaFileParser
._SectionHeaderParser
,
1618 MODEL_META_DATA_SUBSECTION_HEADER
: _SubsectionHeaderParser
,
1621 _Macros
= property(_GetMacros
)
1623 ## DEC file parser class
1625 # @param FilePath The path of platform description file
1626 # @param FileType The raw data of DSC file
1627 # @param Table Database used to retrieve module/package information
1628 # @param Macros Macros used for replacement in file
1630 class DecParser(MetaFileParser
):
1631 # DEC file supported data types (one type per section)
1633 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1634 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
1635 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1636 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1637 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1638 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1639 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1640 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1641 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1642 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1643 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1644 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1645 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
,
1648 ## Constructor of DecParser
1650 # Initialize object of DecParser
1652 # @param FilePath The path of platform description file
1653 # @param FileType The raw data of DSC file
1654 # @param Arch Default Arch value for filtering sections
1655 # @param Table Database used to retrieve module/package information
1657 def __init__(self
, FilePath
, FileType
, Arch
, Table
):
1658 # prevent re-initialization
1659 if hasattr(self
, "_Table"):
1661 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Arch
, Table
, -1)
1663 self
._Version
= 0x00010005 # Only EDK2 dec file is supported
1664 self
._AllPCDs
= [] # Only for check duplicate PCD
1665 self
._AllPcdDict
= {}
1667 self
._CurrentStructurePcdName
= ""
1668 self
._include
_flag
= False
1669 self
._package
_flag
= False
1675 Content
= open(str(self
.MetaFile
), 'r').readlines()
1677 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1679 self
._DefinesCount
= 0
1680 for Index
in range(0, len(Content
)):
1681 Line
, Comment
= CleanString2(Content
[Index
])
1682 self
._CurrentLine
= Line
1683 self
._LineIndex
= Index
1685 # save comment for later use
1687 self
._Comments
.append((Comment
, self
._LineIndex
+ 1))
1693 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1694 self
._SectionHeaderParser
()
1695 if self
._SectionName
== TAB_DEC_DEFINES
.upper():
1696 self
._DefinesCount
+= 1
1699 if self
._SectionType
== MODEL_UNKNOWN
:
1700 EdkLogger
.error("Parser", FORMAT_INVALID
,
1702 "Not able to determine \"%s\" in which section."%self
._CurrentLine
,
1703 self
.MetaFile
, self
._LineIndex
+ 1)
1704 elif len(self
._SectionType
) == 0:
1709 self
._ValueList
= ['', '', '']
1710 self
._SectionParser
[self
._SectionType
[0]](self
)
1711 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
1717 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1718 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1720 for Arch
, ModuleType
, Type
in self
._Scope
:
1721 self
._LastItem
= self
._Store
(
1729 self
._LineIndex
+ 1,
1731 self
._LineIndex
+ 1,
1735 for Comment
, LineNo
in self
._Comments
:
1737 MODEL_META_DATA_COMMENT
,
1751 if self
._DefinesCount
> 1:
1752 EdkLogger
.error('Parser', FORMAT_INVALID
, 'Multiple [Defines] section is exist.', self
.MetaFile
)
1753 if self
._DefinesCount
== 0:
1754 EdkLogger
.error('Parser', FORMAT_INVALID
, 'No [Defines] section exist.',self
.MetaFile
)
1758 ## Section header parser
1760 # The section header is always in following format:
1762 # [section_name.arch<.platform|module_type>]
1764 def _SectionHeaderParser(self
):
1766 self
._SectionName
= ''
1767 self
._SectionType
= []
1770 Line
= re
.sub(',[\s]*', TAB_COMMA_SPLIT
, self
._CurrentLine
)
1771 for Item
in Line
[1:-1].split(TAB_COMMA_SPLIT
):
1773 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
,
1774 "section name can NOT be empty or incorrectly use separator comma",
1775 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1776 ItemList
= Item
.split(TAB_SPLIT
)
1778 # different types of PCD are permissible in one section
1779 self
._SectionName
= ItemList
[0].upper()
1780 if self
._SectionName
== TAB_DEC_DEFINES
.upper() and (len(ItemList
) > 1 or len(Line
.split(TAB_COMMA_SPLIT
)) > 1):
1781 EdkLogger
.error("Parser", FORMAT_INVALID
, "Defines section format is invalid",
1782 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1783 if self
._SectionName
in self
.DataType
:
1784 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1785 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1787 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
1788 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1790 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1794 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1796 Line
=self
._LineIndex
+ 1,
1797 ExtraData
=self
._CurrentLine
1800 if len(ItemList
) > 1:
1801 S1
= ItemList
[1].upper()
1805 # S2 may be Platform or ModuleType
1806 if len(ItemList
) > 2:
1807 S2
= ItemList
[2].upper()
1808 # only Includes, GUIDs, PPIs, Protocols section have Private tag
1809 if self
._SectionName
in [TAB_INCLUDES
.upper(), TAB_GUIDS
.upper(), TAB_PROTOCOLS
.upper(), TAB_PPIS
.upper()]:
1811 EdkLogger
.error("Parser", FORMAT_INVALID
, 'Please use keyword "Private" as section tag modifier.',
1812 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
1816 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1817 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1819 # 'COMMON' must not be used with specific ARCHs at the same section
1820 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1821 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1822 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
1824 # It is not permissible to mix section tags without the Private attribute with section tags with the Private attribute
1825 if 'COMMON' in PrivateList
and len(PrivateList
) > 1:
1826 EdkLogger
.error('Parser', FORMAT_INVALID
, "Can't mix section tags without the Private attribute with section tags with the Private attribute",
1827 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
1829 ## [guids], [ppis] and [protocols] section parser
1831 def _GuidParser(self
):
1832 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1833 if len(TokenList
) < 2:
1834 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1835 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1836 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1837 if TokenList
[0] == '':
1838 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1839 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1840 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1841 if TokenList
[1] == '':
1842 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1843 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1844 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1845 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1846 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1847 ExtraData
=self
._CurrentLine
+ \
1848 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1849 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1850 self
._ValueList
[0] = TokenList
[0]
1851 self
._ValueList
[1] = TokenList
[1]
1853 ## PCD sections parser
1855 # [PcdsFixedAtBuild]
1856 # [PcdsPatchableInModule]
1862 def _PcdParser(self
):
1863 if self
._CurrentStructurePcdName
:
1864 self
._ValueList
[0] = self
._CurrentStructurePcdName
1866 if "|" not in self
._CurrentLine
:
1867 if "<HeaderFiles>" == self
._CurrentLine
:
1868 self
._include
_flag
= True
1869 self
._ValueList
= None
1871 if "<Packages>" == self
._CurrentLine
:
1872 self
._package
_flag
= True
1873 self
._ValueList
= None
1876 if self
._include
_flag
:
1877 self
._ValueList
[1] = "<HeaderFiles>_" + md5
.new(self
._CurrentLine
).hexdigest()
1878 self
._ValueList
[2] = self
._CurrentLine
1879 self
._include
_flag
= False
1880 if self
._package
_flag
and "}" != self
._CurrentLine
:
1881 self
._ValueList
[1] = "<Packages>_" + md5
.new(self
._CurrentLine
).hexdigest()
1882 self
._ValueList
[2] = self
._CurrentLine
1883 if self
._CurrentLine
== "}":
1884 self
._package
_flag
= False
1885 self
._ValueList
= None
1888 PcdTockens
= self
._CurrentLine
.split(TAB_VALUE_SPLIT
)
1889 PcdNames
= PcdTockens
[0].split(TAB_SPLIT
)
1890 if len(PcdNames
) == 2:
1891 self
._CurrentStructurePcdName
= ""
1893 self
._ValueList
[1] = PcdNames
[2]
1894 self
._ValueList
[2] = PcdTockens
[1]
1895 if not self
._CurrentStructurePcdName
:
1896 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1897 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1898 ValueRe
= re
.compile(r
'^[a-zA-Z_][a-zA-Z0-9_]*')
1899 # check PCD information
1900 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1901 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1902 ExtraData
=self
._CurrentLine
+ \
1903 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1904 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1905 # check format of token space GUID CName
1906 if not ValueRe
.match(self
._ValueList
[0]):
1907 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_]*'",
1908 ExtraData
=self
._CurrentLine
+ \
1909 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1910 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1911 # check format of PCD CName
1912 if not ValueRe
.match(self
._ValueList
[1]):
1913 EdkLogger
.error('Parser', FORMAT_INVALID
, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
1914 ExtraData
=self
._CurrentLine
+ \
1915 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1916 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1917 # check PCD datum information
1918 if len(TokenList
) < 2 or TokenList
[1] == '':
1919 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1920 ExtraData
=self
._CurrentLine
+ \
1921 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1922 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1925 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1926 PtrValue
= ValueRe
.findall(TokenList
[1])
1928 # Has VOID* type string, may contain "|" character in the string.
1929 if len(PtrValue
) != 0:
1930 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1931 ValueList
= AnalyzePcdExpression(ptrValueList
)
1932 ValueList
[0] = PtrValue
[0]
1934 ValueList
= AnalyzePcdExpression(TokenList
[1])
1937 # check if there's enough datum information given
1938 if len(ValueList
) != 3:
1939 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1940 ExtraData
=self
._CurrentLine
+ \
1941 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1942 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1943 # check default value
1944 if ValueList
[0] == '':
1945 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1946 ExtraData
=self
._CurrentLine
+ \
1947 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1948 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1950 if ValueList
[1] == '':
1951 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1952 ExtraData
=self
._CurrentLine
+ \
1953 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1954 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1955 # check token of the PCD
1956 if ValueList
[2] == '':
1957 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1958 ExtraData
=self
._CurrentLine
+ \
1959 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1960 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1962 PcdValue
= ValueList
[0]
1965 ValueList
[0] = ValueExpression(PcdValue
, self
._AllPcdDict
)(True)
1966 except WrnExpression
, Value
:
1967 ValueList
[0] = Value
.result
1969 if ValueList
[0] == 'True':
1971 if ValueList
[0] == 'False':
1974 # check format of default value against the datum type
1975 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1977 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1978 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1980 if Cause
== "StructurePcd":
1981 self
._CurrentStructurePcdName
= TAB_SPLIT
.join(self
._ValueList
[0:2])
1982 self
._ValueList
[0] = self
._CurrentStructurePcdName
1983 self
._ValueList
[1] = ValueList
[1].strip()
1985 if ValueList
[0] in ['True', 'true', 'TRUE']:
1987 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1990 # check for duplicate PCD definition
1991 if (self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]) in self
._AllPCDs
:
1992 EdkLogger
.error('Parser', FORMAT_INVALID
,
1993 "The same PCD name and GUID have been already defined",
1994 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1996 self
._AllPCDs
.append((self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]))
1997 self
._AllPcdDict
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = ValueList
[0]
1999 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
2002 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
2003 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
2004 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
2005 MODEL_EFI_GUID
: _GuidParser
,
2006 MODEL_EFI_PPI
: _GuidParser
,
2007 MODEL_EFI_PROTOCOL
: _GuidParser
,
2008 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
2009 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
2010 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
2011 MODEL_PCD_DYNAMIC
: _PcdParser
,
2012 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
2013 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
2014 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
2019 # This acts like the main() function for the script, unless it is 'import'ed into another
2022 if __name__
== '__main__':