2 # This file is used to parse meta files
4 # Copyright (c) 2008 - 2012, 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.
22 import Common
.EdkLogger
as EdkLogger
23 import Common
.GlobalData
as GlobalData
25 from CommonDataClass
.DataClass
import *
26 from Common
.DataType
import *
27 from Common
.String
import *
28 from Common
.Misc
import GuidStructureStringToGuidString
, CheckPcdDatum
, PathClass
, AnalyzePcdData
, AnalyzeDscPcd
29 from Common
.Expression
import *
30 from CommonDataClass
.Exceptions
import *
32 from MetaFileTable
import MetaFileStorage
34 ## A decorator used to parse macro definition
35 def ParseMacro(Parser
):
36 def MacroParser(self
):
37 Match
= gMacroDefPattern
.match(self
._CurrentLine
)
39 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
43 TokenList
= GetSplitValueList(self
._CurrentLine
[Match
.end(1):], TAB_EQUAL_SPLIT
, 1)
46 EdkLogger
.error('Parser', FORMAT_INVALID
, "No macro name given",
47 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
48 if len(TokenList
) < 2:
52 Name
, Value
= TokenList
53 # Global macros can be only defined via environment variable
54 if Name
in GlobalData
.gGlobalDefines
:
55 EdkLogger
.error('Parser', FORMAT_INVALID
, "%s can only be defined via environment variable" % Name
,
56 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
57 # Only upper case letters, digit and '_' are allowed
58 if not gMacroNamePattern
.match(Name
):
59 EdkLogger
.error('Parser', FORMAT_INVALID
, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
60 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
62 Value
= ReplaceMacro(Value
, self
._Macros
)
63 if Type
in self
.DataType
:
64 self
._ItemType
= self
.DataType
[Type
]
66 self
._ItemType
= MODEL_META_DATA_DEFINE
67 # DEFINE defined macros
68 if Type
== TAB_DSC_DEFINES_DEFINE
:
70 # First judge whether this DEFINE is in conditional directive statements or not.
72 if type(self
) == DscParser
and self
._InDirective
> -1:
75 if type(self
) == DecParser
:
76 if MODEL_META_DATA_HEADER
in self
._SectionType
:
77 self
._FileLocalMacros
[Name
] = Value
79 self
._ConstructSectionMacroDict
(Name
, Value
)
80 elif self
._SectionType
== MODEL_META_DATA_HEADER
:
81 self
._FileLocalMacros
[Name
] = Value
83 self
._ConstructSectionMacroDict
(Name
, Value
)
85 # EDK_GLOBAL defined macros
86 elif type(self
) != DscParser
:
87 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used in .dsc file",
88 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
89 elif self
._SectionType
!= MODEL_META_DATA_HEADER
:
90 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used under [Defines] section",
91 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
92 elif (Name
in self
._FileLocalMacros
) and (self
._FileLocalMacros
[Name
] != Value
):
93 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
94 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
96 self
._ValueList
= [Type
, Name
, Value
]
100 ## Base class of parser
102 # This class is used for derivation purpose. The specific parser for one kind
103 # type file must derive this class and implement some public interfaces.
105 # @param FilePath The path of platform description file
106 # @param FileType The raw data of DSC file
107 # @param Table Database used to retrieve module/package information
108 # @param Macros Macros used for replacement in file
109 # @param Owner Owner ID (for sub-section parsing)
110 # @param From ID from which the data comes (for !INCLUDE directive)
112 class MetaFileParser(object):
113 # data type (file content) for specific file type
116 # Parser objects used to implement singleton
121 # One file, one parser object. This factory method makes sure that there's
122 # only one object constructed for one meta file.
124 # @param Class class object of real AutoGen class
125 # (InfParser, DecParser or DscParser)
126 # @param FilePath The path of meta file
127 # @param *args The specific class related parameters
128 # @param **kwargs The specific class related dict parameters
130 def __new__(Class
, FilePath
, *args
, **kwargs
):
131 if FilePath
in Class
.MetaFiles
:
132 return Class
.MetaFiles
[FilePath
]
134 ParserObject
= super(MetaFileParser
, Class
).__new
__(Class
)
135 Class
.MetaFiles
[FilePath
] = ParserObject
138 ## Constructor of MetaFileParser
140 # Initialize object of MetaFileParser
142 # @param FilePath The path of platform description file
143 # @param FileType The raw data of DSC file
144 # @param Table Database used to retrieve module/package information
145 # @param Macros Macros used for replacement in file
146 # @param Owner Owner ID (for sub-section parsing)
147 # @param From ID from which the data comes (for !INCLUDE directive)
149 def __init__(self
, FilePath
, FileType
, Table
, Owner
= -1, From
= -1):
151 self
._RawTable
= Table
152 self
._FileType
= FileType
153 self
.MetaFile
= FilePath
154 self
._FileDir
= self
.MetaFile
.Dir
156 self
._FileLocalMacros
= {}
157 self
._SectionsMacroDict
= {}
159 # for recursive parsing
160 self
._Owner
= [Owner
]
163 # parsr status for parsing
164 self
._ValueList
= ['', '', '', '', '']
167 self
._CurrentLine
= ''
168 self
._SectionType
= MODEL_UNKNOWN
169 self
._SectionName
= ''
170 self
._InSubsection
= False
171 self
._SubsectionType
= MODEL_UNKNOWN
172 self
._SubsectionName
= ''
173 self
._ItemType
= MODEL_UNKNOWN
176 self
._Finished
= False
177 self
._PostProcessed
= False
178 # Different version of meta-file has different way to parse.
181 ## Store the parsed data in table
182 def _Store(self
, *Args
):
183 return self
._Table
.Insert(*Args
)
185 ## Virtual method for starting parse
187 raise NotImplementedError
189 ## Notify a post-process is needed
190 def DoPostProcess(self
):
191 self
._PostProcessed
= False
193 ## Set parsing complete flag in both class and table
195 self
._Finished
= True
196 ## Do not set end flag when processing included files
198 self
._Table
.SetEndFlag()
200 def _PostProcess(self
):
201 self
._PostProcessed
= True
203 ## Get the parse complete flag
204 def _GetFinished(self
):
205 return self
._Finished
207 ## Set the complete flag
208 def _SetFinished(self
, Value
):
209 self
._Finished
= Value
211 ## Use [] style to query data in table, just for readability
213 # DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]
215 def __getitem__(self
, DataInfo
):
216 if type(DataInfo
) != type(()):
217 DataInfo
= (DataInfo
,)
219 # Parse the file first, if necessary
220 if not self
._Finished
:
221 if self
._RawTable
.IsIntegrity():
222 self
._Finished
= True
224 self
._Table
= self
._RawTable
225 self
._PostProcessed
= False
228 # No specific ARCH or Platform given, use raw data
229 if self
._RawTable
and (len(DataInfo
) == 1 or DataInfo
[1] == None):
230 return self
._RawTable
.Query(*DataInfo
)
232 # Do post-process if necessary
233 if not self
._PostProcessed
:
236 return self
._Table
.Query(*DataInfo
)
238 ## Data parser for the common format in different type of file
240 # The common format in the meatfile is like
245 def _CommonParser(self
):
246 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
247 self
._ValueList
[0:len(TokenList
)] = TokenList
249 ## Data parser for the format in which there's path
251 # Only path can have macro used. So we need to replace them before use.
254 def _PathParser(self
):
255 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
256 self
._ValueList
[0:len(TokenList
)] = TokenList
257 # Don't do macro replacement for dsc file at this point
258 if type(self
) != DscParser
:
259 Macros
= self
._Macros
260 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
262 ## Skip unsupported data
264 EdkLogger
.warn("Parser", "Unrecognized content", File
=self
.MetaFile
,
265 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
);
266 self
._ValueList
[0:1] = [self
._CurrentLine
]
268 ## Section header parser
270 # The section header is always in following format:
272 # [section_name.arch<.platform|module_type>]
274 def _SectionHeaderParser(self
):
276 self
._SectionName
= ''
278 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
281 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
,2)
282 # different section should not mix in one section
283 if self
._SectionName
!= '' and self
._SectionName
!= ItemList
[0].upper():
284 EdkLogger
.error('Parser', FORMAT_INVALID
, "Different section names in the same section",
285 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
286 self
._SectionName
= ItemList
[0].upper()
287 if self
._SectionName
in self
.DataType
:
288 self
._SectionType
= self
.DataType
[self
._SectionName
]
289 # Check if the section name is valid
290 if self
._SectionName
not in SECTIONS_HAVE_ITEM_AFTER_ARCH
and len(ItemList
) > 3:
291 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
292 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
293 elif self
._Version
>= 0x00010005:
294 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
295 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
297 self
._SectionType
= MODEL_UNKNOWN
300 if len(ItemList
) > 1:
301 S1
= ItemList
[1].upper()
306 # S2 may be Platform or ModuleType
307 if len(ItemList
) > 2:
308 if self
._SectionName
.upper() in SECTIONS_HAVE_ITEM_PCD
:
311 S2
= ItemList
[2].upper()
314 self
._Scope
.append([S1
, S2
])
316 # 'COMMON' must not be used with specific ARCHs at the same section
317 if 'COMMON' in ArchList
and len(ArchList
) > 1:
318 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
319 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
320 # If the section information is needed later, it should be stored in database
321 self
._ValueList
[0] = self
._SectionName
323 ## [defines] section parser
325 def _DefineParser(self
):
326 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
327 self
._ValueList
[1:len(TokenList
)] = TokenList
328 if not self
._ValueList
[1]:
329 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
330 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
331 if not self
._ValueList
[2]:
332 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
333 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
335 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
336 Name
, Value
= self
._ValueList
[1], self
._ValueList
[2]
337 # Sometimes, we need to make differences between EDK and EDK2 modules
338 if Name
== 'INF_VERSION':
340 self
._Version
= int(Value
, 0)
342 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid version number",
343 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
345 if type(self
) == InfParser
and self
._Version
< 0x00010005:
346 # EDK module allows using defines as macros
347 self
._FileLocalMacros
[Name
] = Value
348 self
._Defines
[Name
] = Value
350 ## [BuildOptions] section parser
352 def _BuildOptionParser(self
):
353 self
._CurrentLine
= CleanString(self
._CurrentLine
, BuildOption
=True)
354 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
355 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
356 if len(TokenList2
) == 2:
357 self
._ValueList
[0] = TokenList2
[0] # toolchain family
358 self
._ValueList
[1] = TokenList2
[1] # keys
360 self
._ValueList
[1] = TokenList
[0]
361 if len(TokenList
) == 2 and type(self
) != DscParser
: # value
362 self
._ValueList
[2] = ReplaceMacro(TokenList
[1], self
._Macros
)
364 if self
._ValueList
[1].count('_') != 4:
368 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
369 ExtraData
=self
._CurrentLine
,
371 Line
=self
._LineIndex
+ 1
374 def _GetMacros(self
):
376 Macros
.update(self
._FileLocalMacros
)
377 Macros
.update(self
._GetApplicableSectionMacro
())
380 ## Construct section Macro dict
381 def _ConstructSectionMacroDict(self
, Name
, Value
):
382 ScopeKey
= [(Scope
[0], Scope
[1]) for Scope
in self
._Scope
]
383 ScopeKey
= tuple(ScopeKey
)
384 SectionDictKey
= self
._SectionType
, ScopeKey
386 # DecParser SectionType is a list, will contain more than one item only in Pcd Section
387 # As Pcd section macro usage is not alllowed, so here it is safe
389 if type(self
) == DecParser
:
390 SectionDictKey
= self
._SectionType
[0], ScopeKey
391 if SectionDictKey
not in self
._SectionsMacroDict
:
392 self
._SectionsMacroDict
[SectionDictKey
] = {}
393 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
394 SectionLocalMacros
[Name
] = Value
396 ## Get section Macros that are applicable to current line, which may come from other sections
397 ## that share the same name while scope is wider
398 def _GetApplicableSectionMacro(self
):
405 ActiveSectionType
= self
._SectionType
406 if type(self
) == DecParser
:
407 ActiveSectionType
= self
._SectionType
[0]
409 for (SectionType
, Scope
) in self
._SectionsMacroDict
:
410 if SectionType
!= ActiveSectionType
:
413 for ActiveScope
in self
._Scope
:
414 Scope0
, Scope1
= ActiveScope
[0], ActiveScope
[1]
415 if(Scope0
, Scope1
) not in Scope
:
418 SpeSpeMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
420 for ActiveScope
in self
._Scope
:
421 Scope0
, Scope1
= ActiveScope
[0], ActiveScope
[1]
422 if(Scope0
, Scope1
) not in Scope
and (Scope0
, "COMMON") not in Scope
and ("COMMON", Scope1
) not in Scope
:
425 ComSpeMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
427 if ("COMMON", "COMMON") in Scope
:
428 ComComMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
430 Macros
.update(ComComMacroDict
)
431 Macros
.update(ComSpeMacroDict
)
432 Macros
.update(SpeSpeMacroDict
)
437 Finished
= property(_GetFinished
, _SetFinished
)
438 _Macros
= property(_GetMacros
)
441 ## INF file parser class
443 # @param FilePath The path of platform description file
444 # @param FileType The raw data of DSC file
445 # @param Table Database used to retrieve module/package information
446 # @param Macros Macros used for replacement in file
448 class InfParser(MetaFileParser
):
449 # INF file supported data types (one type per section)
451 TAB_UNKNOWN
.upper() : MODEL_UNKNOWN
,
452 TAB_INF_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
453 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
454 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
455 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
456 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
457 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
458 TAB_PACKAGES
.upper() : MODEL_META_DATA_PACKAGE
,
459 TAB_NMAKE
.upper() : MODEL_META_DATA_NMAKE
,
460 TAB_INF_FIXED_PCD
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
461 TAB_INF_PATCH_PCD
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
462 TAB_INF_FEATURE_PCD
.upper() : MODEL_PCD_FEATURE_FLAG
,
463 TAB_INF_PCD_EX
.upper() : MODEL_PCD_DYNAMIC_EX
,
464 TAB_INF_PCD
.upper() : MODEL_PCD_DYNAMIC
,
465 TAB_SOURCES
.upper() : MODEL_EFI_SOURCE_FILE
,
466 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
467 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
468 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
469 TAB_DEPEX
.upper() : MODEL_EFI_DEPEX
,
470 TAB_BINARIES
.upper() : MODEL_EFI_BINARY_FILE
,
471 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
474 ## Constructor of InfParser
476 # Initialize object of InfParser
478 # @param FilePath The path of module description file
479 # @param FileType The raw data of DSC file
480 # @param Table Database used to retrieve module/package information
481 # @param Macros Macros used for replacement in file
483 def __init__(self
, FilePath
, FileType
, Table
):
484 # prevent re-initialization
485 if hasattr(self
, "_Table"):
487 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
495 Content
= open(str(self
.MetaFile
), 'r').readlines()
497 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
499 # parse the file line by line
500 IsFindBlockComment
= False
501 GetHeaderComment
= False
506 for Index
in range(0, len(Content
)):
507 # skip empty, commented, block commented lines
508 Line
, Comment
= CleanString2(Content
[Index
], AllowCppStyleComment
=True)
510 if Index
+ 1 < len(Content
):
511 NextLine
, NextComment
= CleanString2(Content
[Index
+ 1])
514 Comments
.append((Comment
, Index
+ 1))
515 elif GetHeaderComment
:
516 SectionComments
.extend(Comments
)
519 if Line
.find(DataType
.TAB_COMMENT_EDK_START
) > -1:
520 IsFindBlockComment
= True
522 if Line
.find(DataType
.TAB_COMMENT_EDK_END
) > -1:
523 IsFindBlockComment
= False
525 if IsFindBlockComment
:
528 self
._LineIndex
= Index
529 self
._CurrentLine
= Line
532 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
533 if not GetHeaderComment
:
534 for Cmt
, LNo
in Comments
:
535 self
._Store
(MODEL_META_DATA_HEADER_COMMENT
, Cmt
, '', '', 'COMMON',
536 'COMMON', self
._Owner
[-1], LNo
, -1, LNo
, -1, 0)
537 GetHeaderComment
= True
539 TailComments
.extend(SectionComments
+ Comments
)
541 self
._SectionHeaderParser
()
542 # Check invalid sections
543 if self
._Version
< 0x00010005:
544 if self
._SectionType
in [MODEL_META_DATA_BUILD_OPTION
,
545 MODEL_EFI_LIBRARY_CLASS
,
546 MODEL_META_DATA_PACKAGE
,
547 MODEL_PCD_FIXED_AT_BUILD
,
548 MODEL_PCD_PATCHABLE_IN_MODULE
,
549 MODEL_PCD_FEATURE_FLAG
,
550 MODEL_PCD_DYNAMIC_EX
,
555 MODEL_META_DATA_USER_EXTENSION
]:
556 EdkLogger
.error('Parser', FORMAT_INVALID
,
557 "Section [%s] is not allowed in inf file without version" % (self
._SectionName
),
558 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
559 elif self
._SectionType
in [MODEL_EFI_INCLUDE
,
560 MODEL_EFI_LIBRARY_INSTANCE
,
561 MODEL_META_DATA_NMAKE
]:
562 EdkLogger
.error('Parser', FORMAT_INVALID
,
563 "Section [%s] is not allowed in inf file with version 0x%08x" % (self
._SectionName
, self
._Version
),
564 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
566 # merge two lines specified by '\' in section NMAKE
567 elif self
._SectionType
== MODEL_META_DATA_NMAKE
:
570 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
573 if NextLine
[0] == TAB_SECTION_START
and NextLine
[-1] == TAB_SECTION_END
:
574 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
577 NmakeLine
= NmakeLine
+ ' ' + Line
[0:-1]
580 self
._CurrentLine
= NmakeLine
+ Line
584 self
._ValueList
= ['', '', '']
585 # parse current line, result will be put in self._ValueList
586 self
._SectionParser
[self
._SectionType
](self
)
587 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
592 Comments
.append((Comment
, Index
+ 1))
594 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
595 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
597 for Arch
, Platform
in self
._Scope
:
598 LastItem
= self
._Store
(self
._SectionType
,
611 for Comment
, LineNo
in Comments
:
612 self
._Store
(MODEL_META_DATA_COMMENT
, Comment
, '', '', Arch
, Platform
,
613 LastItem
, LineNo
, -1, LineNo
, -1, 0)
616 TailComments
.extend(SectionComments
+ Comments
)
617 if IsFindBlockComment
:
618 EdkLogger
.error("Parser", FORMAT_INVALID
, "Open block comments (starting with /*) are expected to end with */",
621 # If there are tail comments in INF file, save to database whatever the comments are
622 for Comment
in TailComments
:
623 self
._Store
(MODEL_META_DATA_TAIL_COMMENT
, Comment
[0], '', '', 'COMMON',
624 'COMMON', self
._Owner
[-1], -1, -1, -1, -1, 0)
627 ## Data parser for the format in which there's path
629 # Only path can have macro used. So we need to replace them before use.
631 def _IncludeParser(self
):
632 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
633 self
._ValueList
[0:len(TokenList
)] = TokenList
634 Macros
= self
._Macros
636 for Index
in range(0, len(self
._ValueList
)):
637 Value
= self
._ValueList
[Index
]
641 if Value
.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value
.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
642 Value
= '$(EDK_SOURCE)' + Value
[17:]
643 if Value
.find('$(EFI_SOURCE)') > -1 or Value
.find('$(EDK_SOURCE)') > -1:
645 elif Value
.startswith('.'):
647 elif Value
.startswith('$('):
650 Value
= '$(EFI_SOURCE)/' + Value
652 self
._ValueList
[Index
] = ReplaceMacro(Value
, Macros
)
654 ## Parse [Sources] section
656 # Only path can have macro used. So we need to replace them before use.
659 def _SourceFileParser(self
):
660 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
661 self
._ValueList
[0:len(TokenList
)] = TokenList
662 Macros
= self
._Macros
663 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
664 if 'COMPONENT_TYPE' in Macros
:
665 if self
._Defines
['COMPONENT_TYPE'].upper() == 'ACPITABLE':
666 self
._ValueList
[0] = GetSplitValueList(self
._ValueList
[0], ' ', 1)[0]
667 if self
._Defines
['BASE_NAME'] == 'Microcode':
669 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
671 ## Parse [Binaries] section
673 # Only path can have macro used. So we need to replace them before use.
676 def _BinaryFileParser(self
):
677 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 2)
678 if len(TokenList
) < 2:
679 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type or path specified",
680 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
681 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
683 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type specified",
684 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
685 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
687 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file path specified",
688 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
689 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
690 self
._ValueList
[0:len(TokenList
)] = TokenList
691 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
693 ## [nmake] section parser (Edk.x style only)
694 def _NmakeParser(self
):
695 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
696 self
._ValueList
[0:len(TokenList
)] = TokenList
698 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
699 # remove self-reference in macro setting
700 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
702 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
704 def _PcdParser(self
):
705 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
706 ValueList
= GetSplitValueList(TokenList
[0], TAB_SPLIT
)
707 if len(ValueList
) != 2:
708 EdkLogger
.error('Parser', FORMAT_INVALID
, "Illegal token space GUID and PCD name format",
709 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
710 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
711 self
._ValueList
[0:1] = ValueList
712 if len(TokenList
) > 1:
713 self
._ValueList
[2] = TokenList
[1]
714 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
715 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
716 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
717 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
719 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
720 if self
._ValueList
[2] != '':
721 InfPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
722 if InfPcdValueList
[0] in ['True', 'true', 'TRUE']:
723 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '1', 1);
724 elif InfPcdValueList
[0] in ['False', 'false', 'FALSE']:
725 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '0', 1);
726 if (self
._ValueList
[0], self
._ValueList
[1]) not in self
.PcdsDict
:
727 self
.PcdsDict
[self
._ValueList
[0], self
._ValueList
[1]] = self
._SectionType
728 elif self
.PcdsDict
[self
._ValueList
[0], self
._ValueList
[1]] != self
._SectionType
:
729 EdkLogger
.error('Parser', FORMAT_INVALID
, "It is not permissible to list a specified PCD in different PCD type sections.",
730 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
731 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
733 ## [depex] section parser
735 def _DepexParser(self
):
736 self
._ValueList
[0:1] = [self
._CurrentLine
]
739 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
740 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
741 MODEL_META_DATA_BUILD_OPTION
: MetaFileParser
._BuildOptionParser
,
742 MODEL_EFI_INCLUDE
: _IncludeParser
, # for Edk.x modules
743 MODEL_EFI_LIBRARY_INSTANCE
: MetaFileParser
._CommonParser
, # for Edk.x modules
744 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
745 MODEL_META_DATA_PACKAGE
: MetaFileParser
._PathParser
,
746 MODEL_META_DATA_NMAKE
: _NmakeParser
, # for Edk.x modules
747 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
748 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
749 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
750 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
751 MODEL_PCD_DYNAMIC
: _PcdParser
,
752 MODEL_EFI_SOURCE_FILE
: _SourceFileParser
,
753 MODEL_EFI_GUID
: MetaFileParser
._CommonParser
,
754 MODEL_EFI_PROTOCOL
: MetaFileParser
._CommonParser
,
755 MODEL_EFI_PPI
: MetaFileParser
._CommonParser
,
756 MODEL_EFI_DEPEX
: _DepexParser
,
757 MODEL_EFI_BINARY_FILE
: _BinaryFileParser
,
758 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
761 ## DSC file parser class
763 # @param FilePath The path of platform description file
764 # @param FileType The raw data of DSC file
765 # @param Table Database used to retrieve module/package information
766 # @param Macros Macros used for replacement in file
767 # @param Owner Owner ID (for sub-section parsing)
768 # @param From ID from which the data comes (for !INCLUDE directive)
770 class DscParser(MetaFileParser
):
771 # DSC file supported data types (one type per section)
773 TAB_SKUIDS
.upper() : MODEL_EFI_SKU_ID
,
774 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
775 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
776 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
777 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
778 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
779 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
780 TAB_PCDS_DYNAMIC_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_DEFAULT
,
781 TAB_PCDS_DYNAMIC_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_HII
,
782 TAB_PCDS_DYNAMIC_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_VPD
,
783 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT
,
784 TAB_PCDS_DYNAMIC_EX_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_HII
,
785 TAB_PCDS_DYNAMIC_EX_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_VPD
,
786 TAB_COMPONENTS
.upper() : MODEL_META_DATA_COMPONENT
,
787 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH
.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
,
788 TAB_DSC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
789 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
790 TAB_DSC_DEFINES_EDKGLOBAL
: MODEL_META_DATA_GLOBAL_DEFINE
,
791 TAB_INCLUDE
.upper() : MODEL_META_DATA_INCLUDE
,
792 TAB_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
793 TAB_IF_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
794 TAB_IF_N_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
,
795 TAB_ELSE_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
,
796 TAB_ELSE
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
797 TAB_END_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
,
800 # Valid names in define section
807 "PCD_INFO_GENERATION",
808 "SUPPORTED_ARCHITECTURES",
817 "FIX_LOAD_TOP_MEMORY_ADDRESS"
820 SymbolPattern
= ValueExpression
.SymbolPattern
822 ## Constructor of DscParser
824 # Initialize object of DscParser
826 # @param FilePath The path of platform description file
827 # @param FileType The raw data of DSC file
828 # @param Table Database used to retrieve module/package information
829 # @param Macros Macros used for replacement in file
830 # @param Owner Owner ID (for sub-section parsing)
831 # @param From ID from which the data comes (for !INCLUDE directive)
833 def __init__(self
, FilePath
, FileType
, Table
, Owner
= -1, From
= -1):
834 # prevent re-initialization
835 if hasattr(self
, "_Table"):
837 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, Owner
, From
)
838 self
._Version
= 0x00010005 # Only EDK2 dsc file is supported
839 # to store conditional directive evaluation result
840 self
._DirectiveStack
= []
841 self
._DirectiveEvalStack
= []
845 # Specify whether current line is in uncertain condition
847 self
._InDirective
= -1
849 # Final valid replacable symbols
852 # Map the ID between the original table and new table to track
855 self
._IdMapping
= {-1:-1}
861 Content
= open(str(self
.MetaFile
), 'r').readlines()
863 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
866 for Index
in range(0, len(Content
)):
867 Line
= CleanString(Content
[Index
])
872 self
._CurrentLine
= Line
873 self
._LineIndex
= Index
874 if self
._InSubsection
and self
._Owner
[-1] == -1:
875 self
._Owner
.append(self
._LastItem
)
878 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
879 self
._SectionType
= MODEL_META_DATA_SECTION_HEADER
881 elif Line
[0] == '}' and self
._InSubsection
:
882 self
._InSubsection
= False
883 self
._SubsectionType
= MODEL_UNKNOWN
884 self
._SubsectionName
= ''
889 elif Line
[0] == TAB_OPTION_START
and Line
[-1] == TAB_OPTION_END
:
890 self
._SubsectionType
= MODEL_META_DATA_SUBSECTION_HEADER
893 self
._DirectiveParser
()
896 if self
._InSubsection
:
897 SectionType
= self
._SubsectionType
899 SectionType
= self
._SectionType
900 self
._ItemType
= SectionType
902 self
._ValueList
= ['', '', '']
903 self
._SectionParser
[SectionType
](self
)
904 if self
._ValueList
== None:
907 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
908 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
910 for Arch
, ModuleType
in self
._Scope
:
911 Owner
= self
._Owner
[-1]
912 if self
._SubsectionType
!= MODEL_UNKNOWN
:
913 Owner
= OwnerId
[Arch
]
914 self
._LastItem
= self
._Store
(
929 if self
._SubsectionType
== MODEL_UNKNOWN
and self
._InSubsection
:
930 OwnerId
[Arch
] = self
._LastItem
932 if self
._DirectiveStack
:
933 Type
, Line
, Text
= self
._DirectiveStack
[-1]
934 EdkLogger
.error('Parser', FORMAT_INVALID
, "No matching '!endif' found",
935 ExtraData
=Text
, File
=self
.MetaFile
, Line
=Line
)
938 ## <subsection_header> parser
939 def _SubsectionHeaderParser(self
):
940 self
._SubsectionName
= self
._CurrentLine
[1:-1].upper()
941 if self
._SubsectionName
in self
.DataType
:
942 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
944 self
._SubsectionType
= MODEL_UNKNOWN
945 EdkLogger
.warn("Parser", "Unrecognized sub-section", File
=self
.MetaFile
,
946 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
947 self
._ValueList
[0] = self
._SubsectionName
949 ## Directive statement parser
950 def _DirectiveParser(self
):
951 self
._ValueList
= ['', '', '']
952 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
953 self
._ValueList
[0:len(TokenList
)] = TokenList
956 DirectiveName
= self
._ValueList
[0].upper()
957 if DirectiveName
not in self
.DataType
:
958 EdkLogger
.error("Parser", FORMAT_INVALID
, "Unknown directive [%s]" % DirectiveName
,
959 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
961 if DirectiveName
in ['!IF', '!IFDEF', '!IFNDEF']:
962 self
._InDirective
+= 1
964 if DirectiveName
in ['!ENDIF']:
965 self
._InDirective
-= 1
967 if DirectiveName
in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self
._ValueList
[1] == '':
968 EdkLogger
.error("Parser", FORMAT_INVALID
, "Missing expression",
969 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
970 ExtraData
=self
._CurrentLine
)
972 ItemType
= self
.DataType
[DirectiveName
]
973 Scope
= [['COMMON', 'COMMON']]
974 if ItemType
== MODEL_META_DATA_INCLUDE
:
976 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
977 # Remove all directives between !if and !endif, including themselves
978 while self
._DirectiveStack
:
979 # Remove any !else or !elseif
980 DirectiveInfo
= self
._DirectiveStack
.pop()
981 if DirectiveInfo
[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
982 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
983 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
986 EdkLogger
.error("Parser", FORMAT_INVALID
, "Redundant '!endif'",
987 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
988 ExtraData
=self
._CurrentLine
)
989 elif ItemType
!= MODEL_META_DATA_INCLUDE
:
990 # Break if there's a !else is followed by a !elseif
991 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
and \
992 self
._DirectiveStack
and \
993 self
._DirectiveStack
[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
994 EdkLogger
.error("Parser", FORMAT_INVALID
, "'!elseif' after '!else'",
995 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
996 ExtraData
=self
._CurrentLine
)
997 self
._DirectiveStack
.append((ItemType
, self
._LineIndex
+ 1, self
._CurrentLine
))
999 EdkLogger
.error('Parser', FORMAT_INVALID
,
1000 "No '!include' allowed in included file",
1001 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
,
1002 Line
=self
._LineIndex
+ 1)
1005 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
1006 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
1008 for Arch
, ModuleType
in Scope
:
1009 self
._LastItem
= self
._Store
(
1018 self
._LineIndex
+ 1,
1020 self
._LineIndex
+ 1,
1025 ## [defines] section parser
1027 def _DefineParser(self
):
1028 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1029 self
._ValueList
[1:len(TokenList
)] = TokenList
1032 if not self
._ValueList
[1]:
1033 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
1034 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1035 if not self
._ValueList
[2]:
1036 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
1037 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1038 if not self
._ValueList
[1] in self
.DefineKeywords
:
1039 EdkLogger
.error('Parser', FORMAT_INVALID
,
1040 "Unknown keyword found: %s. "
1041 "If this is a macro you must "
1042 "add it as a DEFINE in the DSC" % self
._ValueList
[1],
1043 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1044 self
._Defines
[self
._ValueList
[1]] = self
._ValueList
[2]
1045 self
._ItemType
= self
.DataType
[TAB_DSC_DEFINES
.upper()]
1048 def _SkuIdParser(self
):
1049 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1050 if len(TokenList
) != 2:
1051 EdkLogger
.error('Parser', FORMAT_INVALID
, "Correct format is '<Integer>|<UiName>'",
1052 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1053 self
._ValueList
[0:len(TokenList
)] = TokenList
1055 ## Parse Edk style of library modules
1057 def _LibraryInstanceParser(self
):
1058 self
._ValueList
[0] = self
._CurrentLine
1060 ## PCD sections parser
1062 # [PcdsFixedAtBuild]
1063 # [PcdsPatchableInModule]
1066 # [PcdsDynamicExDefault]
1067 # [PcdsDynamicExVpd]
1068 # [PcdsDynamicExHii]
1070 # [PcdsDynamicDefault]
1075 def _PcdParser(self
):
1076 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1077 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1078 if len(TokenList
) == 2:
1079 self
._ValueList
[2] = TokenList
[1]
1080 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1081 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1082 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1083 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1084 if self
._ValueList
[2] == '':
1086 # The PCD values are optional for FIXEDATBUILD and PATCHABLEINMODULE
1088 if self
._SectionType
in (MODEL_PCD_FIXED_AT_BUILD
, MODEL_PCD_PATCHABLE_IN_MODULE
):
1090 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD value given",
1091 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1092 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1094 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD
1095 ValueList
= GetSplitValueList(self
._ValueList
[2])
1096 if len(ValueList
) > 1 and ValueList
[1] != TAB_VOID \
1097 and self
._ItemType
in [MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_EX_DEFAULT
]:
1098 EdkLogger
.error('Parser', FORMAT_INVALID
, "The datum type '%s' of PCD is wrong" % ValueList
[1],
1099 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1101 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1102 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
1103 if DscPcdValueList
[0] in ['True', 'true', 'TRUE']:
1104 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '1', 1);
1105 elif DscPcdValueList
[0] in ['False', 'false', 'FALSE']:
1106 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '0', 1);
1109 ## [components] section parser
1111 def _ComponentParser(self
):
1112 if self
._CurrentLine
[-1] == '{':
1113 self
._ValueList
[0] = self
._CurrentLine
[0:-1].strip()
1114 self
._InSubsection
= True
1116 self
._ValueList
[0] = self
._CurrentLine
1118 ## [LibraryClasses] section
1120 def _LibraryClassParser(self
):
1121 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1122 if len(TokenList
) < 2:
1123 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class or instance specified",
1124 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1125 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1126 if TokenList
[0] == '':
1127 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class specified",
1128 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1129 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1130 if TokenList
[1] == '':
1131 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library instance specified",
1132 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1133 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1135 self
._ValueList
[0:len(TokenList
)] = TokenList
1137 def _CompponentSourceOverridePathParser(self
):
1138 self
._ValueList
[0] = self
._CurrentLine
1140 ## [BuildOptions] section parser
1142 def _BuildOptionParser(self
):
1143 self
._CurrentLine
= CleanString(self
._CurrentLine
, BuildOption
=True)
1144 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1145 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
1146 if len(TokenList2
) == 2:
1147 self
._ValueList
[0] = TokenList2
[0] # toolchain family
1148 self
._ValueList
[1] = TokenList2
[1] # keys
1150 self
._ValueList
[1] = TokenList
[0]
1151 if len(TokenList
) == 2: # value
1152 self
._ValueList
[2] = TokenList
[1]
1154 if self
._ValueList
[1].count('_') != 4:
1158 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
1159 ExtraData
=self
._CurrentLine
,
1161 Line
=self
._LineIndex
+ 1
1164 ## Override parent's method since we'll do all macro replacements in parser
1165 def _GetMacros(self
):
1167 Macros
.update(self
._FileLocalMacros
)
1168 Macros
.update(self
._GetApplicableSectionMacro
())
1169 Macros
.update(GlobalData
.gEdkGlobal
)
1170 Macros
.update(GlobalData
.gPlatformDefines
)
1171 Macros
.update(GlobalData
.gCommandLineDefines
)
1172 # PCD cannot be referenced in macro definition
1173 if self
._ItemType
not in [MODEL_META_DATA_DEFINE
, MODEL_META_DATA_GLOBAL_DEFINE
]:
1174 Macros
.update(self
._Symbols
)
1177 def _PostProcess(self
):
1179 MODEL_META_DATA_SECTION_HEADER
: self
.__ProcessSectionHeader
,
1180 MODEL_META_DATA_SUBSECTION_HEADER
: self
.__ProcessSubsectionHeader
,
1181 MODEL_META_DATA_HEADER
: self
.__ProcessDefine
,
1182 MODEL_META_DATA_DEFINE
: self
.__ProcessDefine
,
1183 MODEL_META_DATA_GLOBAL_DEFINE
: self
.__ProcessDefine
,
1184 MODEL_META_DATA_INCLUDE
: self
.__ProcessDirective
,
1185 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
: self
.__ProcessDirective
,
1186 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
: self
.__ProcessDirective
,
1187 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
: self
.__ProcessDirective
,
1188 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
: self
.__ProcessDirective
,
1189 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
: self
.__ProcessDirective
,
1190 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
: self
.__ProcessDirective
,
1191 MODEL_EFI_SKU_ID
: self
.__ProcessSkuId
,
1192 MODEL_EFI_LIBRARY_INSTANCE
: self
.__ProcessLibraryInstance
,
1193 MODEL_EFI_LIBRARY_CLASS
: self
.__ProcessLibraryClass
,
1194 MODEL_PCD_FIXED_AT_BUILD
: self
.__ProcessPcd
,
1195 MODEL_PCD_PATCHABLE_IN_MODULE
: self
.__ProcessPcd
,
1196 MODEL_PCD_FEATURE_FLAG
: self
.__ProcessPcd
,
1197 MODEL_PCD_DYNAMIC_DEFAULT
: self
.__ProcessPcd
,
1198 MODEL_PCD_DYNAMIC_HII
: self
.__ProcessPcd
,
1199 MODEL_PCD_DYNAMIC_VPD
: self
.__ProcessPcd
,
1200 MODEL_PCD_DYNAMIC_EX_DEFAULT
: self
.__ProcessPcd
,
1201 MODEL_PCD_DYNAMIC_EX_HII
: self
.__ProcessPcd
,
1202 MODEL_PCD_DYNAMIC_EX_VPD
: self
.__ProcessPcd
,
1203 MODEL_META_DATA_COMPONENT
: self
.__ProcessComponent
,
1204 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: self
.__ProcessSourceOverridePath
,
1205 MODEL_META_DATA_BUILD_OPTION
: self
.__ProcessBuildOption
,
1206 MODEL_UNKNOWN
: self
._Skip
,
1207 MODEL_META_DATA_USER_EXTENSION
: self
._Skip
,
1210 self
._Table
= MetaFileStorage(self
._RawTable
.Cur
, self
.MetaFile
, MODEL_FILE_DSC
, True)
1211 self
._Table
.Create()
1212 self
._DirectiveStack
= []
1213 self
._DirectiveEvalStack
= []
1214 self
._FileWithError
= self
.MetaFile
1215 self
._FileLocalMacros
= {}
1216 self
._SectionsMacroDict
= {}
1217 GlobalData
.gPlatformDefines
= {}
1219 # Get all macro and PCD which has straitforward value
1220 self
.__RetrievePcdValue
()
1221 self
._Content
= self
._RawTable
.GetAll()
1222 self
._ContentIndex
= 0
1223 while self
._ContentIndex
< len(self
._Content
) :
1224 Id
, self
._ItemType
, V1
, V2
, V3
, S1
, S2
, Owner
, self
._From
, \
1225 LineStart
, ColStart
, LineEnd
, ColEnd
, Enabled
= self
._Content
[self
._ContentIndex
]
1228 self
._FileWithError
= self
.MetaFile
1230 self
._ContentIndex
+= 1
1232 self
._Scope
= [[S1
, S2
]]
1234 # For !include directive, handle it specially,
1235 # merge arch and module type in case of duplicate items
1237 while self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1238 if self
._ContentIndex
>= len(self
._Content
):
1240 Record
= self
._Content
[self
._ContentIndex
]
1241 if LineStart
== Record
[9] and LineEnd
== Record
[11]:
1242 if [Record
[5], Record
[6]] not in self
._Scope
:
1243 self
._Scope
.append([Record
[5], Record
[6]])
1244 self
._ContentIndex
+= 1
1248 self
._LineIndex
= LineStart
- 1
1249 self
._ValueList
= [V1
, V2
, V3
]
1252 Processer
[self
._ItemType
]()
1253 except EvaluationException
, Excpt
:
1255 # Only catch expression evaluation error here. We need to report
1256 # the precise number of line on which the error occurred
1258 if hasattr(Excpt
, 'Pcd'):
1259 if Excpt
.Pcd
in GlobalData
.gPlatformOtherPcds
:
1260 Info
= GlobalData
.gPlatformOtherPcds
[Excpt
.Pcd
]
1261 EdkLogger
.error('Parser', FORMAT_INVALID
, "Cannot use this PCD (%s) in an expression as"
1262 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
1263 " of the DSC file, and it is currently defined in this section:"
1264 " %s, line #: %d." % (Excpt
.Pcd
, Info
[0], Info
[1]),
1265 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1266 Line
=self
._LineIndex
+ 1)
1268 EdkLogger
.error('Parser', FORMAT_INVALID
, "PCD (%s) is not defined in DSC file" % Excpt
.Pcd
,
1269 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1270 Line
=self
._LineIndex
+ 1)
1272 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid expression: %s" % str(Excpt
),
1273 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1274 Line
=self
._LineIndex
+ 1)
1275 except MacroException
, Excpt
:
1276 EdkLogger
.error('Parser', FORMAT_INVALID
, str(Excpt
),
1277 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1278 Line
=self
._LineIndex
+ 1)
1280 if self
._ValueList
== None:
1283 NewOwner
= self
._IdMapping
.get(Owner
, -1)
1284 self
._Enabled
= int((not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
))
1285 self
._LastItem
= self
._Store
(
1294 self
._LineIndex
+ 1,
1296 self
._LineIndex
+ 1,
1300 self
._IdMapping
[Id
] = self
._LastItem
1302 GlobalData
.gPlatformDefines
.update(self
._FileLocalMacros
)
1303 self
._PostProcessed
= True
1304 self
._Content
= None
1306 def __ProcessSectionHeader(self
):
1307 self
._SectionName
= self
._ValueList
[0]
1308 if self
._SectionName
in self
.DataType
:
1309 self
._SectionType
= self
.DataType
[self
._SectionName
]
1311 self
._SectionType
= MODEL_UNKNOWN
1313 def __ProcessSubsectionHeader(self
):
1314 self
._SubsectionName
= self
._ValueList
[0]
1315 if self
._SubsectionName
in self
.DataType
:
1316 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
1318 self
._SubsectionType
= MODEL_UNKNOWN
1320 def __RetrievePcdValue(self
):
1321 Records
= self
._RawTable
.Query(MODEL_PCD_FEATURE_FLAG
, BelongsToItem
= -1.0)
1322 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1323 Name
= TokenSpaceGuid
+ '.' + PcdName
1324 ValList
, Valid
, Index
= AnalyzeDscPcd(Value
, MODEL_PCD_FEATURE_FLAG
)
1325 self
._Symbols
[Name
] = ValList
[Index
]
1327 Records
= self
._RawTable
.Query(MODEL_PCD_FIXED_AT_BUILD
, BelongsToItem
= -1.0)
1328 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1329 Name
= TokenSpaceGuid
+ '.' + PcdName
1330 ValList
, Valid
, Index
= AnalyzeDscPcd(Value
, MODEL_PCD_FIXED_AT_BUILD
)
1331 self
._Symbols
[Name
] = ValList
[Index
]
1333 Content
= open(str(self
.MetaFile
), 'r').readlines()
1334 GlobalData
.gPlatformOtherPcds
['DSCFILE'] = str(self
.MetaFile
)
1335 for PcdType
in (MODEL_PCD_PATCHABLE_IN_MODULE
, MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_HII
,
1336 MODEL_PCD_DYNAMIC_VPD
, MODEL_PCD_DYNAMIC_EX_DEFAULT
, MODEL_PCD_DYNAMIC_EX_HII
,
1337 MODEL_PCD_DYNAMIC_EX_VPD
):
1338 Records
= self
._RawTable
.Query(PcdType
, BelongsToItem
= -1.0)
1339 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1340 Name
= TokenSpaceGuid
+ '.' + PcdName
1341 if Name
not in GlobalData
.gPlatformOtherPcds
:
1343 while not Content
[Line
- 1].lstrip().startswith(TAB_SECTION_START
):
1345 GlobalData
.gPlatformOtherPcds
[Name
] = (CleanString(Content
[Line
- 1]), PcdLine
, PcdType
)
1347 def __ProcessDefine(self
):
1348 if not self
._Enabled
:
1351 Type
, Name
, Value
= self
._ValueList
1352 Value
= ReplaceMacro(Value
, self
._Macros
, False)
1353 if self
._ItemType
== MODEL_META_DATA_DEFINE
:
1354 if self
._SectionType
== MODEL_META_DATA_HEADER
:
1355 self
._FileLocalMacros
[Name
] = Value
1357 self
._ConstructSectionMacroDict
(Name
, Value
)
1358 elif self
._ItemType
== MODEL_META_DATA_GLOBAL_DEFINE
:
1359 GlobalData
.gEdkGlobal
[Name
] = Value
1362 # Keyword in [Defines] section can be used as Macros
1364 if (self
._ItemType
== MODEL_META_DATA_HEADER
) and (self
._SectionType
== MODEL_META_DATA_HEADER
):
1365 self
._FileLocalMacros
[Name
] = Value
1367 self
._ValueList
= [Type
, Name
, Value
]
1369 def __ProcessDirective(self
):
1371 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1372 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
]:
1373 Macros
= self
._Macros
1374 Macros
.update(GlobalData
.gGlobalDefines
)
1376 Result
= ValueExpression(self
._ValueList
[1], Macros
)()
1377 except SymbolNotFound
, Exc
:
1378 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1380 except WrnExpression
, Excpt
:
1382 # Catch expression evaluation warning here. We need to report
1383 # the precise number of line and return the evaluation result
1385 EdkLogger
.warn('Parser', "Suspicious expression: %s" % str(Excpt
),
1386 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1387 Line
=self
._LineIndex
+ 1)
1388 Result
= Excpt
.result
1390 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1391 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1392 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1393 self
._DirectiveStack
.append(self
._ItemType
)
1394 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
:
1395 Result
= bool(Result
)
1397 Macro
= self
._ValueList
[1]
1398 Macro
= Macro
[2:-1] if (Macro
.startswith("$(") and Macro
.endswith(")")) else Macro
1399 Result
= Macro
in self
._Macros
1400 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
:
1402 self
._DirectiveEvalStack
.append(Result
)
1403 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
:
1404 self
._DirectiveStack
.append(self
._ItemType
)
1405 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1406 self
._DirectiveEvalStack
.append(bool(Result
))
1407 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1408 self
._DirectiveStack
.append(self
._ItemType
)
1409 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1410 self
._DirectiveEvalStack
.append(True)
1411 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1412 # Back to the nearest !if/!ifdef/!ifndef
1413 while self
._DirectiveStack
:
1414 self
._DirectiveEvalStack
.pop()
1415 Directive
= self
._DirectiveStack
.pop()
1416 if Directive
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1417 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1418 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1420 elif self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1421 # The included file must be relative to workspace or same directory as DSC file
1422 __IncludeMacros
= {}
1424 # Allow using system environment variables in path after !include
1426 __IncludeMacros
['WORKSPACE'] = GlobalData
.gGlobalDefines
['WORKSPACE']
1427 if "ECP_SOURCE" in GlobalData
.gGlobalDefines
.keys():
1428 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gGlobalDefines
['ECP_SOURCE']
1430 # During GenFds phase call DSC parser, will go into this branch.
1432 elif "ECP_SOURCE" in GlobalData
.gCommandLineDefines
.keys():
1433 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gCommandLineDefines
['ECP_SOURCE']
1435 __IncludeMacros
['EFI_SOURCE'] = GlobalData
.gGlobalDefines
['EFI_SOURCE']
1436 __IncludeMacros
['EDK_SOURCE'] = GlobalData
.gGlobalDefines
['EDK_SOURCE']
1438 # Allow using MACROs comes from [Defines] section to keep compatible.
1440 __IncludeMacros
.update(self
._Macros
)
1442 IncludedFile
= NormPath(ReplaceMacro(self
._ValueList
[1], __IncludeMacros
, RaiseError
=True))
1444 # First search the include file under the same directory as DSC file
1446 IncludedFile1
= PathClass(IncludedFile
, self
.MetaFile
.Dir
)
1447 ErrorCode
, ErrorInfo1
= IncludedFile1
.Validate()
1450 # Also search file under the WORKSPACE directory
1452 IncludedFile1
= PathClass(IncludedFile
, GlobalData
.gWorkspace
)
1453 ErrorCode
, ErrorInfo2
= IncludedFile1
.Validate()
1455 EdkLogger
.error('parser', ErrorCode
, File
=self
._FileWithError
,
1456 Line
=self
._LineIndex
+ 1, ExtraData
=ErrorInfo1
+ "\n" + ErrorInfo2
)
1458 self
._FileWithError
= IncludedFile1
1460 IncludedFileTable
= MetaFileStorage(self
._Table
.Cur
, IncludedFile1
, MODEL_FILE_DSC
, False)
1461 Owner
= self
._Content
[self
._ContentIndex
- 1][0]
1462 Parser
= DscParser(IncludedFile1
, self
._FileType
, IncludedFileTable
,
1463 Owner
=Owner
, From
=Owner
)
1465 # set the parser status with current status
1466 Parser
._SectionName
= self
._SectionName
1467 Parser
._SectionType
= self
._SectionType
1468 Parser
._Scope
= self
._Scope
1469 Parser
._Enabled
= self
._Enabled
1470 # Parse the included file
1473 # update current status with sub-parser's status
1474 self
._SectionName
= Parser
._SectionName
1475 self
._SectionType
= Parser
._SectionType
1476 self
._Scope
= Parser
._Scope
1477 self
._Enabled
= Parser
._Enabled
1479 # Insert all records in the table for the included file into dsc file table
1480 Records
= IncludedFileTable
.GetAll()
1482 self
._Content
[self
._ContentIndex
:self
._ContentIndex
] = Records
1483 self
._Content
.pop(self
._ContentIndex
- 1)
1484 self
._ValueList
= None
1485 self
._ContentIndex
-= 1
1487 def __ProcessSkuId(self
):
1488 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=True)
1489 for Value
in self
._ValueList
]
1491 def __ProcessLibraryInstance(self
):
1492 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
1494 def __ProcessLibraryClass(self
):
1495 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, RaiseError
=True)
1497 def __ProcessPcd(self
):
1498 if self
._ItemType
not in [MODEL_PCD_FEATURE_FLAG
, MODEL_PCD_FIXED_AT_BUILD
]:
1499 self
._ValueList
[2] = ReplaceMacro(self
._ValueList
[2], self
._Macros
, RaiseError
=True)
1502 ValList
, Valid
, Index
= AnalyzeDscPcd(self
._ValueList
[2], self
._ItemType
)
1504 EdkLogger
.error('build', FORMAT_INVALID
, "Pcd format incorrect.", File
=self
._FileWithError
, Line
=self
._LineIndex
+1,
1505 ExtraData
="%s.%s|%s" % (self
._ValueList
[0], self
._ValueList
[1], self
._ValueList
[2]))
1506 PcdValue
= ValList
[Index
]
1509 ValList
[Index
] = ValueExpression(PcdValue
, self
._Macros
)(True)
1510 except WrnExpression
, Value
:
1511 ValList
[Index
] = Value
.result
1513 if ValList
[Index
] == 'True':
1514 ValList
[Index
] = '1'
1515 if ValList
[Index
] == 'False':
1516 ValList
[Index
] = '0'
1518 GlobalData
.gPlatformPcds
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = PcdValue
1519 self
._ValueList
[2] = '|'.join(ValList
)
1521 def __ProcessComponent(self
):
1522 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1524 def __ProcessSourceOverridePath(self
):
1525 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1527 def __ProcessBuildOption(self
):
1528 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=False)
1529 for Value
in self
._ValueList
]
1532 MODEL_META_DATA_HEADER
: _DefineParser
,
1533 MODEL_EFI_SKU_ID
: _SkuIdParser
,
1534 MODEL_EFI_LIBRARY_INSTANCE
: _LibraryInstanceParser
,
1535 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
1536 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1537 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1538 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1539 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
1540 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
1541 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
1542 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
1543 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
1544 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
1545 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
1546 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: _CompponentSourceOverridePathParser
,
1547 MODEL_META_DATA_BUILD_OPTION
: _BuildOptionParser
,
1548 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1549 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1550 MODEL_META_DATA_SECTION_HEADER
: MetaFileParser
._SectionHeaderParser
,
1551 MODEL_META_DATA_SUBSECTION_HEADER
: _SubsectionHeaderParser
,
1554 _Macros
= property(_GetMacros
)
1556 ## DEC file parser class
1558 # @param FilePath The path of platform description file
1559 # @param FileType The raw data of DSC file
1560 # @param Table Database used to retrieve module/package information
1561 # @param Macros Macros used for replacement in file
1563 class DecParser(MetaFileParser
):
1564 # DEC file supported data types (one type per section)
1566 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1567 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
1568 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1569 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1570 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1571 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1572 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1573 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1574 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1575 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1576 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1577 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1580 ## Constructor of DecParser
1582 # Initialize object of DecParser
1584 # @param FilePath The path of platform description file
1585 # @param FileType The raw data of DSC file
1586 # @param Table Database used to retrieve module/package information
1587 # @param Macros Macros used for replacement in file
1589 def __init__(self
, FilePath
, FileType
, Table
):
1590 # prevent re-initialization
1591 if hasattr(self
, "_Table"):
1593 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, -1)
1595 self
._Version
= 0x00010005 # Only EDK2 dec file is supported
1596 self
._AllPCDs
= [] # Only for check duplicate PCD
1602 Content
= open(str(self
.MetaFile
), 'r').readlines()
1604 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1606 for Index
in range(0, len(Content
)):
1607 Line
, Comment
= CleanString2(Content
[Index
])
1608 self
._CurrentLine
= Line
1609 self
._LineIndex
= Index
1611 # save comment for later use
1613 self
._Comments
.append((Comment
, self
._LineIndex
+ 1))
1619 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1620 self
._SectionHeaderParser
()
1623 elif len(self
._SectionType
) == 0:
1628 self
._ValueList
= ['', '', '']
1629 self
._SectionParser
[self
._SectionType
[0]](self
)
1630 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
1636 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1637 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1639 for Arch
, ModuleType
, Type
in self
._Scope
:
1640 self
._LastItem
= self
._Store
(
1648 self
._LineIndex
+ 1,
1650 self
._LineIndex
+ 1,
1654 for Comment
, LineNo
in self
._Comments
:
1656 MODEL_META_DATA_COMMENT
,
1673 ## Section header parser
1675 # The section header is always in following format:
1677 # [section_name.arch<.platform|module_type>]
1679 def _SectionHeaderParser(self
):
1681 self
._SectionName
= ''
1682 self
._SectionType
= []
1684 Line
= self
._CurrentLine
.replace("%s%s" % (TAB_COMMA_SPLIT
, TAB_SPACE_SPLIT
), TAB_COMMA_SPLIT
)
1685 for Item
in Line
[1:-1].split(TAB_COMMA_SPLIT
):
1687 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
,
1688 "section name can NOT be empty or incorrectly use separator comma",
1689 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1690 ItemList
= Item
.split(TAB_SPLIT
)
1692 # different types of PCD are permissible in one section
1693 self
._SectionName
= ItemList
[0].upper()
1694 if self
._SectionName
in self
.DataType
:
1695 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1696 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1698 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
1699 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1701 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1705 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1707 Line
=self
._LineIndex
+ 1,
1708 ExtraData
=self
._CurrentLine
1711 if len(ItemList
) > 1:
1712 S1
= ItemList
[1].upper()
1716 # S2 may be Platform or ModuleType
1717 if len(ItemList
) > 2:
1718 S2
= ItemList
[2].upper()
1721 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1722 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1724 # 'COMMON' must not be used with specific ARCHs at the same section
1725 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1726 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1727 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
1729 ## [guids], [ppis] and [protocols] section parser
1731 def _GuidParser(self
):
1732 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1733 if len(TokenList
) < 2:
1734 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1735 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1736 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1737 if TokenList
[0] == '':
1738 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1739 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1740 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1741 if TokenList
[1] == '':
1742 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1743 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1744 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1745 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1746 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1747 ExtraData
=self
._CurrentLine
+ \
1748 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1749 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1750 self
._ValueList
[0] = TokenList
[0]
1751 self
._ValueList
[1] = TokenList
[1]
1753 ## PCD sections parser
1755 # [PcdsFixedAtBuild]
1756 # [PcdsPatchableInModule]
1762 def _PcdParser(self
):
1763 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1764 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1765 ValueRe
= re
.compile(r
'^[a-zA-Z_][a-zA-Z0-9_]*')
1766 # check PCD information
1767 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1768 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1769 ExtraData
=self
._CurrentLine
+ \
1770 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1771 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1772 # check format of token space GUID CName
1773 if not ValueRe
.match(self
._ValueList
[0]):
1774 EdkLogger
.error('Parser', FORMAT_INVALID
, "The format of the token space GUID CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
1775 ExtraData
=self
._CurrentLine
+ \
1776 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1777 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1778 # check format of PCD CName
1779 if not ValueRe
.match(self
._ValueList
[1]):
1780 EdkLogger
.error('Parser', FORMAT_INVALID
, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
1781 ExtraData
=self
._CurrentLine
+ \
1782 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1783 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1784 # check PCD datum information
1785 if len(TokenList
) < 2 or TokenList
[1] == '':
1786 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1787 ExtraData
=self
._CurrentLine
+ \
1788 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1789 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1792 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1793 PtrValue
= ValueRe
.findall(TokenList
[1])
1795 # Has VOID* type string, may contain "|" character in the string.
1796 if len(PtrValue
) != 0:
1797 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1798 ValueList
= GetSplitValueList(ptrValueList
)
1799 ValueList
[0] = PtrValue
[0]
1801 ValueList
= GetSplitValueList(TokenList
[1])
1804 # check if there's enough datum information given
1805 if len(ValueList
) != 3:
1806 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1807 ExtraData
=self
._CurrentLine
+ \
1808 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1809 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1810 # check default value
1811 if ValueList
[0] == '':
1812 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1813 ExtraData
=self
._CurrentLine
+ \
1814 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1815 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1817 if ValueList
[1] == '':
1818 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1819 ExtraData
=self
._CurrentLine
+ \
1820 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1821 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1822 # check token of the PCD
1823 if ValueList
[2] == '':
1824 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1825 ExtraData
=self
._CurrentLine
+ \
1826 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1827 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1828 # check format of default value against the datum type
1829 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1831 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1832 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1834 if ValueList
[0] in ['True', 'true', 'TRUE']:
1836 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1839 # check for duplicate PCD definition
1840 if (self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]) in self
._AllPCDs
:
1841 EdkLogger
.error('Parser', FORMAT_INVALID
,
1842 "The same PCD name and GUID have been already defined",
1843 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1845 self
._AllPCDs
.append((self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]))
1847 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
1850 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
1851 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
1852 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
1853 MODEL_EFI_GUID
: _GuidParser
,
1854 MODEL_EFI_PPI
: _GuidParser
,
1855 MODEL_EFI_PROTOCOL
: _GuidParser
,
1856 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1857 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1858 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1859 MODEL_PCD_DYNAMIC
: _PcdParser
,
1860 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
1861 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1862 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1867 # This acts like the main() function for the script, unless it is 'import'ed into another
1870 if __name__
== '__main__':