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_DSC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
743 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
744 TAB_DSC_DEFINES_EDKGLOBAL
: MODEL_META_DATA_GLOBAL_DEFINE
,
745 TAB_INCLUDE
.upper() : MODEL_META_DATA_INCLUDE
,
746 TAB_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
747 TAB_IF_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
748 TAB_IF_N_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
,
749 TAB_ELSE_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
,
750 TAB_ELSE
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
751 TAB_END_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
,
752 TAB_ERROR
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR
,
755 # Valid names in define section
762 "PCD_INFO_GENERATION",
763 "SUPPORTED_ARCHITECTURES",
772 "FIX_LOAD_TOP_MEMORY_ADDRESS"
775 SubSectionDefineKeywords
= [
779 SymbolPattern
= ValueExpression
.SymbolPattern
781 ## Constructor of DscParser
783 # Initialize object of DscParser
785 # @param FilePath The path of platform description file
786 # @param FileType The raw data of DSC file
787 # @param Table Database used to retrieve module/package information
788 # @param Macros Macros used for replacement in file
789 # @param Owner Owner ID (for sub-section parsing)
790 # @param From ID from which the data comes (for !INCLUDE directive)
792 def __init__(self
, FilePath
, FileType
, Table
, Owner
=-1, From
=-1):
793 # prevent re-initialization
794 if hasattr(self
, "_Table"):
796 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, Owner
, From
)
797 self
._Version
= 0x00010005 # Only EDK2 dsc file is supported
798 # to store conditional directive evaluation result
799 self
._DirectiveStack
= []
800 self
._DirectiveEvalStack
= []
803 # Final valid replacable symbols
806 # Map the ID between the original table and new table to track
809 self
._IdMapping
= {-1:-1}
811 self
.TblFile
= EccGlobalData
.gDb
.TblFile
818 Content
= open(str(self
.MetaFile
.Path
), 'r').readlines()
820 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
822 # Insert a record for file
824 Filename
= NormPath(self
.MetaFile
.Path
)
825 FileID
= self
.TblFile
.GetFileId(Filename
)
829 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_DSC
)
832 for Index
in range(0, len(Content
)):
833 Line
= CleanString(Content
[Index
])
838 self
._CurrentLine
= Line
839 self
._LineIndex
= Index
840 if self
._InSubsection
and self
._Owner
[-1] == -1:
841 self
._Owner
.append(self
._LastItem
)
844 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
845 self
._SectionType
= MODEL_META_DATA_SECTION_HEADER
847 elif Line
[0] == '}' and self
._InSubsection
:
848 self
._InSubsection
= False
849 self
._SubsectionType
= MODEL_UNKNOWN
850 self
._SubsectionName
= ''
854 elif Line
[0] == TAB_OPTION_START
and Line
[-1] == TAB_OPTION_END
:
855 self
._SubsectionType
= MODEL_META_DATA_SUBSECTION_HEADER
858 self
._DirectiveParser
()
861 if self
._InSubsection
:
862 SectionType
= self
._SubsectionType
864 SectionType
= self
._SectionType
865 self
._ItemType
= SectionType
867 self
._ValueList
= ['', '', '']
868 self
._SectionParser
[SectionType
](self
)
869 if self
._ValueList
is None:
872 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
873 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
875 for Arch
, ModuleType
in self
._Scope
:
876 self
._LastItem
= self
._Store
(
893 if self
._DirectiveStack
:
894 Type
, Line
, Text
= self
._DirectiveStack
[-1]
895 EdkLogger
.error('Parser', FORMAT_INVALID
, "No matching '!endif' found",
896 ExtraData
=Text
, File
=self
.MetaFile
, Line
=Line
)
899 ## <subsection_header> parser
900 def _SubsectionHeaderParser(self
):
901 self
._SubsectionName
= self
._CurrentLine
[1:-1].upper()
902 if self
._SubsectionName
in self
.DataType
:
903 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
905 self
._SubsectionType
= MODEL_UNKNOWN
906 EdkLogger
.warn("Parser", "Unrecognized sub-section", File
=self
.MetaFile
,
907 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
908 self
._ValueList
[0] = self
._SubsectionName
910 ## Directive statement parser
911 def _DirectiveParser(self
):
912 self
._ValueList
= ['', '', '']
913 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
914 self
._ValueList
[0:len(TokenList
)] = TokenList
917 DirectiveName
= self
._ValueList
[0].upper()
918 if DirectiveName
not in self
.DataType
:
919 EdkLogger
.error("Parser", FORMAT_INVALID
, "Unknown directive [%s]" % DirectiveName
,
920 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
921 if DirectiveName
in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self
._ValueList
[1] == '':
922 EdkLogger
.error("Parser", FORMAT_INVALID
, "Missing expression",
923 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
924 ExtraData
=self
._CurrentLine
)
926 ItemType
= self
.DataType
[DirectiveName
]
927 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
928 # Remove all directives between !if and !endif, including themselves
929 while self
._DirectiveStack
:
930 # Remove any !else or !elseif
931 DirectiveInfo
= self
._DirectiveStack
.pop()
932 if DirectiveInfo
[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
933 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
934 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
937 EdkLogger
.error("Parser", FORMAT_INVALID
, "Redundant '!endif'",
938 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
939 ExtraData
=self
._CurrentLine
)
940 elif ItemType
!= MODEL_META_DATA_INCLUDE
:
941 # Break if there's a !else is followed by a !elseif
942 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
and \
943 self
._DirectiveStack
and \
944 self
._DirectiveStack
[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
945 EdkLogger
.error("Parser", FORMAT_INVALID
, "'!elseif' after '!else'",
946 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
947 ExtraData
=self
._CurrentLine
)
948 self
._DirectiveStack
.append((ItemType
, self
._LineIndex
+1, self
._CurrentLine
))
950 EdkLogger
.error('Parser', FORMAT_INVALID
,
951 "No '!include' allowed in included file",
952 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
,
953 Line
=self
._LineIndex
+1)
956 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
957 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
959 self
._LastItem
= self
._Store
(
976 ## [defines] section parser
978 def _DefineParser(self
):
979 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
980 self
._ValueList
[1:len(TokenList
)] = TokenList
983 if not self
._ValueList
[1]:
984 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
985 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
986 if not self
._ValueList
[2]:
987 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
988 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
989 if (not self
._ValueList
[1] in self
.DefineKeywords
and
990 (self
._InSubsection
and self
._ValueList
[1] not in self
.SubSectionDefineKeywords
)):
991 EdkLogger
.error('Parser', FORMAT_INVALID
,
992 "Unknown keyword found: %s. "
993 "If this is a macro you must "
994 "add it as a DEFINE in the DSC" % self
._ValueList
[1],
995 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
996 self
._Defines
[self
._ValueList
[1]] = self
._ValueList
[2]
997 self
._ItemType
= self
.DataType
[TAB_DSC_DEFINES
.upper()]
1000 def _SkuIdParser(self
):
1001 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1002 if len(TokenList
) != 2:
1003 EdkLogger
.error('Parser', FORMAT_INVALID
, "Correct format is '<Integer>|<UiName>'",
1004 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1005 self
._ValueList
[0:len(TokenList
)] = TokenList
1007 ## Parse Edk style of library modules
1008 def _LibraryInstanceParser(self
):
1009 self
._ValueList
[0] = self
._CurrentLine
1011 ## PCD sections parser
1013 # [PcdsFixedAtBuild]
1014 # [PcdsPatchableInModule]
1017 # [PcdsDynamicExDefault]
1018 # [PcdsDynamicExVpd]
1019 # [PcdsDynamicExHii]
1021 # [PcdsDynamicDefault]
1026 def _PcdParser(self
):
1027 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1028 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1029 if len(TokenList
) == 2:
1030 self
._ValueList
[2] = TokenList
[1]
1031 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1032 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1033 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1034 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1035 if self
._ValueList
[2] == '':
1036 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD value given",
1037 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1038 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1039 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1040 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
1041 if DscPcdValueList
[0] in ['True', 'true', 'TRUE']:
1042 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '1', 1);
1043 elif DscPcdValueList
[0] in ['False', 'false', 'FALSE']:
1044 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '0', 1);
1046 ## [components] section parser
1048 def _ComponentParser(self
):
1049 if self
._CurrentLine
[-1] == '{':
1050 self
._ValueList
[0] = self
._CurrentLine
[0:-1].strip()
1051 self
._InSubsection
= True
1053 self
._ValueList
[0] = self
._CurrentLine
1055 ## [LibraryClasses] section
1057 def _LibraryClassParser(self
):
1058 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1059 if len(TokenList
) < 2:
1060 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class or instance specified",
1061 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1062 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1063 if TokenList
[0] == '':
1064 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class specified",
1065 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1066 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1067 if TokenList
[1] == '':
1068 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library instance specified",
1069 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1070 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1072 self
._ValueList
[0:len(TokenList
)] = TokenList
1075 ## [BuildOptions] section parser
1077 def _BuildOptionParser(self
):
1078 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1079 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
1080 if len(TokenList2
) == 2:
1081 self
._ValueList
[0] = TokenList2
[0] # toolchain family
1082 self
._ValueList
[1] = TokenList2
[1] # keys
1084 self
._ValueList
[1] = TokenList
[0]
1085 if len(TokenList
) == 2: # value
1086 self
._ValueList
[2] = TokenList
[1]
1088 if self
._ValueList
[1].count('_') != 4:
1092 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
1093 ExtraData
=self
._CurrentLine
,
1095 Line
=self
._LineIndex
+1
1098 ## Override parent's method since we'll do all macro replacements in parser
1099 def _GetMacros(self
):
1100 Macros
= dict( [('ARCH', 'IA32'), ('FAMILY', TAB_COMPILER_MSFT
), ('TOOL_CHAIN_TAG', 'VS2008x86'), ('TARGET', 'DEBUG')])
1101 Macros
.update(self
._FileLocalMacros
)
1102 Macros
.update(self
._GetApplicableSectionMacro
())
1103 Macros
.update(GlobalData
.gEdkGlobal
)
1104 Macros
.update(GlobalData
.gPlatformDefines
)
1105 Macros
.update(GlobalData
.gCommandLineDefines
)
1106 # PCD cannot be referenced in macro definition
1107 if self
._ItemType
not in [MODEL_META_DATA_DEFINE
, MODEL_META_DATA_GLOBAL_DEFINE
]:
1108 Macros
.update(self
._Symbols
)
1111 def _PostProcess(self
):
1113 MODEL_META_DATA_SECTION_HEADER
: self
.__ProcessSectionHeader
,
1114 MODEL_META_DATA_SUBSECTION_HEADER
: self
.__ProcessSubsectionHeader
,
1115 MODEL_META_DATA_HEADER
: self
.__ProcessDefine
,
1116 MODEL_META_DATA_DEFINE
: self
.__ProcessDefine
,
1117 MODEL_META_DATA_GLOBAL_DEFINE
: self
.__ProcessDefine
,
1118 MODEL_META_DATA_INCLUDE
: self
.__ProcessDirective
,
1119 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
: self
.__ProcessDirective
,
1120 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
: self
.__ProcessDirective
,
1121 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
: self
.__ProcessDirective
,
1122 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
: self
.__ProcessDirective
,
1123 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
: self
.__ProcessDirective
,
1124 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
: self
.__ProcessDirective
,
1125 MODEL_EFI_SKU_ID
: self
.__ProcessSkuId
,
1126 MODEL_EFI_LIBRARY_INSTANCE
: self
.__ProcessLibraryInstance
,
1127 MODEL_EFI_LIBRARY_CLASS
: self
.__ProcessLibraryClass
,
1128 MODEL_PCD_FIXED_AT_BUILD
: self
.__ProcessPcd
,
1129 MODEL_PCD_PATCHABLE_IN_MODULE
: self
.__ProcessPcd
,
1130 MODEL_PCD_FEATURE_FLAG
: self
.__ProcessPcd
,
1131 MODEL_PCD_DYNAMIC_DEFAULT
: self
.__ProcessPcd
,
1132 MODEL_PCD_DYNAMIC_HII
: self
.__ProcessPcd
,
1133 MODEL_PCD_DYNAMIC_VPD
: self
.__ProcessPcd
,
1134 MODEL_PCD_DYNAMIC_EX_DEFAULT
: self
.__ProcessPcd
,
1135 MODEL_PCD_DYNAMIC_EX_HII
: self
.__ProcessPcd
,
1136 MODEL_PCD_DYNAMIC_EX_VPD
: self
.__ProcessPcd
,
1137 MODEL_META_DATA_COMPONENT
: self
.__ProcessComponent
,
1138 MODEL_META_DATA_BUILD_OPTION
: self
.__ProcessBuildOption
,
1139 MODEL_UNKNOWN
: self
._Skip
,
1140 MODEL_META_DATA_USER_EXTENSION
: self
._Skip
,
1141 MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR
: self
._Skip
,
1144 self
._RawTable
= self
._Table
1145 self
._Table
= MetaFileStorage(self
._RawTable
.Cur
, self
.MetaFile
, MODEL_FILE_DSC
, True)
1146 self
._DirectiveStack
= []
1147 self
._DirectiveEvalStack
= []
1148 self
._FileWithError
= self
.MetaFile
1149 self
._FileLocalMacros
= {}
1150 self
._SectionsMacroDict
= {}
1151 GlobalData
.gPlatformDefines
= {}
1153 # Get all macro and PCD which has straitforward value
1154 self
.__RetrievePcdValue
()
1155 self
._Content
= self
._RawTable
.GetAll()
1156 self
._ContentIndex
= 0
1157 while self
._ContentIndex
< len(self
._Content
) :
1158 Id
, self
._ItemType
, V1
, V2
, V3
, S1
, S2
, Owner
, BelongsToFile
, self
._From
, \
1159 LineStart
, ColStart
, LineEnd
, ColEnd
, Enabled
= self
._Content
[self
._ContentIndex
]
1162 self
._FileWithError
= self
.MetaFile
1164 self
._ContentIndex
+= 1
1166 self
._Scope
= [[S1
, S2
]]
1167 self
._LineIndex
= LineStart
- 1
1168 self
._ValueList
= [V1
, V2
, V3
]
1171 Processer
[self
._ItemType
]()
1172 except EvaluationException
as Excpt
:
1174 # Only catch expression evaluation error here. We need to report
1175 # the precise number of line on which the error occurred
1178 # EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
1179 # File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1180 # Line=self._LineIndex+1)
1181 except MacroException
as Excpt
:
1182 EdkLogger
.error('Parser', FORMAT_INVALID
, str(Excpt
),
1183 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1184 Line
=self
._LineIndex
+1)
1186 if self
._ValueList
is None:
1189 NewOwner
= self
._IdMapping
.get(Owner
, -1)
1190 self
._Enabled
= int((not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
))
1191 self
._LastItem
= self
._Store
(
1207 self
._IdMapping
[Id
] = self
._LastItem
1209 RecordList
= self
._Table
.GetAll()
1211 self
._RawTable
.Drop()
1213 for Record
in RecordList
:
1214 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])
1215 GlobalData
.gPlatformDefines
.update(self
._FileLocalMacros
)
1216 self
._PostProcessed
= True
1217 self
._Content
= None
1219 def __ProcessSectionHeader(self
):
1220 self
._SectionName
= self
._ValueList
[0]
1221 if self
._SectionName
in self
.DataType
:
1222 self
._SectionType
= self
.DataType
[self
._SectionName
]
1224 self
._SectionType
= MODEL_UNKNOWN
1226 def __ProcessSubsectionHeader(self
):
1227 self
._SubsectionName
= self
._ValueList
[0]
1228 if self
._SubsectionName
in self
.DataType
:
1229 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
1231 self
._SubsectionType
= MODEL_UNKNOWN
1233 def __RetrievePcdValue(self
):
1234 Records
= self
._RawTable
.Query(MODEL_PCD_FEATURE_FLAG
, BelongsToItem
=-1.0)
1235 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1236 Value
, DatumType
, MaxDatumSize
= AnalyzePcdData(Value
)
1237 # Only use PCD whose value is straitforward (no macro and PCD)
1238 if self
.SymbolPattern
.findall(Value
):
1240 Name
= TokenSpaceGuid
+ '.' + PcdName
1241 # Don't use PCD with different values.
1242 if Name
in self
._Symbols
and self
._Symbols
[Name
] != Value
:
1243 self
._Symbols
.pop(Name
)
1245 self
._Symbols
[Name
] = Value
1247 Records
= self
._RawTable
.Query(MODEL_PCD_FIXED_AT_BUILD
, BelongsToItem
=-1.0)
1248 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1249 Value
, DatumType
, MaxDatumSize
= AnalyzePcdData(Value
)
1250 # Only use PCD whose value is straitforward (no macro and PCD)
1251 if self
.SymbolPattern
.findall(Value
):
1253 Name
= TokenSpaceGuid
+'.'+PcdName
1254 # Don't use PCD with different values.
1255 if Name
in self
._Symbols
and self
._Symbols
[Name
] != Value
:
1256 self
._Symbols
.pop(Name
)
1258 self
._Symbols
[Name
] = Value
1260 def __ProcessDefine(self
):
1261 if not self
._Enabled
:
1264 Type
, Name
, Value
= self
._ValueList
1265 Value
= ReplaceMacro(Value
, self
._Macros
, False)
1266 if self
._ItemType
== MODEL_META_DATA_DEFINE
:
1267 if self
._SectionType
== MODEL_META_DATA_HEADER
:
1268 self
._FileLocalMacros
[Name
] = Value
1270 SectionDictKey
= self
._SectionType
, self
._Scope
[0][0], self
._Scope
[0][1]
1271 if SectionDictKey
not in self
._SectionsMacroDict
:
1272 self
._SectionsMacroDict
[SectionDictKey
] = {}
1273 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
1274 SectionLocalMacros
[Name
] = Value
1275 elif self
._ItemType
== MODEL_META_DATA_GLOBAL_DEFINE
:
1276 GlobalData
.gEdkGlobal
[Name
] = Value
1279 # Keyword in [Defines] section can be used as Macros
1281 if (self
._ItemType
== MODEL_META_DATA_HEADER
) and (self
._SectionType
== MODEL_META_DATA_HEADER
):
1282 self
._FileLocalMacros
[Name
] = Value
1284 self
._ValueList
= [Type
, Name
, Value
]
1286 def __ProcessDirective(self
):
1288 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1289 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
]:
1290 Macros
= self
._Macros
1291 Macros
.update(GlobalData
.gGlobalDefines
)
1293 Result
= ValueExpression(self
._ValueList
[1], Macros
)()
1294 except SymbolNotFound
as Exc
:
1295 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1297 except WrnExpression
as Excpt
:
1299 # Catch expression evaluation warning here. We need to report
1300 # the precise number of line and return the evaluation result
1302 EdkLogger
.warn('Parser', "Suspicious expression: %s" % str(Excpt
),
1303 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1304 Line
=self
._LineIndex
+1)
1305 Result
= Excpt
.result
1306 except BadExpression
as Exc
:
1307 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1310 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1311 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1312 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1313 self
._DirectiveStack
.append(self
._ItemType
)
1314 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
:
1315 Result
= bool(Result
)
1317 Macro
= self
._ValueList
[1]
1318 Macro
= Macro
[2:-1] if (Macro
.startswith("$(") and Macro
.endswith(")")) else Macro
1319 Result
= Macro
in self
._Macros
1320 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
:
1322 self
._DirectiveEvalStack
.append(Result
)
1323 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
:
1324 self
._DirectiveStack
.append(self
._ItemType
)
1325 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1326 self
._DirectiveEvalStack
.append(bool(Result
))
1327 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1328 self
._DirectiveStack
[-1] = self
._ItemType
1329 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1330 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1331 # Back to the nearest !if/!ifdef/!ifndef
1332 while self
._DirectiveStack
:
1333 self
._DirectiveEvalStack
.pop()
1334 Directive
= self
._DirectiveStack
.pop()
1335 if Directive
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1336 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1337 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
1338 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1340 elif self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1341 # The included file must be relative to workspace or same directory as DSC file
1342 __IncludeMacros
= {}
1344 # Allow using system environment variables in path after !include
1346 __IncludeMacros
['WORKSPACE'] = GlobalData
.gGlobalDefines
['WORKSPACE']
1349 # Allow using MACROs comes from [Defines] section to keep compatible.
1351 __IncludeMacros
.update(self
._Macros
)
1353 IncludedFile
= NormPath(ReplaceMacro(self
._ValueList
[1], __IncludeMacros
, RaiseError
=True))
1355 # First search the include file under the same directory as DSC file
1357 IncludedFile1
= PathClass(IncludedFile
, self
.MetaFile
.Dir
)
1358 ErrorCode
, ErrorInfo1
= IncludedFile1
.Validate()
1361 # Also search file under the WORKSPACE directory
1363 IncludedFile1
= PathClass(IncludedFile
, GlobalData
.gWorkspace
)
1364 ErrorCode
, ErrorInfo2
= IncludedFile1
.Validate()
1366 EdkLogger
.error('parser', ErrorCode
, File
=self
._FileWithError
,
1367 Line
=self
._LineIndex
+1, ExtraData
=ErrorInfo1
+ "\n"+ ErrorInfo2
)
1369 self
._FileWithError
= IncludedFile1
1371 IncludedFileTable
= MetaFileStorage(self
._Table
.Cur
, IncludedFile1
, MODEL_FILE_DSC
, True)
1372 Owner
= self
._Content
[self
._ContentIndex
-1][0]
1373 Parser
= DscParser(IncludedFile1
, self
._FileType
, IncludedFileTable
,
1374 Owner
=Owner
, From
=Owner
)
1376 # set the parser status with current status
1377 Parser
._SectionName
= self
._SectionName
1378 Parser
._SectionType
= self
._SectionType
1379 Parser
._Scope
= self
._Scope
1380 Parser
._Enabled
= self
._Enabled
1381 # Parse the included file
1384 # update current status with sub-parser's status
1385 self
._SectionName
= Parser
._SectionName
1386 self
._SectionType
= Parser
._SectionType
1387 self
._Scope
= Parser
._Scope
1388 self
._Enabled
= Parser
._Enabled
1390 # Insert all records in the table for the included file into dsc file table
1391 Records
= IncludedFileTable
.GetAll()
1393 self
._Content
[self
._ContentIndex
:self
._ContentIndex
] = Records
1394 self
._Content
.pop(self
._ContentIndex
-1)
1395 self
._ValueList
= None
1396 self
._ContentIndex
-= 1
1398 def __ProcessSkuId(self
):
1399 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=True)
1400 for Value
in self
._ValueList
]
1402 def __ProcessLibraryInstance(self
):
1403 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
1405 def __ProcessLibraryClass(self
):
1406 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, RaiseError
=True)
1408 def __ProcessPcd(self
):
1409 ValueList
= GetSplitValueList(self
._ValueList
[2])
1411 # PCD value can be an expression
1413 if len(ValueList
) > 1 and ValueList
[1] == TAB_VOID
:
1414 PcdValue
= ValueList
[0]
1416 ValueList
[0] = ValueExpression(PcdValue
, self
._Macros
)(True)
1417 except WrnExpression
as Value
:
1418 ValueList
[0] = Value
.result
1420 PcdValue
= ValueList
[-1]
1422 ValueList
[-1] = ValueExpression(PcdValue
, self
._Macros
)(True)
1423 except WrnExpression
as Value
:
1424 ValueList
[-1] = Value
.result
1426 if ValueList
[-1] == 'True':
1428 if ValueList
[-1] == 'False':
1431 self
._ValueList
[2] = '|'.join(ValueList
)
1433 def __ProcessComponent(self
):
1434 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1436 def __ProcessBuildOption(self
):
1437 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=False)
1438 for Value
in self
._ValueList
]
1441 MODEL_META_DATA_HEADER
: _DefineParser
,
1442 MODEL_EFI_SKU_ID
: _SkuIdParser
,
1443 MODEL_EFI_LIBRARY_INSTANCE
: _LibraryInstanceParser
,
1444 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
1445 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1446 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1447 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1448 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
1449 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
1450 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
1451 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
1452 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
1453 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
1454 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
1455 MODEL_META_DATA_BUILD_OPTION
: _BuildOptionParser
,
1456 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1457 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1458 MODEL_META_DATA_SECTION_HEADER
: MetaFileParser
._SectionHeaderParser
,
1459 MODEL_META_DATA_SUBSECTION_HEADER
: _SubsectionHeaderParser
,
1462 _Macros
= property(_GetMacros
)
1464 ## DEC file parser class
1466 # @param FilePath The path of platform description file
1467 # @param FileType The raw data of DSC file
1468 # @param Table Database used to retrieve module/package information
1469 # @param Macros Macros used for replacement in file
1471 class DecParser(MetaFileParser
):
1472 # DEC file supported data types (one type per section)
1474 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1475 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
1476 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1477 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1478 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1479 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1480 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1481 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1482 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1483 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1484 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1485 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1488 ## Constructor of DecParser
1490 # Initialize object of DecParser
1492 # @param FilePath The path of platform description file
1493 # @param FileType The raw data of DSC file
1494 # @param Table Database used to retrieve module/package information
1495 # @param Macros Macros used for replacement in file
1497 def __init__(self
, FilePath
, FileType
, Table
):
1498 # prevent re-initialization
1499 if hasattr(self
, "_Table"):
1501 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
1503 self
._Version
= 0x00010005 # Only EDK2 dec file is supported
1504 self
.TblFile
= EccGlobalData
.gDb
.TblFile
1511 Content
= open(str(self
.MetaFile
), 'r').readlines()
1513 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1516 # Insert a record for file
1518 Filename
= NormPath(self
.MetaFile
)
1519 FileID
= self
.TblFile
.GetFileId(Filename
)
1521 self
.FileID
= FileID
1523 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_DEC
)
1525 for Index
in range(0, len(Content
)):
1526 Line
, Comment
= CleanString2(Content
[Index
])
1527 self
._CurrentLine
= Line
1528 self
._LineIndex
= Index
1530 # save comment for later use
1532 self
._Comments
.append((Comment
, self
._LineIndex
+1))
1538 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1539 self
._SectionHeaderParser
()
1542 elif len(self
._SectionType
) == 0:
1547 self
._ValueList
= ['', '', '']
1548 self
._SectionParser
[self
._SectionType
[0]](self
)
1549 if self
._ValueList
is None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
1555 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1556 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1558 for Arch
, ModuleType
, Type
in self
._Scope
:
1559 self
._LastItem
= self
._Store
(
1574 for Comment
, LineNo
in self
._Comments
:
1576 MODEL_META_DATA_COMMENT
,
1593 def _GetApplicableSectionMacro(self
):
1595 for S1
, S2
, SectionType
in self
._Scope
:
1596 for Scope1
, Scope2
in [("COMMON", "COMMON"), ("COMMON", S2
), (S1
, "COMMON"), (S1
, S2
)]:
1597 if (SectionType
, Scope1
, Scope2
) in self
._SectionsMacroDict
:
1598 Macros
.update(self
._SectionsMacroDict
[(SectionType
, Scope1
, Scope2
)])
1601 ## Section header parser
1603 # The section header is always in following format:
1605 # [section_name.arch<.platform|module_type>]
1607 def _SectionHeaderParser(self
):
1609 self
._SectionName
= ''
1610 self
._SectionType
= []
1612 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
1615 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
)
1617 # different types of PCD are permissible in one section
1618 self
._SectionName
= ItemList
[0].upper()
1619 if self
._SectionName
in self
.DataType
:
1620 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1621 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1623 EdkLogger
.warn("Parser", "Unrecognized section", File
=self
.MetaFile
,
1624 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
1627 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1631 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1633 Line
=self
._LineIndex
+1,
1634 ExtraData
=self
._CurrentLine
1637 if len(ItemList
) > 1:
1638 S1
= ItemList
[1].upper()
1642 # S2 may be Platform or ModuleType
1643 if len(ItemList
) > 2:
1644 S2
= ItemList
[2].upper()
1647 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1648 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1650 # 'COMMON' must not be used with specific ARCHs at the same section
1651 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1652 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1653 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
1655 ## [guids], [ppis] and [protocols] section parser
1657 def _GuidParser(self
):
1658 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1659 if len(TokenList
) < 2:
1660 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1661 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1662 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1663 if TokenList
[0] == '':
1664 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1665 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1666 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1667 if TokenList
[1] == '':
1668 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1669 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1670 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1671 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1672 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1673 ExtraData
=self
._CurrentLine
+ \
1674 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1675 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1676 self
._ValueList
[0] = TokenList
[0]
1677 #Parse the Guid value format
1678 GuidValueList
= TokenList
[1].strip(' {}').split(',')
1681 if len(GuidValueList
) == 11:
1682 for GuidValue
in GuidValueList
:
1683 GuidValue
= GuidValue
.strip()
1684 if GuidValue
.startswith('0x') or GuidValue
.startswith('0X'):
1685 HexList
.append('0x' + str(GuidValue
[2:]))
1689 if GuidValue
.startswith('{'):
1690 GuidValue
= GuidValue
.lstrip(' {')
1691 HexList
.append('0x' + str(GuidValue
[2:]))
1693 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])
1695 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1696 ExtraData
=self
._CurrentLine
+ \
1697 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1698 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1699 self
._ValueList
[0] = ''
1701 ## PCD sections parser
1703 # [PcdsFixedAtBuild]
1704 # [PcdsPatchableInModule]
1710 def _PcdParser(self
):
1711 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1712 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1713 # check PCD information
1714 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1715 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1716 ExtraData
=self
._CurrentLine
+ \
1717 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1718 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1719 # check PCD datum information
1720 if len(TokenList
) < 2 or TokenList
[1] == '':
1721 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1722 ExtraData
=self
._CurrentLine
+ \
1723 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1724 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1727 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1728 PtrValue
= ValueRe
.findall(TokenList
[1])
1730 # Has VOID* type string, may contain "|" character in the string.
1731 if len(PtrValue
) != 0:
1732 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1733 ValueList
= GetSplitValueList(ptrValueList
)
1734 ValueList
[0] = PtrValue
[0]
1736 ValueList
= GetSplitValueList(TokenList
[1])
1739 # check if there's enough datum information given
1740 if len(ValueList
) != 3:
1741 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1742 ExtraData
=self
._CurrentLine
+ \
1743 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1744 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1745 # check default value
1746 if ValueList
[0] == '':
1747 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1748 ExtraData
=self
._CurrentLine
+ \
1749 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1750 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1752 if ValueList
[1] == '':
1753 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1754 ExtraData
=self
._CurrentLine
+ \
1755 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1756 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1757 # check token of the PCD
1758 if ValueList
[2] == '':
1759 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1760 ExtraData
=self
._CurrentLine
+ \
1761 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1762 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1763 # check format of default value against the datum type
1764 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1766 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1767 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1769 if EccGlobalData
.gConfig
.UniCheckPCDInfo
== '1' or EccGlobalData
.gConfig
.UniCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
1770 # check Description, Prompt information
1771 PatternDesc
= re
.compile('##\s*([\x21-\x7E\s]*)', re
.S
)
1772 PatternPrompt
= re
.compile('#\s+@Prompt\s+([\x21-\x7E\s]*)', re
.S
)
1775 # check @ValidRange, @ValidList and @Expression format valid
1776 ErrorCodeValid
= '0x0 <= %s <= 0xFFFFFFFF'
1777 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]+)'
1778 PatternValidRng
= re
.compile('^' + '(NOT)?\s*' + PatternValidRangeIn
+ '$')
1779 for Comment
in self
._Comments
:
1780 Comm
= Comment
[0].strip()
1784 Description
= PatternDesc
.findall(Comm
)
1786 Prompt
= PatternPrompt
.findall(Comm
)
1788 ValidFormt
= Comm
.lstrip('#')
1789 ValidFormt
= ValidFormt
.lstrip()
1790 if ValidFormt
[0:11] == '@ValidRange':
1791 ValidFormt
= ValidFormt
[11:]
1792 ValidFormt
= ValidFormt
.lstrip()
1794 ErrorCode
, Expression
= ValidFormt
.split('|', 1)
1797 Expression
= ValidFormt
1798 ErrorCode
, Expression
= ErrorCode
.strip(), Expression
.strip()
1800 if not eval(ErrorCodeValid
% ErrorCode
):
1801 EdkLogger
.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1803 EdkLogger
.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1804 if not PatternValidRng
.search(Expression
):
1805 EdkLogger
.warn('Parser', '@ValidRange Expression(%s) of PCD %s is incorrect format.' % (Expression
, TokenList
[0]))
1806 if ValidFormt
[0:10] == '@ValidList':
1807 ValidFormt
= ValidFormt
[10:]
1808 ValidFormt
= ValidFormt
.lstrip()
1810 ErrorCode
, Expression
= ValidFormt
.split('|', 1)
1813 Expression
= ValidFormt
1814 ErrorCode
, Expression
= ErrorCode
.strip(), Expression
.strip()
1816 if not eval(ErrorCodeValid
% ErrorCode
):
1817 EdkLogger
.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1819 EdkLogger
.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1820 Values
= Expression
.split(',')
1821 for Value
in Values
:
1822 Value
= Value
.strip()
1826 EdkLogger
.warn('Parser', '@ValidList Expression of PCD %s include a invalid value(%s).' % (TokenList
[0], Value
))
1828 if ValidFormt
[0:11] == '@Expression':
1829 ValidFormt
= ValidFormt
[11:]
1830 ValidFormt
= ValidFormt
.lstrip()
1832 ErrorCode
, Expression
= ValidFormt
.split('|', 1)
1835 Expression
= ValidFormt
1836 ErrorCode
, Expression
= ErrorCode
.strip(), Expression
.strip()
1838 if not eval(ErrorCodeValid
% ErrorCode
):
1839 EdkLogger
.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1841 EdkLogger
.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1843 EdkLogger
.warn('Parser', '@Expression Expression of PCD %s is incorrect format.' % TokenList
[0])
1845 EdkLogger
.warn('Parser', 'PCD %s Description information is not provided.' % TokenList
[0])
1847 EdkLogger
.warn('Parser', 'PCD %s Prompt information is not provided.' % TokenList
[0])
1848 # check Description, Prompt localization information
1850 self
._UniObj
.CheckPcdInfo(TokenList
[0])
1852 if ValueList
[0] in ['True', 'true', 'TRUE']:
1854 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1857 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
1860 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
1861 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
1862 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
1863 MODEL_EFI_GUID
: _GuidParser
,
1864 MODEL_EFI_PPI
: _GuidParser
,
1865 MODEL_EFI_PROTOCOL
: _GuidParser
,
1866 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1867 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1868 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1869 MODEL_PCD_DYNAMIC
: _PcdParser
,
1870 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
1871 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1872 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1878 # This class defined the structure used in Fdf object
1880 # @param Filename: Input value for Ffilename of Fdf file, default is None
1881 # @param WorkspaceDir: Input value for current workspace directory, default is None
1884 def __init__(self
, Filename
= None, IsToDatabase
= False, WorkspaceDir
= None, Database
= None):
1885 self
.WorkspaceDir
= WorkspaceDir
1886 self
.IsToDatabase
= IsToDatabase
1888 self
.Cur
= Database
.Cur
1889 self
.TblFile
= Database
.TblFile
1890 self
.TblFdf
= Database
.TblFdf
1895 # Load Fdf file if filename is not None
1897 if Filename
is not None:
1899 self
.LoadFdfFile(Filename
)
1904 # Insert a FDF file record into database
1906 def InsertFile(self
, Filename
):
1908 Filename
= NormPath(Filename
)
1909 if Filename
not in self
.FileList
:
1910 FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_FDF
)
1911 self
.FileList
[Filename
] = FileID
1913 return self
.FileList
[Filename
]
1918 # Load the file if it exists
1920 # @param Filename: Input value for filename of Fdf file
1922 def LoadFdfFile(self
, Filename
):
1927 Filename
= NormPath(Filename
)
1928 Fdf
= FdfParser(Filename
)
1932 # Insert inf file and pcd information
1934 if self
.IsToDatabase
:
1935 (Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
) = \
1936 (0, '', '', '', 'COMMON', 'COMMON', -1, -1, -1, -1, -1, -1, 0)
1937 for Index
in range(0, len(Fdf
.Profile
.PcdDict
)):
1939 for Key
in Fdf
.Profile
.PcdDict
.keys():
1943 FileName
= Fdf
.Profile
.PcdFileLineDict
[Key
][0]
1944 StartLine
= Fdf
.Profile
.PcdFileLineDict
[Key
][1]
1945 BelongsToFile
= self
.InsertFile(FileName
)
1946 self
.TblFdf
.Insert(Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
)
1947 for Index
in range(0, len(Fdf
.Profile
.InfList
)):
1948 Model
= MODEL_META_DATA_COMPONENT
1949 Value1
= Fdf
.Profile
.InfList
[Index
]
1951 FileName
= Fdf
.Profile
.InfFileLineList
[Index
][0]
1952 StartLine
= Fdf
.Profile
.InfFileLineList
[Index
][1]
1953 BelongsToFile
= self
.InsertFile(FileName
)
1954 self
.TblFdf
.Insert(Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
)
1956 class UniParser(object):
1957 # IsExtraUni defined the UNI file is Module UNI or extra Module UNI
1958 # IsModuleUni defined the UNI file is Module UNI or Package UNI
1959 def __init__(self
, FilePath
, IsExtraUni
=False, IsModuleUni
=True):
1960 self
.FilePath
= FilePath
1961 self
.FileName
= os
.path
.basename(FilePath
)
1962 self
.IsExtraUni
= IsExtraUni
1963 self
.IsModuleUni
= IsModuleUni
1970 self
.FileIn
= CodecOpenLongFilePath(self
.FilePath
, Mode
='rb', Encoding
='utf_8').read()
1971 except UnicodeError:
1972 self
.FileIn
= CodecOpenLongFilePath(self
.FilePath
, Mode
='rb', Encoding
='utf_16').read()
1973 except UnicodeError:
1974 self
.FileIn
= CodecOpenLongFilePath(self
.FilePath
, Mode
='rb', Encoding
='utf_16_le').read()
1979 if self
.IsModuleUni
:
1981 ModuleName
= self
.CheckKeyValid('STR_PROPERTIES_MODULE_NAME')
1982 self
.PrintLog('STR_PROPERTIES_MODULE_NAME', ModuleName
)
1984 ModuleAbstract
= self
.CheckKeyValid('STR_MODULE_ABSTRACT')
1985 self
.PrintLog('STR_MODULE_ABSTRACT', ModuleAbstract
)
1986 ModuleDescription
= self
.CheckKeyValid('STR_MODULE_DESCRIPTION')
1987 self
.PrintLog('STR_MODULE_DESCRIPTION', ModuleDescription
)
1990 PackageName
= self
.CheckKeyValid('STR_PROPERTIES_PACKAGE_NAME')
1991 self
.PrintLog('STR_PROPERTIES_PACKAGE_NAME', PackageName
)
1993 PackageAbstract
= self
.CheckKeyValid('STR_PACKAGE_ABSTRACT')
1994 self
.PrintLog('STR_PACKAGE_ABSTRACT', PackageAbstract
)
1995 PackageDescription
= self
.CheckKeyValid('STR_PACKAGE_DESCRIPTION')
1996 self
.PrintLog('STR_PACKAGE_DESCRIPTION', PackageDescription
)
1998 def CheckKeyValid(self
, Key
, Contents
=None):
2000 Contents
= self
.FileIn
2001 KeyPattern
= re
.compile('#string\s+%s\s+.*?#language.*?".*?"' % Key
, re
.S
)
2002 if KeyPattern
.search(Contents
):
2006 def CheckPcdInfo(self
, PcdCName
):
2007 PromptKey
= 'STR_%s_PROMPT' % PcdCName
.replace('.', '_')
2008 PcdPrompt
= self
.CheckKeyValid(PromptKey
)
2009 self
.PrintLog(PromptKey
, PcdPrompt
)
2010 HelpKey
= 'STR_%s_HELP' % PcdCName
.replace('.', '_')
2011 PcdHelp
= self
.CheckKeyValid(HelpKey
)
2012 self
.PrintLog(HelpKey
, PcdHelp
)
2014 def PrintLog(self
, Key
, Value
):
2015 if not Value
and Key
not in self
.Missing
:
2016 Msg
= '%s is missing in the %s file.' % (Key
, self
.FileName
)
2017 EdkLogger
.warn('Parser', Msg
)
2018 EccGlobalData
.gDb
.TblReport
.Insert(EccToolError
.ERROR_GENERAL_CHECK_UNI_HELP_INFO
, OtherMsg
=Msg
, BelongsToTable
='File', BelongsToItem
=-2)
2019 self
.Missing
.append(Key
)
2023 # This acts like the main() function for the script, unless it is 'import'ed into another
2026 if __name__
== '__main__':