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 from __future__
import absolute_import
18 import Common
.LongFilePathOs
as os
23 import Common
.EdkLogger
as EdkLogger
24 import Common
.GlobalData
as GlobalData
25 import Ecc
.EccGlobalData
as EccGlobalData
26 import Ecc
.EccToolError
as EccToolError
28 from CommonDataClass
.DataClass
import *
29 from Common
.DataType
import *
30 from Common
.StringUtils
import *
31 from Common
.Misc
import GuidStructureStringToGuidString
, CheckPcdDatum
, PathClass
, AnalyzePcdData
32 from Common
.Expression
import *
33 from CommonDataClass
.Exceptions
import *
35 from Ecc
.MetaFileWorkspace
.MetaFileTable
import MetaFileStorage
36 from GenFds
.FdfParser
import FdfParser
37 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
38 from Common
.LongFilePathSupport
import CodecOpenLongFilePath
40 ## A decorator used to parse macro definition
41 def ParseMacro(Parser
):
42 def MacroParser(self
):
43 Match
= GlobalData
.gMacroDefPattern
.match(self
._CurrentLine
)
45 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
49 TokenList
= GetSplitValueList(self
._CurrentLine
[Match
.end(1):], TAB_EQUAL_SPLIT
, 1)
52 EdkLogger
.error('Parser', FORMAT_INVALID
, "No macro name given",
53 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
54 if len(TokenList
) < 2:
58 Name
, Value
= TokenList
59 # Global macros can be only defined via environment variable
60 if Name
in GlobalData
.gGlobalDefines
:
61 EdkLogger
.error('Parser', FORMAT_INVALID
, "%s can only be defined via environment variable" % Name
,
62 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
63 # Only upper case letters, digit and '_' are allowed
64 if not GlobalData
.gMacroNamePattern
.match(Name
):
65 EdkLogger
.error('Parser', FORMAT_INVALID
, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
66 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
68 Value
= ReplaceMacro(Value
, self
._Macros
)
69 self
._ItemType
= MODEL_META_DATA_DEFINE
70 # DEFINE defined macros
71 if Type
== TAB_DSC_DEFINES_DEFINE
:
72 if isinstance(self
, DecParser
):
73 if MODEL_META_DATA_HEADER
in self
._SectionType
:
74 self
._FileLocalMacros
[Name
] = Value
76 for Scope
in self
._Scope
:
77 self
._SectionsMacroDict
.setdefault((Scope
[2], Scope
[0], Scope
[1]), {})[Name
] = Value
78 elif self
._SectionType
== MODEL_META_DATA_HEADER
:
79 self
._FileLocalMacros
[Name
] = Value
81 SectionDictKey
= self
._SectionType
, self
._Scope
[0][0], self
._Scope
[0][1]
82 if SectionDictKey
not in self
._SectionsMacroDict
:
83 self
._SectionsMacroDict
[SectionDictKey
] = {}
84 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
85 SectionLocalMacros
[Name
] = Value
86 # EDK_GLOBAL defined macros
87 elif not isinstance(self
, DscParser
):
88 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used in .dsc file",
89 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
90 elif self
._SectionType
!= MODEL_META_DATA_HEADER
:
91 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used under [Defines] section",
92 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
93 elif (Name
in self
._FileLocalMacros
) and (self
._FileLocalMacros
[Name
] != Value
):
94 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
95 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
97 self
._ValueList
= [Type
, Name
, Value
]
101 ## Base class of parser
103 # This class is used for derivation purpose. The specific parser for one kind
104 # type file must derive this class and implement some public interfaces.
106 # @param FilePath The path of platform description file
107 # @param FileType The raw data of DSC file
108 # @param Table Database used to retrieve module/package information
109 # @param Macros Macros used for replacement in file
110 # @param Owner Owner ID (for sub-section parsing)
111 # @param From ID from which the data comes (for !INCLUDE directive)
113 class MetaFileParser(object):
114 # data type (file content) for specific file type
117 # Parser objects used to implement singleton
122 # One file, one parser object. This factory method makes sure that there's
123 # only one object constructed for one meta file.
125 # @param Class class object of real AutoGen class
126 # (InfParser, DecParser or DscParser)
127 # @param FilePath The path of meta file
128 # @param *args The specific class related parameters
129 # @param **kwargs The specific class related dict parameters
131 def __new__(Class
, FilePath
, *args
, **kwargs
):
132 if FilePath
in Class
.MetaFiles
:
133 return Class
.MetaFiles
[FilePath
]
135 ParserObject
= super(MetaFileParser
, Class
).__new
__(Class
)
136 Class
.MetaFiles
[FilePath
] = ParserObject
139 ## Constructor of MetaFileParser
141 # Initialize object of MetaFileParser
143 # @param FilePath The path of platform description file
144 # @param FileType The raw data of DSC file
145 # @param Table Database used to retrieve module/package information
146 # @param Macros Macros used for replacement in file
147 # @param Owner Owner ID (for sub-section parsing)
148 # @param From ID from which the data comes (for !INCLUDE directive)
150 def __init__(self
, FilePath
, FileType
, Table
, Owner
=-1, From
=-1):
152 self
._RawTable
= Table
153 self
._FileType
= FileType
154 self
.MetaFile
= FilePath
156 self
._FileLocalMacros
= {}
157 self
._SectionsMacroDict
= {}
159 # for recursive parsing
160 self
._Owner
= [Owner
]
163 # parsr status for parsing
164 self
._ValueList
= ['', '', '', '', '']
167 self
._CurrentLine
= ''
168 self
._SectionType
= MODEL_UNKNOWN
169 self
._SectionName
= ''
170 self
._InSubsection
= False
171 self
._SubsectionType
= MODEL_UNKNOWN
172 self
._SubsectionName
= ''
173 self
._ItemType
= MODEL_UNKNOWN
176 self
._Finished
= False
177 self
._PostProcessed
= False
178 # Different version of meta-file has different way to parse.
180 # UNI object and extra UNI object
182 self
._UniExtraObj
= None
184 ## Store the parsed data in table
185 def _Store(self
, *Args
):
186 return self
._Table
.Insert(*Args
)
188 ## Virtual method for starting parse
190 raise NotImplementedError
192 ## Notify a post-process is needed
193 def DoPostProcess(self
):
194 self
._PostProcessed
= False
196 ## Set parsing complete flag in both class and table
198 self
._Finished
= True
199 ## Do not set end flag when processing included files
201 self
._Table
.SetEndFlag()
203 def _PostProcess(self
):
204 self
._PostProcessed
= True
206 ## Get the parse complete flag
207 def _GetFinished(self
):
208 return self
._Finished
210 ## Set the complete flag
211 def _SetFinished(self
, Value
):
212 self
._Finished
= Value
214 ## Use [] style to query data in table, just for readability
216 # DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]
218 def __getitem__(self
, DataInfo
):
219 if not isinstance(DataInfo
, type(())):
220 DataInfo
= (DataInfo
,)
222 # Parse the file first, if necessary
223 if not self
._Finished
:
224 if self
._RawTable
.IsIntegrity():
225 self
._Finished
= True
227 self
._Table
= self
._RawTable
228 self
._PostProcessed
= False
231 # No specific ARCH or Platform given, use raw data
232 if self
._RawTable
and (len(DataInfo
) == 1 or DataInfo
[1] is None):
233 return self
._RawTable
.Query(*DataInfo
)
235 # Do post-process if necessary
236 if not self
._PostProcessed
:
239 return self
._Table
.Query(*DataInfo
)
241 ## Data parser for the common format in different type of file
243 # The common format in the meatfile is like
248 def _CommonParser(self
):
249 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
250 self
._ValueList
[0:len(TokenList
)] = TokenList
252 ## Data parser for the format in which there's path
254 # Only path can have macro used. So we need to replace them before use.
257 def _PathParser(self
):
258 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
259 self
._ValueList
[0:len(TokenList
)] = TokenList
260 # Don't do macro replacement for dsc file at this point
261 if not isinstance(self
, DscParser
):
262 Macros
= self
._Macros
263 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
265 ## Skip unsupported data
267 if self
._SectionName
== TAB_USER_EXTENSIONS
.upper() and self
._CurrentLine
.upper().endswith('.UNI'):
268 if EccGlobalData
.gConfig
.UniCheckHelpInfo
== '1' or EccGlobalData
.gConfig
.UniCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
269 ExtraUni
= self
._CurrentLine
.strip()
270 ExtraUniFile
= os
.path
.join(os
.path
.dirname(self
.MetaFile
), ExtraUni
)
271 IsModuleUni
= self
.MetaFile
.upper().endswith('.INF')
272 self
._UniExtraObj
= UniParser(ExtraUniFile
, IsExtraUni
=True, IsModuleUni
=IsModuleUni
)
273 self
._UniExtraObj
.Start()
275 EdkLogger
.warn("Parser", "Unrecognized content", File
=self
.MetaFile
,
276 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
);
277 self
._ValueList
[0:1] = [self
._CurrentLine
]
279 ## Section header parser
281 # The section header is always in following format:
283 # [section_name.arch<.platform|module_type>]
285 def _SectionHeaderParser(self
):
287 self
._SectionName
= ''
289 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
292 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
)
293 # different section should not mix in one section
294 if self
._SectionName
!= '' and self
._SectionName
!= ItemList
[0].upper():
295 EdkLogger
.error('Parser', FORMAT_INVALID
, "Different section names in the same section",
296 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
297 self
._SectionName
= ItemList
[0].upper()
298 if self
._SectionName
in self
.DataType
:
299 self
._SectionType
= self
.DataType
[self
._SectionName
]
301 self
._SectionType
= MODEL_UNKNOWN
302 EdkLogger
.warn("Parser", "Unrecognized section", File
=self
.MetaFile
,
303 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
305 if len(ItemList
) > 1:
306 S1
= ItemList
[1].upper()
310 # S2 may be Platform or ModuleType
311 if len(ItemList
) > 2:
312 S2
= ItemList
[2].upper()
315 self
._Scope
.append([S1
, S2
])
317 # 'COMMON' must not be used with specific ARCHs at the same section
318 if 'COMMON' in ArchList
and len(ArchList
) > 1:
319 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
320 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
321 # If the section information is needed later, it should be stored in database
322 self
._ValueList
[0] = self
._SectionName
324 ## [defines] section parser
326 def _DefineParser(self
):
327 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
328 self
._ValueList
[1:len(TokenList
)] = TokenList
329 if not self
._ValueList
[1]:
330 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
331 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
332 if not self
._ValueList
[2]:
333 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
334 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
336 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
337 Name
, Value
= self
._ValueList
[1], self
._ValueList
[2]
338 # Sometimes, we need to make differences between EDK and EDK2 modules
339 if Name
== 'INF_VERSION':
341 self
._Version
= int(Value
, 0)
343 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid version number",
344 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
345 elif Name
== 'MODULE_UNI_FILE':
346 UniFile
= os
.path
.join(os
.path
.dirname(self
.MetaFile
), Value
)
347 if os
.path
.exists(UniFile
):
348 self
._UniObj
= UniParser(UniFile
, IsExtraUni
=False, IsModuleUni
=True)
351 EdkLogger
.error('Parser', FILE_NOT_FOUND
, "Module UNI file %s is missing." % Value
,
352 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
354 elif Name
== 'PACKAGE_UNI_FILE':
355 UniFile
= os
.path
.join(os
.path
.dirname(self
.MetaFile
), Value
)
356 if os
.path
.exists(UniFile
):
357 self
._UniObj
= UniParser(UniFile
, IsExtraUni
=False, IsModuleUni
=False)
359 if isinstance(self
, InfParser
) and self
._Version
< 0x00010005:
360 # EDK module allows using defines as macros
361 self
._FileLocalMacros
[Name
] = Value
362 self
._Defines
[Name
] = Value
364 ## [BuildOptions] section parser
366 def _BuildOptionParser(self
):
367 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
368 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
369 if len(TokenList2
) == 2:
370 self
._ValueList
[0] = TokenList2
[0] # toolchain family
371 self
._ValueList
[1] = TokenList2
[1] # keys
373 self
._ValueList
[1] = TokenList
[0]
374 if len(TokenList
) == 2 and not isinstance(self
, DscParser
): # value
375 self
._ValueList
[2] = ReplaceMacro(TokenList
[1], self
._Macros
)
377 if self
._ValueList
[1].count('_') != 4:
381 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
382 ExtraData
=self
._CurrentLine
,
384 Line
=self
._LineIndex
+1
387 def _GetMacros(self
):
389 Macros
.update(self
._FileLocalMacros
)
390 Macros
.update(self
._GetApplicableSectionMacro
())
394 ## Get section Macros that are applicable to current line, which may come from other sections
395 ## that share the same name while scope is wider
396 def _GetApplicableSectionMacro(self
):
398 for Scope1
, Scope2
in [("COMMON", "COMMON"), ("COMMON", self
._Scope
[0][1]),
399 (self
._Scope
[0][0], "COMMON"), (self
._Scope
[0][0], self
._Scope
[0][1])]:
400 if (self
._SectionType
, Scope1
, Scope2
) in self
._SectionsMacroDict
:
401 Macros
.update(self
._SectionsMacroDict
[(self
._SectionType
, Scope1
, Scope2
)])
405 Finished
= property(_GetFinished
, _SetFinished
)
406 _Macros
= property(_GetMacros
)
409 ## INF file parser class
411 # @param FilePath The path of platform description file
412 # @param FileType The raw data of DSC file
413 # @param Table Database used to retrieve module/package information
414 # @param Macros Macros used for replacement in file
416 class InfParser(MetaFileParser
):
417 # INF file supported data types (one type per section)
419 TAB_UNKNOWN
.upper() : MODEL_UNKNOWN
,
420 TAB_INF_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
421 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
422 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
423 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
424 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
425 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
426 TAB_PACKAGES
.upper() : MODEL_META_DATA_PACKAGE
,
427 TAB_NMAKE
.upper() : MODEL_META_DATA_NMAKE
,
428 TAB_INF_FIXED_PCD
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
429 TAB_INF_PATCH_PCD
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
430 TAB_INF_FEATURE_PCD
.upper() : MODEL_PCD_FEATURE_FLAG
,
431 TAB_INF_PCD_EX
.upper() : MODEL_PCD_DYNAMIC_EX
,
432 TAB_INF_PCD
.upper() : MODEL_PCD_DYNAMIC
,
433 TAB_SOURCES
.upper() : MODEL_EFI_SOURCE_FILE
,
434 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
435 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
436 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
437 TAB_DEPEX
.upper() : MODEL_EFI_DEPEX
,
438 TAB_BINARIES
.upper() : MODEL_EFI_BINARY_FILE
,
439 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
442 ## Constructor of InfParser
444 # Initialize object of InfParser
446 # @param FilePath The path of module description file
447 # @param FileType The raw data of DSC file
448 # @param Table Database used to retrieve module/package information
449 # @param Macros Macros used for replacement in file
451 def __init__(self
, FilePath
, FileType
, Table
):
452 # prevent re-initialization
453 if hasattr(self
, "_Table"):
455 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
456 self
.TblFile
= EccGlobalData
.gDb
.TblFile
465 Content
= open(str(self
.MetaFile
), 'r').readlines()
467 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
469 # Insert a record for file
471 Filename
= NormPath(self
.MetaFile
)
472 FileID
= self
.TblFile
.GetFileId(Filename
)
476 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_INF
)
478 # parse the file line by line
479 IsFindBlockComment
= False
481 for Index
in range(0, len(Content
)):
482 if self
._SectionType
in [MODEL_EFI_GUID
,
485 MODEL_PCD_FIXED_AT_BUILD
,
486 MODEL_PCD_PATCHABLE_IN_MODULE
,
487 MODEL_PCD_FEATURE_FLAG
,
488 MODEL_PCD_DYNAMIC_EX
,
490 Line
= Content
[Index
].strip()
491 if Line
.startswith(TAB_SPECIAL_COMMENT
):
492 Usage
+= ' ' + Line
[Line
.find(TAB_SPECIAL_COMMENT
):]
494 elif Line
.startswith(TAB_COMMENT_SPLIT
):
496 elif Line
.find(TAB_COMMENT_SPLIT
) > 0:
497 Usage
+= ' ' + Line
[Line
.find(TAB_COMMENT_SPLIT
):]
498 Line
= Line
[:Line
.find(TAB_COMMENT_SPLIT
)]
500 # skip empty, commented, block commented lines
501 Line
= CleanString(Content
[Index
], AllowCppStyleComment
=True)
504 if Index
+ 1 < len(Content
):
505 NextLine
= CleanString(Content
[Index
+ 1])
508 if Line
.find(DataType
.TAB_COMMENT_EDK_START
) > -1:
509 IsFindBlockComment
= True
511 if Line
.find(DataType
.TAB_COMMENT_EDK_END
) > -1:
512 IsFindBlockComment
= False
514 if IsFindBlockComment
:
517 self
._LineIndex
= Index
518 self
._CurrentLine
= Line
521 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
522 self
._SectionHeaderParser
()
523 # Check invalid sections
524 if self
._Version
< 0x00010005:
525 if self
._SectionType
in [MODEL_META_DATA_BUILD_OPTION
,
526 MODEL_EFI_LIBRARY_CLASS
,
527 MODEL_META_DATA_PACKAGE
,
528 MODEL_PCD_FIXED_AT_BUILD
,
529 MODEL_PCD_PATCHABLE_IN_MODULE
,
530 MODEL_PCD_FEATURE_FLAG
,
531 MODEL_PCD_DYNAMIC_EX
,
536 MODEL_META_DATA_USER_EXTENSION
]:
537 EdkLogger
.error('Parser', FORMAT_INVALID
,
538 "Section [%s] is not allowed in inf file without version" % (self
._SectionName
),
539 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
540 elif self
._SectionType
in [MODEL_EFI_INCLUDE
,
541 MODEL_EFI_LIBRARY_INSTANCE
,
542 MODEL_META_DATA_NMAKE
]:
543 EdkLogger
.error('Parser', FORMAT_INVALID
,
544 "Section [%s] is not allowed in inf file with version 0x%08x" % (self
._SectionName
, self
._Version
),
545 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
547 # merge two lines specified by '\' in section NMAKE
548 elif self
._SectionType
== MODEL_META_DATA_NMAKE
:
551 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
554 if NextLine
[0] == TAB_SECTION_START
and NextLine
[-1] == TAB_SECTION_END
:
555 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
558 NmakeLine
= NmakeLine
+ ' ' + Line
[0:-1]
561 self
._CurrentLine
= NmakeLine
+ Line
565 self
._ValueList
= ['', '', '']
566 # parse current line, result will be put in self._ValueList
567 self
._SectionParser
[self
._SectionType
](self
)
568 if self
._ValueList
is None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
572 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
573 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
575 self
._ValueList
[0] = self
._ValueList
[0].replace('/', '\\')
576 Usage
= Usage
.strip()
577 for Arch
, Platform
in self
._Scope
:
578 self
._Store
(self
._SectionType
,
594 if IsFindBlockComment
:
595 EdkLogger
.error("Parser", FORMAT_INVALID
, "Open block comments (starting with /*) are expected to end with */",
599 ## Data parser for the format in which there's path
601 # Only path can have macro used. So we need to replace them before use.
603 def _IncludeParser(self
):
604 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
605 self
._ValueList
[0:len(TokenList
)] = TokenList
606 Macros
= self
._Macros
608 for Index
in range(0, len(self
._ValueList
)):
609 Value
= self
._ValueList
[Index
]
613 self
._ValueList
[Index
] = ReplaceMacro(Value
, Macros
)
615 ## Parse [Sources] section
617 # Only path can have macro used. So we need to replace them before use.
620 def _SourceFileParser(self
):
621 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
622 self
._ValueList
[0:len(TokenList
)] = TokenList
623 Macros
= self
._Macros
624 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
625 if 'COMPONENT_TYPE' in Macros
:
626 if self
._Defines
['COMPONENT_TYPE'].upper() == 'ACPITABLE':
627 self
._ValueList
[0] = GetSplitValueList(self
._ValueList
[0], ' ', 1)[0]
628 if self
._Defines
['BASE_NAME'] == 'Microcode':
630 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
632 ## Parse [Binaries] section
634 # Only path can have macro used. So we need to replace them before use.
637 def _BinaryFileParser(self
):
638 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 2)
639 if len(TokenList
) < 2:
640 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type or path specified",
641 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
642 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
644 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type specified",
645 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
646 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
648 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file path specified",
649 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
650 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
651 self
._ValueList
[0:len(TokenList
)] = TokenList
652 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
654 ## [nmake] section parser (Edk.x style only)
655 def _NmakeParser(self
):
656 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
657 self
._ValueList
[0:len(TokenList
)] = TokenList
659 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
660 # remove self-reference in macro setting
661 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
663 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
665 def _PcdParser(self
):
666 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
667 ValueList
= GetSplitValueList(TokenList
[0], TAB_SPLIT
)
668 if len(ValueList
) != 2:
669 EdkLogger
.error('Parser', FORMAT_INVALID
, "Illegal token space GUID and PCD name format",
670 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
671 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
672 self
._ValueList
[0:1] = ValueList
673 if len(TokenList
) > 1:
674 self
._ValueList
[2] = TokenList
[1]
675 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
676 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
677 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
678 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
680 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
681 if self
._ValueList
[2] != '':
682 InfPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
683 if InfPcdValueList
[0] in ['True', 'true', 'TRUE']:
684 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '1', 1);
685 elif InfPcdValueList
[0] in ['False', 'false', 'FALSE']:
686 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '0', 1);
688 ## [depex] section parser
690 def _DepexParser(self
):
691 self
._ValueList
[0:1] = [self
._CurrentLine
]
694 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
695 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
696 MODEL_META_DATA_BUILD_OPTION
: MetaFileParser
._BuildOptionParser
,
697 MODEL_EFI_INCLUDE
: _IncludeParser
, # for Edk.x modules
698 MODEL_EFI_LIBRARY_INSTANCE
: MetaFileParser
._CommonParser
, # for Edk.x modules
699 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
700 MODEL_META_DATA_PACKAGE
: MetaFileParser
._PathParser
,
701 MODEL_META_DATA_NMAKE
: _NmakeParser
, # for Edk.x modules
702 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
703 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
704 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
705 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
706 MODEL_PCD_DYNAMIC
: _PcdParser
,
707 MODEL_EFI_SOURCE_FILE
: _SourceFileParser
,
708 MODEL_EFI_GUID
: MetaFileParser
._CommonParser
,
709 MODEL_EFI_PROTOCOL
: MetaFileParser
._CommonParser
,
710 MODEL_EFI_PPI
: MetaFileParser
._CommonParser
,
711 MODEL_EFI_DEPEX
: _DepexParser
,
712 MODEL_EFI_BINARY_FILE
: _BinaryFileParser
,
713 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
716 ## DSC file parser class
718 # @param FilePath The path of platform description file
719 # @param FileType The raw data of DSC file
720 # @param Table Database used to retrieve module/package information
721 # @param Macros Macros used for replacement in file
722 # @param Owner Owner ID (for sub-section parsing)
723 # @param From ID from which the data comes (for !INCLUDE directive)
725 class DscParser(MetaFileParser
):
726 # DSC file supported data types (one type per section)
728 TAB_SKUIDS
.upper() : MODEL_EFI_SKU_ID
,
729 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
730 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
731 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
732 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
733 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
734 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
735 TAB_PCDS_DYNAMIC_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_DEFAULT
,
736 TAB_PCDS_DYNAMIC_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_HII
,
737 TAB_PCDS_DYNAMIC_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_VPD
,
738 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT
,
739 TAB_PCDS_DYNAMIC_EX_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_HII
,
740 TAB_PCDS_DYNAMIC_EX_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_VPD
,
741 TAB_COMPONENTS
.upper() : MODEL_META_DATA_COMPONENT
,
742 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH
.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
,
743 TAB_DSC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
744 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
745 TAB_DSC_DEFINES_EDKGLOBAL
: MODEL_META_DATA_GLOBAL_DEFINE
,
746 TAB_INCLUDE
.upper() : MODEL_META_DATA_INCLUDE
,
747 TAB_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
748 TAB_IF_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
749 TAB_IF_N_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
,
750 TAB_ELSE_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
,
751 TAB_ELSE
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
752 TAB_END_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
,
753 TAB_ERROR
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR
,
756 # Valid names in define section
763 "PCD_INFO_GENERATION",
764 "SUPPORTED_ARCHITECTURES",
773 "FIX_LOAD_TOP_MEMORY_ADDRESS"
776 SubSectionDefineKeywords
= [
780 SymbolPattern
= ValueExpression
.SymbolPattern
782 ## Constructor of DscParser
784 # Initialize object of DscParser
786 # @param FilePath The path of platform description file
787 # @param FileType The raw data of DSC file
788 # @param Table Database used to retrieve module/package information
789 # @param Macros Macros used for replacement in file
790 # @param Owner Owner ID (for sub-section parsing)
791 # @param From ID from which the data comes (for !INCLUDE directive)
793 def __init__(self
, FilePath
, FileType
, Table
, Owner
=-1, From
=-1):
794 # prevent re-initialization
795 if hasattr(self
, "_Table"):
797 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, Owner
, From
)
798 self
._Version
= 0x00010005 # Only EDK2 dsc file is supported
799 # to store conditional directive evaluation result
800 self
._DirectiveStack
= []
801 self
._DirectiveEvalStack
= []
804 # Final valid replacable symbols
807 # Map the ID between the original table and new table to track
810 self
._IdMapping
= {-1:-1}
812 self
.TblFile
= EccGlobalData
.gDb
.TblFile
819 Content
= open(str(self
.MetaFile
.Path
), 'r').readlines()
821 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
823 # Insert a record for file
825 Filename
= NormPath(self
.MetaFile
.Path
)
826 FileID
= self
.TblFile
.GetFileId(Filename
)
830 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_DSC
)
833 for Index
in range(0, len(Content
)):
834 Line
= CleanString(Content
[Index
])
839 self
._CurrentLine
= Line
840 self
._LineIndex
= Index
841 if self
._InSubsection
and self
._Owner
[-1] == -1:
842 self
._Owner
.append(self
._LastItem
)
845 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
846 self
._SectionType
= MODEL_META_DATA_SECTION_HEADER
848 elif Line
[0] == '}' and self
._InSubsection
:
849 self
._InSubsection
= False
850 self
._SubsectionType
= MODEL_UNKNOWN
851 self
._SubsectionName
= ''
855 elif Line
[0] == TAB_OPTION_START
and Line
[-1] == TAB_OPTION_END
:
856 self
._SubsectionType
= MODEL_META_DATA_SUBSECTION_HEADER
859 self
._DirectiveParser
()
862 if self
._InSubsection
:
863 SectionType
= self
._SubsectionType
865 SectionType
= self
._SectionType
866 self
._ItemType
= SectionType
868 self
._ValueList
= ['', '', '']
869 self
._SectionParser
[SectionType
](self
)
870 if self
._ValueList
is None:
873 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
874 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
876 for Arch
, ModuleType
in self
._Scope
:
877 self
._LastItem
= self
._Store
(
894 if self
._DirectiveStack
:
895 Type
, Line
, Text
= self
._DirectiveStack
[-1]
896 EdkLogger
.error('Parser', FORMAT_INVALID
, "No matching '!endif' found",
897 ExtraData
=Text
, File
=self
.MetaFile
, Line
=Line
)
900 ## <subsection_header> parser
901 def _SubsectionHeaderParser(self
):
902 self
._SubsectionName
= self
._CurrentLine
[1:-1].upper()
903 if self
._SubsectionName
in self
.DataType
:
904 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
906 self
._SubsectionType
= MODEL_UNKNOWN
907 EdkLogger
.warn("Parser", "Unrecognized sub-section", File
=self
.MetaFile
,
908 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
909 self
._ValueList
[0] = self
._SubsectionName
911 ## Directive statement parser
912 def _DirectiveParser(self
):
913 self
._ValueList
= ['', '', '']
914 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
915 self
._ValueList
[0:len(TokenList
)] = TokenList
918 DirectiveName
= self
._ValueList
[0].upper()
919 if DirectiveName
not in self
.DataType
:
920 EdkLogger
.error("Parser", FORMAT_INVALID
, "Unknown directive [%s]" % DirectiveName
,
921 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
922 if DirectiveName
in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self
._ValueList
[1] == '':
923 EdkLogger
.error("Parser", FORMAT_INVALID
, "Missing expression",
924 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
925 ExtraData
=self
._CurrentLine
)
927 ItemType
= self
.DataType
[DirectiveName
]
928 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
929 # Remove all directives between !if and !endif, including themselves
930 while self
._DirectiveStack
:
931 # Remove any !else or !elseif
932 DirectiveInfo
= self
._DirectiveStack
.pop()
933 if DirectiveInfo
[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
934 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
935 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
938 EdkLogger
.error("Parser", FORMAT_INVALID
, "Redundant '!endif'",
939 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
940 ExtraData
=self
._CurrentLine
)
941 elif ItemType
!= MODEL_META_DATA_INCLUDE
:
942 # Break if there's a !else is followed by a !elseif
943 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
and \
944 self
._DirectiveStack
and \
945 self
._DirectiveStack
[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
946 EdkLogger
.error("Parser", FORMAT_INVALID
, "'!elseif' after '!else'",
947 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
948 ExtraData
=self
._CurrentLine
)
949 self
._DirectiveStack
.append((ItemType
, self
._LineIndex
+1, self
._CurrentLine
))
951 EdkLogger
.error('Parser', FORMAT_INVALID
,
952 "No '!include' allowed in included file",
953 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
,
954 Line
=self
._LineIndex
+1)
957 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
958 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
960 self
._LastItem
= self
._Store
(
977 ## [defines] section parser
979 def _DefineParser(self
):
980 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
981 self
._ValueList
[1:len(TokenList
)] = TokenList
984 if not self
._ValueList
[1]:
985 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
986 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
987 if not self
._ValueList
[2]:
988 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
989 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
990 if (not self
._ValueList
[1] in self
.DefineKeywords
and
991 (self
._InSubsection
and self
._ValueList
[1] not in self
.SubSectionDefineKeywords
)):
992 EdkLogger
.error('Parser', FORMAT_INVALID
,
993 "Unknown keyword found: %s. "
994 "If this is a macro you must "
995 "add it as a DEFINE in the DSC" % self
._ValueList
[1],
996 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
997 self
._Defines
[self
._ValueList
[1]] = self
._ValueList
[2]
998 self
._ItemType
= self
.DataType
[TAB_DSC_DEFINES
.upper()]
1001 def _SkuIdParser(self
):
1002 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1003 if len(TokenList
) != 2:
1004 EdkLogger
.error('Parser', FORMAT_INVALID
, "Correct format is '<Integer>|<UiName>'",
1005 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1006 self
._ValueList
[0:len(TokenList
)] = TokenList
1008 ## Parse Edk style of library modules
1009 def _LibraryInstanceParser(self
):
1010 self
._ValueList
[0] = self
._CurrentLine
1012 ## PCD sections parser
1014 # [PcdsFixedAtBuild]
1015 # [PcdsPatchableInModule]
1018 # [PcdsDynamicExDefault]
1019 # [PcdsDynamicExVpd]
1020 # [PcdsDynamicExHii]
1022 # [PcdsDynamicDefault]
1027 def _PcdParser(self
):
1028 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1029 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1030 if len(TokenList
) == 2:
1031 self
._ValueList
[2] = TokenList
[1]
1032 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1033 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1034 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1035 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1036 if self
._ValueList
[2] == '':
1037 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD value given",
1038 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1039 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1040 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1041 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
1042 if DscPcdValueList
[0] in ['True', 'true', 'TRUE']:
1043 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '1', 1);
1044 elif DscPcdValueList
[0] in ['False', 'false', 'FALSE']:
1045 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '0', 1);
1047 ## [components] section parser
1049 def _ComponentParser(self
):
1050 if self
._CurrentLine
[-1] == '{':
1051 self
._ValueList
[0] = self
._CurrentLine
[0:-1].strip()
1052 self
._InSubsection
= True
1054 self
._ValueList
[0] = self
._CurrentLine
1056 ## [LibraryClasses] section
1058 def _LibraryClassParser(self
):
1059 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1060 if len(TokenList
) < 2:
1061 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class or instance specified",
1062 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1063 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1064 if TokenList
[0] == '':
1065 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class specified",
1066 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1067 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1068 if TokenList
[1] == '':
1069 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library instance specified",
1070 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1071 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1073 self
._ValueList
[0:len(TokenList
)] = TokenList
1075 def _CompponentSourceOverridePathParser(self
):
1076 self
._ValueList
[0] = self
._CurrentLine
1078 ## [BuildOptions] section parser
1080 def _BuildOptionParser(self
):
1081 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1082 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
1083 if len(TokenList2
) == 2:
1084 self
._ValueList
[0] = TokenList2
[0] # toolchain family
1085 self
._ValueList
[1] = TokenList2
[1] # keys
1087 self
._ValueList
[1] = TokenList
[0]
1088 if len(TokenList
) == 2: # value
1089 self
._ValueList
[2] = TokenList
[1]
1091 if self
._ValueList
[1].count('_') != 4:
1095 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
1096 ExtraData
=self
._CurrentLine
,
1098 Line
=self
._LineIndex
+1
1101 ## Override parent's method since we'll do all macro replacements in parser
1102 def _GetMacros(self
):
1103 Macros
= dict( [('ARCH', 'IA32'), ('FAMILY', TAB_COMPILER_MSFT
), ('TOOL_CHAIN_TAG', 'VS2008x86'), ('TARGET', 'DEBUG')])
1104 Macros
.update(self
._FileLocalMacros
)
1105 Macros
.update(self
._GetApplicableSectionMacro
())
1106 Macros
.update(GlobalData
.gEdkGlobal
)
1107 Macros
.update(GlobalData
.gPlatformDefines
)
1108 Macros
.update(GlobalData
.gCommandLineDefines
)
1109 # PCD cannot be referenced in macro definition
1110 if self
._ItemType
not in [MODEL_META_DATA_DEFINE
, MODEL_META_DATA_GLOBAL_DEFINE
]:
1111 Macros
.update(self
._Symbols
)
1114 def _PostProcess(self
):
1116 MODEL_META_DATA_SECTION_HEADER
: self
.__ProcessSectionHeader
,
1117 MODEL_META_DATA_SUBSECTION_HEADER
: self
.__ProcessSubsectionHeader
,
1118 MODEL_META_DATA_HEADER
: self
.__ProcessDefine
,
1119 MODEL_META_DATA_DEFINE
: self
.__ProcessDefine
,
1120 MODEL_META_DATA_GLOBAL_DEFINE
: self
.__ProcessDefine
,
1121 MODEL_META_DATA_INCLUDE
: self
.__ProcessDirective
,
1122 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
: self
.__ProcessDirective
,
1123 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
: self
.__ProcessDirective
,
1124 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
: self
.__ProcessDirective
,
1125 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
: self
.__ProcessDirective
,
1126 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
: self
.__ProcessDirective
,
1127 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
: self
.__ProcessDirective
,
1128 MODEL_EFI_SKU_ID
: self
.__ProcessSkuId
,
1129 MODEL_EFI_LIBRARY_INSTANCE
: self
.__ProcessLibraryInstance
,
1130 MODEL_EFI_LIBRARY_CLASS
: self
.__ProcessLibraryClass
,
1131 MODEL_PCD_FIXED_AT_BUILD
: self
.__ProcessPcd
,
1132 MODEL_PCD_PATCHABLE_IN_MODULE
: self
.__ProcessPcd
,
1133 MODEL_PCD_FEATURE_FLAG
: self
.__ProcessPcd
,
1134 MODEL_PCD_DYNAMIC_DEFAULT
: self
.__ProcessPcd
,
1135 MODEL_PCD_DYNAMIC_HII
: self
.__ProcessPcd
,
1136 MODEL_PCD_DYNAMIC_VPD
: self
.__ProcessPcd
,
1137 MODEL_PCD_DYNAMIC_EX_DEFAULT
: self
.__ProcessPcd
,
1138 MODEL_PCD_DYNAMIC_EX_HII
: self
.__ProcessPcd
,
1139 MODEL_PCD_DYNAMIC_EX_VPD
: self
.__ProcessPcd
,
1140 MODEL_META_DATA_COMPONENT
: self
.__ProcessComponent
,
1141 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: self
.__ProcessSourceOverridePath
,
1142 MODEL_META_DATA_BUILD_OPTION
: self
.__ProcessBuildOption
,
1143 MODEL_UNKNOWN
: self
._Skip
,
1144 MODEL_META_DATA_USER_EXTENSION
: self
._Skip
,
1145 MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR
: self
._Skip
,
1148 self
._RawTable
= self
._Table
1149 self
._Table
= MetaFileStorage(self
._RawTable
.Cur
, self
.MetaFile
, MODEL_FILE_DSC
, True)
1150 self
._DirectiveStack
= []
1151 self
._DirectiveEvalStack
= []
1152 self
._FileWithError
= self
.MetaFile
1153 self
._FileLocalMacros
= {}
1154 self
._SectionsMacroDict
= {}
1155 GlobalData
.gPlatformDefines
= {}
1157 # Get all macro and PCD which has straitforward value
1158 self
.__RetrievePcdValue
()
1159 self
._Content
= self
._RawTable
.GetAll()
1160 self
._ContentIndex
= 0
1161 while self
._ContentIndex
< len(self
._Content
) :
1162 Id
, self
._ItemType
, V1
, V2
, V3
, S1
, S2
, Owner
, BelongsToFile
, self
._From
, \
1163 LineStart
, ColStart
, LineEnd
, ColEnd
, Enabled
= self
._Content
[self
._ContentIndex
]
1166 self
._FileWithError
= self
.MetaFile
1168 self
._ContentIndex
+= 1
1170 self
._Scope
= [[S1
, S2
]]
1171 self
._LineIndex
= LineStart
- 1
1172 self
._ValueList
= [V1
, V2
, V3
]
1175 Processer
[self
._ItemType
]()
1176 except EvaluationException
as Excpt
:
1178 # Only catch expression evaluation error here. We need to report
1179 # the precise number of line on which the error occurred
1182 # EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
1183 # File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1184 # Line=self._LineIndex+1)
1185 except MacroException
as Excpt
:
1186 EdkLogger
.error('Parser', FORMAT_INVALID
, str(Excpt
),
1187 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1188 Line
=self
._LineIndex
+1)
1190 if self
._ValueList
is None:
1193 NewOwner
= self
._IdMapping
.get(Owner
, -1)
1194 self
._Enabled
= int((not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
))
1195 self
._LastItem
= self
._Store
(
1211 self
._IdMapping
[Id
] = self
._LastItem
1213 RecordList
= self
._Table
.GetAll()
1215 self
._RawTable
.Drop()
1217 for Record
in RecordList
:
1218 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])
1219 GlobalData
.gPlatformDefines
.update(self
._FileLocalMacros
)
1220 self
._PostProcessed
= True
1221 self
._Content
= None
1223 def __ProcessSectionHeader(self
):
1224 self
._SectionName
= self
._ValueList
[0]
1225 if self
._SectionName
in self
.DataType
:
1226 self
._SectionType
= self
.DataType
[self
._SectionName
]
1228 self
._SectionType
= MODEL_UNKNOWN
1230 def __ProcessSubsectionHeader(self
):
1231 self
._SubsectionName
= self
._ValueList
[0]
1232 if self
._SubsectionName
in self
.DataType
:
1233 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
1235 self
._SubsectionType
= MODEL_UNKNOWN
1237 def __RetrievePcdValue(self
):
1238 Records
= self
._RawTable
.Query(MODEL_PCD_FEATURE_FLAG
, BelongsToItem
=-1.0)
1239 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1240 Value
, DatumType
, MaxDatumSize
= AnalyzePcdData(Value
)
1241 # Only use PCD whose value is straitforward (no macro and PCD)
1242 if self
.SymbolPattern
.findall(Value
):
1244 Name
= TokenSpaceGuid
+ '.' + PcdName
1245 # Don't use PCD with different values.
1246 if Name
in self
._Symbols
and self
._Symbols
[Name
] != Value
:
1247 self
._Symbols
.pop(Name
)
1249 self
._Symbols
[Name
] = Value
1251 Records
= self
._RawTable
.Query(MODEL_PCD_FIXED_AT_BUILD
, BelongsToItem
=-1.0)
1252 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1253 Value
, DatumType
, MaxDatumSize
= AnalyzePcdData(Value
)
1254 # Only use PCD whose value is straitforward (no macro and PCD)
1255 if self
.SymbolPattern
.findall(Value
):
1257 Name
= TokenSpaceGuid
+'.'+PcdName
1258 # Don't use PCD with different values.
1259 if Name
in self
._Symbols
and self
._Symbols
[Name
] != Value
:
1260 self
._Symbols
.pop(Name
)
1262 self
._Symbols
[Name
] = Value
1264 def __ProcessDefine(self
):
1265 if not self
._Enabled
:
1268 Type
, Name
, Value
= self
._ValueList
1269 Value
= ReplaceMacro(Value
, self
._Macros
, False)
1270 if self
._ItemType
== MODEL_META_DATA_DEFINE
:
1271 if self
._SectionType
== MODEL_META_DATA_HEADER
:
1272 self
._FileLocalMacros
[Name
] = Value
1274 SectionDictKey
= self
._SectionType
, self
._Scope
[0][0], self
._Scope
[0][1]
1275 if SectionDictKey
not in self
._SectionsMacroDict
:
1276 self
._SectionsMacroDict
[SectionDictKey
] = {}
1277 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
1278 SectionLocalMacros
[Name
] = Value
1279 elif self
._ItemType
== MODEL_META_DATA_GLOBAL_DEFINE
:
1280 GlobalData
.gEdkGlobal
[Name
] = Value
1283 # Keyword in [Defines] section can be used as Macros
1285 if (self
._ItemType
== MODEL_META_DATA_HEADER
) and (self
._SectionType
== MODEL_META_DATA_HEADER
):
1286 self
._FileLocalMacros
[Name
] = Value
1288 self
._ValueList
= [Type
, Name
, Value
]
1290 def __ProcessDirective(self
):
1292 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1293 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
]:
1294 Macros
= self
._Macros
1295 Macros
.update(GlobalData
.gGlobalDefines
)
1297 Result
= ValueExpression(self
._ValueList
[1], Macros
)()
1298 except SymbolNotFound
as Exc
:
1299 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1301 except WrnExpression
as Excpt
:
1303 # Catch expression evaluation warning here. We need to report
1304 # the precise number of line and return the evaluation result
1306 EdkLogger
.warn('Parser', "Suspicious expression: %s" % str(Excpt
),
1307 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1308 Line
=self
._LineIndex
+1)
1309 Result
= Excpt
.result
1310 except BadExpression
as Exc
:
1311 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1314 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1315 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1316 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1317 self
._DirectiveStack
.append(self
._ItemType
)
1318 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
:
1319 Result
= bool(Result
)
1321 Macro
= self
._ValueList
[1]
1322 Macro
= Macro
[2:-1] if (Macro
.startswith("$(") and Macro
.endswith(")")) else Macro
1323 Result
= Macro
in self
._Macros
1324 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
:
1326 self
._DirectiveEvalStack
.append(Result
)
1327 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
:
1328 self
._DirectiveStack
.append(self
._ItemType
)
1329 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1330 self
._DirectiveEvalStack
.append(bool(Result
))
1331 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1332 self
._DirectiveStack
[-1] = self
._ItemType
1333 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1334 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1335 # Back to the nearest !if/!ifdef/!ifndef
1336 while self
._DirectiveStack
:
1337 self
._DirectiveEvalStack
.pop()
1338 Directive
= self
._DirectiveStack
.pop()
1339 if Directive
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1340 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1341 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
1342 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1344 elif self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1345 # The included file must be relative to workspace or same directory as DSC file
1346 __IncludeMacros
= {}
1348 # Allow using system environment variables in path after !include
1350 __IncludeMacros
['WORKSPACE'] = GlobalData
.gGlobalDefines
['WORKSPACE']
1353 # Allow using MACROs comes from [Defines] section to keep compatible.
1355 __IncludeMacros
.update(self
._Macros
)
1357 IncludedFile
= NormPath(ReplaceMacro(self
._ValueList
[1], __IncludeMacros
, RaiseError
=True))
1359 # First search the include file under the same directory as DSC file
1361 IncludedFile1
= PathClass(IncludedFile
, self
.MetaFile
.Dir
)
1362 ErrorCode
, ErrorInfo1
= IncludedFile1
.Validate()
1365 # Also search file under the WORKSPACE directory
1367 IncludedFile1
= PathClass(IncludedFile
, GlobalData
.gWorkspace
)
1368 ErrorCode
, ErrorInfo2
= IncludedFile1
.Validate()
1370 EdkLogger
.error('parser', ErrorCode
, File
=self
._FileWithError
,
1371 Line
=self
._LineIndex
+1, ExtraData
=ErrorInfo1
+ "\n"+ ErrorInfo2
)
1373 self
._FileWithError
= IncludedFile1
1375 IncludedFileTable
= MetaFileStorage(self
._Table
.Cur
, IncludedFile1
, MODEL_FILE_DSC
, True)
1376 Owner
= self
._Content
[self
._ContentIndex
-1][0]
1377 Parser
= DscParser(IncludedFile1
, self
._FileType
, IncludedFileTable
,
1378 Owner
=Owner
, From
=Owner
)
1380 # set the parser status with current status
1381 Parser
._SectionName
= self
._SectionName
1382 Parser
._SectionType
= self
._SectionType
1383 Parser
._Scope
= self
._Scope
1384 Parser
._Enabled
= self
._Enabled
1385 # Parse the included file
1388 # update current status with sub-parser's status
1389 self
._SectionName
= Parser
._SectionName
1390 self
._SectionType
= Parser
._SectionType
1391 self
._Scope
= Parser
._Scope
1392 self
._Enabled
= Parser
._Enabled
1394 # Insert all records in the table for the included file into dsc file table
1395 Records
= IncludedFileTable
.GetAll()
1397 self
._Content
[self
._ContentIndex
:self
._ContentIndex
] = Records
1398 self
._Content
.pop(self
._ContentIndex
-1)
1399 self
._ValueList
= None
1400 self
._ContentIndex
-= 1
1402 def __ProcessSkuId(self
):
1403 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=True)
1404 for Value
in self
._ValueList
]
1406 def __ProcessLibraryInstance(self
):
1407 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
1409 def __ProcessLibraryClass(self
):
1410 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, RaiseError
=True)
1412 def __ProcessPcd(self
):
1413 ValueList
= GetSplitValueList(self
._ValueList
[2])
1415 # PCD value can be an expression
1417 if len(ValueList
) > 1 and ValueList
[1] == TAB_VOID
:
1418 PcdValue
= ValueList
[0]
1420 ValueList
[0] = ValueExpression(PcdValue
, self
._Macros
)(True)
1421 except WrnExpression
as Value
:
1422 ValueList
[0] = Value
.result
1424 PcdValue
= ValueList
[-1]
1426 ValueList
[-1] = ValueExpression(PcdValue
, self
._Macros
)(True)
1427 except WrnExpression
as Value
:
1428 ValueList
[-1] = Value
.result
1430 if ValueList
[-1] == 'True':
1432 if ValueList
[-1] == 'False':
1435 self
._ValueList
[2] = '|'.join(ValueList
)
1437 def __ProcessComponent(self
):
1438 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1440 def __ProcessSourceOverridePath(self
):
1441 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1443 def __ProcessBuildOption(self
):
1444 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=False)
1445 for Value
in self
._ValueList
]
1448 MODEL_META_DATA_HEADER
: _DefineParser
,
1449 MODEL_EFI_SKU_ID
: _SkuIdParser
,
1450 MODEL_EFI_LIBRARY_INSTANCE
: _LibraryInstanceParser
,
1451 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
1452 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1453 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1454 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1455 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
1456 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
1457 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
1458 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
1459 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
1460 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
1461 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
1462 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: _CompponentSourceOverridePathParser
,
1463 MODEL_META_DATA_BUILD_OPTION
: _BuildOptionParser
,
1464 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1465 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1466 MODEL_META_DATA_SECTION_HEADER
: MetaFileParser
._SectionHeaderParser
,
1467 MODEL_META_DATA_SUBSECTION_HEADER
: _SubsectionHeaderParser
,
1470 _Macros
= property(_GetMacros
)
1472 ## DEC file parser class
1474 # @param FilePath The path of platform description file
1475 # @param FileType The raw data of DSC file
1476 # @param Table Database used to retrieve module/package information
1477 # @param Macros Macros used for replacement in file
1479 class DecParser(MetaFileParser
):
1480 # DEC file supported data types (one type per section)
1482 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1483 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
1484 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1485 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1486 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1487 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1488 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1489 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1490 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1491 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1492 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1493 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1496 ## Constructor of DecParser
1498 # Initialize object of DecParser
1500 # @param FilePath The path of platform description file
1501 # @param FileType The raw data of DSC file
1502 # @param Table Database used to retrieve module/package information
1503 # @param Macros Macros used for replacement in file
1505 def __init__(self
, FilePath
, FileType
, Table
):
1506 # prevent re-initialization
1507 if hasattr(self
, "_Table"):
1509 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
1511 self
._Version
= 0x00010005 # Only EDK2 dec file is supported
1512 self
.TblFile
= EccGlobalData
.gDb
.TblFile
1519 Content
= open(str(self
.MetaFile
), 'r').readlines()
1521 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1524 # Insert a record for file
1526 Filename
= NormPath(self
.MetaFile
)
1527 FileID
= self
.TblFile
.GetFileId(Filename
)
1529 self
.FileID
= FileID
1531 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_DEC
)
1533 for Index
in range(0, len(Content
)):
1534 Line
, Comment
= CleanString2(Content
[Index
])
1535 self
._CurrentLine
= Line
1536 self
._LineIndex
= Index
1538 # save comment for later use
1540 self
._Comments
.append((Comment
, self
._LineIndex
+1))
1546 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1547 self
._SectionHeaderParser
()
1550 elif len(self
._SectionType
) == 0:
1555 self
._ValueList
= ['', '', '']
1556 self
._SectionParser
[self
._SectionType
[0]](self
)
1557 if self
._ValueList
is None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
1563 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1564 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1566 for Arch
, ModuleType
, Type
in self
._Scope
:
1567 self
._LastItem
= self
._Store
(
1582 for Comment
, LineNo
in self
._Comments
:
1584 MODEL_META_DATA_COMMENT
,
1601 def _GetApplicableSectionMacro(self
):
1603 for S1
, S2
, SectionType
in self
._Scope
:
1604 for Scope1
, Scope2
in [("COMMON", "COMMON"), ("COMMON", S2
), (S1
, "COMMON"), (S1
, S2
)]:
1605 if (SectionType
, Scope1
, Scope2
) in self
._SectionsMacroDict
:
1606 Macros
.update(self
._SectionsMacroDict
[(SectionType
, Scope1
, Scope2
)])
1609 ## Section header parser
1611 # The section header is always in following format:
1613 # [section_name.arch<.platform|module_type>]
1615 def _SectionHeaderParser(self
):
1617 self
._SectionName
= ''
1618 self
._SectionType
= []
1620 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
1623 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
)
1625 # different types of PCD are permissible in one section
1626 self
._SectionName
= ItemList
[0].upper()
1627 if self
._SectionName
in self
.DataType
:
1628 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1629 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1631 EdkLogger
.warn("Parser", "Unrecognized section", File
=self
.MetaFile
,
1632 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
1635 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1639 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1641 Line
=self
._LineIndex
+1,
1642 ExtraData
=self
._CurrentLine
1645 if len(ItemList
) > 1:
1646 S1
= ItemList
[1].upper()
1650 # S2 may be Platform or ModuleType
1651 if len(ItemList
) > 2:
1652 S2
= ItemList
[2].upper()
1655 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1656 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1658 # 'COMMON' must not be used with specific ARCHs at the same section
1659 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1660 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1661 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
1663 ## [guids], [ppis] and [protocols] section parser
1665 def _GuidParser(self
):
1666 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1667 if len(TokenList
) < 2:
1668 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1669 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1670 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1671 if TokenList
[0] == '':
1672 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1673 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1674 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1675 if TokenList
[1] == '':
1676 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1677 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1678 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1679 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1680 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1681 ExtraData
=self
._CurrentLine
+ \
1682 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1683 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1684 self
._ValueList
[0] = TokenList
[0]
1685 #Parse the Guid value format
1686 GuidValueList
= TokenList
[1].strip(' {}').split(',')
1689 if len(GuidValueList
) == 11:
1690 for GuidValue
in GuidValueList
:
1691 GuidValue
= GuidValue
.strip()
1692 if GuidValue
.startswith('0x') or GuidValue
.startswith('0X'):
1693 HexList
.append('0x' + str(GuidValue
[2:]))
1697 if GuidValue
.startswith('{'):
1698 GuidValue
= GuidValue
.lstrip(' {')
1699 HexList
.append('0x' + str(GuidValue
[2:]))
1701 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])
1703 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1704 ExtraData
=self
._CurrentLine
+ \
1705 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1706 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1707 self
._ValueList
[0] = ''
1709 ## PCD sections parser
1711 # [PcdsFixedAtBuild]
1712 # [PcdsPatchableInModule]
1718 def _PcdParser(self
):
1719 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1720 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1721 # check PCD information
1722 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1723 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1724 ExtraData
=self
._CurrentLine
+ \
1725 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1726 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1727 # check PCD datum information
1728 if len(TokenList
) < 2 or TokenList
[1] == '':
1729 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1730 ExtraData
=self
._CurrentLine
+ \
1731 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1732 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1735 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1736 PtrValue
= ValueRe
.findall(TokenList
[1])
1738 # Has VOID* type string, may contain "|" character in the string.
1739 if len(PtrValue
) != 0:
1740 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1741 ValueList
= GetSplitValueList(ptrValueList
)
1742 ValueList
[0] = PtrValue
[0]
1744 ValueList
= GetSplitValueList(TokenList
[1])
1747 # check if there's enough datum information given
1748 if len(ValueList
) != 3:
1749 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1750 ExtraData
=self
._CurrentLine
+ \
1751 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1752 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1753 # check default value
1754 if ValueList
[0] == '':
1755 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1756 ExtraData
=self
._CurrentLine
+ \
1757 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1758 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1760 if ValueList
[1] == '':
1761 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1762 ExtraData
=self
._CurrentLine
+ \
1763 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1764 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1765 # check token of the PCD
1766 if ValueList
[2] == '':
1767 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1768 ExtraData
=self
._CurrentLine
+ \
1769 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1770 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1771 # check format of default value against the datum type
1772 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1774 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1775 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1777 if EccGlobalData
.gConfig
.UniCheckPCDInfo
== '1' or EccGlobalData
.gConfig
.UniCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
1778 # check Description, Prompt information
1779 PatternDesc
= re
.compile('##\s*([\x21-\x7E\s]*)', re
.S
)
1780 PatternPrompt
= re
.compile('#\s+@Prompt\s+([\x21-\x7E\s]*)', re
.S
)
1783 # check @ValidRange, @ValidList and @Expression format valid
1784 ErrorCodeValid
= '0x0 <= %s <= 0xFFFFFFFF'
1785 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]+)'
1786 PatternValidRng
= re
.compile('^' + '(NOT)?\s*' + PatternValidRangeIn
+ '$')
1787 for Comment
in self
._Comments
:
1788 Comm
= Comment
[0].strip()
1792 Description
= PatternDesc
.findall(Comm
)
1794 Prompt
= PatternPrompt
.findall(Comm
)
1796 ValidFormt
= Comm
.lstrip('#')
1797 ValidFormt
= ValidFormt
.lstrip()
1798 if ValidFormt
[0:11] == '@ValidRange':
1799 ValidFormt
= ValidFormt
[11:]
1800 ValidFormt
= ValidFormt
.lstrip()
1802 ErrorCode
, Expression
= ValidFormt
.split('|', 1)
1805 Expression
= ValidFormt
1806 ErrorCode
, Expression
= ErrorCode
.strip(), Expression
.strip()
1808 if not eval(ErrorCodeValid
% ErrorCode
):
1809 EdkLogger
.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1811 EdkLogger
.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1812 if not PatternValidRng
.search(Expression
):
1813 EdkLogger
.warn('Parser', '@ValidRange Expression(%s) of PCD %s is incorrect format.' % (Expression
, TokenList
[0]))
1814 if ValidFormt
[0:10] == '@ValidList':
1815 ValidFormt
= ValidFormt
[10:]
1816 ValidFormt
= ValidFormt
.lstrip()
1818 ErrorCode
, Expression
= ValidFormt
.split('|', 1)
1821 Expression
= ValidFormt
1822 ErrorCode
, Expression
= ErrorCode
.strip(), Expression
.strip()
1824 if not eval(ErrorCodeValid
% ErrorCode
):
1825 EdkLogger
.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1827 EdkLogger
.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1828 Values
= Expression
.split(',')
1829 for Value
in Values
:
1830 Value
= Value
.strip()
1834 EdkLogger
.warn('Parser', '@ValidList Expression of PCD %s include a invalid value(%s).' % (TokenList
[0], Value
))
1836 if ValidFormt
[0:11] == '@Expression':
1837 ValidFormt
= ValidFormt
[11:]
1838 ValidFormt
= ValidFormt
.lstrip()
1840 ErrorCode
, Expression
= ValidFormt
.split('|', 1)
1843 Expression
= ValidFormt
1844 ErrorCode
, Expression
= ErrorCode
.strip(), Expression
.strip()
1846 if not eval(ErrorCodeValid
% ErrorCode
):
1847 EdkLogger
.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1849 EdkLogger
.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1851 EdkLogger
.warn('Parser', '@Expression Expression of PCD %s is incorrect format.' % TokenList
[0])
1853 EdkLogger
.warn('Parser', 'PCD %s Description information is not provided.' % TokenList
[0])
1855 EdkLogger
.warn('Parser', 'PCD %s Prompt information is not provided.' % TokenList
[0])
1856 # check Description, Prompt localization information
1858 self
._UniObj
.CheckPcdInfo(TokenList
[0])
1860 if ValueList
[0] in ['True', 'true', 'TRUE']:
1862 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1865 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
1868 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
1869 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
1870 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
1871 MODEL_EFI_GUID
: _GuidParser
,
1872 MODEL_EFI_PPI
: _GuidParser
,
1873 MODEL_EFI_PROTOCOL
: _GuidParser
,
1874 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1875 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1876 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1877 MODEL_PCD_DYNAMIC
: _PcdParser
,
1878 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
1879 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1880 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1886 # This class defined the structure used in Fdf object
1888 # @param Filename: Input value for Ffilename of Fdf file, default is None
1889 # @param WorkspaceDir: Input value for current workspace directory, default is None
1892 def __init__(self
, Filename
= None, IsToDatabase
= False, WorkspaceDir
= None, Database
= None):
1893 self
.WorkspaceDir
= WorkspaceDir
1894 self
.IsToDatabase
= IsToDatabase
1896 self
.Cur
= Database
.Cur
1897 self
.TblFile
= Database
.TblFile
1898 self
.TblFdf
= Database
.TblFdf
1903 # Load Fdf file if filename is not None
1905 if Filename
is not None:
1907 self
.LoadFdfFile(Filename
)
1912 # Insert a FDF file record into database
1914 def InsertFile(self
, Filename
):
1916 Filename
= NormPath(Filename
)
1917 if Filename
not in self
.FileList
:
1918 FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_FDF
)
1919 self
.FileList
[Filename
] = FileID
1921 return self
.FileList
[Filename
]
1926 # Load the file if it exists
1928 # @param Filename: Input value for filename of Fdf file
1930 def LoadFdfFile(self
, Filename
):
1935 Filename
= NormPath(Filename
)
1936 Fdf
= FdfParser(Filename
)
1940 # Insert inf file and pcd information
1942 if self
.IsToDatabase
:
1943 (Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
) = \
1944 (0, '', '', '', 'COMMON', 'COMMON', -1, -1, -1, -1, -1, -1, 0)
1945 for Index
in range(0, len(Fdf
.Profile
.PcdDict
)):
1947 for Key
in Fdf
.Profile
.PcdDict
.keys():
1951 FileName
= Fdf
.Profile
.PcdFileLineDict
[Key
][0]
1952 StartLine
= Fdf
.Profile
.PcdFileLineDict
[Key
][1]
1953 BelongsToFile
= self
.InsertFile(FileName
)
1954 self
.TblFdf
.Insert(Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
)
1955 for Index
in range(0, len(Fdf
.Profile
.InfList
)):
1956 Model
= MODEL_META_DATA_COMPONENT
1957 Value1
= Fdf
.Profile
.InfList
[Index
]
1959 FileName
= Fdf
.Profile
.InfFileLineList
[Index
][0]
1960 StartLine
= Fdf
.Profile
.InfFileLineList
[Index
][1]
1961 BelongsToFile
= self
.InsertFile(FileName
)
1962 self
.TblFdf
.Insert(Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
)
1964 class UniParser(object):
1965 # IsExtraUni defined the UNI file is Module UNI or extra Module UNI
1966 # IsModuleUni defined the UNI file is Module UNI or Package UNI
1967 def __init__(self
, FilePath
, IsExtraUni
=False, IsModuleUni
=True):
1968 self
.FilePath
= FilePath
1969 self
.FileName
= os
.path
.basename(FilePath
)
1970 self
.IsExtraUni
= IsExtraUni
1971 self
.IsModuleUni
= IsModuleUni
1978 self
.FileIn
= CodecOpenLongFilePath(self
.FilePath
, Mode
='rb', Encoding
='utf_8').read()
1979 except UnicodeError:
1980 self
.FileIn
= CodecOpenLongFilePath(self
.FilePath
, Mode
='rb', Encoding
='utf_16').read()
1981 except UnicodeError:
1982 self
.FileIn
= CodecOpenLongFilePath(self
.FilePath
, Mode
='rb', Encoding
='utf_16_le').read()
1987 if self
.IsModuleUni
:
1989 ModuleName
= self
.CheckKeyValid('STR_PROPERTIES_MODULE_NAME')
1990 self
.PrintLog('STR_PROPERTIES_MODULE_NAME', ModuleName
)
1992 ModuleAbstract
= self
.CheckKeyValid('STR_MODULE_ABSTRACT')
1993 self
.PrintLog('STR_MODULE_ABSTRACT', ModuleAbstract
)
1994 ModuleDescription
= self
.CheckKeyValid('STR_MODULE_DESCRIPTION')
1995 self
.PrintLog('STR_MODULE_DESCRIPTION', ModuleDescription
)
1998 PackageName
= self
.CheckKeyValid('STR_PROPERTIES_PACKAGE_NAME')
1999 self
.PrintLog('STR_PROPERTIES_PACKAGE_NAME', PackageName
)
2001 PackageAbstract
= self
.CheckKeyValid('STR_PACKAGE_ABSTRACT')
2002 self
.PrintLog('STR_PACKAGE_ABSTRACT', PackageAbstract
)
2003 PackageDescription
= self
.CheckKeyValid('STR_PACKAGE_DESCRIPTION')
2004 self
.PrintLog('STR_PACKAGE_DESCRIPTION', PackageDescription
)
2006 def CheckKeyValid(self
, Key
, Contents
=None):
2008 Contents
= self
.FileIn
2009 KeyPattern
= re
.compile('#string\s+%s\s+.*?#language.*?".*?"' % Key
, re
.S
)
2010 if KeyPattern
.search(Contents
):
2014 def CheckPcdInfo(self
, PcdCName
):
2015 PromptKey
= 'STR_%s_PROMPT' % PcdCName
.replace('.', '_')
2016 PcdPrompt
= self
.CheckKeyValid(PromptKey
)
2017 self
.PrintLog(PromptKey
, PcdPrompt
)
2018 HelpKey
= 'STR_%s_HELP' % PcdCName
.replace('.', '_')
2019 PcdHelp
= self
.CheckKeyValid(HelpKey
)
2020 self
.PrintLog(HelpKey
, PcdHelp
)
2022 def PrintLog(self
, Key
, Value
):
2023 if not Value
and Key
not in self
.Missing
:
2024 Msg
= '%s is missing in the %s file.' % (Key
, self
.FileName
)
2025 EdkLogger
.warn('Parser', Msg
)
2026 EccGlobalData
.gDb
.TblReport
.Insert(EccToolError
.ERROR_GENERAL_CHECK_UNI_HELP_INFO
, OtherMsg
=Msg
, BelongsToTable
='File', BelongsToItem
=-2)
2027 self
.Missing
.append(Key
)
2031 # This acts like the main() function for the script, unless it is 'import'ed into another
2034 if __name__
== '__main__':