2 # This file is used to parse meta files
4 # Copyright (c) 2008 - 2010, 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.
21 import Common
.EdkLogger
as EdkLogger
22 from CommonDataClass
.DataClass
import *
23 from Common
.DataType
import *
24 from Common
.String
import *
25 from Common
.Misc
import Blist
, GuidStructureStringToGuidString
, CheckPcdDatum
27 ## Base class of parser
29 # This class is used for derivation purpose. The specific parser for one kind
30 # type file must derive this class and implement some public interfaces.
32 # @param FilePath The path of platform description file
33 # @param FileType The raw data of DSC file
34 # @param Table Database used to retrieve module/package information
35 # @param Macros Macros used for replacement in file
36 # @param Owner Owner ID (for sub-section parsing)
37 # @param From ID from which the data comes (for !INCLUDE directive)
39 class MetaFileParser(object):
40 # data type (file content) for specific file type
43 # Parser objects used to implement singleton
48 # One file, one parser object. This factory method makes sure that there's
49 # only one object constructed for one meta file.
51 # @param Class class object of real AutoGen class
52 # (InfParser, DecParser or DscParser)
53 # @param FilePath The path of meta file
54 # @param *args The specific class related parameters
55 # @param **kwargs The specific class related dict parameters
57 def __new__(Class
, FilePath
, *args
, **kwargs
):
58 if FilePath
in Class
.MetaFiles
:
59 return Class
.MetaFiles
[FilePath
]
61 ParserObject
= super(MetaFileParser
, Class
).__new
__(Class
)
62 Class
.MetaFiles
[FilePath
] = ParserObject
65 ## Constructor of MetaFileParser
67 # Initialize object of MetaFileParser
69 # @param FilePath The path of platform description file
70 # @param FileType The raw data of DSC file
71 # @param Table Database used to retrieve module/package information
72 # @param Macros Macros used for replacement in file
73 # @param Owner Owner ID (for sub-section parsing)
74 # @param From ID from which the data comes (for !INCLUDE directive)
76 def __init__(self
, FilePath
, FileType
, Table
, Macros
=None, Owner
=-1, From
=-1):
77 # prevent re-initialization
78 if hasattr(self
, "_Table"):
81 self
._FileType
= FileType
82 self
.MetaFile
= FilePath
83 self
._FileDir
= os
.path
.dirname(self
.MetaFile
)
84 self
._Macros
= copy
.copy(Macros
)
85 self
._Macros
["WORKSPACE"] = os
.environ
["WORKSPACE"]
87 # for recursive parsing
91 # parsr status for parsing
93 self
._ValueList
= ['', '', '', '', '']
96 self
._CurrentLine
= ''
97 self
._SectionType
= MODEL_UNKNOWN
98 self
._SectionName
= ''
99 self
._InSubsection
= False
100 self
._SubsectionType
= MODEL_UNKNOWN
101 self
._SubsectionName
= ''
104 self
._Finished
= False
106 ## Store the parsed data in table
107 def _Store(self
, *Args
):
108 return self
._Table
.Insert(*Args
)
110 ## Virtual method for starting parse
112 raise NotImplementedError
114 ## Set parsing complete flag in both class and table
116 self
._Finished
= True
117 ## Do not set end flag when processing included files
119 self
._Table
.SetEndFlag()
121 ## Return the table containg parsed data
123 # If the parse complete flag is not set, this method will try to parse the
124 # file before return the table
127 if not self
._Finished
:
131 ## Get the parse complete flag
132 def _GetFinished(self
):
133 return self
._Finished
135 ## Set the complete flag
136 def _SetFinished(self
, Value
):
137 self
._Finished
= Value
139 ## Use [] style to query data in table, just for readability
141 # DataInfo = [data_type, scope1(arch), scope2(platform,moduletype)]
143 def __getitem__(self
, DataInfo
):
144 if type(DataInfo
) != type(()):
145 DataInfo
= (DataInfo
,)
146 return self
.Table
.Query(*DataInfo
)
148 ## Data parser for the common format in different type of file
150 # The common format in the meatfile is like
154 def _CommonParser(self
):
155 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
156 self
._ValueList
[0:len(TokenList
)] = TokenList
158 ## Data parser for the format in which there's path
160 # Only path can have macro used. So we need to replace them before use.
162 def _PathParser(self
):
163 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
164 self
._ValueList
[0:len(TokenList
)] = TokenList
165 if len(self
._Macros
) > 0:
166 for Index
in range(0, len(self
._ValueList
)):
167 Value
= self
._ValueList
[Index
]
168 if Value
== None or Value
== '':
170 self
._ValueList
[Index
] = NormPath(Value
, self
._Macros
)
172 ## Skip unsupported data
174 EdkLogger
.warn("Parser", "Unrecognized content", File
=self
.MetaFile
,
175 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
);
176 self
._ValueList
[0:1] = [self
._CurrentLine
]
178 ## Section header parser
180 # The section header is always in following format:
182 # [section_name.arch<.platform|module_type>]
184 def _SectionHeaderParser(self
):
186 self
._SectionName
= ''
188 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
191 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
)
192 # different section should not mix in one section
193 if self
._SectionName
!= '' and self
._SectionName
!= ItemList
[0].upper():
194 EdkLogger
.error('Parser', FORMAT_INVALID
, "Different section names in the same section",
195 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
196 self
._SectionName
= ItemList
[0].upper()
197 if self
._SectionName
in self
.DataType
:
198 self
._SectionType
= self
.DataType
[self
._SectionName
]
200 self
._SectionType
= MODEL_UNKNOWN
201 EdkLogger
.warn("Parser", "Unrecognized section", File
=self
.MetaFile
,
202 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
204 if len(ItemList
) > 1:
205 S1
= ItemList
[1].upper()
209 # S2 may be Platform or ModuleType
210 if len(ItemList
) > 2:
211 S2
= ItemList
[2].upper()
214 self
._Scope
.append([S1
, S2
])
216 # 'COMMON' must not be used with specific ARCHs at the same section
217 if 'COMMON' in ArchList
and len(ArchList
) > 1:
218 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
219 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
221 ## [defines] section parser
222 def _DefineParser(self
):
223 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
224 self
._ValueList
[0:len(TokenList
)] = TokenList
225 if self
._ValueList
[1] == '':
226 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
227 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
229 ## DEFINE name=value parser
230 def _MacroParser(self
):
231 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
232 MacroType
= TokenList
[0]
233 if len(TokenList
) < 2 or TokenList
[1] == '':
234 EdkLogger
.error('Parser', FORMAT_INVALID
, "No macro name/value given",
235 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
236 TokenList
= GetSplitValueList(TokenList
[1], TAB_EQUAL_SPLIT
, 1)
237 if TokenList
[0] == '':
238 EdkLogger
.error('Parser', FORMAT_INVALID
, "No macro name given",
239 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
241 # Macros defined in the command line override ones defined in the meta-data file
242 if not TokenList
[0] in self
._Macros
:
243 if len(TokenList
) == 1:
244 self
._Macros
[TokenList
[0]] = ''
246 # keep the macro definition for later use
247 self
._Macros
[TokenList
[0]] = ReplaceMacro(TokenList
[1], self
._Macros
, False)
249 return TokenList
[0], self
._Macros
[TokenList
[0]]
251 ## [BuildOptions] section parser
252 def _BuildOptionParser(self
):
253 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
254 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
255 if len(TokenList2
) == 2:
256 self
._ValueList
[0] = TokenList2
[0] # toolchain family
257 self
._ValueList
[1] = TokenList2
[1] # keys
259 self
._ValueList
[1] = TokenList
[0]
260 if len(TokenList
) == 2: # value
261 self
._ValueList
[2] = ReplaceMacro(TokenList
[1], self
._Macros
)
263 if self
._ValueList
[1].count('_') != 4:
267 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
268 ExtraData
=self
._CurrentLine
,
270 Line
=self
._LineIndex
+1
274 Table
= property(_GetTable
)
275 Finished
= property(_GetFinished
, _SetFinished
)
278 ## INF file parser class
280 # @param FilePath The path of platform description file
281 # @param FileType The raw data of DSC file
282 # @param Table Database used to retrieve module/package information
283 # @param Macros Macros used for replacement in file
285 class InfParser(MetaFileParser
):
286 # INF file supported data types (one type per section)
288 TAB_UNKNOWN
.upper() : MODEL_UNKNOWN
,
289 TAB_INF_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
290 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
291 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
292 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
293 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
294 TAB_PACKAGES
.upper() : MODEL_META_DATA_PACKAGE
,
295 TAB_NMAKE
.upper() : MODEL_META_DATA_NMAKE
,
296 TAB_INF_FIXED_PCD
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
297 TAB_INF_PATCH_PCD
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
298 TAB_INF_FEATURE_PCD
.upper() : MODEL_PCD_FEATURE_FLAG
,
299 TAB_INF_PCD_EX
.upper() : MODEL_PCD_DYNAMIC_EX
,
300 TAB_INF_PCD
.upper() : MODEL_PCD_DYNAMIC
,
301 TAB_SOURCES
.upper() : MODEL_EFI_SOURCE_FILE
,
302 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
303 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
304 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
305 TAB_DEPEX
.upper() : MODEL_EFI_DEPEX
,
306 TAB_BINARIES
.upper() : MODEL_EFI_BINARY_FILE
,
307 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
310 ## Constructor of InfParser
312 # Initialize object of InfParser
314 # @param FilePath The path of module description file
315 # @param FileType The raw data of DSC file
316 # @param Table Database used to retrieve module/package information
317 # @param Macros Macros used for replacement in file
319 def __init__(self
, FilePath
, FileType
, Table
, Macros
=None):
320 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, Macros
)
326 self
._Content
= open(self
.MetaFile
, 'r').readlines()
328 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
330 # parse the file line by line
331 IsFindBlockComment
= False
333 for Index
in range(0, len(self
._Content
)):
334 # skip empty, commented, block commented lines
335 Line
= CleanString(self
._Content
[Index
], AllowCppStyleComment
=True)
337 if Index
+ 1 < len(self
._Content
):
338 NextLine
= CleanString(self
._Content
[Index
+ 1])
341 if Line
.find(DataType
.TAB_COMMENT_R8_START
) > -1:
342 IsFindBlockComment
= True
344 if Line
.find(DataType
.TAB_COMMENT_R8_END
) > -1:
345 IsFindBlockComment
= False
347 if IsFindBlockComment
:
350 self
._LineIndex
= Index
351 self
._CurrentLine
= Line
354 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
355 self
._SectionHeaderParser
()
357 # merge two lines specified by '\' in section NMAKE
358 elif self
._SectionType
== MODEL_META_DATA_NMAKE
:
361 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
364 if NextLine
[0] == TAB_SECTION_START
and NextLine
[-1] == TAB_SECTION_END
:
365 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
368 NmakeLine
= NmakeLine
+ ' ' + Line
[0:-1]
371 self
._CurrentLine
= NmakeLine
+ Line
373 elif Line
.upper().startswith('DEFINE '):
374 # file private macros
379 self
._ValueList
= ['','','']
380 # parse current line, result will be put in self._ValueList
381 self
._SectionParser
[self
._SectionType
](self
)
382 if self
._ValueList
== None:
385 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
386 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
388 for Arch
, Platform
in self
._Scope
:
389 self
._Store
(self
._SectionType
,
402 if IsFindBlockComment
:
403 EdkLogger
.error("Parser", FORMAT_INVALID
, "Open block comments (starting with /*) are expected to end with */",
407 ## Data parser for the format in which there's path
409 # Only path can have macro used. So we need to replace them before use.
411 def _IncludeParser(self
):
412 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
413 self
._ValueList
[0:len(TokenList
)] = TokenList
414 if len(self
._Macros
) > 0:
415 for Index
in range(0, len(self
._ValueList
)):
416 Value
= self
._ValueList
[Index
]
417 if Value
.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value
.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
418 Value
= '$(EDK_SOURCE)' + Value
[17:]
419 if Value
.find('$(EFI_SOURCE)') > -1 or Value
.find('$(EDK_SOURCE)') > -1:
421 elif Value
.startswith('.'):
423 elif Value
.startswith('$('):
426 Value
= '$(EFI_SOURCE)/' + Value
428 if Value
== None or Value
== '':
430 self
._ValueList
[Index
] = NormPath(Value
, self
._Macros
)
432 ## Parse [Sources] section
434 # Only path can have macro used. So we need to replace them before use.
436 def _SourceFileParser(self
):
437 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
438 self
._ValueList
[0:len(TokenList
)] = TokenList
439 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
440 if 'COMPONENT_TYPE' in self
._Macros
:
441 if self
._Macros
['COMPONENT_TYPE'].upper() == 'ACPITABLE':
442 self
._ValueList
[0] = GetSplitValueList(self
._ValueList
[0], ' ', 1)[0]
443 if self
._Macros
['BASE_NAME'] == 'Microcode':
445 if len(self
._Macros
) > 0:
446 for Index
in range(0, len(self
._ValueList
)):
447 Value
= self
._ValueList
[Index
]
448 if Value
== None or Value
== '':
450 self
._ValueList
[Index
] = NormPath(Value
, self
._Macros
)
452 ## Parse [Binaries] section
454 # Only path can have macro used. So we need to replace them before use.
456 def _BinaryFileParser(self
):
457 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 2)
458 if len(TokenList
) < 2:
459 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type or path specified",
460 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
461 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
463 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type specified",
464 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
465 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
467 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file path specified",
468 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
469 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
470 self
._ValueList
[0:len(TokenList
)] = TokenList
471 self
._ValueList
[1] = NormPath(self
._ValueList
[1], self
._Macros
)
473 ## [defines] section parser
474 def _DefineParser(self
):
475 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
476 self
._ValueList
[0:len(TokenList
)] = TokenList
477 if self
._ValueList
[1] == '':
478 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
479 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
480 self
._Macros
[TokenList
[0]] = ReplaceMacro(TokenList
[1], self
._Macros
, False)
482 ## [nmake] section parser (R8.x style only)
483 def _NmakeParser(self
):
484 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
485 self
._ValueList
[0:len(TokenList
)] = TokenList
487 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, False)
488 # remove self-reference in macro setting
489 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
491 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
492 def _PcdParser(self
):
493 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
494 ValueList
= GetSplitValueList(TokenList
[0], TAB_SPLIT
)
495 if len(ValueList
) != 2:
496 EdkLogger
.error('Parser', FORMAT_INVALID
, "Illegal token space GUID and PCD name format",
497 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
498 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
499 self
._ValueList
[0:1] = ValueList
500 if len(TokenList
) > 1:
501 self
._ValueList
[2] = TokenList
[1]
502 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
503 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
504 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
505 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
506 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
507 if self
._ValueList
[2] != '':
508 InfPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
509 if InfPcdValueList
[0] in ['True', 'true', 'TRUE']:
510 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '1', 1);
511 elif InfPcdValueList
[0] in ['False', 'false', 'FALSE']:
512 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '0', 1);
514 ## [depex] section parser
515 def _DepexParser(self
):
516 self
._ValueList
[0:1] = [self
._CurrentLine
]
519 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
520 MODEL_META_DATA_HEADER
: _DefineParser
,
521 MODEL_META_DATA_BUILD_OPTION
: MetaFileParser
._BuildOptionParser
,
522 MODEL_EFI_INCLUDE
: _IncludeParser
, # for R8.x modules
523 MODEL_EFI_LIBRARY_INSTANCE
: MetaFileParser
._CommonParser
, # for R8.x modules
524 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
525 MODEL_META_DATA_PACKAGE
: MetaFileParser
._PathParser
,
526 MODEL_META_DATA_NMAKE
: _NmakeParser
, # for R8.x modules
527 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
528 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
529 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
530 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
531 MODEL_PCD_DYNAMIC
: _PcdParser
,
532 MODEL_EFI_SOURCE_FILE
: _SourceFileParser
,
533 MODEL_EFI_GUID
: MetaFileParser
._CommonParser
,
534 MODEL_EFI_PROTOCOL
: MetaFileParser
._CommonParser
,
535 MODEL_EFI_PPI
: MetaFileParser
._CommonParser
,
536 MODEL_EFI_DEPEX
: _DepexParser
,
537 MODEL_EFI_BINARY_FILE
: _BinaryFileParser
,
538 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
541 ## DSC file parser class
543 # @param FilePath The path of platform description file
544 # @param FileType The raw data of DSC file
545 # @param Table Database used to retrieve module/package information
546 # @param Macros Macros used for replacement in file
547 # @param Owner Owner ID (for sub-section parsing)
548 # @param From ID from which the data comes (for !INCLUDE directive)
550 class DscParser(MetaFileParser
):
551 # DSC file supported data types (one type per section)
553 TAB_SKUIDS
.upper() : MODEL_EFI_SKU_ID
,
554 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
555 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
556 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
557 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
558 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
559 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
560 TAB_PCDS_DYNAMIC_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_DEFAULT
,
561 TAB_PCDS_DYNAMIC_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_HII
,
562 TAB_PCDS_DYNAMIC_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_VPD
,
563 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT
,
564 TAB_PCDS_DYNAMIC_EX_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_HII
,
565 TAB_PCDS_DYNAMIC_EX_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_VPD
,
566 TAB_COMPONENTS
.upper() : MODEL_META_DATA_COMPONENT
,
567 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH
.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
,
568 TAB_DSC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
569 TAB_INCLUDE
.upper() : MODEL_META_DATA_INCLUDE
,
570 TAB_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
571 TAB_IF_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
572 TAB_IF_N_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
,
573 TAB_ELSE_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
,
574 TAB_ELSE
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
575 TAB_END_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
,
578 # sections which allow "!include" directive
579 _IncludeAllowedSection
= [
580 TAB_COMMON_DEFINES
.upper(),
581 TAB_LIBRARIES
.upper(),
582 TAB_LIBRARY_CLASSES
.upper(),
584 TAB_COMPONENTS
.upper(),
585 TAB_BUILD_OPTIONS
.upper(),
586 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper(),
587 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper(),
588 TAB_PCDS_FEATURE_FLAG_NULL
.upper(),
589 TAB_PCDS_DYNAMIC_DEFAULT_NULL
.upper(),
590 TAB_PCDS_DYNAMIC_HII_NULL
.upper(),
591 TAB_PCDS_DYNAMIC_VPD_NULL
.upper(),
592 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
.upper(),
593 TAB_PCDS_DYNAMIC_EX_HII_NULL
.upper(),
594 TAB_PCDS_DYNAMIC_EX_VPD_NULL
.upper(),
597 # operators which can be used in "!if/!ifdef/!ifndef" directives
599 "!" : lambda a
: not a
,
600 "!=" : lambda a
,b
: a
!=b
,
601 "==" : lambda a
,b
: a
==b
,
602 ">" : lambda a
,b
: a
>b
,
603 "<" : lambda a
,b
: a
<b
,
604 "=>" : lambda a
,b
: a
>=b
,
605 ">=" : lambda a
,b
: a
>=b
,
606 "<=" : lambda a
,b
: a
<=b
,
607 "=<" : lambda a
,b
: a
<=b
,
610 ## Constructor of DscParser
612 # Initialize object of DscParser
614 # @param FilePath The path of platform description file
615 # @param FileType The raw data of DSC file
616 # @param Table Database used to retrieve module/package information
617 # @param Macros Macros used for replacement in file
618 # @param Owner Owner ID (for sub-section parsing)
619 # @param From ID from which the data comes (for !INCLUDE directive)
621 def __init__(self
, FilePath
, FileType
, Table
, Macros
=None, Owner
=-1, From
=-1):
622 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, Macros
, Owner
, From
)
623 # to store conditional directive evaluation result
629 if self
._Content
== None:
630 self
._Content
= open(self
.MetaFile
, 'r').readlines()
632 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
634 for Index
in range(0, len(self
._Content
)):
635 Line
= CleanString(self
._Content
[Index
])
639 self
._CurrentLine
= Line
640 self
._LineIndex
= Index
641 if self
._InSubsection
and self
._Owner
== -1:
642 self
._Owner
= self
._LastItem
645 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
646 self
._SectionHeaderParser
()
650 self
._InSubsection
= False
651 self
._SubsectionType
= MODEL_UNKNOWN
652 self
._SubsectionName
= ''
656 elif Line
[0] == TAB_OPTION_START
and Line
[-1] == TAB_OPTION_END
:
657 self
._SubsectionHeaderParser
()
661 self
._DirectiveParser
()
663 # file private macros
664 elif Line
.upper().startswith('DEFINE '):
665 if self
._Enabled
< 0:
666 # Do not parse the macro and add it to self._Macros dictionary if directives
667 # statement is evaluated to false.
670 (Name
, Value
) = self
._MacroParser
()
671 # Make the defined macro in DSC [Defines] section also
672 # available for FDF file.
673 if self
._SectionName
== TAB_COMMON_DEFINES
.upper():
674 self
._LastItem
= self
._Store
(
675 MODEL_META_DATA_GLOBAL_DEFINE
,
690 elif Line
.upper().startswith('EDK_GLOBAL '):
691 if self
._Enabled
< 0:
692 # Do not parse the macro and add it to self._Macros dictionary
693 # if previous directives statement is evaluated to false.
696 (Name
, Value
) = self
._MacroParser
()
697 for Arch
, ModuleType
in self
._Scope
:
698 self
._LastItem
= self
._Store
(
699 MODEL_META_DATA_DEFINE
,
716 if self
._InSubsection
:
717 SectionType
= self
._SubsectionType
718 SectionName
= self
._SubsectionName
720 SectionType
= self
._SectionType
721 SectionName
= self
._SectionName
723 self
._ValueList
= ['', '', '']
724 self
._SectionParser
[SectionType
](self
)
725 if self
._ValueList
== None:
729 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
730 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
732 for Arch
, ModuleType
in self
._Scope
:
733 self
._LastItem
= self
._Store
(
750 ## [defines] section parser
751 def _DefineParser(self
):
752 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
753 if len(TokenList
) < 2:
754 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
755 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
756 # 'FLASH_DEFINITION', 'OUTPUT_DIRECTORY' need special processing
757 if TokenList
[0] in ['FLASH_DEFINITION', 'OUTPUT_DIRECTORY']:
758 TokenList
[1] = NormPath(TokenList
[1], self
._Macros
)
759 self
._ValueList
[0:len(TokenList
)] = TokenList
760 # Treat elements in the [defines] section as global macros for FDF file.
761 self
._LastItem
= self
._Store
(
762 MODEL_META_DATA_GLOBAL_DEFINE
,
777 ## <subsection_header> parser
778 def _SubsectionHeaderParser(self
):
779 self
._SubsectionName
= self
._CurrentLine
[1:-1].upper()
780 if self
._SubsectionName
in self
.DataType
:
781 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
783 self
._SubsectionType
= MODEL_UNKNOWN
784 EdkLogger
.warn("Parser", "Unrecognized sub-section", File
=self
.MetaFile
,
785 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
787 ## Directive statement parser
788 def _DirectiveParser(self
):
789 self
._ValueList
= ['','','']
790 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
791 self
._ValueList
[0:len(TokenList
)] = TokenList
792 DirectiveName
= self
._ValueList
[0].upper()
793 if DirectiveName
not in self
.DataType
:
794 EdkLogger
.error("Parser", FORMAT_INVALID
, "Unknown directive [%s]" % DirectiveName
,
795 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
796 if DirectiveName
in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self
._ValueList
[1] == '':
797 EdkLogger
.error("Parser", FORMAT_INVALID
, "Missing expression",
798 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
799 ExtraData
=self
._CurrentLine
)
800 # keep the directive in database first
801 self
._LastItem
= self
._Store
(
802 self
.DataType
[DirectiveName
],
817 # process the directive
818 if DirectiveName
== "!INCLUDE":
819 if not self
._SectionName
in self
._IncludeAllowedSection
:
820 EdkLogger
.error("Parser", FORMAT_INVALID
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
821 ExtraData
="'!include' is not allowed under section [%s]" % self
._SectionName
)
822 # the included file must be relative to workspace
823 IncludedFile
= os
.path
.join(os
.environ
["WORKSPACE"], NormPath(self
._ValueList
[1], self
._Macros
))
824 Parser
= DscParser(IncludedFile
, self
._FileType
, self
._Table
, self
._Macros
, From
=self
._LastItem
)
825 # set the parser status with current status
826 Parser
._SectionName
= self
._SectionName
827 Parser
._SectionType
= self
._SectionType
828 Parser
._Scope
= self
._Scope
829 Parser
._Enabled
= self
._Enabled
833 EdkLogger
.error("Parser", PARSER_ERROR
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
834 ExtraData
="Failed to parse content in file %s" % IncludedFile
)
835 # insert an imaginary token in the DSC table to indicate its external dependency on another file
836 self
._Store
(MODEL_EXTERNAL_DEPENDENCY
, IncludedFile
, str(os
.stat(IncludedFile
)[8]), "")
837 # update current status with sub-parser's status
838 self
._SectionName
= Parser
._SectionName
839 self
._SectionType
= Parser
._SectionType
840 self
._Scope
= Parser
._Scope
841 self
._Enabled
= Parser
._Enabled
842 self
._Macros
.update(Parser
._Macros
)
844 if DirectiveName
in ["!IF", "!IFDEF", "!IFNDEF"]:
845 # evaluate the expression
846 Result
= self
._Evaluate
(self
._ValueList
[1])
847 if DirectiveName
== "!IFNDEF":
849 self
._Eval
.append(Result
)
850 elif DirectiveName
in ["!ELSEIF"]:
851 # evaluate the expression
852 self
._Eval
[-1] = (not self
._Eval
[-1]) & self
._Evaluate
(self
._ValueList
[1])
853 elif DirectiveName
in ["!ELSE"]:
854 self
._Eval
[-1] = not self
._Eval
[-1]
855 elif DirectiveName
in ["!ENDIF"]:
856 if len(self
._Eval
) > 0:
859 EdkLogger
.error("Parser", FORMAT_INVALID
, "!IF..[!ELSE]..!ENDIF doesn't match",
860 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
861 if self
._Eval
.Result
== False:
862 self
._Enabled
= 0 - len(self
._Eval
)
864 self
._Enabled
= len(self
._Eval
)
866 ## Evaluate the Token for its value; for now only macros are supported.
867 def _EvaluateToken(self
, TokenName
, Expression
):
868 if TokenName
.startswith("$(") and TokenName
.endswith(")"):
869 Name
= TokenName
[2:-1]
870 return self
._Macros
.get(Name
)
872 EdkLogger
.error('Parser', FORMAT_INVALID
, "Unknown operand '%(Token)s', "
873 "please use '$(%(Token)s)' if '%(Token)s' is a macro" % {"Token" : TokenName
},
874 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=Expression
)
876 ## Evaluate the value of expression in "if/ifdef/ifndef" directives
877 def _Evaluate(self
, Expression
):
878 TokenList
= Expression
.split()
879 TokenNumber
= len(TokenList
)
880 # one operand, guess it's just a macro name
882 TokenValue
= self
._EvaluateToken
(TokenList
[0], Expression
)
883 return TokenValue
!= None
884 # two operands, suppose it's "!xxx" format
885 elif TokenNumber
== 2:
887 if Op
not in self
._OP
_:
888 EdkLogger
.error('Parser', FORMAT_INVALID
, "Unsupported operator [%s]" % Op
, File
=self
.MetaFile
,
889 Line
=self
._LineIndex
+1, ExtraData
=Expression
)
890 if TokenList
[1].upper() == 'TRUE':
894 return self
._OP
_[Op
](Value
)
896 elif TokenNumber
== 3:
897 TokenValue
= self
._EvaluateToken
(TokenList
[0], Expression
)
898 if TokenValue
== None:
901 if Value
[0] in ["'", '"'] and Value
[-1] in ["'", '"']:
904 if Op
not in self
._OP
_:
905 EdkLogger
.error('Parser', FORMAT_INVALID
, "Unsupported operator [%s]" % Op
, File
=self
.MetaFile
,
906 Line
=self
._LineIndex
+1, ExtraData
=Expression
)
907 return self
._OP
_[Op
](TokenValue
, Value
)
909 EdkLogger
.error('Parser', FORMAT_INVALID
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
910 ExtraData
=Expression
)
912 ## PCD sections parser
915 # [PcdsPatchableInModule]
918 # [PcdsDynamicExDefault]
922 # [PcdsDynamicDefault]
926 def _PcdParser(self
):
927 TokenList
= GetSplitValueList(ReplaceMacro(self
._CurrentLine
, self
._Macros
), TAB_VALUE_SPLIT
, 1)
928 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
929 if len(TokenList
) == 2:
930 self
._ValueList
[2] = TokenList
[1]
931 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
932 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
933 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
934 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
935 if self
._ValueList
[2] == '':
936 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD value given",
937 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
938 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
939 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
940 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
941 if DscPcdValueList
[0] in ['True', 'true', 'TRUE']:
942 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '1', 1);
943 elif DscPcdValueList
[0] in ['False', 'false', 'FALSE']:
944 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '0', 1);
946 ## [components] section parser
947 def _ComponentParser(self
):
948 if self
._CurrentLine
[-1] == '{':
949 self
._ValueList
[0] = self
._CurrentLine
[0:-1].strip()
950 self
._InSubsection
= True
952 self
._ValueList
[0] = self
._CurrentLine
953 if len(self
._Macros
) > 0:
954 self
._ValueList
[0] = NormPath(self
._ValueList
[0], self
._Macros
)
956 def _LibraryClassParser(self
):
957 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
958 if len(TokenList
) < 2:
959 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class or instance specified",
960 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
961 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
962 if TokenList
[0] == '':
963 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class specified",
964 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
965 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
966 if TokenList
[1] == '':
967 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library instance specified",
968 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
969 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
970 self
._ValueList
[0:len(TokenList
)] = TokenList
971 if len(self
._Macros
) > 0:
972 self
._ValueList
[1] = NormPath(self
._ValueList
[1], self
._Macros
)
974 def _CompponentSourceOverridePathParser(self
):
975 if len(self
._Macros
) > 0:
976 self
._ValueList
[0] = NormPath(self
._CurrentLine
, self
._Macros
)
979 MODEL_META_DATA_HEADER
: _DefineParser
,
980 MODEL_EFI_SKU_ID
: MetaFileParser
._CommonParser
,
981 MODEL_EFI_LIBRARY_INSTANCE
: MetaFileParser
._PathParser
,
982 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
983 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
984 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
985 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
986 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
987 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
988 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
989 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
990 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
991 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
992 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
993 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: _CompponentSourceOverridePathParser
,
994 MODEL_META_DATA_BUILD_OPTION
: MetaFileParser
._BuildOptionParser
,
995 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
996 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
999 ## DEC file parser class
1001 # @param FilePath The path of platform description file
1002 # @param FileType The raw data of DSC file
1003 # @param Table Database used to retrieve module/package information
1004 # @param Macros Macros used for replacement in file
1006 class DecParser(MetaFileParser
):
1007 # DEC file supported data types (one type per section)
1009 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1010 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1011 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1012 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1013 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1014 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1015 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1016 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1017 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1018 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1019 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1022 ## Constructor of DecParser
1024 # Initialize object of DecParser
1026 # @param FilePath The path of platform description file
1027 # @param FileType The raw data of DSC file
1028 # @param Table Database used to retrieve module/package information
1029 # @param Macros Macros used for replacement in file
1031 def __init__(self
, FilePath
, FileType
, Table
, Macro
=None):
1032 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, Macro
, -1)
1038 if self
._Content
== None:
1039 self
._Content
= open(self
.MetaFile
, 'r').readlines()
1041 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1043 for Index
in range(0, len(self
._Content
)):
1044 Line
, Comment
= CleanString2(self
._Content
[Index
])
1045 self
._CurrentLine
= Line
1046 self
._LineIndex
= Index
1048 # save comment for later use
1050 self
._Comments
.append((Comment
, self
._LineIndex
+1))
1056 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1057 self
._SectionHeaderParser
()
1060 elif Line
.startswith('DEFINE '):
1063 elif len(self
._SectionType
) == 0:
1068 self
._ValueList
= ['','','']
1069 self
._SectionParser
[self
._SectionType
[0]](self
)
1070 if self
._ValueList
== None:
1075 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1076 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1078 for Arch
, ModuleType
, Type
in self
._Scope
:
1079 self
._LastItem
= self
._Store
(
1093 for Comment
, LineNo
in self
._Comments
:
1095 MODEL_META_DATA_COMMENT
,
1111 ## Section header parser
1113 # The section header is always in following format:
1115 # [section_name.arch<.platform|module_type>]
1117 def _SectionHeaderParser(self
):
1119 self
._SectionName
= ''
1120 self
._SectionType
= []
1122 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
1125 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
)
1127 # different types of PCD are permissible in one section
1128 self
._SectionName
= ItemList
[0].upper()
1129 if self
._SectionName
in self
.DataType
:
1130 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1131 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1133 EdkLogger
.warn("Parser", "Unrecognized section", File
=self
.MetaFile
,
1134 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
1137 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1141 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1143 Line
=self
._LineIndex
+1,
1144 ExtraData
=self
._CurrentLine
1147 if len(ItemList
) > 1:
1148 S1
= ItemList
[1].upper()
1152 # S2 may be Platform or ModuleType
1153 if len(ItemList
) > 2:
1154 S2
= ItemList
[2].upper()
1157 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1158 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1160 # 'COMMON' must not be used with specific ARCHs at the same section
1161 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1162 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1163 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
1165 ## [guids], [ppis] and [protocols] section parser
1166 def _GuidParser(self
):
1167 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1168 if len(TokenList
) < 2:
1169 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1170 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1171 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1172 if TokenList
[0] == '':
1173 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1174 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1175 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1176 if TokenList
[1] == '':
1177 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1178 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1179 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1180 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1181 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1182 ExtraData
=self
._CurrentLine
+ \
1183 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1184 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1185 self
._ValueList
[0] = TokenList
[0]
1186 self
._ValueList
[1] = TokenList
[1]
1188 ## PCD sections parser
1190 # [PcdsFixedAtBuild]
1191 # [PcdsPatchableInModule]
1196 def _PcdParser(self
):
1197 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1198 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1199 # check PCD information
1200 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1201 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1202 ExtraData
=self
._CurrentLine
+ \
1203 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1204 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1205 # check PCD datum information
1206 if len(TokenList
) < 2 or TokenList
[1] == '':
1207 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1208 ExtraData
=self
._CurrentLine
+ \
1209 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1210 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1213 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1214 PtrValue
= ValueRe
.findall(TokenList
[1])
1216 # Has VOID* type string, may contain "|" character in the string.
1217 if len(PtrValue
) != 0:
1218 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1219 ValueList
= GetSplitValueList(ptrValueList
)
1220 ValueList
[0] = PtrValue
[0]
1222 ValueList
= GetSplitValueList(TokenList
[1])
1225 # check if there's enough datum information given
1226 if len(ValueList
) != 3:
1227 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1228 ExtraData
=self
._CurrentLine
+ \
1229 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1230 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1231 # check default value
1232 if ValueList
[0] == '':
1233 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1234 ExtraData
=self
._CurrentLine
+ \
1235 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1236 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1238 if ValueList
[1] == '':
1239 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1240 ExtraData
=self
._CurrentLine
+ \
1241 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1242 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1243 # check token of the PCD
1244 if ValueList
[2] == '':
1245 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1246 ExtraData
=self
._CurrentLine
+ \
1247 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1248 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1249 # check format of default value against the datum type
1250 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1252 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1253 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1254 if ValueList
[0] in ['True', 'true', 'TRUE']:
1256 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1259 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
1262 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
1263 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
1264 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
1265 MODEL_EFI_GUID
: _GuidParser
,
1266 MODEL_EFI_PPI
: _GuidParser
,
1267 MODEL_EFI_PROTOCOL
: _GuidParser
,
1268 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1269 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1270 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1271 MODEL_PCD_DYNAMIC
: _PcdParser
,
1272 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
1273 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1274 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1279 # This acts like the main() function for the script, unless it is 'import'ed into another
1282 if __name__
== '__main__':