2 # This file is used to parse meta files
4 # Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.<BR>
5 # (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
6 # This program and the accompanying materials
7 # are licensed and made available under the terms and conditions of the BSD License
8 # which accompanies this distribution. The full text of the license may be found at
9 # http://opensource.org/licenses/bsd-license.php
11 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 import Common
.LongFilePathOs
as os
23 import Common
.EdkLogger
as EdkLogger
24 import Common
.GlobalData
as GlobalData
26 from CommonDataClass
.DataClass
import *
27 from Common
.DataType
import *
28 from Common
.String
import *
29 from Common
.Misc
import GuidStructureStringToGuidString
, CheckPcdDatum
, PathClass
, AnalyzePcdData
, AnalyzeDscPcd
, AnalyzePcdExpression
30 from Common
.Expression
import *
31 from CommonDataClass
.Exceptions
import *
32 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
34 from MetaFileTable
import MetaFileStorage
35 from MetaFileCommentParser
import CheckInfComment
37 ## A decorator used to parse macro definition
38 def ParseMacro(Parser
):
39 def MacroParser(self
):
40 Match
= gMacroDefPattern
.match(self
._CurrentLine
)
42 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
46 TokenList
= GetSplitValueList(self
._CurrentLine
[Match
.end(1):], TAB_EQUAL_SPLIT
, 1)
49 EdkLogger
.error('Parser', FORMAT_INVALID
, "No macro name given",
50 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
51 if len(TokenList
) < 2:
55 Name
, Value
= TokenList
56 # Global macros can be only defined via environment variable
57 if Name
in GlobalData
.gGlobalDefines
:
58 EdkLogger
.error('Parser', FORMAT_INVALID
, "%s can only be defined via environment variable" % Name
,
59 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
60 # Only upper case letters, digit and '_' are allowed
61 if not gMacroNamePattern
.match(Name
):
62 EdkLogger
.error('Parser', FORMAT_INVALID
, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
63 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
65 Value
= ReplaceMacro(Value
, self
._Macros
)
66 if Type
in self
.DataType
:
67 self
._ItemType
= self
.DataType
[Type
]
69 self
._ItemType
= MODEL_META_DATA_DEFINE
70 # DEFINE defined macros
71 if Type
== TAB_DSC_DEFINES_DEFINE
:
73 # First judge whether this DEFINE is in conditional directive statements or not.
75 if type(self
) == DscParser
and self
._InDirective
> -1:
78 if type(self
) == DecParser
:
79 if MODEL_META_DATA_HEADER
in self
._SectionType
:
80 self
._FileLocalMacros
[Name
] = Value
82 self
._ConstructSectionMacroDict
(Name
, Value
)
83 elif self
._SectionType
== MODEL_META_DATA_HEADER
:
84 self
._FileLocalMacros
[Name
] = Value
86 self
._ConstructSectionMacroDict
(Name
, Value
)
88 # EDK_GLOBAL defined macros
89 elif type(self
) != DscParser
:
90 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used in .dsc file",
91 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
92 elif self
._SectionType
!= MODEL_META_DATA_HEADER
:
93 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used under [Defines] section",
94 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
95 elif (Name
in self
._FileLocalMacros
) and (self
._FileLocalMacros
[Name
] != Value
):
96 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
97 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
99 self
._ValueList
= [Type
, Name
, Value
]
103 ## Base class of parser
105 # This class is used for derivation purpose. The specific parser for one kind
106 # type file must derive this class and implement some public interfaces.
108 # @param FilePath The path of platform description file
109 # @param FileType The raw data of DSC file
110 # @param Table Database used to retrieve module/package information
111 # @param Macros Macros used for replacement in file
112 # @param Owner Owner ID (for sub-section parsing)
113 # @param From ID from which the data comes (for !INCLUDE directive)
115 class MetaFileParser(object):
116 # data type (file content) for specific file type
119 # Parser objects used to implement singleton
124 # One file, one parser object. This factory method makes sure that there's
125 # only one object constructed for one meta file.
127 # @param Class class object of real AutoGen class
128 # (InfParser, DecParser or DscParser)
129 # @param FilePath The path of meta file
130 # @param *args The specific class related parameters
131 # @param **kwargs The specific class related dict parameters
133 def __new__(Class
, FilePath
, *args
, **kwargs
):
134 if FilePath
in Class
.MetaFiles
:
135 return Class
.MetaFiles
[FilePath
]
137 ParserObject
= super(MetaFileParser
, Class
).__new
__(Class
)
138 Class
.MetaFiles
[FilePath
] = ParserObject
141 ## Constructor of MetaFileParser
143 # Initialize object of MetaFileParser
145 # @param FilePath The path of platform description file
146 # @param FileType The raw data of DSC file
147 # @param Arch Default Arch value for filtering sections
148 # @param Table Database used to retrieve module/package information
149 # @param Owner Owner ID (for sub-section parsing)
150 # @param From ID from which the data comes (for !INCLUDE directive)
152 def __init__(self
, FilePath
, FileType
, Arch
, Table
, Owner
= -1, From
= -1):
154 self
._RawTable
= Table
156 self
._FileType
= FileType
157 self
.MetaFile
= FilePath
158 self
._FileDir
= self
.MetaFile
.Dir
160 self
._FileLocalMacros
= {}
161 self
._SectionsMacroDict
= {}
163 # for recursive parsing
164 self
._Owner
= [Owner
]
167 # parsr status for parsing
168 self
._ValueList
= ['', '', '', '', '']
171 self
._CurrentLine
= ''
172 self
._SectionType
= MODEL_UNKNOWN
173 self
._SectionName
= ''
174 self
._InSubsection
= False
175 self
._SubsectionType
= MODEL_UNKNOWN
176 self
._SubsectionName
= ''
177 self
._ItemType
= MODEL_UNKNOWN
180 self
._Finished
= False
181 self
._PostProcessed
= False
182 # Different version of meta-file has different way to parse.
185 ## Store the parsed data in table
186 def _Store(self
, *Args
):
187 return self
._Table
.Insert(*Args
)
189 ## Virtual method for starting parse
191 raise NotImplementedError
193 ## Notify a post-process is needed
194 def DoPostProcess(self
):
195 self
._PostProcessed
= False
197 ## Set parsing complete flag in both class and table
199 self
._Finished
= True
200 ## Do not set end flag when processing included files
202 self
._Table
.SetEndFlag()
204 def _PostProcess(self
):
205 self
._PostProcessed
= True
207 ## Get the parse complete flag
208 def _GetFinished(self
):
209 return self
._Finished
211 ## Set the complete flag
212 def _SetFinished(self
, Value
):
213 self
._Finished
= Value
215 ## Remove records that do not match given Filter Arch
216 def _FilterRecordList(self
, RecordList
, FilterArch
):
218 for Record
in RecordList
:
220 if Arch
== 'COMMON' or Arch
== FilterArch
:
221 NewRecordList
.append(Record
)
224 ## Use [] style to query data in table, just for readability
226 # DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]
228 def __getitem__(self
, DataInfo
):
229 if type(DataInfo
) != type(()):
230 DataInfo
= (DataInfo
,)
232 # Parse the file first, if necessary
233 if not self
._Finished
:
234 if self
._RawTable
.IsIntegrity():
235 self
._Finished
= True
237 self
._Table
= self
._RawTable
238 self
._PostProcessed
= False
241 # No specific ARCH or Platform given, use raw data
242 if self
._RawTable
and (len(DataInfo
) == 1 or DataInfo
[1] == None):
243 return self
._FilterRecordList
(self
._RawTable
.Query(*DataInfo
), self
._Arch
)
245 # Do post-process if necessary
246 if not self
._PostProcessed
:
249 return self
._FilterRecordList
(self
._Table
.Query(*DataInfo
), DataInfo
[1])
251 ## Data parser for the common format in different type of file
253 # The common format in the meatfile is like
258 def _CommonParser(self
):
259 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
260 self
._ValueList
[0:len(TokenList
)] = TokenList
262 ## Data parser for the format in which there's path
264 # Only path can have macro used. So we need to replace them before use.
267 def _PathParser(self
):
268 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
269 self
._ValueList
[0:len(TokenList
)] = TokenList
270 # Don't do macro replacement for dsc file at this point
271 if type(self
) != DscParser
:
272 Macros
= self
._Macros
273 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
275 ## Skip unsupported data
277 EdkLogger
.warn("Parser", "Unrecognized content", File
=self
.MetaFile
,
278 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
);
279 self
._ValueList
[0:1] = [self
._CurrentLine
]
281 ## Skip unsupported data for UserExtension Section
282 def _SkipUserExtension(self
):
283 self
._ValueList
[0:1] = [self
._CurrentLine
]
285 ## Section header parser
287 # The section header is always in following format:
289 # [section_name.arch<.platform|module_type>]
291 def _SectionHeaderParser(self
):
293 self
._SectionName
= ''
295 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
298 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
,2)
299 # different section should not mix in one section
300 if self
._SectionName
!= '' and self
._SectionName
!= ItemList
[0].upper():
301 EdkLogger
.error('Parser', FORMAT_INVALID
, "Different section names in the same section",
302 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
303 self
._SectionName
= ItemList
[0].upper()
304 if self
._SectionName
in self
.DataType
:
305 self
._SectionType
= self
.DataType
[self
._SectionName
]
306 # Check if the section name is valid
307 if self
._SectionName
not in SECTIONS_HAVE_ITEM_AFTER_ARCH
and len(ItemList
) > 3:
308 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
309 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
310 elif self
._Version
>= 0x00010005:
311 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
312 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
314 self
._SectionType
= MODEL_UNKNOWN
317 if len(ItemList
) > 1:
318 S1
= ItemList
[1].upper()
323 # S2 may be Platform or ModuleType
324 if len(ItemList
) > 2:
325 if self
._SectionName
.upper() in SECTIONS_HAVE_ITEM_PCD
:
328 S2
= ItemList
[2].upper()
331 self
._Scope
.append([S1
, S2
])
333 # 'COMMON' must not be used with specific ARCHs at the same section
334 if 'COMMON' in ArchList
and len(ArchList
) > 1:
335 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
336 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
337 # If the section information is needed later, it should be stored in database
338 self
._ValueList
[0] = self
._SectionName
340 ## [defines] section parser
342 def _DefineParser(self
):
343 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
344 self
._ValueList
[1:len(TokenList
)] = TokenList
345 if not self
._ValueList
[1]:
346 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
347 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
348 if not self
._ValueList
[2]:
349 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
350 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
352 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
353 Name
, Value
= self
._ValueList
[1], self
._ValueList
[2]
354 # Sometimes, we need to make differences between EDK and EDK2 modules
355 if Name
== 'INF_VERSION':
356 if re
.match(r
'0[xX][\da-f-A-F]{5,8}', Value
):
357 self
._Version
= int(Value
, 0)
358 elif re
.match(r
'\d+\.\d+', Value
):
359 ValueList
= Value
.split('.')
360 Major
= '%04o' % int(ValueList
[0], 0)
361 Minor
= '%04o' % int(ValueList
[1], 0)
362 self
._Version
= int('0x' + Major
+ Minor
, 0)
364 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid version number",
365 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
367 if type(self
) == InfParser
and self
._Version
< 0x00010005:
368 # EDK module allows using defines as macros
369 self
._FileLocalMacros
[Name
] = Value
370 self
._Defines
[Name
] = Value
372 ## [BuildOptions] section parser
374 def _BuildOptionParser(self
):
375 self
._CurrentLine
= CleanString(self
._CurrentLine
, BuildOption
=True)
376 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
377 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
378 if len(TokenList2
) == 2:
379 self
._ValueList
[0] = TokenList2
[0] # toolchain family
380 self
._ValueList
[1] = TokenList2
[1] # keys
382 self
._ValueList
[1] = TokenList
[0]
383 if len(TokenList
) == 2 and type(self
) != DscParser
: # value
384 self
._ValueList
[2] = ReplaceMacro(TokenList
[1], self
._Macros
)
386 if self
._ValueList
[1].count('_') != 4:
390 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
391 ExtraData
=self
._CurrentLine
,
393 Line
=self
._LineIndex
+ 1
395 def GetValidExpression(self
, TokenSpaceGuid
, PcdCName
):
396 return self
._Table
.GetValidExpression(TokenSpaceGuid
, PcdCName
)
397 def _GetMacros(self
):
399 Macros
.update(self
._FileLocalMacros
)
400 Macros
.update(self
._GetApplicableSectionMacro
())
403 ## Construct section Macro dict
404 def _ConstructSectionMacroDict(self
, Name
, Value
):
405 ScopeKey
= [(Scope
[0], Scope
[1]) for Scope
in self
._Scope
]
406 ScopeKey
= tuple(ScopeKey
)
407 SectionDictKey
= self
._SectionType
, ScopeKey
409 # DecParser SectionType is a list, will contain more than one item only in Pcd Section
410 # As Pcd section macro usage is not alllowed, so here it is safe
412 if type(self
) == DecParser
:
413 SectionDictKey
= self
._SectionType
[0], ScopeKey
414 if SectionDictKey
not in self
._SectionsMacroDict
:
415 self
._SectionsMacroDict
[SectionDictKey
] = {}
416 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
417 SectionLocalMacros
[Name
] = Value
419 ## Get section Macros that are applicable to current line, which may come from other sections
420 ## that share the same name while scope is wider
421 def _GetApplicableSectionMacro(self
):
428 ActiveSectionType
= self
._SectionType
429 if type(self
) == DecParser
:
430 ActiveSectionType
= self
._SectionType
[0]
432 for (SectionType
, Scope
) in self
._SectionsMacroDict
:
433 if SectionType
!= ActiveSectionType
:
436 for ActiveScope
in self
._Scope
:
437 Scope0
, Scope1
= ActiveScope
[0], ActiveScope
[1]
438 if(Scope0
, Scope1
) not in Scope
:
441 SpeSpeMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
443 for ActiveScope
in self
._Scope
:
444 Scope0
, Scope1
= ActiveScope
[0], ActiveScope
[1]
445 if(Scope0
, Scope1
) not in Scope
and (Scope0
, "COMMON") not in Scope
and ("COMMON", Scope1
) not in Scope
:
448 ComSpeMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
450 if ("COMMON", "COMMON") in Scope
:
451 ComComMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
453 Macros
.update(ComComMacroDict
)
454 Macros
.update(ComSpeMacroDict
)
455 Macros
.update(SpeSpeMacroDict
)
460 Finished
= property(_GetFinished
, _SetFinished
)
461 _Macros
= property(_GetMacros
)
464 ## INF file parser class
466 # @param FilePath The path of platform description file
467 # @param FileType The raw data of DSC file
468 # @param Table Database used to retrieve module/package information
469 # @param Macros Macros used for replacement in file
471 class InfParser(MetaFileParser
):
472 # INF file supported data types (one type per section)
474 TAB_UNKNOWN
.upper() : MODEL_UNKNOWN
,
475 TAB_INF_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
476 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
477 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
478 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
479 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
480 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
481 TAB_PACKAGES
.upper() : MODEL_META_DATA_PACKAGE
,
482 TAB_NMAKE
.upper() : MODEL_META_DATA_NMAKE
,
483 TAB_INF_FIXED_PCD
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
484 TAB_INF_PATCH_PCD
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
485 TAB_INF_FEATURE_PCD
.upper() : MODEL_PCD_FEATURE_FLAG
,
486 TAB_INF_PCD_EX
.upper() : MODEL_PCD_DYNAMIC_EX
,
487 TAB_INF_PCD
.upper() : MODEL_PCD_DYNAMIC
,
488 TAB_SOURCES
.upper() : MODEL_EFI_SOURCE_FILE
,
489 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
490 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
491 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
492 TAB_DEPEX
.upper() : MODEL_EFI_DEPEX
,
493 TAB_BINARIES
.upper() : MODEL_EFI_BINARY_FILE
,
494 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
497 ## Constructor of InfParser
499 # Initialize object of InfParser
501 # @param FilePath The path of module description file
502 # @param FileType The raw data of DSC file
503 # @param Arch Default Arch value for filtering sections
504 # @param Table Database used to retrieve module/package information
506 def __init__(self
, FilePath
, FileType
, Arch
, Table
):
507 # prevent re-initialization
508 if hasattr(self
, "_Table"):
510 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Arch
, Table
)
518 Content
= open(str(self
.MetaFile
), 'r').readlines()
520 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
522 # parse the file line by line
523 IsFindBlockComment
= False
524 GetHeaderComment
= False
529 for Index
in range(0, len(Content
)):
530 # skip empty, commented, block commented lines
531 Line
, Comment
= CleanString2(Content
[Index
], AllowCppStyleComment
=True)
533 if Index
+ 1 < len(Content
):
534 NextLine
, NextComment
= CleanString2(Content
[Index
+ 1])
537 Comments
.append((Comment
, Index
+ 1))
538 elif GetHeaderComment
:
539 SectionComments
.extend(Comments
)
542 if Line
.find(DataType
.TAB_COMMENT_EDK_START
) > -1:
543 IsFindBlockComment
= True
545 if Line
.find(DataType
.TAB_COMMENT_EDK_END
) > -1:
546 IsFindBlockComment
= False
548 if IsFindBlockComment
:
551 self
._LineIndex
= Index
552 self
._CurrentLine
= Line
555 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
556 if not GetHeaderComment
:
557 for Cmt
, LNo
in Comments
:
558 self
._Store
(MODEL_META_DATA_HEADER_COMMENT
, Cmt
, '', '', 'COMMON',
559 'COMMON', self
._Owner
[-1], LNo
, -1, LNo
, -1, 0)
560 GetHeaderComment
= True
562 TailComments
.extend(SectionComments
+ Comments
)
564 self
._SectionHeaderParser
()
565 # Check invalid sections
566 if self
._Version
< 0x00010005:
567 if self
._SectionType
in [MODEL_META_DATA_BUILD_OPTION
,
568 MODEL_EFI_LIBRARY_CLASS
,
569 MODEL_META_DATA_PACKAGE
,
570 MODEL_PCD_FIXED_AT_BUILD
,
571 MODEL_PCD_PATCHABLE_IN_MODULE
,
572 MODEL_PCD_FEATURE_FLAG
,
573 MODEL_PCD_DYNAMIC_EX
,
578 MODEL_META_DATA_USER_EXTENSION
]:
579 EdkLogger
.error('Parser', FORMAT_INVALID
,
580 "Section [%s] is not allowed in inf file without version" % (self
._SectionName
),
581 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
582 elif self
._SectionType
in [MODEL_EFI_INCLUDE
,
583 MODEL_EFI_LIBRARY_INSTANCE
,
584 MODEL_META_DATA_NMAKE
]:
585 EdkLogger
.error('Parser', FORMAT_INVALID
,
586 "Section [%s] is not allowed in inf file with version 0x%08x" % (self
._SectionName
, self
._Version
),
587 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
589 # merge two lines specified by '\' in section NMAKE
590 elif self
._SectionType
== MODEL_META_DATA_NMAKE
:
593 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
596 if NextLine
[0] == TAB_SECTION_START
and NextLine
[-1] == TAB_SECTION_END
:
597 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
600 NmakeLine
= NmakeLine
+ ' ' + Line
[0:-1]
603 self
._CurrentLine
= NmakeLine
+ Line
607 self
._ValueList
= ['', '', '']
608 # parse current line, result will be put in self._ValueList
609 self
._SectionParser
[self
._SectionType
](self
)
610 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
615 Comments
.append((Comment
, Index
+ 1))
616 if GlobalData
.gOptions
and GlobalData
.gOptions
.CheckUsage
:
617 CheckInfComment(self
._SectionType
, Comments
, str(self
.MetaFile
), Index
+ 1, self
._ValueList
)
619 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
620 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
622 for Arch
, Platform
in self
._Scope
:
623 LastItem
= self
._Store
(self
._SectionType
,
636 for Comment
, LineNo
in Comments
:
637 self
._Store
(MODEL_META_DATA_COMMENT
, Comment
, '', '', Arch
, Platform
,
638 LastItem
, LineNo
, -1, LineNo
, -1, 0)
641 TailComments
.extend(SectionComments
+ Comments
)
642 if IsFindBlockComment
:
643 EdkLogger
.error("Parser", FORMAT_INVALID
, "Open block comments (starting with /*) are expected to end with */",
646 # If there are tail comments in INF file, save to database whatever the comments are
647 for Comment
in TailComments
:
648 self
._Store
(MODEL_META_DATA_TAIL_COMMENT
, Comment
[0], '', '', 'COMMON',
649 'COMMON', self
._Owner
[-1], -1, -1, -1, -1, 0)
652 ## Data parser for the format in which there's path
654 # Only path can have macro used. So we need to replace them before use.
656 def _IncludeParser(self
):
657 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
658 self
._ValueList
[0:len(TokenList
)] = TokenList
659 Macros
= self
._Macros
661 for Index
in range(0, len(self
._ValueList
)):
662 Value
= self
._ValueList
[Index
]
666 if Value
.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value
.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
667 Value
= '$(EDK_SOURCE)' + Value
[17:]
668 if Value
.find('$(EFI_SOURCE)') > -1 or Value
.find('$(EDK_SOURCE)') > -1:
670 elif Value
.startswith('.'):
672 elif Value
.startswith('$('):
675 Value
= '$(EFI_SOURCE)/' + Value
677 self
._ValueList
[Index
] = ReplaceMacro(Value
, Macros
)
679 ## Parse [Sources] section
681 # Only path can have macro used. So we need to replace them before use.
684 def _SourceFileParser(self
):
685 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
686 self
._ValueList
[0:len(TokenList
)] = TokenList
687 Macros
= self
._Macros
688 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
689 if 'COMPONENT_TYPE' in Macros
:
690 if self
._Defines
['COMPONENT_TYPE'].upper() == 'ACPITABLE':
691 self
._ValueList
[0] = GetSplitValueList(self
._ValueList
[0], ' ', 1)[0]
692 if self
._Defines
['BASE_NAME'] == 'Microcode':
694 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
696 ## Parse [Binaries] section
698 # Only path can have macro used. So we need to replace them before use.
701 def _BinaryFileParser(self
):
702 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 2)
703 if len(TokenList
) < 2:
704 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type or path specified",
705 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
706 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
708 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type specified",
709 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
710 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
712 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file path specified",
713 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
714 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
715 self
._ValueList
[0:len(TokenList
)] = TokenList
716 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
718 ## [nmake] section parser (Edk.x style only)
719 def _NmakeParser(self
):
720 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
721 self
._ValueList
[0:len(TokenList
)] = TokenList
723 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
724 # remove self-reference in macro setting
725 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
727 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
729 def _PcdParser(self
):
730 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
731 ValueList
= GetSplitValueList(TokenList
[0], TAB_SPLIT
)
732 if len(ValueList
) != 2:
733 EdkLogger
.error('Parser', FORMAT_INVALID
, "Illegal token space GUID and PCD name format",
734 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
735 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
736 self
._ValueList
[0:1] = ValueList
737 if len(TokenList
) > 1:
738 self
._ValueList
[2] = TokenList
[1]
739 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
740 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
741 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
742 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
744 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
745 if self
._ValueList
[2] != '':
746 InfPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
747 if InfPcdValueList
[0] in ['True', 'true', 'TRUE']:
748 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '1', 1);
749 elif InfPcdValueList
[0] in ['False', 'false', 'FALSE']:
750 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '0', 1);
751 if (self
._ValueList
[0], self
._ValueList
[1]) not in self
.PcdsDict
:
752 self
.PcdsDict
[self
._ValueList
[0], self
._ValueList
[1]] = self
._SectionType
753 elif self
.PcdsDict
[self
._ValueList
[0], self
._ValueList
[1]] != self
._SectionType
:
754 EdkLogger
.error('Parser', FORMAT_INVALID
, "It is not permissible to list a specified PCD in different PCD type sections.",
755 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
756 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
758 ## [depex] section parser
760 def _DepexParser(self
):
761 self
._ValueList
[0:1] = [self
._CurrentLine
]
764 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
765 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
766 MODEL_META_DATA_BUILD_OPTION
: MetaFileParser
._BuildOptionParser
,
767 MODEL_EFI_INCLUDE
: _IncludeParser
, # for Edk.x modules
768 MODEL_EFI_LIBRARY_INSTANCE
: MetaFileParser
._CommonParser
, # for Edk.x modules
769 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
770 MODEL_META_DATA_PACKAGE
: MetaFileParser
._PathParser
,
771 MODEL_META_DATA_NMAKE
: _NmakeParser
, # for Edk.x modules
772 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
773 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
774 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
775 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
776 MODEL_PCD_DYNAMIC
: _PcdParser
,
777 MODEL_EFI_SOURCE_FILE
: _SourceFileParser
,
778 MODEL_EFI_GUID
: MetaFileParser
._CommonParser
,
779 MODEL_EFI_PROTOCOL
: MetaFileParser
._CommonParser
,
780 MODEL_EFI_PPI
: MetaFileParser
._CommonParser
,
781 MODEL_EFI_DEPEX
: _DepexParser
,
782 MODEL_EFI_BINARY_FILE
: _BinaryFileParser
,
783 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
786 ## DSC file parser class
788 # @param FilePath The path of platform description file
789 # @param FileType The raw data of DSC file
790 # @param Table Database used to retrieve module/package information
791 # @param Macros Macros used for replacement in file
792 # @param Owner Owner ID (for sub-section parsing)
793 # @param From ID from which the data comes (for !INCLUDE directive)
795 class DscParser(MetaFileParser
):
796 # DSC file supported data types (one type per section)
798 TAB_SKUIDS
.upper() : MODEL_EFI_SKU_ID
,
799 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
800 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
801 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
802 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
803 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
804 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
805 TAB_PCDS_DYNAMIC_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_DEFAULT
,
806 TAB_PCDS_DYNAMIC_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_HII
,
807 TAB_PCDS_DYNAMIC_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_VPD
,
808 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT
,
809 TAB_PCDS_DYNAMIC_EX_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_HII
,
810 TAB_PCDS_DYNAMIC_EX_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_VPD
,
811 TAB_COMPONENTS
.upper() : MODEL_META_DATA_COMPONENT
,
812 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH
.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
,
813 TAB_DSC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
814 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
815 TAB_DSC_DEFINES_EDKGLOBAL
: MODEL_META_DATA_GLOBAL_DEFINE
,
816 TAB_INCLUDE
.upper() : MODEL_META_DATA_INCLUDE
,
817 TAB_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
818 TAB_IF_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
819 TAB_IF_N_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
,
820 TAB_ELSE_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
,
821 TAB_ELSE
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
822 TAB_END_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
,
823 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
,
826 # Valid names in define section
833 "PCD_INFO_GENERATION",
834 "PCD_VAR_CHECK_GENERATION",
835 "SUPPORTED_ARCHITECTURES",
844 "FIX_LOAD_TOP_MEMORY_ADDRESS",
849 SubSectionDefineKeywords
= [
853 SymbolPattern
= ValueExpression
.SymbolPattern
855 ## Constructor of DscParser
857 # Initialize object of DscParser
859 # @param FilePath The path of platform description file
860 # @param FileType The raw data of DSC file
861 # @param Arch Default Arch value for filtering sections
862 # @param Table Database used to retrieve module/package information
863 # @param Owner Owner ID (for sub-section parsing)
864 # @param From ID from which the data comes (for !INCLUDE directive)
866 def __init__(self
, FilePath
, FileType
, Arch
, Table
, Owner
= -1, From
= -1):
867 # prevent re-initialization
868 if hasattr(self
, "_Table"):
870 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Arch
, Table
, Owner
, From
)
871 self
._Version
= 0x00010005 # Only EDK2 dsc file is supported
872 # to store conditional directive evaluation result
873 self
._DirectiveStack
= []
874 self
._DirectiveEvalStack
= []
878 # Specify whether current line is in uncertain condition
880 self
._InDirective
= -1
882 # Final valid replacable symbols
885 # Map the ID between the original table and new table to track
888 self
._IdMapping
= {-1:-1}
894 Content
= open(str(self
.MetaFile
), 'r').readlines()
896 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
899 for Index
in range(0, len(Content
)):
900 Line
= CleanString(Content
[Index
])
905 self
._CurrentLine
= Line
906 self
._LineIndex
= Index
907 if self
._InSubsection
and self
._Owner
[-1] == -1:
908 self
._Owner
.append(self
._LastItem
)
911 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
912 self
._SectionType
= MODEL_META_DATA_SECTION_HEADER
914 elif Line
[0] == '}' and self
._InSubsection
:
915 self
._InSubsection
= False
916 self
._SubsectionType
= MODEL_UNKNOWN
917 self
._SubsectionName
= ''
922 elif Line
[0] == TAB_OPTION_START
and Line
[-1] == TAB_OPTION_END
:
923 self
._SubsectionType
= MODEL_META_DATA_SUBSECTION_HEADER
926 self
._DirectiveParser
()
928 if Line
[0] == TAB_OPTION_START
and not self
._InSubsection
:
929 EdkLogger
.error("Parser", FILE_READ_FAILURE
, "Missing the '{' before %s in Line %s" % (Line
, Index
+1),ExtraData
=self
.MetaFile
)
931 if self
._InSubsection
:
932 SectionType
= self
._SubsectionType
934 SectionType
= self
._SectionType
935 self
._ItemType
= SectionType
937 self
._ValueList
= ['', '', '']
938 self
._SectionParser
[SectionType
](self
)
939 if self
._ValueList
== None:
942 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
943 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
945 for Arch
, ModuleType
in self
._Scope
:
946 Owner
= self
._Owner
[-1]
947 if self
._SubsectionType
!= MODEL_UNKNOWN
:
948 Owner
= OwnerId
[Arch
]
949 self
._LastItem
= self
._Store
(
964 if self
._SubsectionType
== MODEL_UNKNOWN
and self
._InSubsection
:
965 OwnerId
[Arch
] = self
._LastItem
967 if self
._DirectiveStack
:
968 Type
, Line
, Text
= self
._DirectiveStack
[-1]
969 EdkLogger
.error('Parser', FORMAT_INVALID
, "No matching '!endif' found",
970 ExtraData
=Text
, File
=self
.MetaFile
, Line
=Line
)
973 ## <subsection_header> parser
974 def _SubsectionHeaderParser(self
):
975 self
._SubsectionName
= self
._CurrentLine
[1:-1].upper()
976 if self
._SubsectionName
in self
.DataType
:
977 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
979 self
._SubsectionType
= MODEL_UNKNOWN
980 EdkLogger
.warn("Parser", "Unrecognized sub-section", File
=self
.MetaFile
,
981 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
982 self
._ValueList
[0] = self
._SubsectionName
984 ## Directive statement parser
985 def _DirectiveParser(self
):
986 self
._ValueList
= ['', '', '']
987 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
988 self
._ValueList
[0:len(TokenList
)] = TokenList
991 DirectiveName
= self
._ValueList
[0].upper()
992 if DirectiveName
not in self
.DataType
:
993 EdkLogger
.error("Parser", FORMAT_INVALID
, "Unknown directive [%s]" % DirectiveName
,
994 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
996 if DirectiveName
in ['!IF', '!IFDEF', '!IFNDEF']:
997 self
._InDirective
+= 1
999 if DirectiveName
in ['!ENDIF']:
1000 self
._InDirective
-= 1
1002 if DirectiveName
in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self
._ValueList
[1] == '':
1003 EdkLogger
.error("Parser", FORMAT_INVALID
, "Missing expression",
1004 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
1005 ExtraData
=self
._CurrentLine
)
1007 ItemType
= self
.DataType
[DirectiveName
]
1008 Scope
= [['COMMON', 'COMMON']]
1009 if ItemType
== MODEL_META_DATA_INCLUDE
:
1011 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1012 # Remove all directives between !if and !endif, including themselves
1013 while self
._DirectiveStack
:
1014 # Remove any !else or !elseif
1015 DirectiveInfo
= self
._DirectiveStack
.pop()
1016 if DirectiveInfo
[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1017 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1018 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1021 EdkLogger
.error("Parser", FORMAT_INVALID
, "Redundant '!endif'",
1022 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
1023 ExtraData
=self
._CurrentLine
)
1024 elif ItemType
!= MODEL_META_DATA_INCLUDE
:
1025 # Break if there's a !else is followed by a !elseif
1026 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
and \
1027 self
._DirectiveStack
and \
1028 self
._DirectiveStack
[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1029 EdkLogger
.error("Parser", FORMAT_INVALID
, "'!elseif' after '!else'",
1030 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
1031 ExtraData
=self
._CurrentLine
)
1032 self
._DirectiveStack
.append((ItemType
, self
._LineIndex
+ 1, self
._CurrentLine
))
1035 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
1036 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
1038 for Arch
, ModuleType
in Scope
:
1039 self
._LastItem
= self
._Store
(
1048 self
._LineIndex
+ 1,
1050 self
._LineIndex
+ 1,
1055 ## [defines] section parser
1057 def _DefineParser(self
):
1058 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1059 self
._ValueList
[1:len(TokenList
)] = TokenList
1062 if not self
._ValueList
[1]:
1063 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
1064 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1065 if not self
._ValueList
[2]:
1066 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
1067 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1068 if (not self
._ValueList
[1] in self
.DefineKeywords
and
1069 (self
._InSubsection
and self
._ValueList
[1] not in self
.SubSectionDefineKeywords
)):
1070 EdkLogger
.error('Parser', FORMAT_INVALID
,
1071 "Unknown keyword found: %s. "
1072 "If this is a macro you must "
1073 "add it as a DEFINE in the DSC" % self
._ValueList
[1],
1074 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1075 if not self
._InSubsection
:
1076 self
._Defines
[self
._ValueList
[1]] = self
._ValueList
[2]
1077 self
._ItemType
= self
.DataType
[TAB_DSC_DEFINES
.upper()]
1080 def _SkuIdParser(self
):
1081 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1082 if len(TokenList
) != 2:
1083 EdkLogger
.error('Parser', FORMAT_INVALID
, "Correct format is '<Integer>|<UiName>'",
1084 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1085 self
._ValueList
[0:len(TokenList
)] = TokenList
1087 ## Parse Edk style of library modules
1089 def _LibraryInstanceParser(self
):
1090 self
._ValueList
[0] = self
._CurrentLine
1092 ## PCD sections parser
1094 # [PcdsFixedAtBuild]
1095 # [PcdsPatchableInModule]
1098 # [PcdsDynamicExDefault]
1099 # [PcdsDynamicExVpd]
1100 # [PcdsDynamicExHii]
1102 # [PcdsDynamicDefault]
1107 def _PcdParser(self
):
1108 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1109 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1110 if len(TokenList
) == 2:
1111 self
._ValueList
[2] = TokenList
[1]
1112 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1113 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1114 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1115 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1116 if self
._ValueList
[2] == '':
1118 # The PCD values are optional for FIXEDATBUILD and PATCHABLEINMODULE
1120 if self
._SectionType
in (MODEL_PCD_FIXED_AT_BUILD
, MODEL_PCD_PATCHABLE_IN_MODULE
):
1122 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD value given",
1123 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1124 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1126 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD
1127 ValueList
= GetSplitValueList(self
._ValueList
[2])
1128 if len(ValueList
) > 1 and ValueList
[1] != TAB_VOID \
1129 and self
._ItemType
in [MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_EX_DEFAULT
]:
1130 EdkLogger
.error('Parser', FORMAT_INVALID
, "The datum type '%s' of PCD is wrong" % ValueList
[1],
1131 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1133 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1134 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
1135 if DscPcdValueList
[0] in ['True', 'true', 'TRUE']:
1136 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '1', 1);
1137 elif DscPcdValueList
[0] in ['False', 'false', 'FALSE']:
1138 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '0', 1);
1141 ## [components] section parser
1143 def _ComponentParser(self
):
1144 if self
._CurrentLine
[-1] == '{':
1145 self
._ValueList
[0] = self
._CurrentLine
[0:-1].strip()
1146 self
._InSubsection
= True
1148 self
._ValueList
[0] = self
._CurrentLine
1150 ## [LibraryClasses] section
1152 def _LibraryClassParser(self
):
1153 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1154 if len(TokenList
) < 2:
1155 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class or instance specified",
1156 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1157 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1158 if TokenList
[0] == '':
1159 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class specified",
1160 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1161 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1162 if TokenList
[1] == '':
1163 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library instance specified",
1164 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1165 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1167 self
._ValueList
[0:len(TokenList
)] = TokenList
1169 def _CompponentSourceOverridePathParser(self
):
1170 self
._ValueList
[0] = self
._CurrentLine
1172 ## [BuildOptions] section parser
1174 def _BuildOptionParser(self
):
1175 self
._CurrentLine
= CleanString(self
._CurrentLine
, BuildOption
=True)
1176 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1177 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
1178 if len(TokenList2
) == 2:
1179 self
._ValueList
[0] = TokenList2
[0] # toolchain family
1180 self
._ValueList
[1] = TokenList2
[1] # keys
1182 self
._ValueList
[1] = TokenList
[0]
1183 if len(TokenList
) == 2: # value
1184 self
._ValueList
[2] = TokenList
[1]
1186 if self
._ValueList
[1].count('_') != 4:
1190 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
1191 ExtraData
=self
._CurrentLine
,
1193 Line
=self
._LineIndex
+ 1
1196 ## Override parent's method since we'll do all macro replacements in parser
1197 def _GetMacros(self
):
1199 Macros
.update(self
._FileLocalMacros
)
1200 Macros
.update(self
._GetApplicableSectionMacro
())
1201 Macros
.update(GlobalData
.gEdkGlobal
)
1202 Macros
.update(GlobalData
.gPlatformDefines
)
1203 Macros
.update(GlobalData
.gCommandLineDefines
)
1204 # PCD cannot be referenced in macro definition
1205 if self
._ItemType
not in [MODEL_META_DATA_DEFINE
, MODEL_META_DATA_GLOBAL_DEFINE
]:
1206 Macros
.update(self
._Symbols
)
1209 def _PostProcess(self
):
1211 MODEL_META_DATA_SECTION_HEADER
: self
.__ProcessSectionHeader
,
1212 MODEL_META_DATA_SUBSECTION_HEADER
: self
.__ProcessSubsectionHeader
,
1213 MODEL_META_DATA_HEADER
: self
.__ProcessDefine
,
1214 MODEL_META_DATA_DEFINE
: self
.__ProcessDefine
,
1215 MODEL_META_DATA_GLOBAL_DEFINE
: self
.__ProcessDefine
,
1216 MODEL_META_DATA_INCLUDE
: self
.__ProcessDirective
,
1217 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
: self
.__ProcessDirective
,
1218 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
: self
.__ProcessDirective
,
1219 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
: self
.__ProcessDirective
,
1220 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
: self
.__ProcessDirective
,
1221 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
: self
.__ProcessDirective
,
1222 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
: self
.__ProcessDirective
,
1223 MODEL_EFI_SKU_ID
: self
.__ProcessSkuId
,
1224 MODEL_EFI_LIBRARY_INSTANCE
: self
.__ProcessLibraryInstance
,
1225 MODEL_EFI_LIBRARY_CLASS
: self
.__ProcessLibraryClass
,
1226 MODEL_PCD_FIXED_AT_BUILD
: self
.__ProcessPcd
,
1227 MODEL_PCD_PATCHABLE_IN_MODULE
: self
.__ProcessPcd
,
1228 MODEL_PCD_FEATURE_FLAG
: self
.__ProcessPcd
,
1229 MODEL_PCD_DYNAMIC_DEFAULT
: self
.__ProcessPcd
,
1230 MODEL_PCD_DYNAMIC_HII
: self
.__ProcessPcd
,
1231 MODEL_PCD_DYNAMIC_VPD
: self
.__ProcessPcd
,
1232 MODEL_PCD_DYNAMIC_EX_DEFAULT
: self
.__ProcessPcd
,
1233 MODEL_PCD_DYNAMIC_EX_HII
: self
.__ProcessPcd
,
1234 MODEL_PCD_DYNAMIC_EX_VPD
: self
.__ProcessPcd
,
1235 MODEL_META_DATA_COMPONENT
: self
.__ProcessComponent
,
1236 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: self
.__ProcessSourceOverridePath
,
1237 MODEL_META_DATA_BUILD_OPTION
: self
.__ProcessBuildOption
,
1238 MODEL_UNKNOWN
: self
._Skip
,
1239 MODEL_META_DATA_USER_EXTENSION
: self
._SkipUserExtension
,
1242 self
._Table
= MetaFileStorage(self
._RawTable
.Cur
, self
.MetaFile
, MODEL_FILE_DSC
, True)
1243 self
._Table
.Create()
1244 self
._DirectiveStack
= []
1245 self
._DirectiveEvalStack
= []
1246 self
._FileWithError
= self
.MetaFile
1247 self
._FileLocalMacros
= {}
1248 self
._SectionsMacroDict
= {}
1249 GlobalData
.gPlatformDefines
= {}
1251 # Get all macro and PCD which has straitforward value
1252 self
.__RetrievePcdValue
()
1253 self
._Content
= self
._RawTable
.GetAll()
1254 self
._ContentIndex
= 0
1255 self
._InSubsection
= False
1256 while self
._ContentIndex
< len(self
._Content
) :
1257 Id
, self
._ItemType
, V1
, V2
, V3
, S1
, S2
, Owner
, self
._From
, \
1258 LineStart
, ColStart
, LineEnd
, ColEnd
, Enabled
= self
._Content
[self
._ContentIndex
]
1261 self
._FileWithError
= self
.MetaFile
1263 self
._ContentIndex
+= 1
1265 self
._Scope
= [[S1
, S2
]]
1267 # For !include directive, handle it specially,
1268 # merge arch and module type in case of duplicate items
1270 while self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1271 if self
._ContentIndex
>= len(self
._Content
):
1273 Record
= self
._Content
[self
._ContentIndex
]
1274 if LineStart
== Record
[9] and LineEnd
== Record
[11]:
1275 if [Record
[5], Record
[6]] not in self
._Scope
:
1276 self
._Scope
.append([Record
[5], Record
[6]])
1277 self
._ContentIndex
+= 1
1281 self
._LineIndex
= LineStart
- 1
1282 self
._ValueList
= [V1
, V2
, V3
]
1284 if Owner
> 0 and Owner
in self
._IdMapping
:
1285 self
._InSubsection
= True
1287 self
._InSubsection
= False
1289 Processer
[self
._ItemType
]()
1290 except EvaluationException
, Excpt
:
1292 # Only catch expression evaluation error here. We need to report
1293 # the precise number of line on which the error occurred
1295 if hasattr(Excpt
, 'Pcd'):
1296 if Excpt
.Pcd
in GlobalData
.gPlatformOtherPcds
:
1297 Info
= GlobalData
.gPlatformOtherPcds
[Excpt
.Pcd
]
1298 EdkLogger
.error('Parser', FORMAT_INVALID
, "Cannot use this PCD (%s) in an expression as"
1299 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
1300 " of the DSC file, and it is currently defined in this section:"
1301 " %s, line #: %d." % (Excpt
.Pcd
, Info
[0], Info
[1]),
1302 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1303 Line
=self
._LineIndex
+ 1)
1305 EdkLogger
.error('Parser', FORMAT_INVALID
, "PCD (%s) is not defined in DSC file" % Excpt
.Pcd
,
1306 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1307 Line
=self
._LineIndex
+ 1)
1309 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid expression: %s" % str(Excpt
),
1310 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1311 Line
=self
._LineIndex
+ 1)
1312 except MacroException
, Excpt
:
1313 EdkLogger
.error('Parser', FORMAT_INVALID
, str(Excpt
),
1314 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1315 Line
=self
._LineIndex
+ 1)
1317 if self
._ValueList
== None:
1320 NewOwner
= self
._IdMapping
.get(Owner
, -1)
1321 self
._Enabled
= int((not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
))
1322 self
._LastItem
= self
._Store
(
1331 self
._LineIndex
+ 1,
1333 self
._LineIndex
+ 1,
1337 self
._IdMapping
[Id
] = self
._LastItem
1339 GlobalData
.gPlatformDefines
.update(self
._FileLocalMacros
)
1340 self
._PostProcessed
= True
1341 self
._Content
= None
1343 def __ProcessSectionHeader(self
):
1344 self
._SectionName
= self
._ValueList
[0]
1345 if self
._SectionName
in self
.DataType
:
1346 self
._SectionType
= self
.DataType
[self
._SectionName
]
1348 self
._SectionType
= MODEL_UNKNOWN
1350 def __ProcessSubsectionHeader(self
):
1351 self
._SubsectionName
= self
._ValueList
[0]
1352 if self
._SubsectionName
in self
.DataType
:
1353 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
1355 self
._SubsectionType
= MODEL_UNKNOWN
1357 def __RetrievePcdValue(self
):
1358 Content
= open(str(self
.MetaFile
), 'r').readlines()
1359 GlobalData
.gPlatformOtherPcds
['DSCFILE'] = str(self
.MetaFile
)
1360 for PcdType
in (MODEL_PCD_PATCHABLE_IN_MODULE
, MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_HII
,
1361 MODEL_PCD_DYNAMIC_VPD
, MODEL_PCD_DYNAMIC_EX_DEFAULT
, MODEL_PCD_DYNAMIC_EX_HII
,
1362 MODEL_PCD_DYNAMIC_EX_VPD
):
1363 Records
= self
._RawTable
.Query(PcdType
, BelongsToItem
= -1.0)
1364 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1365 Name
= TokenSpaceGuid
+ '.' + PcdName
1366 if Name
not in GlobalData
.gPlatformOtherPcds
:
1368 while not Content
[Line
- 1].lstrip().startswith(TAB_SECTION_START
):
1370 GlobalData
.gPlatformOtherPcds
[Name
] = (CleanString(Content
[Line
- 1]), PcdLine
, PcdType
)
1372 def __ProcessDefine(self
):
1373 if not self
._Enabled
:
1376 Type
, Name
, Value
= self
._ValueList
1377 Value
= ReplaceMacro(Value
, self
._Macros
, False)
1379 # If it is <Defines>, return
1381 if self
._InSubsection
:
1382 self
._ValueList
= [Type
, Name
, Value
]
1385 if self
._ItemType
== MODEL_META_DATA_DEFINE
:
1386 if self
._SectionType
== MODEL_META_DATA_HEADER
:
1387 self
._FileLocalMacros
[Name
] = Value
1389 self
._ConstructSectionMacroDict
(Name
, Value
)
1390 elif self
._ItemType
== MODEL_META_DATA_GLOBAL_DEFINE
:
1391 GlobalData
.gEdkGlobal
[Name
] = Value
1394 # Keyword in [Defines] section can be used as Macros
1396 if (self
._ItemType
== MODEL_META_DATA_HEADER
) and (self
._SectionType
== MODEL_META_DATA_HEADER
):
1397 self
._FileLocalMacros
[Name
] = Value
1399 self
._ValueList
= [Type
, Name
, Value
]
1401 def __ProcessDirective(self
):
1403 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1404 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
]:
1405 Macros
= self
._Macros
1406 Macros
.update(GlobalData
.gGlobalDefines
)
1408 Result
= ValueExpression(self
._ValueList
[1], Macros
)()
1409 except SymbolNotFound
, Exc
:
1410 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1412 except WrnExpression
, Excpt
:
1414 # Catch expression evaluation warning here. We need to report
1415 # the precise number of line and return the evaluation result
1417 EdkLogger
.warn('Parser', "Suspicious expression: %s" % str(Excpt
),
1418 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1419 Line
=self
._LineIndex
+ 1)
1420 Result
= Excpt
.result
1422 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1423 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1424 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1425 self
._DirectiveStack
.append(self
._ItemType
)
1426 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
:
1427 Result
= bool(Result
)
1429 Macro
= self
._ValueList
[1]
1430 Macro
= Macro
[2:-1] if (Macro
.startswith("$(") and Macro
.endswith(")")) else Macro
1431 Result
= Macro
in self
._Macros
1432 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
:
1434 self
._DirectiveEvalStack
.append(Result
)
1435 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
:
1436 self
._DirectiveStack
.append(self
._ItemType
)
1437 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1438 self
._DirectiveEvalStack
.append(bool(Result
))
1439 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1440 self
._DirectiveStack
.append(self
._ItemType
)
1441 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1442 self
._DirectiveEvalStack
.append(True)
1443 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1444 # Back to the nearest !if/!ifdef/!ifndef
1445 while self
._DirectiveStack
:
1446 self
._DirectiveEvalStack
.pop()
1447 Directive
= self
._DirectiveStack
.pop()
1448 if Directive
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1449 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1450 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1452 elif self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1453 # The included file must be relative to workspace or same directory as DSC file
1454 __IncludeMacros
= {}
1456 # Allow using system environment variables in path after !include
1458 __IncludeMacros
['WORKSPACE'] = GlobalData
.gGlobalDefines
['WORKSPACE']
1459 if "ECP_SOURCE" in GlobalData
.gGlobalDefines
.keys():
1460 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gGlobalDefines
['ECP_SOURCE']
1462 # During GenFds phase call DSC parser, will go into this branch.
1464 elif "ECP_SOURCE" in GlobalData
.gCommandLineDefines
.keys():
1465 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gCommandLineDefines
['ECP_SOURCE']
1467 __IncludeMacros
['EFI_SOURCE'] = GlobalData
.gGlobalDefines
['EFI_SOURCE']
1468 __IncludeMacros
['EDK_SOURCE'] = GlobalData
.gGlobalDefines
['EDK_SOURCE']
1470 # Allow using MACROs comes from [Defines] section to keep compatible.
1472 __IncludeMacros
.update(self
._Macros
)
1474 IncludedFile
= NormPath(ReplaceMacro(self
._ValueList
[1], __IncludeMacros
, RaiseError
=True))
1476 # First search the include file under the same directory as DSC file
1478 IncludedFile1
= PathClass(IncludedFile
, self
.MetaFile
.Dir
)
1479 ErrorCode
, ErrorInfo1
= IncludedFile1
.Validate()
1482 # Also search file under the WORKSPACE directory
1484 IncludedFile1
= PathClass(IncludedFile
, GlobalData
.gWorkspace
)
1485 ErrorCode
, ErrorInfo2
= IncludedFile1
.Validate()
1487 EdkLogger
.error('parser', ErrorCode
, File
=self
._FileWithError
,
1488 Line
=self
._LineIndex
+ 1, ExtraData
=ErrorInfo1
+ "\n" + ErrorInfo2
)
1490 self
._FileWithError
= IncludedFile1
1492 IncludedFileTable
= MetaFileStorage(self
._Table
.Cur
, IncludedFile1
, MODEL_FILE_DSC
, False)
1493 Owner
= self
._Content
[self
._ContentIndex
- 1][0]
1494 Parser
= DscParser(IncludedFile1
, self
._FileType
, self
._Arch
, IncludedFileTable
,
1495 Owner
=Owner
, From
=Owner
)
1497 # Does not allow lower level included file to include upper level included file
1498 if Parser
._From
!= Owner
and int(Owner
) > int (Parser
._From
):
1499 EdkLogger
.error('parser', FILE_ALREADY_EXIST
, File
=self
._FileWithError
,
1500 Line
=self
._LineIndex
+ 1, ExtraData
="{0} is already included at a higher level.".format(IncludedFile1
))
1503 # set the parser status with current status
1504 Parser
._SectionName
= self
._SectionName
1505 Parser
._SectionType
= self
._SectionType
1506 Parser
._Scope
= self
._Scope
1507 Parser
._Enabled
= self
._Enabled
1508 # Parse the included file
1511 # update current status with sub-parser's status
1512 self
._SectionName
= Parser
._SectionName
1513 self
._SectionType
= Parser
._SectionType
1514 self
._Scope
= Parser
._Scope
1515 self
._Enabled
= Parser
._Enabled
1517 # Insert all records in the table for the included file into dsc file table
1518 Records
= IncludedFileTable
.GetAll()
1520 self
._Content
[self
._ContentIndex
:self
._ContentIndex
] = Records
1521 self
._Content
.pop(self
._ContentIndex
- 1)
1522 self
._ValueList
= None
1523 self
._ContentIndex
-= 1
1525 def __ProcessSkuId(self
):
1526 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=True)
1527 for Value
in self
._ValueList
]
1529 def __ProcessLibraryInstance(self
):
1530 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
1532 def __ProcessLibraryClass(self
):
1533 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, RaiseError
=True)
1535 def __ProcessPcd(self
):
1536 if self
._ItemType
not in [MODEL_PCD_FEATURE_FLAG
, MODEL_PCD_FIXED_AT_BUILD
]:
1537 self
._ValueList
[2] = ReplaceMacro(self
._ValueList
[2], self
._Macros
, RaiseError
=True)
1540 ValList
, Valid
, Index
= AnalyzeDscPcd(self
._ValueList
[2], self
._ItemType
)
1542 EdkLogger
.error('build', FORMAT_INVALID
, "Pcd format incorrect.", File
=self
._FileWithError
, Line
=self
._LineIndex
+ 1,
1543 ExtraData
="%s.%s|%s" % (self
._ValueList
[0], self
._ValueList
[1], self
._ValueList
[2]))
1544 PcdValue
= ValList
[Index
]
1547 ValList
[Index
] = ValueExpression(PcdValue
, self
._Macros
)(True)
1548 except WrnExpression
, Value
:
1549 ValList
[Index
] = Value
.result
1551 if ValList
[Index
] == 'True':
1552 ValList
[Index
] = '1'
1553 if ValList
[Index
] == 'False':
1554 ValList
[Index
] = '0'
1556 if (not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
):
1557 GlobalData
.gPlatformPcds
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = PcdValue
1558 self
._Symbols
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = PcdValue
1559 self
._ValueList
[2] = '|'.join(ValList
)
1561 def __ProcessComponent(self
):
1562 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1564 def __ProcessSourceOverridePath(self
):
1565 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1567 def __ProcessBuildOption(self
):
1568 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=False)
1569 for Value
in self
._ValueList
]
1572 MODEL_META_DATA_HEADER
: _DefineParser
,
1573 MODEL_EFI_SKU_ID
: _SkuIdParser
,
1574 MODEL_EFI_LIBRARY_INSTANCE
: _LibraryInstanceParser
,
1575 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
1576 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1577 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1578 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1579 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
1580 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
1581 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
1582 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
1583 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
1584 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
1585 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
1586 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: _CompponentSourceOverridePathParser
,
1587 MODEL_META_DATA_BUILD_OPTION
: _BuildOptionParser
,
1588 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1589 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
1590 MODEL_META_DATA_SECTION_HEADER
: MetaFileParser
._SectionHeaderParser
,
1591 MODEL_META_DATA_SUBSECTION_HEADER
: _SubsectionHeaderParser
,
1594 _Macros
= property(_GetMacros
)
1596 ## DEC file parser class
1598 # @param FilePath The path of platform description file
1599 # @param FileType The raw data of DSC file
1600 # @param Table Database used to retrieve module/package information
1601 # @param Macros Macros used for replacement in file
1603 class DecParser(MetaFileParser
):
1604 # DEC file supported data types (one type per section)
1606 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1607 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
1608 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1609 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1610 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1611 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1612 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1613 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1614 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1615 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1616 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1617 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1618 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
,
1621 ## Constructor of DecParser
1623 # Initialize object of DecParser
1625 # @param FilePath The path of platform description file
1626 # @param FileType The raw data of DSC file
1627 # @param Arch Default Arch value for filtering sections
1628 # @param Table Database used to retrieve module/package information
1630 def __init__(self
, FilePath
, FileType
, Arch
, Table
):
1631 # prevent re-initialization
1632 if hasattr(self
, "_Table"):
1634 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Arch
, Table
, -1)
1636 self
._Version
= 0x00010005 # Only EDK2 dec file is supported
1637 self
._AllPCDs
= [] # Only for check duplicate PCD
1638 self
._AllPcdDict
= {}
1644 Content
= open(str(self
.MetaFile
), 'r').readlines()
1646 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1648 for Index
in range(0, len(Content
)):
1649 Line
, Comment
= CleanString2(Content
[Index
])
1650 self
._CurrentLine
= Line
1651 self
._LineIndex
= Index
1653 # save comment for later use
1655 self
._Comments
.append((Comment
, self
._LineIndex
+ 1))
1661 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1662 self
._SectionHeaderParser
()
1665 elif len(self
._SectionType
) == 0:
1670 self
._ValueList
= ['', '', '']
1671 self
._SectionParser
[self
._SectionType
[0]](self
)
1672 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
1678 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1679 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1681 for Arch
, ModuleType
, Type
in self
._Scope
:
1682 self
._LastItem
= self
._Store
(
1690 self
._LineIndex
+ 1,
1692 self
._LineIndex
+ 1,
1696 for Comment
, LineNo
in self
._Comments
:
1698 MODEL_META_DATA_COMMENT
,
1715 ## Section header parser
1717 # The section header is always in following format:
1719 # [section_name.arch<.platform|module_type>]
1721 def _SectionHeaderParser(self
):
1723 self
._SectionName
= ''
1724 self
._SectionType
= []
1727 Line
= self
._CurrentLine
.replace("%s%s" % (TAB_COMMA_SPLIT
, TAB_SPACE_SPLIT
), TAB_COMMA_SPLIT
)
1728 for Item
in Line
[1:-1].split(TAB_COMMA_SPLIT
):
1730 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
,
1731 "section name can NOT be empty or incorrectly use separator comma",
1732 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1733 ItemList
= Item
.split(TAB_SPLIT
)
1735 # different types of PCD are permissible in one section
1736 self
._SectionName
= ItemList
[0].upper()
1737 if self
._SectionName
in self
.DataType
:
1738 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1739 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1741 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
1742 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1744 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1748 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1750 Line
=self
._LineIndex
+ 1,
1751 ExtraData
=self
._CurrentLine
1754 if len(ItemList
) > 1:
1755 S1
= ItemList
[1].upper()
1759 # S2 may be Platform or ModuleType
1760 if len(ItemList
) > 2:
1761 S2
= ItemList
[2].upper()
1762 # only Includes, GUIDs, PPIs, Protocols section have Private tag
1763 if self
._SectionName
in [TAB_INCLUDES
.upper(), TAB_GUIDS
.upper(), TAB_PROTOCOLS
.upper(), TAB_PPIS
.upper()]:
1765 EdkLogger
.error("Parser", FORMAT_INVALID
, 'Please use keyword "Private" as section tag modifier.',
1766 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
1770 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1771 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1773 # 'COMMON' must not be used with specific ARCHs at the same section
1774 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1775 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1776 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
1778 # It is not permissible to mix section tags without the Private attribute with section tags with the Private attribute
1779 if 'COMMON' in PrivateList
and len(PrivateList
) > 1:
1780 EdkLogger
.error('Parser', FORMAT_INVALID
, "Can't mix section tags without the Private attribute with section tags with the Private attribute",
1781 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
1783 ## [guids], [ppis] and [protocols] section parser
1785 def _GuidParser(self
):
1786 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1787 if len(TokenList
) < 2:
1788 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1789 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1790 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1791 if TokenList
[0] == '':
1792 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1793 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1794 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1795 if TokenList
[1] == '':
1796 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1797 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1798 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1799 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1800 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1801 ExtraData
=self
._CurrentLine
+ \
1802 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1803 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1804 self
._ValueList
[0] = TokenList
[0]
1805 self
._ValueList
[1] = TokenList
[1]
1807 ## PCD sections parser
1809 # [PcdsFixedAtBuild]
1810 # [PcdsPatchableInModule]
1816 def _PcdParser(self
):
1817 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1818 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1819 ValueRe
= re
.compile(r
'^[a-zA-Z_][a-zA-Z0-9_]*')
1820 # check PCD information
1821 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1822 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1823 ExtraData
=self
._CurrentLine
+ \
1824 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1825 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1826 # check format of token space GUID CName
1827 if not ValueRe
.match(self
._ValueList
[0]):
1828 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_]*'",
1829 ExtraData
=self
._CurrentLine
+ \
1830 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1831 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1832 # check format of PCD CName
1833 if not ValueRe
.match(self
._ValueList
[1]):
1834 EdkLogger
.error('Parser', FORMAT_INVALID
, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
1835 ExtraData
=self
._CurrentLine
+ \
1836 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1837 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1838 # check PCD datum information
1839 if len(TokenList
) < 2 or TokenList
[1] == '':
1840 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1841 ExtraData
=self
._CurrentLine
+ \
1842 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1843 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1846 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1847 PtrValue
= ValueRe
.findall(TokenList
[1])
1849 # Has VOID* type string, may contain "|" character in the string.
1850 if len(PtrValue
) != 0:
1851 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1852 ValueList
= AnalyzePcdExpression(ptrValueList
)
1853 ValueList
[0] = PtrValue
[0]
1855 ValueList
= AnalyzePcdExpression(TokenList
[1])
1858 # check if there's enough datum information given
1859 if len(ValueList
) != 3:
1860 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1861 ExtraData
=self
._CurrentLine
+ \
1862 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1863 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1864 # check default value
1865 if ValueList
[0] == '':
1866 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1867 ExtraData
=self
._CurrentLine
+ \
1868 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1869 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1871 if ValueList
[1] == '':
1872 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1873 ExtraData
=self
._CurrentLine
+ \
1874 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1875 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1876 # check token of the PCD
1877 if ValueList
[2] == '':
1878 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1879 ExtraData
=self
._CurrentLine
+ \
1880 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1881 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1883 PcdValue
= ValueList
[0]
1886 ValueList
[0] = ValueExpression(PcdValue
, self
._AllPcdDict
)(True)
1887 except WrnExpression
, Value
:
1888 ValueList
[0] = Value
.result
1890 if ValueList
[0] == 'True':
1892 if ValueList
[0] == 'False':
1895 # check format of default value against the datum type
1896 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1898 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1899 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1901 if ValueList
[0] in ['True', 'true', 'TRUE']:
1903 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1906 # check for duplicate PCD definition
1907 if (self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]) in self
._AllPCDs
:
1908 EdkLogger
.error('Parser', FORMAT_INVALID
,
1909 "The same PCD name and GUID have been already defined",
1910 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1912 self
._AllPCDs
.append((self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]))
1913 self
._AllPcdDict
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = ValueList
[0]
1915 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
1918 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
1919 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
1920 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
1921 MODEL_EFI_GUID
: _GuidParser
,
1922 MODEL_EFI_PPI
: _GuidParser
,
1923 MODEL_EFI_PROTOCOL
: _GuidParser
,
1924 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1925 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1926 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1927 MODEL_PCD_DYNAMIC
: _PcdParser
,
1928 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
1929 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1930 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
1935 # This acts like the main() function for the script, unless it is 'import'ed into another
1938 if __name__
== '__main__':