2 # This file is used to parse meta files
4 # Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 import Common
.LongFilePathOs
as os
22 import Common
.EdkLogger
as EdkLogger
23 import Common
.GlobalData
as GlobalData
26 from CommonDataClass
.DataClass
import *
27 from Common
.DataType
import *
28 from Common
.String
import *
29 from Common
.Misc
import GuidStructureStringToGuidString
, CheckPcdDatum
, PathClass
, AnalyzePcdData
30 from Common
.Expression
import *
31 from CommonDataClass
.Exceptions
import *
33 from MetaFileTable
import MetaFileStorage
34 from GenFds
.FdfParser
import FdfParser
35 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
36 from Common
.LongFilePathSupport
import CodecOpenLongFilePath
38 ## A decorator used to parse macro definition
39 def ParseMacro(Parser
):
40 def MacroParser(self
):
41 Match
= gMacroDefPattern
.match(self
._CurrentLine
)
43 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
47 TokenList
= GetSplitValueList(self
._CurrentLine
[Match
.end(1):], TAB_EQUAL_SPLIT
, 1)
50 EdkLogger
.error('Parser', FORMAT_INVALID
, "No macro name given",
51 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
52 if len(TokenList
) < 2:
56 Name
, Value
= TokenList
57 # Global macros can be only defined via environment variable
58 if Name
in GlobalData
.gGlobalDefines
:
59 EdkLogger
.error('Parser', FORMAT_INVALID
, "%s can only be defined via environment variable" % Name
,
60 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
61 # Only upper case letters, digit and '_' are allowed
62 if not gMacroNamePattern
.match(Name
):
63 EdkLogger
.error('Parser', FORMAT_INVALID
, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
64 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
66 Value
= ReplaceMacro(Value
, self
._Macros
)
67 self
._ItemType
= MODEL_META_DATA_DEFINE
68 # DEFINE defined macros
69 if Type
== TAB_DSC_DEFINES_DEFINE
:
70 if type(self
) == DecParser
:
71 if MODEL_META_DATA_HEADER
in self
._SectionType
:
72 self
._FileLocalMacros
[Name
] = Value
74 for Scope
in self
._Scope
:
75 self
._SectionsMacroDict
.setdefault((Scope
[2], Scope
[0], Scope
[1]), {})[Name
] = Value
76 elif self
._SectionType
== MODEL_META_DATA_HEADER
:
77 self
._FileLocalMacros
[Name
] = Value
79 SectionDictKey
= self
._SectionType
, self
._Scope
[0][0], self
._Scope
[0][1]
80 if SectionDictKey
not in self
._SectionsMacroDict
:
81 self
._SectionsMacroDict
[SectionDictKey
] = {}
82 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
83 SectionLocalMacros
[Name
] = Value
84 # EDK_GLOBAL defined macros
85 elif type(self
) != DscParser
:
86 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used in .dsc file",
87 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
88 elif self
._SectionType
!= MODEL_META_DATA_HEADER
:
89 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used under [Defines] section",
90 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
91 elif (Name
in self
._FileLocalMacros
) and (self
._FileLocalMacros
[Name
] != Value
):
92 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
93 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
95 self
._ValueList
= [Type
, Name
, Value
]
99 ## Base class of parser
101 # This class is used for derivation purpose. The specific parser for one kind
102 # type file must derive this class and implement some public interfaces.
104 # @param FilePath The path of platform description file
105 # @param FileType The raw data of DSC file
106 # @param Table Database used to retrieve module/package information
107 # @param Macros Macros used for replacement in file
108 # @param Owner Owner ID (for sub-section parsing)
109 # @param From ID from which the data comes (for !INCLUDE directive)
111 class MetaFileParser(object):
112 # data type (file content) for specific file type
115 # Parser objects used to implement singleton
120 # One file, one parser object. This factory method makes sure that there's
121 # only one object constructed for one meta file.
123 # @param Class class object of real AutoGen class
124 # (InfParser, DecParser or DscParser)
125 # @param FilePath The path of meta file
126 # @param *args The specific class related parameters
127 # @param **kwargs The specific class related dict parameters
129 def __new__(Class
, FilePath
, *args
, **kwargs
):
130 if FilePath
in Class
.MetaFiles
:
131 return Class
.MetaFiles
[FilePath
]
133 ParserObject
= super(MetaFileParser
, Class
).__new
__(Class
)
134 Class
.MetaFiles
[FilePath
] = ParserObject
137 ## Constructor of MetaFileParser
139 # Initialize object of MetaFileParser
141 # @param FilePath The path of platform description file
142 # @param FileType The raw data of DSC file
143 # @param Table Database used to retrieve module/package information
144 # @param Macros Macros used for replacement in file
145 # @param Owner Owner ID (for sub-section parsing)
146 # @param From ID from which the data comes (for !INCLUDE directive)
148 def __init__(self
, FilePath
, FileType
, Table
, Owner
=-1, From
=-1):
150 self
._RawTable
= Table
151 self
._FileType
= FileType
152 self
.MetaFile
= FilePath
154 self
._FileLocalMacros
= {}
155 self
._SectionsMacroDict
= {}
157 # for recursive parsing
158 self
._Owner
= [Owner
]
161 # parsr status for parsing
162 self
._ValueList
= ['', '', '', '', '']
165 self
._CurrentLine
= ''
166 self
._SectionType
= MODEL_UNKNOWN
167 self
._SectionName
= ''
168 self
._InSubsection
= False
169 self
._SubsectionType
= MODEL_UNKNOWN
170 self
._SubsectionName
= ''
171 self
._ItemType
= MODEL_UNKNOWN
174 self
._Finished
= False
175 self
._PostProcessed
= False
176 # Different version of meta-file has different way to parse.
178 # UNI object and extra UNI object
180 self
._UniExtraObj
= None
182 ## Store the parsed data in table
183 def _Store(self
, *Args
):
184 return self
._Table
.Insert(*Args
)
186 ## Virtual method for starting parse
188 raise NotImplementedError
190 ## Notify a post-process is needed
191 def DoPostProcess(self
):
192 self
._PostProcessed
= False
194 ## Set parsing complete flag in both class and table
196 self
._Finished
= True
197 ## Do not set end flag when processing included files
199 self
._Table
.SetEndFlag()
201 def _PostProcess(self
):
202 self
._PostProcessed
= True
204 ## Get the parse complete flag
205 def _GetFinished(self
):
206 return self
._Finished
208 ## Set the complete flag
209 def _SetFinished(self
, Value
):
210 self
._Finished
= Value
212 ## Use [] style to query data in table, just for readability
214 # DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]
216 def __getitem__(self
, DataInfo
):
217 if type(DataInfo
) != type(()):
218 DataInfo
= (DataInfo
,)
220 # Parse the file first, if necessary
221 if not self
._Finished
:
222 if self
._RawTable
.IsIntegrity():
223 self
._Finished
= True
225 self
._Table
= self
._RawTable
226 self
._PostProcessed
= False
229 # No specific ARCH or Platform given, use raw data
230 if self
._RawTable
and (len(DataInfo
) == 1 or DataInfo
[1] == None):
231 return self
._RawTable
.Query(*DataInfo
)
233 # Do post-process if necessary
234 if not self
._PostProcessed
:
237 return self
._Table
.Query(*DataInfo
)
239 ## Data parser for the common format in different type of file
241 # The common format in the meatfile is like
246 def _CommonParser(self
):
247 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
248 self
._ValueList
[0:len(TokenList
)] = TokenList
250 ## Data parser for the format in which there's path
252 # Only path can have macro used. So we need to replace them before use.
255 def _PathParser(self
):
256 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
257 self
._ValueList
[0:len(TokenList
)] = TokenList
258 # Don't do macro replacement for dsc file at this point
259 if type(self
) != DscParser
:
260 Macros
= self
._Macros
261 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
263 ## Skip unsupported data
265 if self
._SectionName
== TAB_USER_EXTENSIONS
.upper() and self
._CurrentLine
.upper().endswith('.UNI'):
266 if EccGlobalData
.gConfig
.UniCheckHelpInfo
== '1' or EccGlobalData
.gConfig
.UniCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
267 ExtraUni
= self
._CurrentLine
.strip()
268 ExtraUniFile
= os
.path
.join(os
.path
.dirname(self
.MetaFile
), ExtraUni
)
269 IsModuleUni
= self
.MetaFile
.upper().endswith('.INF')
270 self
._UniExtraObj
= UniParser(ExtraUniFile
, IsExtraUni
=True, IsModuleUni
=IsModuleUni
)
271 self
._UniExtraObj
.Start()
273 EdkLogger
.warn("Parser", "Unrecognized content", File
=self
.MetaFile
,
274 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
);
275 self
._ValueList
[0:1] = [self
._CurrentLine
]
277 ## Section header parser
279 # The section header is always in following format:
281 # [section_name.arch<.platform|module_type>]
283 def _SectionHeaderParser(self
):
285 self
._SectionName
= ''
287 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
290 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
)
291 # different section should not mix in one section
292 if self
._SectionName
!= '' and self
._SectionName
!= ItemList
[0].upper():
293 EdkLogger
.error('Parser', FORMAT_INVALID
, "Different section names in the same section",
294 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
295 self
._SectionName
= ItemList
[0].upper()
296 if self
._SectionName
in self
.DataType
:
297 self
._SectionType
= self
.DataType
[self
._SectionName
]
299 self
._SectionType
= MODEL_UNKNOWN
300 EdkLogger
.warn("Parser", "Unrecognized section", File
=self
.MetaFile
,
301 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
303 if len(ItemList
) > 1:
304 S1
= ItemList
[1].upper()
308 # S2 may be Platform or ModuleType
309 if len(ItemList
) > 2:
310 S2
= ItemList
[2].upper()
313 self
._Scope
.append([S1
, S2
])
315 # 'COMMON' must not be used with specific ARCHs at the same section
316 if 'COMMON' in ArchList
and len(ArchList
) > 1:
317 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
318 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
319 # If the section information is needed later, it should be stored in database
320 self
._ValueList
[0] = self
._SectionName
322 ## [defines] section parser
324 def _DefineParser(self
):
325 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
326 self
._ValueList
[1:len(TokenList
)] = TokenList
327 if not self
._ValueList
[1]:
328 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
329 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
330 if not self
._ValueList
[2]:
331 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
332 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
334 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
335 Name
, Value
= self
._ValueList
[1], self
._ValueList
[2]
336 # Sometimes, we need to make differences between EDK and EDK2 modules
337 if Name
== 'INF_VERSION':
339 self
._Version
= int(Value
, 0)
341 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid version number",
342 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
343 elif Name
== 'MODULE_UNI_FILE':
344 UniFile
= os
.path
.join(os
.path
.dirname(self
.MetaFile
), Value
)
345 if os
.path
.exists(UniFile
):
346 self
._UniObj
= UniParser(UniFile
, IsExtraUni
=False, IsModuleUni
=True)
349 EdkLogger
.error('Parser', FILE_NOT_FOUND
, "Module UNI file %s is missing." % Value
,
350 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
352 elif Name
== 'PACKAGE_UNI_FILE':
353 UniFile
= os
.path
.join(os
.path
.dirname(self
.MetaFile
), Value
)
354 if os
.path
.exists(UniFile
):
355 self
._UniObj
= UniParser(UniFile
, IsExtraUni
=False, IsModuleUni
=False)
357 if type(self
) == InfParser
and self
._Version
< 0x00010005:
358 # EDK module allows using defines as macros
359 self
._FileLocalMacros
[Name
] = Value
360 self
._Defines
[Name
] = Value
362 ## [BuildOptions] section parser
364 def _BuildOptionParser(self
):
365 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
366 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
367 if len(TokenList2
) == 2:
368 self
._ValueList
[0] = TokenList2
[0] # toolchain family
369 self
._ValueList
[1] = TokenList2
[1] # keys
371 self
._ValueList
[1] = TokenList
[0]
372 if len(TokenList
) == 2 and type(self
) != DscParser
: # value
373 self
._ValueList
[2] = ReplaceMacro(TokenList
[1], self
._Macros
)
375 if self
._ValueList
[1].count('_') != 4:
379 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
380 ExtraData
=self
._CurrentLine
,
382 Line
=self
._LineIndex
+1
385 def _GetMacros(self
):
387 Macros
.update(self
._FileLocalMacros
)
388 Macros
.update(self
._GetApplicableSectionMacro
())
392 ## Get section Macros that are applicable to current line, which may come from other sections
393 ## that share the same name while scope is wider
394 def _GetApplicableSectionMacro(self
):
396 for Scope1
, Scope2
in [("COMMON", "COMMON"), ("COMMON", self
._Scope
[0][1]),
397 (self
._Scope
[0][0], "COMMON"), (self
._Scope
[0][0], self
._Scope
[0][1])]:
398 if (self
._SectionType
, Scope1
, Scope2
) in self
._SectionsMacroDict
:
399 Macros
.update(self
._SectionsMacroDict
[(self
._SectionType
, Scope1
, Scope2
)])
403 Finished
= property(_GetFinished
, _SetFinished
)
404 _Macros
= property(_GetMacros
)
407 ## INF file parser class
409 # @param FilePath The path of platform description file
410 # @param FileType The raw data of DSC file
411 # @param Table Database used to retrieve module/package information
412 # @param Macros Macros used for replacement in file
414 class InfParser(MetaFileParser
):
415 # INF file supported data types (one type per section)
417 TAB_UNKNOWN
.upper() : MODEL_UNKNOWN
,
418 TAB_INF_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
419 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
420 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
421 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
422 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
423 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
424 TAB_PACKAGES
.upper() : MODEL_META_DATA_PACKAGE
,
425 TAB_NMAKE
.upper() : MODEL_META_DATA_NMAKE
,
426 TAB_INF_FIXED_PCD
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
427 TAB_INF_PATCH_PCD
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
428 TAB_INF_FEATURE_PCD
.upper() : MODEL_PCD_FEATURE_FLAG
,
429 TAB_INF_PCD_EX
.upper() : MODEL_PCD_DYNAMIC_EX
,
430 TAB_INF_PCD
.upper() : MODEL_PCD_DYNAMIC
,
431 TAB_SOURCES
.upper() : MODEL_EFI_SOURCE_FILE
,
432 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
433 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
434 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
435 TAB_DEPEX
.upper() : MODEL_EFI_DEPEX
,
436 TAB_BINARIES
.upper() : MODEL_EFI_BINARY_FILE
,
437 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
440 ## Constructor of InfParser
442 # Initialize object of InfParser
444 # @param FilePath The path of module description file
445 # @param FileType The raw data of DSC file
446 # @param Table Database used to retrieve module/package information
447 # @param Macros Macros used for replacement in file
449 def __init__(self
, FilePath
, FileType
, Table
):
450 # prevent re-initialization
451 if hasattr(self
, "_Table"):
453 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
454 self
.TblFile
= EccGlobalData
.gDb
.TblFile
463 Content
= open(str(self
.MetaFile
), 'r').readlines()
465 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
467 # Insert a record for file
469 Filename
= NormPath(self
.MetaFile
)
470 FileID
= self
.TblFile
.GetFileId(Filename
)
474 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_INF
)
476 # parse the file line by line
477 IsFindBlockComment
= False
479 for Index
in range(0, len(Content
)):
480 if self
._SectionType
in [MODEL_EFI_GUID
,
483 MODEL_PCD_FIXED_AT_BUILD
,
484 MODEL_PCD_PATCHABLE_IN_MODULE
,
485 MODEL_PCD_FEATURE_FLAG
,
486 MODEL_PCD_DYNAMIC_EX
,
488 Line
= Content
[Index
].strip()
489 if Line
.startswith(TAB_SPECIAL_COMMENT
):
490 Usage
+= ' ' + Line
[Line
.find(TAB_SPECIAL_COMMENT
):]
492 elif Line
.startswith(TAB_COMMENT_SPLIT
):
494 elif Line
.find(TAB_COMMENT_SPLIT
) > 0:
495 Usage
+= ' ' + Line
[Line
.find(TAB_COMMENT_SPLIT
):]
496 Line
= Line
[:Line
.find(TAB_COMMENT_SPLIT
)]
498 # skip empty, commented, block commented lines
499 Line
= CleanString(Content
[Index
], AllowCppStyleComment
=True)
502 if Index
+ 1 < len(Content
):
503 NextLine
= CleanString(Content
[Index
+ 1])
506 if Line
.find(DataType
.TAB_COMMENT_EDK_START
) > -1:
507 IsFindBlockComment
= True
509 if Line
.find(DataType
.TAB_COMMENT_EDK_END
) > -1:
510 IsFindBlockComment
= False
512 if IsFindBlockComment
:
515 self
._LineIndex
= Index
516 self
._CurrentLine
= Line
519 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
520 self
._SectionHeaderParser
()
521 # Check invalid sections
522 if self
._Version
< 0x00010005:
523 if self
._SectionType
in [MODEL_META_DATA_BUILD_OPTION
,
524 MODEL_EFI_LIBRARY_CLASS
,
525 MODEL_META_DATA_PACKAGE
,
526 MODEL_PCD_FIXED_AT_BUILD
,
527 MODEL_PCD_PATCHABLE_IN_MODULE
,
528 MODEL_PCD_FEATURE_FLAG
,
529 MODEL_PCD_DYNAMIC_EX
,
534 MODEL_META_DATA_USER_EXTENSION
]:
535 EdkLogger
.error('Parser', FORMAT_INVALID
,
536 "Section [%s] is not allowed in inf file without version" % (self
._SectionName
),
537 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
538 elif self
._SectionType
in [MODEL_EFI_INCLUDE
,
539 MODEL_EFI_LIBRARY_INSTANCE
,
540 MODEL_META_DATA_NMAKE
]:
541 EdkLogger
.error('Parser', FORMAT_INVALID
,
542 "Section [%s] is not allowed in inf file with version 0x%08x" % (self
._SectionName
, self
._Version
),
543 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
545 # merge two lines specified by '\' in section NMAKE
546 elif self
._SectionType
== MODEL_META_DATA_NMAKE
:
549 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
552 if NextLine
[0] == TAB_SECTION_START
and NextLine
[-1] == TAB_SECTION_END
:
553 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
556 NmakeLine
= NmakeLine
+ ' ' + Line
[0:-1]
559 self
._CurrentLine
= NmakeLine
+ Line
563 self
._ValueList
= ['','','']
564 # parse current line, result will be put in self._ValueList
565 self
._SectionParser
[self
._SectionType
](self
)
566 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
570 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
571 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
573 self
._ValueList
[0] = self
._ValueList
[0].replace('/', '\\')
574 Usage
= Usage
.strip()
575 for Arch
, Platform
in self
._Scope
:
576 self
._Store
(self
._SectionType
,
592 if IsFindBlockComment
:
593 EdkLogger
.error("Parser", FORMAT_INVALID
, "Open block comments (starting with /*) are expected to end with */",
597 ## Data parser for the format in which there's path
599 # Only path can have macro used. So we need to replace them before use.
601 def _IncludeParser(self
):
602 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
603 self
._ValueList
[0:len(TokenList
)] = TokenList
604 Macros
= self
._Macros
606 for Index
in range(0, len(self
._ValueList
)):
607 Value
= self
._ValueList
[Index
]
611 if Value
.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value
.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
612 Value
= '$(EDK_SOURCE)' + Value
[17:]
613 if Value
.find('$(EFI_SOURCE)') > -1 or Value
.find('$(EDK_SOURCE)') > -1:
615 elif Value
.startswith('.'):
617 elif Value
.startswith('$('):
620 Value
= '$(EFI_SOURCE)/' + Value
622 self
._ValueList
[Index
] = ReplaceMacro(Value
, Macros
)
624 ## Parse [Sources] section
626 # Only path can have macro used. So we need to replace them before use.
629 def _SourceFileParser(self
):
630 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
631 self
._ValueList
[0:len(TokenList
)] = TokenList
632 Macros
= self
._Macros
633 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
634 if 'COMPONENT_TYPE' in Macros
:
635 if self
._Defines
['COMPONENT_TYPE'].upper() == 'ACPITABLE':
636 self
._ValueList
[0] = GetSplitValueList(self
._ValueList
[0], ' ', 1)[0]
637 if self
._Defines
['BASE_NAME'] == 'Microcode':
639 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
641 ## Parse [Binaries] section
643 # Only path can have macro used. So we need to replace them before use.
646 def _BinaryFileParser(self
):
647 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 2)
648 if len(TokenList
) < 2:
649 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type or path specified",
650 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
651 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
653 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type specified",
654 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
655 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
657 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file path specified",
658 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
659 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
660 self
._ValueList
[0:len(TokenList
)] = TokenList
661 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
663 ## [nmake] section parser (Edk.x style only)
664 def _NmakeParser(self
):
665 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
666 self
._ValueList
[0:len(TokenList
)] = TokenList
668 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
669 # remove self-reference in macro setting
670 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
672 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
674 def _PcdParser(self
):
675 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
676 ValueList
= GetSplitValueList(TokenList
[0], TAB_SPLIT
)
677 if len(ValueList
) != 2:
678 EdkLogger
.error('Parser', FORMAT_INVALID
, "Illegal token space GUID and PCD name format",
679 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
680 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
681 self
._ValueList
[0:1] = ValueList
682 if len(TokenList
) > 1:
683 self
._ValueList
[2] = TokenList
[1]
684 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
685 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
686 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
687 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
689 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
690 if self
._ValueList
[2] != '':
691 InfPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
692 if InfPcdValueList
[0] in ['True', 'true', 'TRUE']:
693 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '1', 1);
694 elif InfPcdValueList
[0] in ['False', 'false', 'FALSE']:
695 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '0', 1);
697 ## [depex] section parser
699 def _DepexParser(self
):
700 self
._ValueList
[0:1] = [self
._CurrentLine
]
703 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
704 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
705 MODEL_META_DATA_BUILD_OPTION
: MetaFileParser
._BuildOptionParser
,
706 MODEL_EFI_INCLUDE
: _IncludeParser
, # for Edk.x modules
707 MODEL_EFI_LIBRARY_INSTANCE
: MetaFileParser
._CommonParser
, # for Edk.x modules
708 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
709 MODEL_META_DATA_PACKAGE
: MetaFileParser
._PathParser
,
710 MODEL_META_DATA_NMAKE
: _NmakeParser
, # for Edk.x modules
711 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
712 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
713 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
714 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
715 MODEL_PCD_DYNAMIC
: _PcdParser
,
716 MODEL_EFI_SOURCE_FILE
: _SourceFileParser
,
717 MODEL_EFI_GUID
: MetaFileParser
._CommonParser
,
718 MODEL_EFI_PROTOCOL
: MetaFileParser
._CommonParser
,
719 MODEL_EFI_PPI
: MetaFileParser
._CommonParser
,
720 MODEL_EFI_DEPEX
: _DepexParser
,
721 MODEL_EFI_BINARY_FILE
: _BinaryFileParser
,
722 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
725 ## DSC file parser class
727 # @param FilePath The path of platform description file
728 # @param FileType The raw data of DSC file
729 # @param Table Database used to retrieve module/package information
730 # @param Macros Macros used for replacement in file
731 # @param Owner Owner ID (for sub-section parsing)
732 # @param From ID from which the data comes (for !INCLUDE directive)
734 class DscParser(MetaFileParser
):
735 # DSC file supported data types (one type per section)
737 TAB_SKUIDS
.upper() : MODEL_EFI_SKU_ID
,
738 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
739 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
740 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
741 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
742 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
743 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
744 TAB_PCDS_DYNAMIC_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_DEFAULT
,
745 TAB_PCDS_DYNAMIC_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_HII
,
746 TAB_PCDS_DYNAMIC_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_VPD
,
747 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT
,
748 TAB_PCDS_DYNAMIC_EX_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_HII
,
749 TAB_PCDS_DYNAMIC_EX_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_VPD
,
750 TAB_COMPONENTS
.upper() : MODEL_META_DATA_COMPONENT
,
751 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH
.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
,
752 TAB_DSC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
753 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
754 TAB_DSC_DEFINES_EDKGLOBAL
: MODEL_META_DATA_GLOBAL_DEFINE
,
755 TAB_INCLUDE
.upper() : MODEL_META_DATA_INCLUDE
,
756 TAB_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
757 TAB_IF_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
758 TAB_IF_N_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
,
759 TAB_ELSE_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
,
760 TAB_ELSE
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
761 TAB_END_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
,
762 TAB_ERROR
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR
,
765 # Valid names in define section
772 "PCD_INFO_GENERATION",
773 "SUPPORTED_ARCHITECTURES",
782 "FIX_LOAD_TOP_MEMORY_ADDRESS"
785 SymbolPattern
= ValueExpression
.SymbolPattern
787 ## Constructor of DscParser
789 # Initialize object of DscParser
791 # @param FilePath The path of platform description file
792 # @param FileType The raw data of DSC file
793 # @param Table Database used to retrieve module/package information
794 # @param Macros Macros used for replacement in file
795 # @param Owner Owner ID (for sub-section parsing)
796 # @param From ID from which the data comes (for !INCLUDE directive)
798 def __init__(self
, FilePath
, FileType
, Table
, Owner
=-1, From
=-1):
799 # prevent re-initialization
800 if hasattr(self
, "_Table"):
802 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, Owner
, From
)
803 self
._Version
= 0x00010005 # Only EDK2 dsc file is supported
804 # to store conditional directive evaluation result
805 self
._DirectiveStack
= []
806 self
._DirectiveEvalStack
= []
809 # Final valid replacable symbols
812 # Map the ID between the original table and new table to track
815 self
._IdMapping
= {-1:-1}
817 self
.TblFile
= EccGlobalData
.gDb
.TblFile
824 Content
= open(str(self
.MetaFile
.Path
), 'r').readlines()
826 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
828 # Insert a record for file
830 Filename
= NormPath(self
.MetaFile
.Path
)
831 FileID
= self
.TblFile
.GetFileId(Filename
)
835 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_DSC
)
838 for Index
in range(0, len(Content
)):
839 Line
= CleanString(Content
[Index
])
844 self
._CurrentLine
= Line
845 self
._LineIndex
= Index
846 if self
._InSubsection
and self
._Owner
[-1] == -1:
847 self
._Owner
.append(self
._LastItem
)
850 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
851 self
._SectionType
= MODEL_META_DATA_SECTION_HEADER
853 elif Line
[0] == '}' and self
._InSubsection
:
854 self
._InSubsection
= False
855 self
._SubsectionType
= MODEL_UNKNOWN
856 self
._SubsectionName
= ''
860 elif Line
[0] == TAB_OPTION_START
and Line
[-1] == TAB_OPTION_END
:
861 self
._SubsectionType
= MODEL_META_DATA_SUBSECTION_HEADER
864 self
._DirectiveParser
()
867 if self
._InSubsection
:
868 SectionType
= self
._SubsectionType
870 SectionType
= self
._SectionType
871 self
._ItemType
= SectionType
873 self
._ValueList
= ['', '', '']
874 self
._SectionParser
[SectionType
](self
)
875 if self
._ValueList
== None:
878 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
879 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
881 for Arch
, ModuleType
in self
._Scope
:
882 self
._LastItem
= self
._Store
(
899 if self
._DirectiveStack
:
900 Type
, Line
, Text
= self
._DirectiveStack
[-1]
901 EdkLogger
.error('Parser', FORMAT_INVALID
, "No matching '!endif' found",
902 ExtraData
=Text
, File
=self
.MetaFile
, Line
=Line
)
905 ## <subsection_header> parser
906 def _SubsectionHeaderParser(self
):
907 self
._SubsectionName
= self
._CurrentLine
[1:-1].upper()
908 if self
._SubsectionName
in self
.DataType
:
909 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
911 self
._SubsectionType
= MODEL_UNKNOWN
912 EdkLogger
.warn("Parser", "Unrecognized sub-section", File
=self
.MetaFile
,
913 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
914 self
._ValueList
[0] = self
._SubsectionName
916 ## Directive statement parser
917 def _DirectiveParser(self
):
918 self
._ValueList
= ['','','']
919 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
920 self
._ValueList
[0:len(TokenList
)] = TokenList
923 DirectiveName
= self
._ValueList
[0].upper()
924 if DirectiveName
not in self
.DataType
:
925 EdkLogger
.error("Parser", FORMAT_INVALID
, "Unknown directive [%s]" % DirectiveName
,
926 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
927 if DirectiveName
in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self
._ValueList
[1] == '':
928 EdkLogger
.error("Parser", FORMAT_INVALID
, "Missing expression",
929 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
930 ExtraData
=self
._CurrentLine
)
932 ItemType
= self
.DataType
[DirectiveName
]
933 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
934 # Remove all directives between !if and !endif, including themselves
935 while self
._DirectiveStack
:
936 # Remove any !else or !elseif
937 DirectiveInfo
= self
._DirectiveStack
.pop()
938 if DirectiveInfo
[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
939 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
940 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
943 EdkLogger
.error("Parser", FORMAT_INVALID
, "Redundant '!endif'",
944 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
945 ExtraData
=self
._CurrentLine
)
946 elif ItemType
!= MODEL_META_DATA_INCLUDE
:
947 # Break if there's a !else is followed by a !elseif
948 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
and \
949 self
._DirectiveStack
and \
950 self
._DirectiveStack
[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
951 EdkLogger
.error("Parser", FORMAT_INVALID
, "'!elseif' after '!else'",
952 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
953 ExtraData
=self
._CurrentLine
)
954 self
._DirectiveStack
.append((ItemType
, self
._LineIndex
+1, self
._CurrentLine
))
956 EdkLogger
.error('Parser', FORMAT_INVALID
,
957 "No '!include' allowed in included file",
958 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
,
959 Line
=self
._LineIndex
+1)
962 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
963 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
965 self
._LastItem
= self
._Store
(
982 ## [defines] section parser
984 def _DefineParser(self
):
985 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
986 self
._ValueList
[1:len(TokenList
)] = TokenList
989 if not self
._ValueList
[1]:
990 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
991 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
992 if not self
._ValueList
[2]:
993 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
994 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
995 if not self
._ValueList
[1] in self
.DefineKeywords
:
996 EdkLogger
.error('Parser', FORMAT_INVALID
,
997 "Unknown keyword found: %s. "
998 "If this is a macro you must "
999 "add it as a DEFINE in the DSC" % self
._ValueList
[1],
1000 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1001 self
._Defines
[self
._ValueList
[1]] = self
._ValueList
[2]
1002 self
._ItemType
= self
.DataType
[TAB_DSC_DEFINES
.upper()]
1005 def _SkuIdParser(self
):
1006 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1007 if len(TokenList
) != 2:
1008 EdkLogger
.error('Parser', FORMAT_INVALID
, "Correct format is '<Integer>|<UiName>'",
1009 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1010 self
._ValueList
[0:len(TokenList
)] = TokenList
1012 ## Parse Edk style of library modules
1013 def _LibraryInstanceParser(self
):
1014 self
._ValueList
[0] = self
._CurrentLine
1016 ## PCD sections parser
1018 # [PcdsFixedAtBuild]
1019 # [PcdsPatchableInModule]
1022 # [PcdsDynamicExDefault]
1023 # [PcdsDynamicExVpd]
1024 # [PcdsDynamicExHii]
1026 # [PcdsDynamicDefault]
1031 def _PcdParser(self
):
1032 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1033 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1034 if len(TokenList
) == 2:
1035 self
._ValueList
[2] = TokenList
[1]
1036 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1037 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1038 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1039 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1040 if self
._ValueList
[2] == '':
1041 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD value given",
1042 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1043 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1044 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1045 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
1046 if DscPcdValueList
[0] in ['True', 'true', 'TRUE']:
1047 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '1', 1);
1048 elif DscPcdValueList
[0] in ['False', 'false', 'FALSE']:
1049 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '0', 1);
1051 ## [components] section parser
1053 def _ComponentParser(self
):
1054 if self
._CurrentLine
[-1] == '{':
1055 self
._ValueList
[0] = self
._CurrentLine
[0:-1].strip()
1056 self
._InSubsection
= True
1058 self
._ValueList
[0] = self
._CurrentLine
1060 ## [LibraryClasses] section
1062 def _LibraryClassParser(self
):
1063 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1064 if len(TokenList
) < 2:
1065 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class or instance specified",
1066 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1067 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1068 if TokenList
[0] == '':
1069 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class specified",
1070 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1071 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1072 if TokenList
[1] == '':
1073 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library instance specified",
1074 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1075 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1077 self
._ValueList
[0:len(TokenList
)] = TokenList
1079 def _CompponentSourceOverridePathParser(self
):
1080 self
._ValueList
[0] = self
._CurrentLine
1082 ## [BuildOptions] section parser
1084 def _BuildOptionParser(self
):
1085 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1086 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
1087 if len(TokenList2
) == 2:
1088 self
._ValueList
[0] = TokenList2
[0] # toolchain family
1089 self
._ValueList
[1] = TokenList2
[1] # keys
1091 self
._ValueList
[1] = TokenList
[0]
1092 if len(TokenList
) == 2: # value
1093 self
._ValueList
[2] = TokenList
[1]
1095 if self
._ValueList
[1].count('_') != 4:
1099 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
1100 ExtraData
=self
._CurrentLine
,
1102 Line
=self
._LineIndex
+1
1105 ## Override parent's method since we'll do all macro replacements in parser
1106 def _GetMacros(self
):
1107 Macros
= dict( [('ARCH','IA32'), ('FAMILY','MSFT'),('TOOL_CHAIN_TAG','VS2008x86'),('TARGET','DEBUG')])
1108 Macros
.update(self
._FileLocalMacros
)
1109 Macros
.update(self
._GetApplicableSectionMacro
())
1110 Macros
.update(GlobalData
.gEdkGlobal
)
1111 Macros
.update(GlobalData
.gPlatformDefines
)
1112 Macros
.update(GlobalData
.gCommandLineDefines
)
1113 # PCD cannot be referenced in macro definition
1114 if self
._ItemType
not in [MODEL_META_DATA_DEFINE
, MODEL_META_DATA_GLOBAL_DEFINE
]:
1115 Macros
.update(self
._Symbols
)
1118 def _PostProcess(self
):
1120 MODEL_META_DATA_SECTION_HEADER
: self
.__ProcessSectionHeader
,
1121 MODEL_META_DATA_SUBSECTION_HEADER
: self
.__ProcessSubsectionHeader
,
1122 MODEL_META_DATA_HEADER
: self
.__ProcessDefine
,
1123 MODEL_META_DATA_DEFINE
: self
.__ProcessDefine
,
1124 MODEL_META_DATA_GLOBAL_DEFINE
: self
.__ProcessDefine
,
1125 MODEL_META_DATA_INCLUDE
: self
.__ProcessDirective
,
1126 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
: self
.__ProcessDirective
,
1127 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
: self
.__ProcessDirective
,
1128 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
: self
.__ProcessDirective
,
1129 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
: self
.__ProcessDirective
,
1130 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
: self
.__ProcessDirective
,
1131 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
: self
.__ProcessDirective
,
1132 MODEL_EFI_SKU_ID
: self
.__ProcessSkuId
,
1133 MODEL_EFI_LIBRARY_INSTANCE
: self
.__ProcessLibraryInstance
,
1134 MODEL_EFI_LIBRARY_CLASS
: self
.__ProcessLibraryClass
,
1135 MODEL_PCD_FIXED_AT_BUILD
: self
.__ProcessPcd
,
1136 MODEL_PCD_PATCHABLE_IN_MODULE
: self
.__ProcessPcd
,
1137 MODEL_PCD_FEATURE_FLAG
: self
.__ProcessPcd
,
1138 MODEL_PCD_DYNAMIC_DEFAULT
: self
.__ProcessPcd
,
1139 MODEL_PCD_DYNAMIC_HII
: self
.__ProcessPcd
,
1140 MODEL_PCD_DYNAMIC_VPD
: self
.__ProcessPcd
,
1141 MODEL_PCD_DYNAMIC_EX_DEFAULT
: self
.__ProcessPcd
,
1142 MODEL_PCD_DYNAMIC_EX_HII
: self
.__ProcessPcd
,
1143 MODEL_PCD_DYNAMIC_EX_VPD
: self
.__ProcessPcd
,
1144 MODEL_META_DATA_COMPONENT
: self
.__ProcessComponent
,
1145 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: self
.__ProcessSourceOverridePath
,
1146 MODEL_META_DATA_BUILD_OPTION
: self
.__ProcessBuildOption
,
1147 MODEL_UNKNOWN
: self
._Skip
,
1148 MODEL_META_DATA_USER_EXTENSION
: self
._Skip
,
1149 MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR
: self
._Skip
,
1152 self
._RawTable
= self
._Table
1153 self
._Table
= MetaFileStorage(self
._RawTable
.Cur
, self
.MetaFile
, MODEL_FILE_DSC
, True)
1154 self
._DirectiveStack
= []
1155 self
._DirectiveEvalStack
= []
1156 self
._FileWithError
= self
.MetaFile
1157 self
._FileLocalMacros
= {}
1158 self
._SectionsMacroDict
= {}
1159 GlobalData
.gPlatformDefines
= {}
1161 # Get all macro and PCD which has straitforward value
1162 self
.__RetrievePcdValue
()
1163 self
._Content
= self
._RawTable
.GetAll()
1164 self
._ContentIndex
= 0
1165 while self
._ContentIndex
< len(self
._Content
) :
1166 Id
, self
._ItemType
, V1
, V2
, V3
, S1
, S2
, Owner
, BelongsToFile
, self
._From
, \
1167 LineStart
, ColStart
, LineEnd
, ColEnd
, Enabled
= self
._Content
[self
._ContentIndex
]
1170 self
._FileWithError
= self
.MetaFile
1172 self
._ContentIndex
+= 1
1174 self
._Scope
= [[S1
, S2
]]
1175 self
._LineIndex
= LineStart
- 1
1176 self
._ValueList
= [V1
, V2
, V3
]
1179 Processer
[self
._ItemType
]()
1180 except EvaluationException
, Excpt
:
1182 # Only catch expression evaluation error here. We need to report
1183 # the precise number of line on which the error occurred
1186 # EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
1187 # File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1188 # Line=self._LineIndex+1)
1189 except MacroException
, Excpt
:
1190 EdkLogger
.error('Parser', FORMAT_INVALID
, str(Excpt
),
1191 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1192 Line
=self
._LineIndex
+1)
1194 if self
._ValueList
== None:
1197 NewOwner
= self
._IdMapping
.get(Owner
, -1)
1198 self
._Enabled
= int((not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
))
1199 self
._LastItem
= self
._Store
(
1215 self
._IdMapping
[Id
] = self
._LastItem
1217 RecordList
= self
._Table
.GetAll()
1219 self
._RawTable
.Drop()
1221 for Record
in RecordList
:
1222 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])
1223 GlobalData
.gPlatformDefines
.update(self
._FileLocalMacros
)
1224 self
._PostProcessed
= True
1225 self
._Content
= None
1227 def __ProcessSectionHeader(self
):
1228 self
._SectionName
= self
._ValueList
[0]
1229 if self
._SectionName
in self
.DataType
:
1230 self
._SectionType
= self
.DataType
[self
._SectionName
]
1232 self
._SectionType
= MODEL_UNKNOWN
1234 def __ProcessSubsectionHeader(self
):
1235 self
._SubsectionName
= self
._ValueList
[0]
1236 if self
._SubsectionName
in self
.DataType
:
1237 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
1239 self
._SubsectionType
= MODEL_UNKNOWN
1241 def __RetrievePcdValue(self
):
1242 Records
= self
._RawTable
.Query(MODEL_PCD_FEATURE_FLAG
, BelongsToItem
=-1.0)
1243 for TokenSpaceGuid
,PcdName
,Value
,Dummy2
,Dummy3
,ID
,Line
in Records
:
1244 Value
, DatumType
, MaxDatumSize
= AnalyzePcdData(Value
)
1245 # Only use PCD whose value is straitforward (no macro and PCD)
1246 if self
.SymbolPattern
.findall(Value
):
1248 Name
= TokenSpaceGuid
+ '.' + PcdName
1249 # Don't use PCD with different values.
1250 if Name
in self
._Symbols
and self
._Symbols
[Name
] != Value
:
1251 self
._Symbols
.pop(Name
)
1253 self
._Symbols
[Name
] = Value
1255 Records
= self
._RawTable
.Query(MODEL_PCD_FIXED_AT_BUILD
, BelongsToItem
=-1.0)
1256 for TokenSpaceGuid
,PcdName
,Value
,Dummy2
,Dummy3
,ID
,Line
in Records
:
1257 Value
, DatumType
, MaxDatumSize
= AnalyzePcdData(Value
)
1258 # Only use PCD whose value is straitforward (no macro and PCD)
1259 if self
.SymbolPattern
.findall(Value
):
1261 Name
= TokenSpaceGuid
+'.'+PcdName
1262 # Don't use PCD with different values.
1263 if Name
in self
._Symbols
and self
._Symbols
[Name
] != Value
:
1264 self
._Symbols
.pop(Name
)
1266 self
._Symbols
[Name
] = Value
1268 def __ProcessDefine(self
):
1269 if not self
._Enabled
:
1272 Type
, Name
, Value
= self
._ValueList
1273 Value
= ReplaceMacro(Value
, self
._Macros
, False)
1274 if self
._ItemType
== MODEL_META_DATA_DEFINE
:
1275 if self
._SectionType
== MODEL_META_DATA_HEADER
:
1276 self
._FileLocalMacros
[Name
] = Value
1278 SectionDictKey
= self
._SectionType
, self
._Scope
[0][0], self
._Scope
[0][1]
1279 if SectionDictKey
not in self
._SectionsMacroDict
:
1280 self
._SectionsMacroDict
[SectionDictKey
] = {}
1281 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
1282 SectionLocalMacros
[Name
] = Value
1283 elif self
._ItemType
== MODEL_META_DATA_GLOBAL_DEFINE
:
1284 GlobalData
.gEdkGlobal
[Name
] = Value
1287 # Keyword in [Defines] section can be used as Macros
1289 if (self
._ItemType
== MODEL_META_DATA_HEADER
) and (self
._SectionType
== MODEL_META_DATA_HEADER
):
1290 self
._FileLocalMacros
[Name
] = Value
1292 self
._ValueList
= [Type
, Name
, Value
]
1294 def __ProcessDirective(self
):
1296 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1297 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
]:
1298 Macros
= self
._Macros
1299 Macros
.update(GlobalData
.gGlobalDefines
)
1301 Result
= ValueExpression(self
._ValueList
[1], Macros
)()
1302 except SymbolNotFound
, Exc
:
1303 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1305 except WrnExpression
, Excpt
:
1307 # Catch expression evaluation warning here. We need to report
1308 # the precise number of line and return the evaluation result
1310 EdkLogger
.warn('Parser', "Suspicious expression: %s" % str(Excpt
),
1311 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1312 Line
=self
._LineIndex
+1)
1313 Result
= Excpt
.result
1315 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1316 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1317 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1318 self
._DirectiveStack
.append(self
._ItemType
)
1319 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
:
1320 Result
= bool(Result
)
1322 Macro
= self
._ValueList
[1]
1323 Macro
= Macro
[2:-1] if (Macro
.startswith("$(") and Macro
.endswith(")")) else Macro
1324 Result
= Macro
in self
._Macros
1325 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
:
1327 self
._DirectiveEvalStack
.append(Result
)
1328 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
:
1329 self
._DirectiveStack
.append(self
._ItemType
)
1330 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1331 self
._DirectiveEvalStack
.append(bool(Result
))
1332 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1333 self
._DirectiveStack
[-1] = self
._ItemType
1334 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1335 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1336 # Back to the nearest !if/!ifdef/!ifndef
1337 while self
._DirectiveStack
:
1338 self
._DirectiveEvalStack
.pop()
1339 Directive
= self
._DirectiveStack
.pop()
1340 if Directive
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1341 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1342 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
1343 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1345 elif self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1346 # The included file must be relative to workspace or same directory as DSC file
1347 __IncludeMacros
= {}
1349 # Allow using system environment variables in path after !include
1351 __IncludeMacros
['WORKSPACE'] = GlobalData
.gGlobalDefines
['WORKSPACE']
1352 if "ECP_SOURCE" in GlobalData
.gGlobalDefines
.keys():
1353 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gGlobalDefines
['ECP_SOURCE']
1355 # During GenFds phase call DSC parser, will go into this branch.
1357 elif "ECP_SOURCE" in GlobalData
.gCommandLineDefines
.keys():
1358 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gCommandLineDefines
['ECP_SOURCE']
1360 __IncludeMacros
['EFI_SOURCE'] = GlobalData
.gGlobalDefines
['EFI_SOURCE']
1361 __IncludeMacros
['EDK_SOURCE'] = GlobalData
.gGlobalDefines
['EDK_SOURCE']
1363 # Allow using MACROs comes from [Defines] section to keep compatible.
1365 __IncludeMacros
.update(self
._Macros
)
1367 IncludedFile
= NormPath(ReplaceMacro(self
._ValueList
[1], __IncludeMacros
, RaiseError
=True))
1369 # First search the include file under the same directory as DSC file
1371 IncludedFile1
= PathClass(IncludedFile
, self
.MetaFile
.Dir
)
1372 ErrorCode
, ErrorInfo1
= IncludedFile1
.Validate()
1375 # Also search file under the WORKSPACE directory
1377 IncludedFile1
= PathClass(IncludedFile
, GlobalData
.gWorkspace
)
1378 ErrorCode
, ErrorInfo2
= IncludedFile1
.Validate()
1380 EdkLogger
.error('parser', ErrorCode
, File
=self
._FileWithError
,
1381 Line
=self
._LineIndex
+1, ExtraData
=ErrorInfo1
+ "\n"+ ErrorInfo2
)
1383 self
._FileWithError
= IncludedFile1
1385 IncludedFileTable
= MetaFileStorage(self
._Table
.Cur
, IncludedFile1
, MODEL_FILE_DSC
, True)
1386 Owner
= self
._Content
[self
._ContentIndex
-1][0]
1387 Parser
= DscParser(IncludedFile1
, self
._FileType
, IncludedFileTable
,
1388 Owner
=Owner
, From
=Owner
)
1390 # set the parser status with current status
1391 Parser
._SectionName
= self
._SectionName
1392 Parser
._SectionType
= self
._SectionType
1393 Parser
._Scope
= self
._Scope
1394 Parser
._Enabled
= self
._Enabled
1395 # Parse the included file
1398 # update current status with sub-parser's status
1399 self
._SectionName
= Parser
._SectionName
1400 self
._SectionType
= Parser
._SectionType
1401 self
._Scope
= Parser
._Scope
1402 self
._Enabled
= Parser
._Enabled
1404 # Insert all records in the table for the included file into dsc file table
1405 Records
= IncludedFileTable
.GetAll()
1407 self
._Content
[self
._ContentIndex
:self
._ContentIndex
] = Records
1408 self
._Content
.pop(self
._ContentIndex
-1)
1409 self
._ValueList
= None
1410 self
._ContentIndex
-= 1
1412 def __ProcessSkuId(self
):
1413 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=True)
1414 for Value
in self
._ValueList
]
1416 def __ProcessLibraryInstance(self
):
1417 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
1419 def __ProcessLibraryClass(self
):
1420 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, RaiseError
=True)
1422 def __ProcessPcd(self
):
1423 ValueList
= GetSplitValueList(self
._ValueList
[2])
1425 # PCD value can be an expression
1427 if len(ValueList
) > 1 and ValueList
[1] == 'VOID*':
1428 PcdValue
= ValueList
[0]
1430 ValueList
[0] = ValueExpression(PcdValue
, self
._Macros
)(True)
1431 except WrnExpression
, Value
:
1432 ValueList
[0] = Value
.result
1434 PcdValue
= ValueList
[-1]
1436 ValueList
[-1] = ValueExpression(PcdValue
, self
._Macros
)(True)
1437 except WrnExpression
, Value
:
1438 ValueList
[-1] = Value
.result
1440 if ValueList
[-1] == 'True':
1442 if ValueList
[-1] == 'False':
1445 self
._ValueList
[2] = '|'.join(ValueList
)
1447 def __ProcessComponent(self
):
1448 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1450 def __ProcessSourceOverridePath(self
):
1451 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1453 def __ProcessBuildOption(self
):
1454 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=False)
1455 for Value
in self
._ValueList
]
1458 MODEL_META_DATA_HEADER
: _DefineParser
,
1459 MODEL_EFI_SKU_ID
: _SkuIdParser
,
1460 MODEL_EFI_LIBRARY_INSTANCE
: _LibraryInstanceParser
,
1461 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
1462 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1463 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1464 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1465 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
1466 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
1467 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
1468 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
1469 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
1470 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
1471 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
1472 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: _CompponentSourceOverridePathParser
,
1473 MODEL_META_DATA_BUILD_OPTION
: _BuildOptionParser
,
1474 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1475 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1476 MODEL_META_DATA_SECTION_HEADER
: MetaFileParser
._SectionHeaderParser
,
1477 MODEL_META_DATA_SUBSECTION_HEADER
: _SubsectionHeaderParser
,
1480 _Macros
= property(_GetMacros
)
1482 ## DEC file parser class
1484 # @param FilePath The path of platform description file
1485 # @param FileType The raw data of DSC file
1486 # @param Table Database used to retrieve module/package information
1487 # @param Macros Macros used for replacement in file
1489 class DecParser(MetaFileParser
):
1490 # DEC file supported data types (one type per section)
1492 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1493 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
1494 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1495 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1496 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1497 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1498 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1499 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1500 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1501 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1502 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1503 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1506 ## Constructor of DecParser
1508 # Initialize object of DecParser
1510 # @param FilePath The path of platform description file
1511 # @param FileType The raw data of DSC file
1512 # @param Table Database used to retrieve module/package information
1513 # @param Macros Macros used for replacement in file
1515 def __init__(self
, FilePath
, FileType
, Table
):
1516 # prevent re-initialization
1517 if hasattr(self
, "_Table"):
1519 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
1521 self
._Version
= 0x00010005 # Only EDK2 dec file is supported
1522 self
.TblFile
= EccGlobalData
.gDb
.TblFile
1529 Content
= open(str(self
.MetaFile
), 'r').readlines()
1531 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1534 # Insert a record for file
1536 Filename
= NormPath(self
.MetaFile
)
1537 FileID
= self
.TblFile
.GetFileId(Filename
)
1539 self
.FileID
= FileID
1541 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_DEC
)
1543 for Index
in range(0, len(Content
)):
1544 Line
, Comment
= CleanString2(Content
[Index
])
1545 self
._CurrentLine
= Line
1546 self
._LineIndex
= Index
1548 # save comment for later use
1550 self
._Comments
.append((Comment
, self
._LineIndex
+1))
1556 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1557 self
._SectionHeaderParser
()
1560 elif len(self
._SectionType
) == 0:
1565 self
._ValueList
= ['','','']
1566 self
._SectionParser
[self
._SectionType
[0]](self
)
1567 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
1573 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1574 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1576 for Arch
, ModuleType
, Type
in self
._Scope
:
1577 self
._LastItem
= self
._Store
(
1592 for Comment
, LineNo
in self
._Comments
:
1594 MODEL_META_DATA_COMMENT
,
1611 def _GetApplicableSectionMacro(self
):
1613 for S1
, S2
, SectionType
in self
._Scope
:
1614 for Scope1
, Scope2
in [("COMMON", "COMMON"), ("COMMON", S2
), (S1
, "COMMON"), (S1
, S2
)]:
1615 if (SectionType
, Scope1
, Scope2
) in self
._SectionsMacroDict
:
1616 Macros
.update(self
._SectionsMacroDict
[(SectionType
, Scope1
, Scope2
)])
1619 ## Section header parser
1621 # The section header is always in following format:
1623 # [section_name.arch<.platform|module_type>]
1625 def _SectionHeaderParser(self
):
1627 self
._SectionName
= ''
1628 self
._SectionType
= []
1630 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
1633 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
)
1635 # different types of PCD are permissible in one section
1636 self
._SectionName
= ItemList
[0].upper()
1637 if self
._SectionName
in self
.DataType
:
1638 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1639 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1641 EdkLogger
.warn("Parser", "Unrecognized section", File
=self
.MetaFile
,
1642 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
1645 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1649 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1651 Line
=self
._LineIndex
+1,
1652 ExtraData
=self
._CurrentLine
1655 if len(ItemList
) > 1:
1656 S1
= ItemList
[1].upper()
1660 # S2 may be Platform or ModuleType
1661 if len(ItemList
) > 2:
1662 S2
= ItemList
[2].upper()
1665 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1666 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1668 # 'COMMON' must not be used with specific ARCHs at the same section
1669 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1670 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1671 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
1673 ## [guids], [ppis] and [protocols] section parser
1675 def _GuidParser(self
):
1676 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1677 if len(TokenList
) < 2:
1678 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1679 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1680 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1681 if TokenList
[0] == '':
1682 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1683 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1684 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1685 if TokenList
[1] == '':
1686 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1687 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1688 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1689 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1690 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1691 ExtraData
=self
._CurrentLine
+ \
1692 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1693 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1694 self
._ValueList
[0] = TokenList
[0]
1695 #Parse the Guid value format
1696 GuidValueList
= TokenList
[1].strip(' {}').split(',')
1699 if len(GuidValueList
) == 11:
1700 for GuidValue
in GuidValueList
:
1701 GuidValue
= GuidValue
.strip()
1702 if GuidValue
.startswith('0x') or GuidValue
.startswith('0X'):
1703 HexList
.append('0x' + str(GuidValue
[2:]))
1707 if GuidValue
.startswith('{'):
1708 HexList
.append('0x' + str(GuidValue
[3:]))
1710 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])
1712 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1713 ExtraData
=self
._CurrentLine
+ \
1714 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1715 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1716 self
._ValueList
[0] = ''
1718 ## PCD sections parser
1720 # [PcdsFixedAtBuild]
1721 # [PcdsPatchableInModule]
1727 def _PcdParser(self
):
1728 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1729 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1730 # check PCD information
1731 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1732 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1733 ExtraData
=self
._CurrentLine
+ \
1734 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1735 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1736 # check PCD datum information
1737 if len(TokenList
) < 2 or TokenList
[1] == '':
1738 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1739 ExtraData
=self
._CurrentLine
+ \
1740 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1741 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1744 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1745 PtrValue
= ValueRe
.findall(TokenList
[1])
1747 # Has VOID* type string, may contain "|" character in the string.
1748 if len(PtrValue
) != 0:
1749 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1750 ValueList
= GetSplitValueList(ptrValueList
)
1751 ValueList
[0] = PtrValue
[0]
1753 ValueList
= GetSplitValueList(TokenList
[1])
1756 # check if there's enough datum information given
1757 if len(ValueList
) != 3:
1758 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1759 ExtraData
=self
._CurrentLine
+ \
1760 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1761 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1762 # check default value
1763 if ValueList
[0] == '':
1764 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1765 ExtraData
=self
._CurrentLine
+ \
1766 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1767 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1769 if ValueList
[1] == '':
1770 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1771 ExtraData
=self
._CurrentLine
+ \
1772 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1773 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1774 # check token of the PCD
1775 if ValueList
[2] == '':
1776 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1777 ExtraData
=self
._CurrentLine
+ \
1778 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1779 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1780 # check format of default value against the datum type
1781 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1783 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1784 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1786 if ValueList
[0] in ['True', 'true', 'TRUE']:
1788 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1791 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
1794 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
1795 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
1796 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
1797 MODEL_EFI_GUID
: _GuidParser
,
1798 MODEL_EFI_PPI
: _GuidParser
,
1799 MODEL_EFI_PROTOCOL
: _GuidParser
,
1800 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1801 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1802 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1803 MODEL_PCD_DYNAMIC
: _PcdParser
,
1804 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
1805 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1806 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1812 # This class defined basic Fdf object which is used by inheriting
1814 # @param object: Inherited from object class
1816 class FdfObject(object):
1822 # This class defined the structure used in Fdf object
1824 # @param FdfObject: Inherited from FdfObject class
1825 # @param Filename: Input value for Ffilename of Fdf file, default is None
1826 # @param WorkspaceDir: Input value for current workspace directory, default is None
1828 class Fdf(FdfObject
):
1829 def __init__(self
, Filename
= None, IsToDatabase
= False, WorkspaceDir
= None, Database
= None):
1830 self
.WorkspaceDir
= WorkspaceDir
1831 self
.IsToDatabase
= IsToDatabase
1833 self
.Cur
= Database
.Cur
1834 self
.TblFile
= Database
.TblFile
1835 self
.TblFdf
= Database
.TblFdf
1840 # Load Fdf file if filename is not None
1842 if Filename
!= None:
1844 self
.LoadFdfFile(Filename
)
1849 # Insert a FDF file record into database
1851 def InsertFile(self
, Filename
):
1853 Filename
= NormPath(Filename
)
1854 if Filename
not in self
.FileList
:
1855 FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_FDF
)
1856 self
.FileList
[Filename
] = FileID
1858 return self
.FileList
[Filename
]
1863 # Load the file if it exists
1865 # @param Filename: Input value for filename of Fdf file
1867 def LoadFdfFile(self
, Filename
):
1872 Filename
= NormPath(Filename
)
1873 Fdf
= FdfParser(Filename
)
1877 # Insert inf file and pcd information
1879 if self
.IsToDatabase
:
1880 (Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
) = \
1881 (0, '', '', '', 'COMMON', 'COMMON', -1, -1, -1, -1, -1, -1, 0)
1882 for Index
in range(0, len(Fdf
.Profile
.PcdDict
)):
1884 for Key
in Fdf
.Profile
.PcdDict
.keys():
1888 FileName
= Fdf
.Profile
.PcdFileLineDict
[Key
][0]
1889 StartLine
= Fdf
.Profile
.PcdFileLineDict
[Key
][1]
1890 BelongsToFile
= self
.InsertFile(FileName
)
1891 self
.TblFdf
.Insert(Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
)
1892 for Index
in range(0, len(Fdf
.Profile
.InfList
)):
1893 Model
= MODEL_META_DATA_COMPONENT
1894 Value1
= Fdf
.Profile
.InfList
[Index
]
1896 FileName
= Fdf
.Profile
.InfFileLineList
[Index
][0]
1897 StartLine
= Fdf
.Profile
.InfFileLineList
[Index
][1]
1898 BelongsToFile
= self
.InsertFile(FileName
)
1899 self
.TblFdf
.Insert(Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
)
1901 class UniParser(object):
1902 # IsExtraUni defined the UNI file is Module UNI or extra Module UNI
1903 # IsModuleUni defined the UNI file is Module UNI or Package UNI
1904 def __init__(self
, FilePath
, IsExtraUni
=False, IsModuleUni
=True):
1905 self
.FilePath
= FilePath
1906 self
.FileName
= os
.path
.basename(FilePath
)
1907 self
.IsExtraUni
= IsExtraUni
1908 self
.IsModuleUni
= IsModuleUni
1915 self
.FileIn
= CodecOpenLongFilePath(self
.FilePath
, Mode
= 'rb', Encoding
= 'utf_16').read()
1916 except UnicodeError:
1917 self
.FileIn
= CodecOpenLongFilePath(self
.FilePath
, Mode
= 'rb', Encoding
= 'utf_16_le').read()
1922 if self
.IsModuleUni
:
1924 ModuleName
= self
.CheckKeyValid('STR_PROPERTIES_MODULE_NAME')
1925 self
.PrintLog('STR_PROPERTIES_MODULE_NAME', ModuleName
)
1927 ModuleAbstract
= self
.CheckKeyValid('STR_MODULE_ABSTRACT')
1928 self
.PrintLog('STR_MODULE_ABSTRACT', ModuleAbstract
)
1929 ModuleDescription
= self
.CheckKeyValid('STR_MODULE_DESCRIPTION')
1930 self
.PrintLog('STR_MODULE_DESCRIPTION', ModuleDescription
)
1933 PackageName
= self
.CheckKeyValid('STR_PROPERTIES_PACKAGE_NAME')
1934 self
.PrintLog('STR_PROPERTIES_PACKAGE_NAME', PackageName
)
1936 PackageAbstract
= self
.CheckKeyValid('STR_PACKAGE_ABSTRACT')
1937 self
.PrintLog('STR_PACKAGE_ABSTRACT', PackageAbstract
)
1938 PackageDescription
= self
.CheckKeyValid('STR_PACKAGE_DESCRIPTION')
1939 self
.PrintLog('STR_PACKAGE_DESCRIPTION', PackageDescription
)
1941 def CheckKeyValid(self
, Key
, Contents
=None):
1943 Contents
= self
.FileIn
1944 KeyPattern
= re
.compile('#string\s+%s\s+.*?#language.*?".*?"' % Key
, re
.S
)
1945 if KeyPattern
.search(Contents
):
1949 def CheckPcdInfo(self
, PcdCName
):
1950 PromptKey
= 'STR_%s_PROMPT' % PcdCName
.replace('.', '_')
1951 PcdPrompt
= self
.CheckKeyValid(PromptKey
)
1952 self
.PrintLog(PromptKey
, PcdPrompt
)
1953 HelpKey
= 'STR_%s_HELP' % PcdCName
.replace('.', '_')
1954 PcdHelp
= self
.CheckKeyValid(HelpKey
)
1955 self
.PrintLog(HelpKey
, PcdHelp
)
1957 def PrintLog(self
, Key
, Value
):
1958 if not Value
and Key
not in self
.Missing
:
1959 Msg
= '%s is missing in the %s file.' % (Key
, self
.FileName
)
1960 EdkLogger
.warn('Parser', Msg
)
1961 EccGlobalData
.gDb
.TblReport
.Insert(EccToolError
.ERROR_GENERAL_CHECK_UNI_HELP_INFO
, OtherMsg
=Msg
, BelongsToTable
='File', BelongsToItem
=-2)
1962 self
.Missing
.append(Key
)
1966 # This acts like the main() function for the script, unless it is 'import'ed into another
1969 if __name__
== '__main__':