2 # This file is used to parse meta files
4 # Copyright (c) 2008 - 2018, 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
27 from CommonDataClass
.DataClass
import *
28 from Common
.DataType
import *
29 from Common
.StringUtils
import *
30 from Common
.Misc
import GuidStructureStringToGuidString
, CheckPcdDatum
, PathClass
, AnalyzePcdData
31 from Common
.Expression
import *
32 from CommonDataClass
.Exceptions
import *
34 from MetaFileTable
import MetaFileStorage
35 from GenFds
.FdfParser
import FdfParser
36 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
37 from Common
.LongFilePathSupport
import CodecOpenLongFilePath
39 ## A decorator used to parse macro definition
40 def ParseMacro(Parser
):
41 def MacroParser(self
):
42 Match
= gMacroDefPattern
.match(self
._CurrentLine
)
44 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
48 TokenList
= GetSplitValueList(self
._CurrentLine
[Match
.end(1):], TAB_EQUAL_SPLIT
, 1)
51 EdkLogger
.error('Parser', FORMAT_INVALID
, "No macro name given",
52 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
53 if len(TokenList
) < 2:
57 Name
, Value
= TokenList
58 # Global macros can be only defined via environment variable
59 if Name
in GlobalData
.gGlobalDefines
:
60 EdkLogger
.error('Parser', FORMAT_INVALID
, "%s can only be defined via environment variable" % Name
,
61 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
62 # Only upper case letters, digit and '_' are allowed
63 if not gMacroNamePattern
.match(Name
):
64 EdkLogger
.error('Parser', FORMAT_INVALID
, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
65 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
67 Value
= ReplaceMacro(Value
, self
._Macros
)
68 self
._ItemType
= MODEL_META_DATA_DEFINE
69 # DEFINE defined macros
70 if Type
== TAB_DSC_DEFINES_DEFINE
:
71 if isinstance(self
, DecParser
):
72 if MODEL_META_DATA_HEADER
in self
._SectionType
:
73 self
._FileLocalMacros
[Name
] = Value
75 for Scope
in self
._Scope
:
76 self
._SectionsMacroDict
.setdefault((Scope
[2], Scope
[0], Scope
[1]), {})[Name
] = Value
77 elif self
._SectionType
== MODEL_META_DATA_HEADER
:
78 self
._FileLocalMacros
[Name
] = Value
80 SectionDictKey
= self
._SectionType
, self
._Scope
[0][0], self
._Scope
[0][1]
81 if SectionDictKey
not in self
._SectionsMacroDict
:
82 self
._SectionsMacroDict
[SectionDictKey
] = {}
83 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
84 SectionLocalMacros
[Name
] = Value
85 # EDK_GLOBAL defined macros
86 elif not isinstance(self
, DscParser
):
87 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used in .dsc file",
88 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
89 elif self
._SectionType
!= MODEL_META_DATA_HEADER
:
90 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used under [Defines] section",
91 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
92 elif (Name
in self
._FileLocalMacros
) and (self
._FileLocalMacros
[Name
] != Value
):
93 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
94 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
96 self
._ValueList
= [Type
, Name
, Value
]
100 ## Base class of parser
102 # This class is used for derivation purpose. The specific parser for one kind
103 # type file must derive this class and implement some public interfaces.
105 # @param FilePath The path of platform description file
106 # @param FileType The raw data of DSC file
107 # @param Table Database used to retrieve module/package information
108 # @param Macros Macros used for replacement in file
109 # @param Owner Owner ID (for sub-section parsing)
110 # @param From ID from which the data comes (for !INCLUDE directive)
112 class MetaFileParser(object):
113 # data type (file content) for specific file type
116 # Parser objects used to implement singleton
121 # One file, one parser object. This factory method makes sure that there's
122 # only one object constructed for one meta file.
124 # @param Class class object of real AutoGen class
125 # (InfParser, DecParser or DscParser)
126 # @param FilePath The path of meta file
127 # @param *args The specific class related parameters
128 # @param **kwargs The specific class related dict parameters
130 def __new__(Class
, FilePath
, *args
, **kwargs
):
131 if FilePath
in Class
.MetaFiles
:
132 return Class
.MetaFiles
[FilePath
]
134 ParserObject
= super(MetaFileParser
, Class
).__new
__(Class
)
135 Class
.MetaFiles
[FilePath
] = ParserObject
138 ## Constructor of MetaFileParser
140 # Initialize object of MetaFileParser
142 # @param FilePath The path of platform description file
143 # @param FileType The raw data of DSC file
144 # @param Table Database used to retrieve module/package information
145 # @param Macros Macros used for replacement in file
146 # @param Owner Owner ID (for sub-section parsing)
147 # @param From ID from which the data comes (for !INCLUDE directive)
149 def __init__(self
, FilePath
, FileType
, Table
, Owner
=-1, From
=-1):
151 self
._RawTable
= Table
152 self
._FileType
= FileType
153 self
.MetaFile
= FilePath
155 self
._FileLocalMacros
= {}
156 self
._SectionsMacroDict
= {}
158 # for recursive parsing
159 self
._Owner
= [Owner
]
162 # parsr status for parsing
163 self
._ValueList
= ['', '', '', '', '']
166 self
._CurrentLine
= ''
167 self
._SectionType
= MODEL_UNKNOWN
168 self
._SectionName
= ''
169 self
._InSubsection
= False
170 self
._SubsectionType
= MODEL_UNKNOWN
171 self
._SubsectionName
= ''
172 self
._ItemType
= MODEL_UNKNOWN
175 self
._Finished
= False
176 self
._PostProcessed
= False
177 # Different version of meta-file has different way to parse.
179 # UNI object and extra UNI object
181 self
._UniExtraObj
= None
183 ## Store the parsed data in table
184 def _Store(self
, *Args
):
185 return self
._Table
.Insert(*Args
)
187 ## Virtual method for starting parse
189 raise NotImplementedError
191 ## Notify a post-process is needed
192 def DoPostProcess(self
):
193 self
._PostProcessed
= False
195 ## Set parsing complete flag in both class and table
197 self
._Finished
= True
198 ## Do not set end flag when processing included files
200 self
._Table
.SetEndFlag()
202 def _PostProcess(self
):
203 self
._PostProcessed
= True
205 ## Get the parse complete flag
206 def _GetFinished(self
):
207 return self
._Finished
209 ## Set the complete flag
210 def _SetFinished(self
, Value
):
211 self
._Finished
= Value
213 ## Use [] style to query data in table, just for readability
215 # DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]
217 def __getitem__(self
, DataInfo
):
218 if not isinstance(DataInfo
, type(())):
219 DataInfo
= (DataInfo
,)
221 # Parse the file first, if necessary
222 if not self
._Finished
:
223 if self
._RawTable
.IsIntegrity():
224 self
._Finished
= True
226 self
._Table
= self
._RawTable
227 self
._PostProcessed
= False
230 # No specific ARCH or Platform given, use raw data
231 if self
._RawTable
and (len(DataInfo
) == 1 or DataInfo
[1] is None):
232 return self
._RawTable
.Query(*DataInfo
)
234 # Do post-process if necessary
235 if not self
._PostProcessed
:
238 return self
._Table
.Query(*DataInfo
)
240 ## Data parser for the common format in different type of file
242 # The common format in the meatfile is like
247 def _CommonParser(self
):
248 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
249 self
._ValueList
[0:len(TokenList
)] = TokenList
251 ## Data parser for the format in which there's path
253 # Only path can have macro used. So we need to replace them before use.
256 def _PathParser(self
):
257 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
258 self
._ValueList
[0:len(TokenList
)] = TokenList
259 # Don't do macro replacement for dsc file at this point
260 if not isinstance(self
, DscParser
):
261 Macros
= self
._Macros
262 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
264 ## Skip unsupported data
266 if self
._SectionName
== TAB_USER_EXTENSIONS
.upper() and self
._CurrentLine
.upper().endswith('.UNI'):
267 if EccGlobalData
.gConfig
.UniCheckHelpInfo
== '1' or EccGlobalData
.gConfig
.UniCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
268 ExtraUni
= self
._CurrentLine
.strip()
269 ExtraUniFile
= os
.path
.join(os
.path
.dirname(self
.MetaFile
), ExtraUni
)
270 IsModuleUni
= self
.MetaFile
.upper().endswith('.INF')
271 self
._UniExtraObj
= UniParser(ExtraUniFile
, IsExtraUni
=True, IsModuleUni
=IsModuleUni
)
272 self
._UniExtraObj
.Start()
274 EdkLogger
.warn("Parser", "Unrecognized content", File
=self
.MetaFile
,
275 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
);
276 self
._ValueList
[0:1] = [self
._CurrentLine
]
278 ## Section header parser
280 # The section header is always in following format:
282 # [section_name.arch<.platform|module_type>]
284 def _SectionHeaderParser(self
):
286 self
._SectionName
= ''
288 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
291 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
)
292 # different section should not mix in one section
293 if self
._SectionName
!= '' and self
._SectionName
!= ItemList
[0].upper():
294 EdkLogger
.error('Parser', FORMAT_INVALID
, "Different section names in the same section",
295 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
296 self
._SectionName
= ItemList
[0].upper()
297 if self
._SectionName
in self
.DataType
:
298 self
._SectionType
= self
.DataType
[self
._SectionName
]
300 self
._SectionType
= MODEL_UNKNOWN
301 EdkLogger
.warn("Parser", "Unrecognized section", File
=self
.MetaFile
,
302 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
304 if len(ItemList
) > 1:
305 S1
= ItemList
[1].upper()
309 # S2 may be Platform or ModuleType
310 if len(ItemList
) > 2:
311 S2
= ItemList
[2].upper()
314 self
._Scope
.append([S1
, S2
])
316 # 'COMMON' must not be used with specific ARCHs at the same section
317 if 'COMMON' in ArchList
and len(ArchList
) > 1:
318 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
319 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
320 # If the section information is needed later, it should be stored in database
321 self
._ValueList
[0] = self
._SectionName
323 ## [defines] section parser
325 def _DefineParser(self
):
326 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
327 self
._ValueList
[1:len(TokenList
)] = TokenList
328 if not self
._ValueList
[1]:
329 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
330 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
331 if not self
._ValueList
[2]:
332 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
333 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
335 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
336 Name
, Value
= self
._ValueList
[1], self
._ValueList
[2]
337 # Sometimes, we need to make differences between EDK and EDK2 modules
338 if Name
== 'INF_VERSION':
340 self
._Version
= int(Value
, 0)
342 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid version number",
343 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
344 elif Name
== 'MODULE_UNI_FILE':
345 UniFile
= os
.path
.join(os
.path
.dirname(self
.MetaFile
), Value
)
346 if os
.path
.exists(UniFile
):
347 self
._UniObj
= UniParser(UniFile
, IsExtraUni
=False, IsModuleUni
=True)
350 EdkLogger
.error('Parser', FILE_NOT_FOUND
, "Module UNI file %s is missing." % Value
,
351 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
353 elif Name
== 'PACKAGE_UNI_FILE':
354 UniFile
= os
.path
.join(os
.path
.dirname(self
.MetaFile
), Value
)
355 if os
.path
.exists(UniFile
):
356 self
._UniObj
= UniParser(UniFile
, IsExtraUni
=False, IsModuleUni
=False)
358 if isinstance(self
, InfParser
) and self
._Version
< 0x00010005:
359 # EDK module allows using defines as macros
360 self
._FileLocalMacros
[Name
] = Value
361 self
._Defines
[Name
] = Value
363 ## [BuildOptions] section parser
365 def _BuildOptionParser(self
):
366 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
367 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
368 if len(TokenList2
) == 2:
369 self
._ValueList
[0] = TokenList2
[0] # toolchain family
370 self
._ValueList
[1] = TokenList2
[1] # keys
372 self
._ValueList
[1] = TokenList
[0]
373 if len(TokenList
) == 2 and not isinstance(self
, DscParser
): # value
374 self
._ValueList
[2] = ReplaceMacro(TokenList
[1], self
._Macros
)
376 if self
._ValueList
[1].count('_') != 4:
380 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
381 ExtraData
=self
._CurrentLine
,
383 Line
=self
._LineIndex
+1
386 def _GetMacros(self
):
388 Macros
.update(self
._FileLocalMacros
)
389 Macros
.update(self
._GetApplicableSectionMacro
())
393 ## Get section Macros that are applicable to current line, which may come from other sections
394 ## that share the same name while scope is wider
395 def _GetApplicableSectionMacro(self
):
397 for Scope1
, Scope2
in [("COMMON", "COMMON"), ("COMMON", self
._Scope
[0][1]),
398 (self
._Scope
[0][0], "COMMON"), (self
._Scope
[0][0], self
._Scope
[0][1])]:
399 if (self
._SectionType
, Scope1
, Scope2
) in self
._SectionsMacroDict
:
400 Macros
.update(self
._SectionsMacroDict
[(self
._SectionType
, Scope1
, Scope2
)])
404 Finished
= property(_GetFinished
, _SetFinished
)
405 _Macros
= property(_GetMacros
)
408 ## INF file parser class
410 # @param FilePath The path of platform description file
411 # @param FileType The raw data of DSC file
412 # @param Table Database used to retrieve module/package information
413 # @param Macros Macros used for replacement in file
415 class InfParser(MetaFileParser
):
416 # INF file supported data types (one type per section)
418 TAB_UNKNOWN
.upper() : MODEL_UNKNOWN
,
419 TAB_INF_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
420 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
421 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
422 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
423 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
424 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
425 TAB_PACKAGES
.upper() : MODEL_META_DATA_PACKAGE
,
426 TAB_NMAKE
.upper() : MODEL_META_DATA_NMAKE
,
427 TAB_INF_FIXED_PCD
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
428 TAB_INF_PATCH_PCD
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
429 TAB_INF_FEATURE_PCD
.upper() : MODEL_PCD_FEATURE_FLAG
,
430 TAB_INF_PCD_EX
.upper() : MODEL_PCD_DYNAMIC_EX
,
431 TAB_INF_PCD
.upper() : MODEL_PCD_DYNAMIC
,
432 TAB_SOURCES
.upper() : MODEL_EFI_SOURCE_FILE
,
433 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
434 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
435 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
436 TAB_DEPEX
.upper() : MODEL_EFI_DEPEX
,
437 TAB_BINARIES
.upper() : MODEL_EFI_BINARY_FILE
,
438 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
441 ## Constructor of InfParser
443 # Initialize object of InfParser
445 # @param FilePath The path of module description file
446 # @param FileType The raw data of DSC file
447 # @param Table Database used to retrieve module/package information
448 # @param Macros Macros used for replacement in file
450 def __init__(self
, FilePath
, FileType
, Table
):
451 # prevent re-initialization
452 if hasattr(self
, "_Table"):
454 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
455 self
.TblFile
= EccGlobalData
.gDb
.TblFile
464 Content
= open(str(self
.MetaFile
), 'r').readlines()
466 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
468 # Insert a record for file
470 Filename
= NormPath(self
.MetaFile
)
471 FileID
= self
.TblFile
.GetFileId(Filename
)
475 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_INF
)
477 # parse the file line by line
478 IsFindBlockComment
= False
480 for Index
in range(0, len(Content
)):
481 if self
._SectionType
in [MODEL_EFI_GUID
,
484 MODEL_PCD_FIXED_AT_BUILD
,
485 MODEL_PCD_PATCHABLE_IN_MODULE
,
486 MODEL_PCD_FEATURE_FLAG
,
487 MODEL_PCD_DYNAMIC_EX
,
489 Line
= Content
[Index
].strip()
490 if Line
.startswith(TAB_SPECIAL_COMMENT
):
491 Usage
+= ' ' + Line
[Line
.find(TAB_SPECIAL_COMMENT
):]
493 elif Line
.startswith(TAB_COMMENT_SPLIT
):
495 elif Line
.find(TAB_COMMENT_SPLIT
) > 0:
496 Usage
+= ' ' + Line
[Line
.find(TAB_COMMENT_SPLIT
):]
497 Line
= Line
[:Line
.find(TAB_COMMENT_SPLIT
)]
499 # skip empty, commented, block commented lines
500 Line
= CleanString(Content
[Index
], AllowCppStyleComment
=True)
503 if Index
+ 1 < len(Content
):
504 NextLine
= CleanString(Content
[Index
+ 1])
507 if Line
.find(DataType
.TAB_COMMENT_EDK_START
) > -1:
508 IsFindBlockComment
= True
510 if Line
.find(DataType
.TAB_COMMENT_EDK_END
) > -1:
511 IsFindBlockComment
= False
513 if IsFindBlockComment
:
516 self
._LineIndex
= Index
517 self
._CurrentLine
= Line
520 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
521 self
._SectionHeaderParser
()
522 # Check invalid sections
523 if self
._Version
< 0x00010005:
524 if self
._SectionType
in [MODEL_META_DATA_BUILD_OPTION
,
525 MODEL_EFI_LIBRARY_CLASS
,
526 MODEL_META_DATA_PACKAGE
,
527 MODEL_PCD_FIXED_AT_BUILD
,
528 MODEL_PCD_PATCHABLE_IN_MODULE
,
529 MODEL_PCD_FEATURE_FLAG
,
530 MODEL_PCD_DYNAMIC_EX
,
535 MODEL_META_DATA_USER_EXTENSION
]:
536 EdkLogger
.error('Parser', FORMAT_INVALID
,
537 "Section [%s] is not allowed in inf file without version" % (self
._SectionName
),
538 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
539 elif self
._SectionType
in [MODEL_EFI_INCLUDE
,
540 MODEL_EFI_LIBRARY_INSTANCE
,
541 MODEL_META_DATA_NMAKE
]:
542 EdkLogger
.error('Parser', FORMAT_INVALID
,
543 "Section [%s] is not allowed in inf file with version 0x%08x" % (self
._SectionName
, self
._Version
),
544 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
546 # merge two lines specified by '\' in section NMAKE
547 elif self
._SectionType
== MODEL_META_DATA_NMAKE
:
550 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
553 if NextLine
[0] == TAB_SECTION_START
and NextLine
[-1] == TAB_SECTION_END
:
554 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
557 NmakeLine
= NmakeLine
+ ' ' + Line
[0:-1]
560 self
._CurrentLine
= NmakeLine
+ Line
564 self
._ValueList
= ['', '', '']
565 # parse current line, result will be put in self._ValueList
566 self
._SectionParser
[self
._SectionType
](self
)
567 if self
._ValueList
is None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
571 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
572 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
574 self
._ValueList
[0] = self
._ValueList
[0].replace('/', '\\')
575 Usage
= Usage
.strip()
576 for Arch
, Platform
in self
._Scope
:
577 self
._Store
(self
._SectionType
,
593 if IsFindBlockComment
:
594 EdkLogger
.error("Parser", FORMAT_INVALID
, "Open block comments (starting with /*) are expected to end with */",
598 ## Data parser for the format in which there's path
600 # Only path can have macro used. So we need to replace them before use.
602 def _IncludeParser(self
):
603 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
604 self
._ValueList
[0:len(TokenList
)] = TokenList
605 Macros
= self
._Macros
607 for Index
in range(0, len(self
._ValueList
)):
608 Value
= self
._ValueList
[Index
]
612 if Value
.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value
.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
613 Value
= '$(EDK_SOURCE)' + Value
[17:]
614 if Value
.find('$(EFI_SOURCE)') > -1 or Value
.find('$(EDK_SOURCE)') > -1:
616 elif Value
.startswith('.'):
618 elif Value
.startswith('$('):
621 Value
= '$(EFI_SOURCE)/' + Value
623 self
._ValueList
[Index
] = ReplaceMacro(Value
, Macros
)
625 ## Parse [Sources] section
627 # Only path can have macro used. So we need to replace them before use.
630 def _SourceFileParser(self
):
631 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
632 self
._ValueList
[0:len(TokenList
)] = TokenList
633 Macros
= self
._Macros
634 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
635 if 'COMPONENT_TYPE' in Macros
:
636 if self
._Defines
['COMPONENT_TYPE'].upper() == 'ACPITABLE':
637 self
._ValueList
[0] = GetSplitValueList(self
._ValueList
[0], ' ', 1)[0]
638 if self
._Defines
['BASE_NAME'] == 'Microcode':
640 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
642 ## Parse [Binaries] section
644 # Only path can have macro used. So we need to replace them before use.
647 def _BinaryFileParser(self
):
648 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 2)
649 if len(TokenList
) < 2:
650 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type or path specified",
651 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
652 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
654 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type specified",
655 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
656 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
658 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file path specified",
659 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
660 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
661 self
._ValueList
[0:len(TokenList
)] = TokenList
662 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
664 ## [nmake] section parser (Edk.x style only)
665 def _NmakeParser(self
):
666 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
667 self
._ValueList
[0:len(TokenList
)] = TokenList
669 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
670 # remove self-reference in macro setting
671 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
673 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
675 def _PcdParser(self
):
676 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
677 ValueList
= GetSplitValueList(TokenList
[0], TAB_SPLIT
)
678 if len(ValueList
) != 2:
679 EdkLogger
.error('Parser', FORMAT_INVALID
, "Illegal token space GUID and PCD name format",
680 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
681 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
682 self
._ValueList
[0:1] = ValueList
683 if len(TokenList
) > 1:
684 self
._ValueList
[2] = TokenList
[1]
685 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
686 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
687 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
688 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
690 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
691 if self
._ValueList
[2] != '':
692 InfPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
693 if InfPcdValueList
[0] in ['True', 'true', 'TRUE']:
694 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '1', 1);
695 elif InfPcdValueList
[0] in ['False', 'false', 'FALSE']:
696 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '0', 1);
698 ## [depex] section parser
700 def _DepexParser(self
):
701 self
._ValueList
[0:1] = [self
._CurrentLine
]
704 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
705 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
706 MODEL_META_DATA_BUILD_OPTION
: MetaFileParser
._BuildOptionParser
,
707 MODEL_EFI_INCLUDE
: _IncludeParser
, # for Edk.x modules
708 MODEL_EFI_LIBRARY_INSTANCE
: MetaFileParser
._CommonParser
, # for Edk.x modules
709 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
710 MODEL_META_DATA_PACKAGE
: MetaFileParser
._PathParser
,
711 MODEL_META_DATA_NMAKE
: _NmakeParser
, # for Edk.x modules
712 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
713 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
714 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
715 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
716 MODEL_PCD_DYNAMIC
: _PcdParser
,
717 MODEL_EFI_SOURCE_FILE
: _SourceFileParser
,
718 MODEL_EFI_GUID
: MetaFileParser
._CommonParser
,
719 MODEL_EFI_PROTOCOL
: MetaFileParser
._CommonParser
,
720 MODEL_EFI_PPI
: MetaFileParser
._CommonParser
,
721 MODEL_EFI_DEPEX
: _DepexParser
,
722 MODEL_EFI_BINARY_FILE
: _BinaryFileParser
,
723 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
726 ## DSC file parser class
728 # @param FilePath The path of platform description file
729 # @param FileType The raw data of DSC file
730 # @param Table Database used to retrieve module/package information
731 # @param Macros Macros used for replacement in file
732 # @param Owner Owner ID (for sub-section parsing)
733 # @param From ID from which the data comes (for !INCLUDE directive)
735 class DscParser(MetaFileParser
):
736 # DSC file supported data types (one type per section)
738 TAB_SKUIDS
.upper() : MODEL_EFI_SKU_ID
,
739 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
740 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
741 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
742 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
743 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
744 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
745 TAB_PCDS_DYNAMIC_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_DEFAULT
,
746 TAB_PCDS_DYNAMIC_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_HII
,
747 TAB_PCDS_DYNAMIC_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_VPD
,
748 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT
,
749 TAB_PCDS_DYNAMIC_EX_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_HII
,
750 TAB_PCDS_DYNAMIC_EX_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_VPD
,
751 TAB_COMPONENTS
.upper() : MODEL_META_DATA_COMPONENT
,
752 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH
.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
,
753 TAB_DSC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
754 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
755 TAB_DSC_DEFINES_EDKGLOBAL
: MODEL_META_DATA_GLOBAL_DEFINE
,
756 TAB_INCLUDE
.upper() : MODEL_META_DATA_INCLUDE
,
757 TAB_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
758 TAB_IF_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
759 TAB_IF_N_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
,
760 TAB_ELSE_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
,
761 TAB_ELSE
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
762 TAB_END_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
,
763 TAB_ERROR
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR
,
766 # Valid names in define section
773 "PCD_INFO_GENERATION",
774 "SUPPORTED_ARCHITECTURES",
783 "FIX_LOAD_TOP_MEMORY_ADDRESS"
786 SubSectionDefineKeywords
= [
790 SymbolPattern
= ValueExpression
.SymbolPattern
792 ## Constructor of DscParser
794 # Initialize object of DscParser
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 def __init__(self
, FilePath
, FileType
, Table
, Owner
=-1, From
=-1):
804 # prevent re-initialization
805 if hasattr(self
, "_Table"):
807 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, Owner
, From
)
808 self
._Version
= 0x00010005 # Only EDK2 dsc file is supported
809 # to store conditional directive evaluation result
810 self
._DirectiveStack
= []
811 self
._DirectiveEvalStack
= []
814 # Final valid replacable symbols
817 # Map the ID between the original table and new table to track
820 self
._IdMapping
= {-1:-1}
822 self
.TblFile
= EccGlobalData
.gDb
.TblFile
829 Content
= open(str(self
.MetaFile
.Path
), 'r').readlines()
831 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
833 # Insert a record for file
835 Filename
= NormPath(self
.MetaFile
.Path
)
836 FileID
= self
.TblFile
.GetFileId(Filename
)
840 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_DSC
)
843 for Index
in range(0, len(Content
)):
844 Line
= CleanString(Content
[Index
])
849 self
._CurrentLine
= Line
850 self
._LineIndex
= Index
851 if self
._InSubsection
and self
._Owner
[-1] == -1:
852 self
._Owner
.append(self
._LastItem
)
855 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
856 self
._SectionType
= MODEL_META_DATA_SECTION_HEADER
858 elif Line
[0] == '}' and self
._InSubsection
:
859 self
._InSubsection
= False
860 self
._SubsectionType
= MODEL_UNKNOWN
861 self
._SubsectionName
= ''
865 elif Line
[0] == TAB_OPTION_START
and Line
[-1] == TAB_OPTION_END
:
866 self
._SubsectionType
= MODEL_META_DATA_SUBSECTION_HEADER
869 self
._DirectiveParser
()
872 if self
._InSubsection
:
873 SectionType
= self
._SubsectionType
875 SectionType
= self
._SectionType
876 self
._ItemType
= SectionType
878 self
._ValueList
= ['', '', '']
879 self
._SectionParser
[SectionType
](self
)
880 if self
._ValueList
is None:
883 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
884 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
886 for Arch
, ModuleType
in self
._Scope
:
887 self
._LastItem
= self
._Store
(
904 if self
._DirectiveStack
:
905 Type
, Line
, Text
= self
._DirectiveStack
[-1]
906 EdkLogger
.error('Parser', FORMAT_INVALID
, "No matching '!endif' found",
907 ExtraData
=Text
, File
=self
.MetaFile
, Line
=Line
)
910 ## <subsection_header> parser
911 def _SubsectionHeaderParser(self
):
912 self
._SubsectionName
= self
._CurrentLine
[1:-1].upper()
913 if self
._SubsectionName
in self
.DataType
:
914 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
916 self
._SubsectionType
= MODEL_UNKNOWN
917 EdkLogger
.warn("Parser", "Unrecognized sub-section", File
=self
.MetaFile
,
918 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
919 self
._ValueList
[0] = self
._SubsectionName
921 ## Directive statement parser
922 def _DirectiveParser(self
):
923 self
._ValueList
= ['', '', '']
924 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
925 self
._ValueList
[0:len(TokenList
)] = TokenList
928 DirectiveName
= self
._ValueList
[0].upper()
929 if DirectiveName
not in self
.DataType
:
930 EdkLogger
.error("Parser", FORMAT_INVALID
, "Unknown directive [%s]" % DirectiveName
,
931 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
932 if DirectiveName
in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self
._ValueList
[1] == '':
933 EdkLogger
.error("Parser", FORMAT_INVALID
, "Missing expression",
934 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
935 ExtraData
=self
._CurrentLine
)
937 ItemType
= self
.DataType
[DirectiveName
]
938 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
939 # Remove all directives between !if and !endif, including themselves
940 while self
._DirectiveStack
:
941 # Remove any !else or !elseif
942 DirectiveInfo
= self
._DirectiveStack
.pop()
943 if DirectiveInfo
[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
944 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
945 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
948 EdkLogger
.error("Parser", FORMAT_INVALID
, "Redundant '!endif'",
949 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
950 ExtraData
=self
._CurrentLine
)
951 elif ItemType
!= MODEL_META_DATA_INCLUDE
:
952 # Break if there's a !else is followed by a !elseif
953 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
and \
954 self
._DirectiveStack
and \
955 self
._DirectiveStack
[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
956 EdkLogger
.error("Parser", FORMAT_INVALID
, "'!elseif' after '!else'",
957 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
958 ExtraData
=self
._CurrentLine
)
959 self
._DirectiveStack
.append((ItemType
, self
._LineIndex
+1, self
._CurrentLine
))
961 EdkLogger
.error('Parser', FORMAT_INVALID
,
962 "No '!include' allowed in included file",
963 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
,
964 Line
=self
._LineIndex
+1)
967 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
968 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
970 self
._LastItem
= self
._Store
(
987 ## [defines] section parser
989 def _DefineParser(self
):
990 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
991 self
._ValueList
[1:len(TokenList
)] = TokenList
994 if not self
._ValueList
[1]:
995 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
996 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
997 if not self
._ValueList
[2]:
998 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
999 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1000 if (not self
._ValueList
[1] in self
.DefineKeywords
and
1001 (self
._InSubsection
and self
._ValueList
[1] not in self
.SubSectionDefineKeywords
)):
1002 EdkLogger
.error('Parser', FORMAT_INVALID
,
1003 "Unknown keyword found: %s. "
1004 "If this is a macro you must "
1005 "add it as a DEFINE in the DSC" % self
._ValueList
[1],
1006 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1007 self
._Defines
[self
._ValueList
[1]] = self
._ValueList
[2]
1008 self
._ItemType
= self
.DataType
[TAB_DSC_DEFINES
.upper()]
1011 def _SkuIdParser(self
):
1012 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1013 if len(TokenList
) != 2:
1014 EdkLogger
.error('Parser', FORMAT_INVALID
, "Correct format is '<Integer>|<UiName>'",
1015 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1016 self
._ValueList
[0:len(TokenList
)] = TokenList
1018 ## Parse Edk style of library modules
1019 def _LibraryInstanceParser(self
):
1020 self
._ValueList
[0] = self
._CurrentLine
1022 ## PCD sections parser
1024 # [PcdsFixedAtBuild]
1025 # [PcdsPatchableInModule]
1028 # [PcdsDynamicExDefault]
1029 # [PcdsDynamicExVpd]
1030 # [PcdsDynamicExHii]
1032 # [PcdsDynamicDefault]
1037 def _PcdParser(self
):
1038 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1039 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1040 if len(TokenList
) == 2:
1041 self
._ValueList
[2] = TokenList
[1]
1042 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1043 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1044 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1045 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1046 if self
._ValueList
[2] == '':
1047 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD value given",
1048 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1049 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1050 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1051 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
1052 if DscPcdValueList
[0] in ['True', 'true', 'TRUE']:
1053 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '1', 1);
1054 elif DscPcdValueList
[0] in ['False', 'false', 'FALSE']:
1055 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '0', 1);
1057 ## [components] section parser
1059 def _ComponentParser(self
):
1060 if self
._CurrentLine
[-1] == '{':
1061 self
._ValueList
[0] = self
._CurrentLine
[0:-1].strip()
1062 self
._InSubsection
= True
1064 self
._ValueList
[0] = self
._CurrentLine
1066 ## [LibraryClasses] section
1068 def _LibraryClassParser(self
):
1069 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1070 if len(TokenList
) < 2:
1071 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class or instance specified",
1072 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1073 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1074 if TokenList
[0] == '':
1075 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class specified",
1076 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1077 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1078 if TokenList
[1] == '':
1079 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library instance specified",
1080 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1081 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1083 self
._ValueList
[0:len(TokenList
)] = TokenList
1085 def _CompponentSourceOverridePathParser(self
):
1086 self
._ValueList
[0] = self
._CurrentLine
1088 ## [BuildOptions] section parser
1090 def _BuildOptionParser(self
):
1091 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1092 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
1093 if len(TokenList2
) == 2:
1094 self
._ValueList
[0] = TokenList2
[0] # toolchain family
1095 self
._ValueList
[1] = TokenList2
[1] # keys
1097 self
._ValueList
[1] = TokenList
[0]
1098 if len(TokenList
) == 2: # value
1099 self
._ValueList
[2] = TokenList
[1]
1101 if self
._ValueList
[1].count('_') != 4:
1105 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
1106 ExtraData
=self
._CurrentLine
,
1108 Line
=self
._LineIndex
+1
1111 ## Override parent's method since we'll do all macro replacements in parser
1112 def _GetMacros(self
):
1113 Macros
= dict( [('ARCH', 'IA32'), ('FAMILY', 'MSFT'), ('TOOL_CHAIN_TAG', 'VS2008x86'), ('TARGET', 'DEBUG')])
1114 Macros
.update(self
._FileLocalMacros
)
1115 Macros
.update(self
._GetApplicableSectionMacro
())
1116 Macros
.update(GlobalData
.gEdkGlobal
)
1117 Macros
.update(GlobalData
.gPlatformDefines
)
1118 Macros
.update(GlobalData
.gCommandLineDefines
)
1119 # PCD cannot be referenced in macro definition
1120 if self
._ItemType
not in [MODEL_META_DATA_DEFINE
, MODEL_META_DATA_GLOBAL_DEFINE
]:
1121 Macros
.update(self
._Symbols
)
1124 def _PostProcess(self
):
1126 MODEL_META_DATA_SECTION_HEADER
: self
.__ProcessSectionHeader
,
1127 MODEL_META_DATA_SUBSECTION_HEADER
: self
.__ProcessSubsectionHeader
,
1128 MODEL_META_DATA_HEADER
: self
.__ProcessDefine
,
1129 MODEL_META_DATA_DEFINE
: self
.__ProcessDefine
,
1130 MODEL_META_DATA_GLOBAL_DEFINE
: self
.__ProcessDefine
,
1131 MODEL_META_DATA_INCLUDE
: self
.__ProcessDirective
,
1132 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
: self
.__ProcessDirective
,
1133 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
: self
.__ProcessDirective
,
1134 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
: self
.__ProcessDirective
,
1135 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
: self
.__ProcessDirective
,
1136 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
: self
.__ProcessDirective
,
1137 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
: self
.__ProcessDirective
,
1138 MODEL_EFI_SKU_ID
: self
.__ProcessSkuId
,
1139 MODEL_EFI_LIBRARY_INSTANCE
: self
.__ProcessLibraryInstance
,
1140 MODEL_EFI_LIBRARY_CLASS
: self
.__ProcessLibraryClass
,
1141 MODEL_PCD_FIXED_AT_BUILD
: self
.__ProcessPcd
,
1142 MODEL_PCD_PATCHABLE_IN_MODULE
: self
.__ProcessPcd
,
1143 MODEL_PCD_FEATURE_FLAG
: self
.__ProcessPcd
,
1144 MODEL_PCD_DYNAMIC_DEFAULT
: self
.__ProcessPcd
,
1145 MODEL_PCD_DYNAMIC_HII
: self
.__ProcessPcd
,
1146 MODEL_PCD_DYNAMIC_VPD
: self
.__ProcessPcd
,
1147 MODEL_PCD_DYNAMIC_EX_DEFAULT
: self
.__ProcessPcd
,
1148 MODEL_PCD_DYNAMIC_EX_HII
: self
.__ProcessPcd
,
1149 MODEL_PCD_DYNAMIC_EX_VPD
: self
.__ProcessPcd
,
1150 MODEL_META_DATA_COMPONENT
: self
.__ProcessComponent
,
1151 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: self
.__ProcessSourceOverridePath
,
1152 MODEL_META_DATA_BUILD_OPTION
: self
.__ProcessBuildOption
,
1153 MODEL_UNKNOWN
: self
._Skip
,
1154 MODEL_META_DATA_USER_EXTENSION
: self
._Skip
,
1155 MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR
: self
._Skip
,
1158 self
._RawTable
= self
._Table
1159 self
._Table
= MetaFileStorage(self
._RawTable
.Cur
, self
.MetaFile
, MODEL_FILE_DSC
, True)
1160 self
._DirectiveStack
= []
1161 self
._DirectiveEvalStack
= []
1162 self
._FileWithError
= self
.MetaFile
1163 self
._FileLocalMacros
= {}
1164 self
._SectionsMacroDict
= {}
1165 GlobalData
.gPlatformDefines
= {}
1167 # Get all macro and PCD which has straitforward value
1168 self
.__RetrievePcdValue
()
1169 self
._Content
= self
._RawTable
.GetAll()
1170 self
._ContentIndex
= 0
1171 while self
._ContentIndex
< len(self
._Content
) :
1172 Id
, self
._ItemType
, V1
, V2
, V3
, S1
, S2
, Owner
, BelongsToFile
, self
._From
, \
1173 LineStart
, ColStart
, LineEnd
, ColEnd
, Enabled
= self
._Content
[self
._ContentIndex
]
1176 self
._FileWithError
= self
.MetaFile
1178 self
._ContentIndex
+= 1
1180 self
._Scope
= [[S1
, S2
]]
1181 self
._LineIndex
= LineStart
- 1
1182 self
._ValueList
= [V1
, V2
, V3
]
1185 Processer
[self
._ItemType
]()
1186 except EvaluationException
as Excpt
:
1188 # Only catch expression evaluation error here. We need to report
1189 # the precise number of line on which the error occurred
1192 # EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
1193 # File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1194 # Line=self._LineIndex+1)
1195 except MacroException
as Excpt
:
1196 EdkLogger
.error('Parser', FORMAT_INVALID
, str(Excpt
),
1197 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1198 Line
=self
._LineIndex
+1)
1200 if self
._ValueList
is None:
1203 NewOwner
= self
._IdMapping
.get(Owner
, -1)
1204 self
._Enabled
= int((not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
))
1205 self
._LastItem
= self
._Store
(
1221 self
._IdMapping
[Id
] = self
._LastItem
1223 RecordList
= self
._Table
.GetAll()
1225 self
._RawTable
.Drop()
1227 for Record
in RecordList
:
1228 EccGlobalData
.gDb
.TblDsc
.Insert(Record
[1], Record
[2], Record
[3], Record
[4], Record
[5], Record
[6], Record
[7], Record
[8], Record
[9], Record
[10], Record
[11], Record
[12], Record
[13], Record
[14])
1229 GlobalData
.gPlatformDefines
.update(self
._FileLocalMacros
)
1230 self
._PostProcessed
= True
1231 self
._Content
= None
1233 def __ProcessSectionHeader(self
):
1234 self
._SectionName
= self
._ValueList
[0]
1235 if self
._SectionName
in self
.DataType
:
1236 self
._SectionType
= self
.DataType
[self
._SectionName
]
1238 self
._SectionType
= MODEL_UNKNOWN
1240 def __ProcessSubsectionHeader(self
):
1241 self
._SubsectionName
= self
._ValueList
[0]
1242 if self
._SubsectionName
in self
.DataType
:
1243 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
1245 self
._SubsectionType
= MODEL_UNKNOWN
1247 def __RetrievePcdValue(self
):
1248 Records
= self
._RawTable
.Query(MODEL_PCD_FEATURE_FLAG
, BelongsToItem
=-1.0)
1249 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1250 Value
, DatumType
, MaxDatumSize
= AnalyzePcdData(Value
)
1251 # Only use PCD whose value is straitforward (no macro and PCD)
1252 if self
.SymbolPattern
.findall(Value
):
1254 Name
= TokenSpaceGuid
+ '.' + PcdName
1255 # Don't use PCD with different values.
1256 if Name
in self
._Symbols
and self
._Symbols
[Name
] != Value
:
1257 self
._Symbols
.pop(Name
)
1259 self
._Symbols
[Name
] = Value
1261 Records
= self
._RawTable
.Query(MODEL_PCD_FIXED_AT_BUILD
, BelongsToItem
=-1.0)
1262 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1263 Value
, DatumType
, MaxDatumSize
= AnalyzePcdData(Value
)
1264 # Only use PCD whose value is straitforward (no macro and PCD)
1265 if self
.SymbolPattern
.findall(Value
):
1267 Name
= TokenSpaceGuid
+'.'+PcdName
1268 # Don't use PCD with different values.
1269 if Name
in self
._Symbols
and self
._Symbols
[Name
] != Value
:
1270 self
._Symbols
.pop(Name
)
1272 self
._Symbols
[Name
] = Value
1274 def __ProcessDefine(self
):
1275 if not self
._Enabled
:
1278 Type
, Name
, Value
= self
._ValueList
1279 Value
= ReplaceMacro(Value
, self
._Macros
, False)
1280 if self
._ItemType
== MODEL_META_DATA_DEFINE
:
1281 if self
._SectionType
== MODEL_META_DATA_HEADER
:
1282 self
._FileLocalMacros
[Name
] = Value
1284 SectionDictKey
= self
._SectionType
, self
._Scope
[0][0], self
._Scope
[0][1]
1285 if SectionDictKey
not in self
._SectionsMacroDict
:
1286 self
._SectionsMacroDict
[SectionDictKey
] = {}
1287 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
1288 SectionLocalMacros
[Name
] = Value
1289 elif self
._ItemType
== MODEL_META_DATA_GLOBAL_DEFINE
:
1290 GlobalData
.gEdkGlobal
[Name
] = Value
1293 # Keyword in [Defines] section can be used as Macros
1295 if (self
._ItemType
== MODEL_META_DATA_HEADER
) and (self
._SectionType
== MODEL_META_DATA_HEADER
):
1296 self
._FileLocalMacros
[Name
] = Value
1298 self
._ValueList
= [Type
, Name
, Value
]
1300 def __ProcessDirective(self
):
1302 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1303 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
]:
1304 Macros
= self
._Macros
1305 Macros
.update(GlobalData
.gGlobalDefines
)
1307 Result
= ValueExpression(self
._ValueList
[1], Macros
)()
1308 except SymbolNotFound
as Exc
:
1309 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1311 except WrnExpression
as Excpt
:
1313 # Catch expression evaluation warning here. We need to report
1314 # the precise number of line and return the evaluation result
1316 EdkLogger
.warn('Parser', "Suspicious expression: %s" % str(Excpt
),
1317 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1318 Line
=self
._LineIndex
+1)
1319 Result
= Excpt
.result
1320 except BadExpression
as Exc
:
1321 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1324 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1325 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1326 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1327 self
._DirectiveStack
.append(self
._ItemType
)
1328 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
:
1329 Result
= bool(Result
)
1331 Macro
= self
._ValueList
[1]
1332 Macro
= Macro
[2:-1] if (Macro
.startswith("$(") and Macro
.endswith(")")) else Macro
1333 Result
= Macro
in self
._Macros
1334 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
:
1336 self
._DirectiveEvalStack
.append(Result
)
1337 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
:
1338 self
._DirectiveStack
.append(self
._ItemType
)
1339 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1340 self
._DirectiveEvalStack
.append(bool(Result
))
1341 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1342 self
._DirectiveStack
[-1] = self
._ItemType
1343 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1344 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1345 # Back to the nearest !if/!ifdef/!ifndef
1346 while self
._DirectiveStack
:
1347 self
._DirectiveEvalStack
.pop()
1348 Directive
= self
._DirectiveStack
.pop()
1349 if Directive
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1350 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1351 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
1352 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1354 elif self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1355 # The included file must be relative to workspace or same directory as DSC file
1356 __IncludeMacros
= {}
1358 # Allow using system environment variables in path after !include
1360 __IncludeMacros
['WORKSPACE'] = GlobalData
.gGlobalDefines
['WORKSPACE']
1361 if "ECP_SOURCE" in GlobalData
.gGlobalDefines
.keys():
1362 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gGlobalDefines
['ECP_SOURCE']
1364 # During GenFds phase call DSC parser, will go into this branch.
1366 elif "ECP_SOURCE" in GlobalData
.gCommandLineDefines
.keys():
1367 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gCommandLineDefines
['ECP_SOURCE']
1369 __IncludeMacros
['EFI_SOURCE'] = GlobalData
.gGlobalDefines
['EFI_SOURCE']
1370 __IncludeMacros
['EDK_SOURCE'] = GlobalData
.gGlobalDefines
['EDK_SOURCE']
1372 # Allow using MACROs comes from [Defines] section to keep compatible.
1374 __IncludeMacros
.update(self
._Macros
)
1376 IncludedFile
= NormPath(ReplaceMacro(self
._ValueList
[1], __IncludeMacros
, RaiseError
=True))
1378 # First search the include file under the same directory as DSC file
1380 IncludedFile1
= PathClass(IncludedFile
, self
.MetaFile
.Dir
)
1381 ErrorCode
, ErrorInfo1
= IncludedFile1
.Validate()
1384 # Also search file under the WORKSPACE directory
1386 IncludedFile1
= PathClass(IncludedFile
, GlobalData
.gWorkspace
)
1387 ErrorCode
, ErrorInfo2
= IncludedFile1
.Validate()
1389 EdkLogger
.error('parser', ErrorCode
, File
=self
._FileWithError
,
1390 Line
=self
._LineIndex
+1, ExtraData
=ErrorInfo1
+ "\n"+ ErrorInfo2
)
1392 self
._FileWithError
= IncludedFile1
1394 IncludedFileTable
= MetaFileStorage(self
._Table
.Cur
, IncludedFile1
, MODEL_FILE_DSC
, True)
1395 Owner
= self
._Content
[self
._ContentIndex
-1][0]
1396 Parser
= DscParser(IncludedFile1
, self
._FileType
, IncludedFileTable
,
1397 Owner
=Owner
, From
=Owner
)
1399 # set the parser status with current status
1400 Parser
._SectionName
= self
._SectionName
1401 Parser
._SectionType
= self
._SectionType
1402 Parser
._Scope
= self
._Scope
1403 Parser
._Enabled
= self
._Enabled
1404 # Parse the included file
1407 # update current status with sub-parser's status
1408 self
._SectionName
= Parser
._SectionName
1409 self
._SectionType
= Parser
._SectionType
1410 self
._Scope
= Parser
._Scope
1411 self
._Enabled
= Parser
._Enabled
1413 # Insert all records in the table for the included file into dsc file table
1414 Records
= IncludedFileTable
.GetAll()
1416 self
._Content
[self
._ContentIndex
:self
._ContentIndex
] = Records
1417 self
._Content
.pop(self
._ContentIndex
-1)
1418 self
._ValueList
= None
1419 self
._ContentIndex
-= 1
1421 def __ProcessSkuId(self
):
1422 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=True)
1423 for Value
in self
._ValueList
]
1425 def __ProcessLibraryInstance(self
):
1426 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
1428 def __ProcessLibraryClass(self
):
1429 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, RaiseError
=True)
1431 def __ProcessPcd(self
):
1432 ValueList
= GetSplitValueList(self
._ValueList
[2])
1434 # PCD value can be an expression
1436 if len(ValueList
) > 1 and ValueList
[1] == TAB_VOID
:
1437 PcdValue
= ValueList
[0]
1439 ValueList
[0] = ValueExpression(PcdValue
, self
._Macros
)(True)
1440 except WrnExpression
as Value
:
1441 ValueList
[0] = Value
.result
1443 PcdValue
= ValueList
[-1]
1445 ValueList
[-1] = ValueExpression(PcdValue
, self
._Macros
)(True)
1446 except WrnExpression
as Value
:
1447 ValueList
[-1] = Value
.result
1449 if ValueList
[-1] == 'True':
1451 if ValueList
[-1] == 'False':
1454 self
._ValueList
[2] = '|'.join(ValueList
)
1456 def __ProcessComponent(self
):
1457 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1459 def __ProcessSourceOverridePath(self
):
1460 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1462 def __ProcessBuildOption(self
):
1463 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=False)
1464 for Value
in self
._ValueList
]
1467 MODEL_META_DATA_HEADER
: _DefineParser
,
1468 MODEL_EFI_SKU_ID
: _SkuIdParser
,
1469 MODEL_EFI_LIBRARY_INSTANCE
: _LibraryInstanceParser
,
1470 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
1471 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1472 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1473 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1474 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
1475 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
1476 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
1477 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
1478 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
1479 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
1480 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
1481 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: _CompponentSourceOverridePathParser
,
1482 MODEL_META_DATA_BUILD_OPTION
: _BuildOptionParser
,
1483 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1484 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1485 MODEL_META_DATA_SECTION_HEADER
: MetaFileParser
._SectionHeaderParser
,
1486 MODEL_META_DATA_SUBSECTION_HEADER
: _SubsectionHeaderParser
,
1489 _Macros
= property(_GetMacros
)
1491 ## DEC file parser class
1493 # @param FilePath The path of platform description file
1494 # @param FileType The raw data of DSC file
1495 # @param Table Database used to retrieve module/package information
1496 # @param Macros Macros used for replacement in file
1498 class DecParser(MetaFileParser
):
1499 # DEC file supported data types (one type per section)
1501 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1502 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
1503 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1504 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1505 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1506 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1507 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1508 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1509 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1510 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1511 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1512 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1515 ## Constructor of DecParser
1517 # Initialize object of DecParser
1519 # @param FilePath The path of platform description file
1520 # @param FileType The raw data of DSC file
1521 # @param Table Database used to retrieve module/package information
1522 # @param Macros Macros used for replacement in file
1524 def __init__(self
, FilePath
, FileType
, Table
):
1525 # prevent re-initialization
1526 if hasattr(self
, "_Table"):
1528 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
1530 self
._Version
= 0x00010005 # Only EDK2 dec file is supported
1531 self
.TblFile
= EccGlobalData
.gDb
.TblFile
1538 Content
= open(str(self
.MetaFile
), 'r').readlines()
1540 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1543 # Insert a record for file
1545 Filename
= NormPath(self
.MetaFile
)
1546 FileID
= self
.TblFile
.GetFileId(Filename
)
1548 self
.FileID
= FileID
1550 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_DEC
)
1552 for Index
in range(0, len(Content
)):
1553 Line
, Comment
= CleanString2(Content
[Index
])
1554 self
._CurrentLine
= Line
1555 self
._LineIndex
= Index
1557 # save comment for later use
1559 self
._Comments
.append((Comment
, self
._LineIndex
+1))
1565 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1566 self
._SectionHeaderParser
()
1569 elif len(self
._SectionType
) == 0:
1574 self
._ValueList
= ['', '', '']
1575 self
._SectionParser
[self
._SectionType
[0]](self
)
1576 if self
._ValueList
is None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
1582 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1583 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1585 for Arch
, ModuleType
, Type
in self
._Scope
:
1586 self
._LastItem
= self
._Store
(
1601 for Comment
, LineNo
in self
._Comments
:
1603 MODEL_META_DATA_COMMENT
,
1620 def _GetApplicableSectionMacro(self
):
1622 for S1
, S2
, SectionType
in self
._Scope
:
1623 for Scope1
, Scope2
in [("COMMON", "COMMON"), ("COMMON", S2
), (S1
, "COMMON"), (S1
, S2
)]:
1624 if (SectionType
, Scope1
, Scope2
) in self
._SectionsMacroDict
:
1625 Macros
.update(self
._SectionsMacroDict
[(SectionType
, Scope1
, Scope2
)])
1628 ## Section header parser
1630 # The section header is always in following format:
1632 # [section_name.arch<.platform|module_type>]
1634 def _SectionHeaderParser(self
):
1636 self
._SectionName
= ''
1637 self
._SectionType
= []
1639 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
1642 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
)
1644 # different types of PCD are permissible in one section
1645 self
._SectionName
= ItemList
[0].upper()
1646 if self
._SectionName
in self
.DataType
:
1647 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1648 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1650 EdkLogger
.warn("Parser", "Unrecognized section", File
=self
.MetaFile
,
1651 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
1654 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1658 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1660 Line
=self
._LineIndex
+1,
1661 ExtraData
=self
._CurrentLine
1664 if len(ItemList
) > 1:
1665 S1
= ItemList
[1].upper()
1669 # S2 may be Platform or ModuleType
1670 if len(ItemList
) > 2:
1671 S2
= ItemList
[2].upper()
1674 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1675 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1677 # 'COMMON' must not be used with specific ARCHs at the same section
1678 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1679 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1680 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
1682 ## [guids], [ppis] and [protocols] section parser
1684 def _GuidParser(self
):
1685 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1686 if len(TokenList
) < 2:
1687 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1688 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1689 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1690 if TokenList
[0] == '':
1691 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1692 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1693 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1694 if TokenList
[1] == '':
1695 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1696 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1697 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1698 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1699 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1700 ExtraData
=self
._CurrentLine
+ \
1701 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1702 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1703 self
._ValueList
[0] = TokenList
[0]
1704 #Parse the Guid value format
1705 GuidValueList
= TokenList
[1].strip(' {}').split(',')
1708 if len(GuidValueList
) == 11:
1709 for GuidValue
in GuidValueList
:
1710 GuidValue
= GuidValue
.strip()
1711 if GuidValue
.startswith('0x') or GuidValue
.startswith('0X'):
1712 HexList
.append('0x' + str(GuidValue
[2:]))
1716 if GuidValue
.startswith('{'):
1717 GuidValue
= GuidValue
.lstrip(' {')
1718 HexList
.append('0x' + str(GuidValue
[2:]))
1720 self
._ValueList
[1] = "{ %s, %s, %s, { %s, %s, %s, %s, %s, %s, %s, %s }}" % (HexList
[0], HexList
[1], HexList
[2], HexList
[3], HexList
[4], HexList
[5], HexList
[6], HexList
[7], HexList
[8], HexList
[9], HexList
[10])
1722 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1723 ExtraData
=self
._CurrentLine
+ \
1724 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1725 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1726 self
._ValueList
[0] = ''
1728 ## PCD sections parser
1730 # [PcdsFixedAtBuild]
1731 # [PcdsPatchableInModule]
1737 def _PcdParser(self
):
1738 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1739 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1740 # check PCD information
1741 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1742 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1743 ExtraData
=self
._CurrentLine
+ \
1744 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1745 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1746 # check PCD datum information
1747 if len(TokenList
) < 2 or TokenList
[1] == '':
1748 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1749 ExtraData
=self
._CurrentLine
+ \
1750 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1751 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1754 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1755 PtrValue
= ValueRe
.findall(TokenList
[1])
1757 # Has VOID* type string, may contain "|" character in the string.
1758 if len(PtrValue
) != 0:
1759 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1760 ValueList
= GetSplitValueList(ptrValueList
)
1761 ValueList
[0] = PtrValue
[0]
1763 ValueList
= GetSplitValueList(TokenList
[1])
1766 # check if there's enough datum information given
1767 if len(ValueList
) != 3:
1768 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1769 ExtraData
=self
._CurrentLine
+ \
1770 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1771 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1772 # check default value
1773 if ValueList
[0] == '':
1774 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1775 ExtraData
=self
._CurrentLine
+ \
1776 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1777 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1779 if ValueList
[1] == '':
1780 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1781 ExtraData
=self
._CurrentLine
+ \
1782 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1783 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1784 # check token of the PCD
1785 if ValueList
[2] == '':
1786 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1787 ExtraData
=self
._CurrentLine
+ \
1788 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1789 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1790 # check format of default value against the datum type
1791 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1793 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1794 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1796 if EccGlobalData
.gConfig
.UniCheckPCDInfo
== '1' or EccGlobalData
.gConfig
.UniCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
1797 # check Description, Prompt information
1798 PatternDesc
= re
.compile('##\s*([\x21-\x7E\s]*)', re
.S
)
1799 PatternPrompt
= re
.compile('#\s+@Prompt\s+([\x21-\x7E\s]*)', re
.S
)
1802 # check @ValidRange, @ValidList and @Expression format valid
1803 ErrorCodeValid
= '0x0 <= %s <= 0xFFFFFFFF'
1804 PatternValidRangeIn
= '(NOT)?\s*(\d+\s*-\s*\d+|0[xX][a-fA-F0-9]+\s*-\s*0[xX][a-fA-F0-9]+|LT\s*\d+|LT\s*0[xX][a-fA-F0-9]+|GT\s*\d+|GT\s*0[xX][a-fA-F0-9]+|LE\s*\d+|LE\s*0[xX][a-fA-F0-9]+|GE\s*\d+|GE\s*0[xX][a-fA-F0-9]+|XOR\s*\d+|XOR\s*0[xX][a-fA-F0-9]+|EQ\s*\d+|EQ\s*0[xX][a-fA-F0-9]+)'
1805 PatternValidRng
= re
.compile('^' + '(NOT)?\s*' + PatternValidRangeIn
+ '$')
1806 for Comment
in self
._Comments
:
1807 Comm
= Comment
[0].strip()
1811 Description
= PatternDesc
.findall(Comm
)
1813 Prompt
= PatternPrompt
.findall(Comm
)
1815 ValidFormt
= Comm
.lstrip('#')
1816 ValidFormt
= ValidFormt
.lstrip()
1817 if ValidFormt
[0:11] == '@ValidRange':
1818 ValidFormt
= ValidFormt
[11:]
1819 ValidFormt
= ValidFormt
.lstrip()
1821 ErrorCode
, Expression
= ValidFormt
.split('|', 1)
1824 Expression
= ValidFormt
1825 ErrorCode
, Expression
= ErrorCode
.strip(), Expression
.strip()
1827 if not eval(ErrorCodeValid
% ErrorCode
):
1828 EdkLogger
.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1830 EdkLogger
.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1831 if not PatternValidRng
.search(Expression
):
1832 EdkLogger
.warn('Parser', '@ValidRange Expression(%s) of PCD %s is incorrect format.' % (Expression
, TokenList
[0]))
1833 if ValidFormt
[0:10] == '@ValidList':
1834 ValidFormt
= ValidFormt
[10:]
1835 ValidFormt
= ValidFormt
.lstrip()
1837 ErrorCode
, Expression
= ValidFormt
.split('|', 1)
1840 Expression
= ValidFormt
1841 ErrorCode
, Expression
= ErrorCode
.strip(), Expression
.strip()
1843 if not eval(ErrorCodeValid
% ErrorCode
):
1844 EdkLogger
.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1846 EdkLogger
.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1847 Values
= Expression
.split(',')
1848 for Value
in Values
:
1849 Value
= Value
.strip()
1853 EdkLogger
.warn('Parser', '@ValidList Expression of PCD %s include a invalid value(%s).' % (TokenList
[0], Value
))
1855 if ValidFormt
[0:11] == '@Expression':
1856 ValidFormt
= ValidFormt
[11:]
1857 ValidFormt
= ValidFormt
.lstrip()
1859 ErrorCode
, Expression
= ValidFormt
.split('|', 1)
1862 Expression
= ValidFormt
1863 ErrorCode
, Expression
= ErrorCode
.strip(), Expression
.strip()
1865 if not eval(ErrorCodeValid
% ErrorCode
):
1866 EdkLogger
.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1868 EdkLogger
.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1870 EdkLogger
.warn('Parser', '@Expression Expression of PCD %s is incorrect format.' % TokenList
[0])
1872 EdkLogger
.warn('Parser', 'PCD %s Description information is not provided.' % TokenList
[0])
1874 EdkLogger
.warn('Parser', 'PCD %s Prompt information is not provided.' % TokenList
[0])
1875 # check Description, Prompt localization information
1877 self
._UniObj
.CheckPcdInfo(TokenList
[0])
1879 if ValueList
[0] in ['True', 'true', 'TRUE']:
1881 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1884 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
1887 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
1888 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
1889 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
1890 MODEL_EFI_GUID
: _GuidParser
,
1891 MODEL_EFI_PPI
: _GuidParser
,
1892 MODEL_EFI_PROTOCOL
: _GuidParser
,
1893 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1894 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1895 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1896 MODEL_PCD_DYNAMIC
: _PcdParser
,
1897 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
1898 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1899 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1905 # This class defined the structure used in Fdf object
1907 # @param Filename: Input value for Ffilename of Fdf file, default is None
1908 # @param WorkspaceDir: Input value for current workspace directory, default is None
1911 def __init__(self
, Filename
= None, IsToDatabase
= False, WorkspaceDir
= None, Database
= None):
1912 self
.WorkspaceDir
= WorkspaceDir
1913 self
.IsToDatabase
= IsToDatabase
1915 self
.Cur
= Database
.Cur
1916 self
.TblFile
= Database
.TblFile
1917 self
.TblFdf
= Database
.TblFdf
1922 # Load Fdf file if filename is not None
1924 if Filename
is not None:
1926 self
.LoadFdfFile(Filename
)
1931 # Insert a FDF file record into database
1933 def InsertFile(self
, Filename
):
1935 Filename
= NormPath(Filename
)
1936 if Filename
not in self
.FileList
:
1937 FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_FDF
)
1938 self
.FileList
[Filename
] = FileID
1940 return self
.FileList
[Filename
]
1945 # Load the file if it exists
1947 # @param Filename: Input value for filename of Fdf file
1949 def LoadFdfFile(self
, Filename
):
1954 Filename
= NormPath(Filename
)
1955 Fdf
= FdfParser(Filename
)
1959 # Insert inf file and pcd information
1961 if self
.IsToDatabase
:
1962 (Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
) = \
1963 (0, '', '', '', 'COMMON', 'COMMON', -1, -1, -1, -1, -1, -1, 0)
1964 for Index
in range(0, len(Fdf
.Profile
.PcdDict
)):
1966 for Key
in Fdf
.Profile
.PcdDict
.keys():
1970 FileName
= Fdf
.Profile
.PcdFileLineDict
[Key
][0]
1971 StartLine
= Fdf
.Profile
.PcdFileLineDict
[Key
][1]
1972 BelongsToFile
= self
.InsertFile(FileName
)
1973 self
.TblFdf
.Insert(Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
)
1974 for Index
in range(0, len(Fdf
.Profile
.InfList
)):
1975 Model
= MODEL_META_DATA_COMPONENT
1976 Value1
= Fdf
.Profile
.InfList
[Index
]
1978 FileName
= Fdf
.Profile
.InfFileLineList
[Index
][0]
1979 StartLine
= Fdf
.Profile
.InfFileLineList
[Index
][1]
1980 BelongsToFile
= self
.InsertFile(FileName
)
1981 self
.TblFdf
.Insert(Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
)
1983 class UniParser(object):
1984 # IsExtraUni defined the UNI file is Module UNI or extra Module UNI
1985 # IsModuleUni defined the UNI file is Module UNI or Package UNI
1986 def __init__(self
, FilePath
, IsExtraUni
=False, IsModuleUni
=True):
1987 self
.FilePath
= FilePath
1988 self
.FileName
= os
.path
.basename(FilePath
)
1989 self
.IsExtraUni
= IsExtraUni
1990 self
.IsModuleUni
= IsModuleUni
1997 self
.FileIn
= CodecOpenLongFilePath(self
.FilePath
, Mode
='rb', Encoding
='utf_8').read()
1998 except UnicodeError:
1999 self
.FileIn
= CodecOpenLongFilePath(self
.FilePath
, Mode
='rb', Encoding
='utf_16').read()
2000 except UnicodeError:
2001 self
.FileIn
= CodecOpenLongFilePath(self
.FilePath
, Mode
='rb', Encoding
='utf_16_le').read()
2006 if self
.IsModuleUni
:
2008 ModuleName
= self
.CheckKeyValid('STR_PROPERTIES_MODULE_NAME')
2009 self
.PrintLog('STR_PROPERTIES_MODULE_NAME', ModuleName
)
2011 ModuleAbstract
= self
.CheckKeyValid('STR_MODULE_ABSTRACT')
2012 self
.PrintLog('STR_MODULE_ABSTRACT', ModuleAbstract
)
2013 ModuleDescription
= self
.CheckKeyValid('STR_MODULE_DESCRIPTION')
2014 self
.PrintLog('STR_MODULE_DESCRIPTION', ModuleDescription
)
2017 PackageName
= self
.CheckKeyValid('STR_PROPERTIES_PACKAGE_NAME')
2018 self
.PrintLog('STR_PROPERTIES_PACKAGE_NAME', PackageName
)
2020 PackageAbstract
= self
.CheckKeyValid('STR_PACKAGE_ABSTRACT')
2021 self
.PrintLog('STR_PACKAGE_ABSTRACT', PackageAbstract
)
2022 PackageDescription
= self
.CheckKeyValid('STR_PACKAGE_DESCRIPTION')
2023 self
.PrintLog('STR_PACKAGE_DESCRIPTION', PackageDescription
)
2025 def CheckKeyValid(self
, Key
, Contents
=None):
2027 Contents
= self
.FileIn
2028 KeyPattern
= re
.compile('#string\s+%s\s+.*?#language.*?".*?"' % Key
, re
.S
)
2029 if KeyPattern
.search(Contents
):
2033 def CheckPcdInfo(self
, PcdCName
):
2034 PromptKey
= 'STR_%s_PROMPT' % PcdCName
.replace('.', '_')
2035 PcdPrompt
= self
.CheckKeyValid(PromptKey
)
2036 self
.PrintLog(PromptKey
, PcdPrompt
)
2037 HelpKey
= 'STR_%s_HELP' % PcdCName
.replace('.', '_')
2038 PcdHelp
= self
.CheckKeyValid(HelpKey
)
2039 self
.PrintLog(HelpKey
, PcdHelp
)
2041 def PrintLog(self
, Key
, Value
):
2042 if not Value
and Key
not in self
.Missing
:
2043 Msg
= '%s is missing in the %s file.' % (Key
, self
.FileName
)
2044 EdkLogger
.warn('Parser', Msg
)
2045 EccGlobalData
.gDb
.TblReport
.Insert(EccToolError
.ERROR_GENERAL_CHECK_UNI_HELP_INFO
, OtherMsg
=Msg
, BelongsToTable
='File', BelongsToItem
=-2)
2046 self
.Missing
.append(Key
)
2050 # This acts like the main() function for the script, unless it is 'import'ed into another
2053 if __name__
== '__main__':