2 # This file is used to parse meta files
4 # Copyright (c) 2008 - 2017, 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 MacroUsed
= GlobalData
.gMacroRefPattern
.findall(Value
)
355 if len(MacroUsed
) != 0:
356 for Macro
in MacroUsed
:
357 if Macro
in GlobalData
.gGlobalDefines
:
358 EdkLogger
.error("Parser", FORMAT_INVALID
, "Global macro %s is not permitted." % (Macro
), ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
360 EdkLogger
.error("Parser", FORMAT_INVALID
, "%s not defined" % (Macro
), ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
361 # Sometimes, we need to make differences between EDK and EDK2 modules
362 if Name
== 'INF_VERSION':
363 if re
.match(r
'0[xX][\da-f-A-F]{5,8}', Value
):
364 self
._Version
= int(Value
, 0)
365 elif re
.match(r
'\d+\.\d+', Value
):
366 ValueList
= Value
.split('.')
367 Major
= '%04o' % int(ValueList
[0], 0)
368 Minor
= '%04o' % int(ValueList
[1], 0)
369 self
._Version
= int('0x' + Major
+ Minor
, 0)
371 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid version number",
372 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
374 if type(self
) == InfParser
and self
._Version
< 0x00010005:
375 # EDK module allows using defines as macros
376 self
._FileLocalMacros
[Name
] = Value
377 self
._Defines
[Name
] = Value
379 ## [BuildOptions] section parser
381 def _BuildOptionParser(self
):
382 self
._CurrentLine
= CleanString(self
._CurrentLine
, BuildOption
=True)
383 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
384 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
385 if len(TokenList2
) == 2:
386 self
._ValueList
[0] = TokenList2
[0] # toolchain family
387 self
._ValueList
[1] = TokenList2
[1] # keys
389 self
._ValueList
[1] = TokenList
[0]
390 if len(TokenList
) == 2 and type(self
) != DscParser
: # value
391 self
._ValueList
[2] = ReplaceMacro(TokenList
[1], self
._Macros
)
393 if self
._ValueList
[1].count('_') != 4:
397 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
398 ExtraData
=self
._CurrentLine
,
400 Line
=self
._LineIndex
+ 1
402 def GetValidExpression(self
, TokenSpaceGuid
, PcdCName
):
403 return self
._Table
.GetValidExpression(TokenSpaceGuid
, PcdCName
)
404 def _GetMacros(self
):
406 Macros
.update(self
._FileLocalMacros
)
407 Macros
.update(self
._GetApplicableSectionMacro
())
410 ## Construct section Macro dict
411 def _ConstructSectionMacroDict(self
, Name
, Value
):
412 ScopeKey
= [(Scope
[0], Scope
[1]) for Scope
in self
._Scope
]
413 ScopeKey
= tuple(ScopeKey
)
414 SectionDictKey
= self
._SectionType
, ScopeKey
416 # DecParser SectionType is a list, will contain more than one item only in Pcd Section
417 # As Pcd section macro usage is not alllowed, so here it is safe
419 if type(self
) == DecParser
:
420 SectionDictKey
= self
._SectionType
[0], ScopeKey
421 if SectionDictKey
not in self
._SectionsMacroDict
:
422 self
._SectionsMacroDict
[SectionDictKey
] = {}
423 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
424 SectionLocalMacros
[Name
] = Value
426 ## Get section Macros that are applicable to current line, which may come from other sections
427 ## that share the same name while scope is wider
428 def _GetApplicableSectionMacro(self
):
435 ActiveSectionType
= self
._SectionType
436 if type(self
) == DecParser
:
437 ActiveSectionType
= self
._SectionType
[0]
439 for (SectionType
, Scope
) in self
._SectionsMacroDict
:
440 if SectionType
!= ActiveSectionType
:
443 for ActiveScope
in self
._Scope
:
444 Scope0
, Scope1
= ActiveScope
[0], ActiveScope
[1]
445 if(Scope0
, Scope1
) not in Scope
:
448 SpeSpeMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
450 for ActiveScope
in self
._Scope
:
451 Scope0
, Scope1
= ActiveScope
[0], ActiveScope
[1]
452 if(Scope0
, Scope1
) not in Scope
and (Scope0
, "COMMON") not in Scope
and ("COMMON", Scope1
) not in Scope
:
455 ComSpeMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
457 if ("COMMON", "COMMON") in Scope
:
458 ComComMacroDict
.update(self
._SectionsMacroDict
[(SectionType
, Scope
)])
460 Macros
.update(ComComMacroDict
)
461 Macros
.update(ComSpeMacroDict
)
462 Macros
.update(SpeSpeMacroDict
)
467 Finished
= property(_GetFinished
, _SetFinished
)
468 _Macros
= property(_GetMacros
)
471 ## INF file parser class
473 # @param FilePath The path of platform description file
474 # @param FileType The raw data of DSC file
475 # @param Table Database used to retrieve module/package information
476 # @param Macros Macros used for replacement in file
478 class InfParser(MetaFileParser
):
479 # INF file supported data types (one type per section)
481 TAB_UNKNOWN
.upper() : MODEL_UNKNOWN
,
482 TAB_INF_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
483 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
484 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
485 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
486 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
487 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
488 TAB_PACKAGES
.upper() : MODEL_META_DATA_PACKAGE
,
489 TAB_NMAKE
.upper() : MODEL_META_DATA_NMAKE
,
490 TAB_INF_FIXED_PCD
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
491 TAB_INF_PATCH_PCD
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
492 TAB_INF_FEATURE_PCD
.upper() : MODEL_PCD_FEATURE_FLAG
,
493 TAB_INF_PCD_EX
.upper() : MODEL_PCD_DYNAMIC_EX
,
494 TAB_INF_PCD
.upper() : MODEL_PCD_DYNAMIC
,
495 TAB_SOURCES
.upper() : MODEL_EFI_SOURCE_FILE
,
496 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
497 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
498 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
499 TAB_DEPEX
.upper() : MODEL_EFI_DEPEX
,
500 TAB_BINARIES
.upper() : MODEL_EFI_BINARY_FILE
,
501 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
504 ## Constructor of InfParser
506 # Initialize object of InfParser
508 # @param FilePath The path of module description file
509 # @param FileType The raw data of DSC file
510 # @param Arch Default Arch value for filtering sections
511 # @param Table Database used to retrieve module/package information
513 def __init__(self
, FilePath
, FileType
, Arch
, Table
):
514 # prevent re-initialization
515 if hasattr(self
, "_Table"):
517 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Arch
, Table
)
525 Content
= open(str(self
.MetaFile
), 'r').readlines()
527 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
529 # parse the file line by line
530 IsFindBlockComment
= False
531 GetHeaderComment
= False
536 for Index
in range(0, len(Content
)):
537 # skip empty, commented, block commented lines
538 Line
, Comment
= CleanString2(Content
[Index
], AllowCppStyleComment
=True)
540 if Index
+ 1 < len(Content
):
541 NextLine
, NextComment
= CleanString2(Content
[Index
+ 1])
544 Comments
.append((Comment
, Index
+ 1))
545 elif GetHeaderComment
:
546 SectionComments
.extend(Comments
)
549 if Line
.find(DataType
.TAB_COMMENT_EDK_START
) > -1:
550 IsFindBlockComment
= True
552 if Line
.find(DataType
.TAB_COMMENT_EDK_END
) > -1:
553 IsFindBlockComment
= False
555 if IsFindBlockComment
:
558 self
._LineIndex
= Index
559 self
._CurrentLine
= Line
562 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
563 if not GetHeaderComment
:
564 for Cmt
, LNo
in Comments
:
565 self
._Store
(MODEL_META_DATA_HEADER_COMMENT
, Cmt
, '', '', 'COMMON',
566 'COMMON', self
._Owner
[-1], LNo
, -1, LNo
, -1, 0)
567 GetHeaderComment
= True
569 TailComments
.extend(SectionComments
+ Comments
)
571 self
._SectionHeaderParser
()
572 # Check invalid sections
573 if self
._Version
< 0x00010005:
574 if self
._SectionType
in [MODEL_META_DATA_BUILD_OPTION
,
575 MODEL_EFI_LIBRARY_CLASS
,
576 MODEL_META_DATA_PACKAGE
,
577 MODEL_PCD_FIXED_AT_BUILD
,
578 MODEL_PCD_PATCHABLE_IN_MODULE
,
579 MODEL_PCD_FEATURE_FLAG
,
580 MODEL_PCD_DYNAMIC_EX
,
585 MODEL_META_DATA_USER_EXTENSION
]:
586 EdkLogger
.error('Parser', FORMAT_INVALID
,
587 "Section [%s] is not allowed in inf file without version" % (self
._SectionName
),
588 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
589 elif self
._SectionType
in [MODEL_EFI_INCLUDE
,
590 MODEL_EFI_LIBRARY_INSTANCE
,
591 MODEL_META_DATA_NMAKE
]:
592 EdkLogger
.error('Parser', FORMAT_INVALID
,
593 "Section [%s] is not allowed in inf file with version 0x%08x" % (self
._SectionName
, self
._Version
),
594 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
596 # merge two lines specified by '\' in section NMAKE
597 elif self
._SectionType
== MODEL_META_DATA_NMAKE
:
600 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
603 if NextLine
[0] == TAB_SECTION_START
and NextLine
[-1] == TAB_SECTION_END
:
604 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
607 NmakeLine
= NmakeLine
+ ' ' + Line
[0:-1]
610 self
._CurrentLine
= NmakeLine
+ Line
614 self
._ValueList
= ['', '', '']
615 # parse current line, result will be put in self._ValueList
616 self
._SectionParser
[self
._SectionType
](self
)
617 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
622 Comments
.append((Comment
, Index
+ 1))
623 if GlobalData
.gOptions
and GlobalData
.gOptions
.CheckUsage
:
624 CheckInfComment(self
._SectionType
, Comments
, str(self
.MetaFile
), Index
+ 1, self
._ValueList
)
626 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
627 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
629 for Arch
, Platform
in self
._Scope
:
630 LastItem
= self
._Store
(self
._SectionType
,
643 for Comment
, LineNo
in Comments
:
644 self
._Store
(MODEL_META_DATA_COMMENT
, Comment
, '', '', Arch
, Platform
,
645 LastItem
, LineNo
, -1, LineNo
, -1, 0)
648 TailComments
.extend(SectionComments
+ Comments
)
649 if IsFindBlockComment
:
650 EdkLogger
.error("Parser", FORMAT_INVALID
, "Open block comments (starting with /*) are expected to end with */",
653 # If there are tail comments in INF file, save to database whatever the comments are
654 for Comment
in TailComments
:
655 self
._Store
(MODEL_META_DATA_TAIL_COMMENT
, Comment
[0], '', '', 'COMMON',
656 'COMMON', self
._Owner
[-1], -1, -1, -1, -1, 0)
659 ## Data parser for the format in which there's path
661 # Only path can have macro used. So we need to replace them before use.
663 def _IncludeParser(self
):
664 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
665 self
._ValueList
[0:len(TokenList
)] = TokenList
666 Macros
= self
._Macros
668 for Index
in range(0, len(self
._ValueList
)):
669 Value
= self
._ValueList
[Index
]
673 if Value
.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value
.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
674 Value
= '$(EDK_SOURCE)' + Value
[17:]
675 if Value
.find('$(EFI_SOURCE)') > -1 or Value
.find('$(EDK_SOURCE)') > -1:
677 elif Value
.startswith('.'):
679 elif Value
.startswith('$('):
682 Value
= '$(EFI_SOURCE)/' + Value
684 self
._ValueList
[Index
] = ReplaceMacro(Value
, Macros
)
686 ## Parse [Sources] section
688 # Only path can have macro used. So we need to replace them before use.
691 def _SourceFileParser(self
):
692 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
693 self
._ValueList
[0:len(TokenList
)] = TokenList
694 Macros
= self
._Macros
695 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
696 if 'COMPONENT_TYPE' in Macros
:
697 if self
._Defines
['COMPONENT_TYPE'].upper() == 'ACPITABLE':
698 self
._ValueList
[0] = GetSplitValueList(self
._ValueList
[0], ' ', 1)[0]
699 if self
._Defines
['BASE_NAME'] == 'Microcode':
701 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
703 ## Parse [Binaries] section
705 # Only path can have macro used. So we need to replace them before use.
708 def _BinaryFileParser(self
):
709 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 2)
710 if len(TokenList
) < 2:
711 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type or path specified",
712 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
713 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
715 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type specified",
716 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
717 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
719 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file path specified",
720 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
721 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
722 self
._ValueList
[0:len(TokenList
)] = TokenList
723 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
725 ## [nmake] section parser (Edk.x style only)
726 def _NmakeParser(self
):
727 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
728 self
._ValueList
[0:len(TokenList
)] = TokenList
730 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
731 # remove self-reference in macro setting
732 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
734 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
736 def _PcdParser(self
):
737 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
738 ValueList
= GetSplitValueList(TokenList
[0], TAB_SPLIT
)
739 if len(ValueList
) != 2:
740 EdkLogger
.error('Parser', FORMAT_INVALID
, "Illegal token space GUID and PCD name format",
741 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
742 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
743 self
._ValueList
[0:1] = ValueList
744 if len(TokenList
) > 1:
745 self
._ValueList
[2] = TokenList
[1]
746 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
747 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
748 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
749 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
751 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
752 if self
._ValueList
[2] != '':
753 InfPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
754 if InfPcdValueList
[0] in ['True', 'true', 'TRUE']:
755 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '1', 1);
756 elif InfPcdValueList
[0] in ['False', 'false', 'FALSE']:
757 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '0', 1);
758 if (self
._ValueList
[0], self
._ValueList
[1]) not in self
.PcdsDict
:
759 self
.PcdsDict
[self
._ValueList
[0], self
._ValueList
[1]] = self
._SectionType
760 elif self
.PcdsDict
[self
._ValueList
[0], self
._ValueList
[1]] != self
._SectionType
:
761 EdkLogger
.error('Parser', FORMAT_INVALID
, "It is not permissible to list a specified PCD in different PCD type sections.",
762 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
763 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
765 ## [depex] section parser
767 def _DepexParser(self
):
768 self
._ValueList
[0:1] = [self
._CurrentLine
]
771 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
772 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
773 MODEL_META_DATA_BUILD_OPTION
: MetaFileParser
._BuildOptionParser
,
774 MODEL_EFI_INCLUDE
: _IncludeParser
, # for Edk.x modules
775 MODEL_EFI_LIBRARY_INSTANCE
: MetaFileParser
._CommonParser
, # for Edk.x modules
776 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
777 MODEL_META_DATA_PACKAGE
: MetaFileParser
._PathParser
,
778 MODEL_META_DATA_NMAKE
: _NmakeParser
, # for Edk.x modules
779 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
780 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
781 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
782 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
783 MODEL_PCD_DYNAMIC
: _PcdParser
,
784 MODEL_EFI_SOURCE_FILE
: _SourceFileParser
,
785 MODEL_EFI_GUID
: MetaFileParser
._CommonParser
,
786 MODEL_EFI_PROTOCOL
: MetaFileParser
._CommonParser
,
787 MODEL_EFI_PPI
: MetaFileParser
._CommonParser
,
788 MODEL_EFI_DEPEX
: _DepexParser
,
789 MODEL_EFI_BINARY_FILE
: _BinaryFileParser
,
790 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
793 ## DSC file parser class
795 # @param FilePath The path of platform description file
796 # @param FileType The raw data of DSC file
797 # @param Table Database used to retrieve module/package information
798 # @param Macros Macros used for replacement in file
799 # @param Owner Owner ID (for sub-section parsing)
800 # @param From ID from which the data comes (for !INCLUDE directive)
802 class DscParser(MetaFileParser
):
803 # DSC file supported data types (one type per section)
805 TAB_SKUIDS
.upper() : MODEL_EFI_SKU_ID
,
806 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
807 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
808 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
809 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
810 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
811 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
812 TAB_PCDS_DYNAMIC_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_DEFAULT
,
813 TAB_PCDS_DYNAMIC_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_HII
,
814 TAB_PCDS_DYNAMIC_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_VPD
,
815 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT
,
816 TAB_PCDS_DYNAMIC_EX_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_HII
,
817 TAB_PCDS_DYNAMIC_EX_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_VPD
,
818 TAB_COMPONENTS
.upper() : MODEL_META_DATA_COMPONENT
,
819 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH
.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
,
820 TAB_DSC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
821 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
822 TAB_DSC_DEFINES_EDKGLOBAL
: MODEL_META_DATA_GLOBAL_DEFINE
,
823 TAB_INCLUDE
.upper() : MODEL_META_DATA_INCLUDE
,
824 TAB_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
825 TAB_IF_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
826 TAB_IF_N_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
,
827 TAB_ELSE_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
,
828 TAB_ELSE
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
829 TAB_END_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
,
830 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
,
833 # Valid names in define section
840 "PCD_INFO_GENERATION",
841 "PCD_VAR_CHECK_GENERATION",
842 "SUPPORTED_ARCHITECTURES",
851 "FIX_LOAD_TOP_MEMORY_ADDRESS",
856 SubSectionDefineKeywords
= [
860 SymbolPattern
= ValueExpression
.SymbolPattern
862 IncludedFiles
= set()
864 ## Constructor of DscParser
866 # Initialize object of DscParser
868 # @param FilePath The path of platform description file
869 # @param FileType The raw data of DSC file
870 # @param Arch Default Arch value for filtering sections
871 # @param Table Database used to retrieve module/package information
872 # @param Owner Owner ID (for sub-section parsing)
873 # @param From ID from which the data comes (for !INCLUDE directive)
875 def __init__(self
, FilePath
, FileType
, Arch
, Table
, Owner
= -1, From
= -1):
876 # prevent re-initialization
877 if hasattr(self
, "_Table"):
879 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Arch
, Table
, Owner
, From
)
880 self
._Version
= 0x00010005 # Only EDK2 dsc file is supported
881 # to store conditional directive evaluation result
882 self
._DirectiveStack
= []
883 self
._DirectiveEvalStack
= []
887 # Specify whether current line is in uncertain condition
889 self
._InDirective
= -1
891 # Final valid replacable symbols
894 # Map the ID between the original table and new table to track
897 self
._IdMapping
= {-1:-1}
903 Content
= open(str(self
.MetaFile
), 'r').readlines()
905 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
908 for Index
in range(0, len(Content
)):
909 Line
= CleanString(Content
[Index
])
914 self
._CurrentLine
= Line
915 self
._LineIndex
= Index
916 if self
._InSubsection
and self
._Owner
[-1] == -1:
917 self
._Owner
.append(self
._LastItem
)
920 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
921 self
._SectionType
= MODEL_META_DATA_SECTION_HEADER
923 elif Line
[0] == '}' and self
._InSubsection
:
924 self
._InSubsection
= False
925 self
._SubsectionType
= MODEL_UNKNOWN
926 self
._SubsectionName
= ''
931 elif Line
[0] == TAB_OPTION_START
and Line
[-1] == TAB_OPTION_END
:
932 self
._SubsectionType
= MODEL_META_DATA_SUBSECTION_HEADER
935 self
._DirectiveParser
()
937 if Line
[0] == TAB_OPTION_START
and not self
._InSubsection
:
938 EdkLogger
.error("Parser", FILE_READ_FAILURE
, "Missing the '{' before %s in Line %s" % (Line
, Index
+1),ExtraData
=self
.MetaFile
)
940 if self
._InSubsection
:
941 SectionType
= self
._SubsectionType
943 SectionType
= self
._SectionType
944 self
._ItemType
= SectionType
946 self
._ValueList
= ['', '', '']
947 self
._SectionParser
[SectionType
](self
)
948 if self
._ValueList
== None:
951 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
952 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
954 for Arch
, ModuleType
in self
._Scope
:
955 Owner
= self
._Owner
[-1]
956 if self
._SubsectionType
!= MODEL_UNKNOWN
:
957 Owner
= OwnerId
[Arch
]
958 self
._LastItem
= self
._Store
(
973 if self
._SubsectionType
== MODEL_UNKNOWN
and self
._InSubsection
:
974 OwnerId
[Arch
] = self
._LastItem
976 if self
._DirectiveStack
:
977 Type
, Line
, Text
= self
._DirectiveStack
[-1]
978 EdkLogger
.error('Parser', FORMAT_INVALID
, "No matching '!endif' found",
979 ExtraData
=Text
, File
=self
.MetaFile
, Line
=Line
)
982 ## <subsection_header> parser
983 def _SubsectionHeaderParser(self
):
984 self
._SubsectionName
= self
._CurrentLine
[1:-1].upper()
985 if self
._SubsectionName
in self
.DataType
:
986 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
988 self
._SubsectionType
= MODEL_UNKNOWN
989 EdkLogger
.warn("Parser", "Unrecognized sub-section", File
=self
.MetaFile
,
990 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
991 self
._ValueList
[0] = self
._SubsectionName
993 ## Directive statement parser
994 def _DirectiveParser(self
):
995 self
._ValueList
= ['', '', '']
996 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
997 self
._ValueList
[0:len(TokenList
)] = TokenList
1000 DirectiveName
= self
._ValueList
[0].upper()
1001 if DirectiveName
not in self
.DataType
:
1002 EdkLogger
.error("Parser", FORMAT_INVALID
, "Unknown directive [%s]" % DirectiveName
,
1003 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1005 if DirectiveName
in ['!IF', '!IFDEF', '!IFNDEF']:
1006 self
._InDirective
+= 1
1008 if DirectiveName
in ['!ENDIF']:
1009 self
._InDirective
-= 1
1011 if DirectiveName
in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self
._ValueList
[1] == '':
1012 EdkLogger
.error("Parser", FORMAT_INVALID
, "Missing expression",
1013 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
1014 ExtraData
=self
._CurrentLine
)
1016 ItemType
= self
.DataType
[DirectiveName
]
1017 Scope
= [['COMMON', 'COMMON']]
1018 if ItemType
== MODEL_META_DATA_INCLUDE
:
1020 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1021 # Remove all directives between !if and !endif, including themselves
1022 while self
._DirectiveStack
:
1023 # Remove any !else or !elseif
1024 DirectiveInfo
= self
._DirectiveStack
.pop()
1025 if DirectiveInfo
[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1026 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1027 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1030 EdkLogger
.error("Parser", FORMAT_INVALID
, "Redundant '!endif'",
1031 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
1032 ExtraData
=self
._CurrentLine
)
1033 elif ItemType
!= MODEL_META_DATA_INCLUDE
:
1034 # Break if there's a !else is followed by a !elseif
1035 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
and \
1036 self
._DirectiveStack
and \
1037 self
._DirectiveStack
[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1038 EdkLogger
.error("Parser", FORMAT_INVALID
, "'!elseif' after '!else'",
1039 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1,
1040 ExtraData
=self
._CurrentLine
)
1041 self
._DirectiveStack
.append((ItemType
, self
._LineIndex
+ 1, self
._CurrentLine
))
1044 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
1045 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
1047 for Arch
, ModuleType
in Scope
:
1048 self
._LastItem
= self
._Store
(
1057 self
._LineIndex
+ 1,
1059 self
._LineIndex
+ 1,
1064 ## [defines] section parser
1066 def _DefineParser(self
):
1067 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1068 self
._ValueList
[1:len(TokenList
)] = TokenList
1071 if not self
._ValueList
[1]:
1072 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
1073 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1074 if not self
._ValueList
[2]:
1075 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
1076 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1077 if (not self
._ValueList
[1] in self
.DefineKeywords
and
1078 (self
._InSubsection
and self
._ValueList
[1] not in self
.SubSectionDefineKeywords
)):
1079 EdkLogger
.error('Parser', FORMAT_INVALID
,
1080 "Unknown keyword found: %s. "
1081 "If this is a macro you must "
1082 "add it as a DEFINE in the DSC" % self
._ValueList
[1],
1083 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1084 if not self
._InSubsection
:
1085 self
._Defines
[self
._ValueList
[1]] = self
._ValueList
[2]
1086 self
._ItemType
= self
.DataType
[TAB_DSC_DEFINES
.upper()]
1089 def _SkuIdParser(self
):
1090 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1091 if len(TokenList
) != 2:
1092 EdkLogger
.error('Parser', FORMAT_INVALID
, "Correct format is '<Integer>|<UiName>'",
1093 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1094 self
._ValueList
[0:len(TokenList
)] = TokenList
1096 ## Parse Edk style of library modules
1098 def _LibraryInstanceParser(self
):
1099 self
._ValueList
[0] = self
._CurrentLine
1101 ## PCD sections parser
1103 # [PcdsFixedAtBuild]
1104 # [PcdsPatchableInModule]
1107 # [PcdsDynamicExDefault]
1108 # [PcdsDynamicExVpd]
1109 # [PcdsDynamicExHii]
1111 # [PcdsDynamicDefault]
1116 def _PcdParser(self
):
1117 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1118 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1119 if len(TokenList
) == 2:
1120 self
._ValueList
[2] = TokenList
[1]
1121 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1122 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1123 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1124 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1125 if self
._ValueList
[2] == '':
1127 # The PCD values are optional for FIXEDATBUILD and PATCHABLEINMODULE
1129 if self
._SectionType
in (MODEL_PCD_FIXED_AT_BUILD
, MODEL_PCD_PATCHABLE_IN_MODULE
):
1131 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD value given",
1132 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1133 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1135 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD
1136 ValueList
= GetSplitValueList(self
._ValueList
[2])
1137 if len(ValueList
) > 1 and ValueList
[1] != TAB_VOID \
1138 and self
._ItemType
in [MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_EX_DEFAULT
]:
1139 EdkLogger
.error('Parser', FORMAT_INVALID
, "The datum type '%s' of PCD is wrong" % ValueList
[1],
1140 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1142 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1143 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
1144 if DscPcdValueList
[0] in ['True', 'true', 'TRUE']:
1145 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '1', 1);
1146 elif DscPcdValueList
[0] in ['False', 'false', 'FALSE']:
1147 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '0', 1);
1150 ## [components] section parser
1152 def _ComponentParser(self
):
1153 if self
._CurrentLine
[-1] == '{':
1154 self
._ValueList
[0] = self
._CurrentLine
[0:-1].strip()
1155 self
._InSubsection
= True
1157 self
._ValueList
[0] = self
._CurrentLine
1159 ## [LibraryClasses] section
1161 def _LibraryClassParser(self
):
1162 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1163 if len(TokenList
) < 2:
1164 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class or instance specified",
1165 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1166 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1167 if TokenList
[0] == '':
1168 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class specified",
1169 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1170 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1171 if TokenList
[1] == '':
1172 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library instance specified",
1173 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1174 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1176 self
._ValueList
[0:len(TokenList
)] = TokenList
1178 def _CompponentSourceOverridePathParser(self
):
1179 self
._ValueList
[0] = self
._CurrentLine
1181 ## [BuildOptions] section parser
1183 def _BuildOptionParser(self
):
1184 self
._CurrentLine
= CleanString(self
._CurrentLine
, BuildOption
=True)
1185 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1186 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
1187 if len(TokenList2
) == 2:
1188 self
._ValueList
[0] = TokenList2
[0] # toolchain family
1189 self
._ValueList
[1] = TokenList2
[1] # keys
1191 self
._ValueList
[1] = TokenList
[0]
1192 if len(TokenList
) == 2: # value
1193 self
._ValueList
[2] = TokenList
[1]
1195 if self
._ValueList
[1].count('_') != 4:
1199 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
1200 ExtraData
=self
._CurrentLine
,
1202 Line
=self
._LineIndex
+ 1
1205 ## Override parent's method since we'll do all macro replacements in parser
1206 def _GetMacros(self
):
1208 Macros
.update(self
._FileLocalMacros
)
1209 Macros
.update(self
._GetApplicableSectionMacro
())
1210 Macros
.update(GlobalData
.gEdkGlobal
)
1211 Macros
.update(GlobalData
.gPlatformDefines
)
1212 Macros
.update(GlobalData
.gCommandLineDefines
)
1213 # PCD cannot be referenced in macro definition
1214 if self
._ItemType
not in [MODEL_META_DATA_DEFINE
, MODEL_META_DATA_GLOBAL_DEFINE
]:
1215 Macros
.update(self
._Symbols
)
1218 def _PostProcess(self
):
1220 MODEL_META_DATA_SECTION_HEADER
: self
.__ProcessSectionHeader
,
1221 MODEL_META_DATA_SUBSECTION_HEADER
: self
.__ProcessSubsectionHeader
,
1222 MODEL_META_DATA_HEADER
: self
.__ProcessDefine
,
1223 MODEL_META_DATA_DEFINE
: self
.__ProcessDefine
,
1224 MODEL_META_DATA_GLOBAL_DEFINE
: self
.__ProcessDefine
,
1225 MODEL_META_DATA_INCLUDE
: self
.__ProcessDirective
,
1226 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
: self
.__ProcessDirective
,
1227 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
: self
.__ProcessDirective
,
1228 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
: self
.__ProcessDirective
,
1229 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
: self
.__ProcessDirective
,
1230 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
: self
.__ProcessDirective
,
1231 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
: self
.__ProcessDirective
,
1232 MODEL_EFI_SKU_ID
: self
.__ProcessSkuId
,
1233 MODEL_EFI_LIBRARY_INSTANCE
: self
.__ProcessLibraryInstance
,
1234 MODEL_EFI_LIBRARY_CLASS
: self
.__ProcessLibraryClass
,
1235 MODEL_PCD_FIXED_AT_BUILD
: self
.__ProcessPcd
,
1236 MODEL_PCD_PATCHABLE_IN_MODULE
: self
.__ProcessPcd
,
1237 MODEL_PCD_FEATURE_FLAG
: self
.__ProcessPcd
,
1238 MODEL_PCD_DYNAMIC_DEFAULT
: self
.__ProcessPcd
,
1239 MODEL_PCD_DYNAMIC_HII
: self
.__ProcessPcd
,
1240 MODEL_PCD_DYNAMIC_VPD
: self
.__ProcessPcd
,
1241 MODEL_PCD_DYNAMIC_EX_DEFAULT
: self
.__ProcessPcd
,
1242 MODEL_PCD_DYNAMIC_EX_HII
: self
.__ProcessPcd
,
1243 MODEL_PCD_DYNAMIC_EX_VPD
: self
.__ProcessPcd
,
1244 MODEL_META_DATA_COMPONENT
: self
.__ProcessComponent
,
1245 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: self
.__ProcessSourceOverridePath
,
1246 MODEL_META_DATA_BUILD_OPTION
: self
.__ProcessBuildOption
,
1247 MODEL_UNKNOWN
: self
._Skip
,
1248 MODEL_META_DATA_USER_EXTENSION
: self
._SkipUserExtension
,
1251 self
._Table
= MetaFileStorage(self
._RawTable
.Cur
, self
.MetaFile
, MODEL_FILE_DSC
, True)
1252 self
._Table
.Create()
1253 self
._DirectiveStack
= []
1254 self
._DirectiveEvalStack
= []
1255 self
._FileWithError
= self
.MetaFile
1256 self
._FileLocalMacros
= {}
1257 self
._SectionsMacroDict
= {}
1258 GlobalData
.gPlatformDefines
= {}
1260 # Get all macro and PCD which has straitforward value
1261 self
.__RetrievePcdValue
()
1262 self
._Content
= self
._RawTable
.GetAll()
1263 self
._ContentIndex
= 0
1264 self
._InSubsection
= False
1265 while self
._ContentIndex
< len(self
._Content
) :
1266 Id
, self
._ItemType
, V1
, V2
, V3
, S1
, S2
, Owner
, self
._From
, \
1267 LineStart
, ColStart
, LineEnd
, ColEnd
, Enabled
= self
._Content
[self
._ContentIndex
]
1270 self
._FileWithError
= self
.MetaFile
1272 self
._ContentIndex
+= 1
1274 self
._Scope
= [[S1
, S2
]]
1276 # For !include directive, handle it specially,
1277 # merge arch and module type in case of duplicate items
1279 while self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1280 if self
._ContentIndex
>= len(self
._Content
):
1282 Record
= self
._Content
[self
._ContentIndex
]
1283 if LineStart
== Record
[9] and LineEnd
== Record
[11]:
1284 if [Record
[5], Record
[6]] not in self
._Scope
:
1285 self
._Scope
.append([Record
[5], Record
[6]])
1286 self
._ContentIndex
+= 1
1290 self
._LineIndex
= LineStart
- 1
1291 self
._ValueList
= [V1
, V2
, V3
]
1293 if Owner
> 0 and Owner
in self
._IdMapping
:
1294 self
._InSubsection
= True
1296 self
._InSubsection
= False
1298 Processer
[self
._ItemType
]()
1299 except EvaluationException
, Excpt
:
1301 # Only catch expression evaluation error here. We need to report
1302 # the precise number of line on which the error occurred
1304 if hasattr(Excpt
, 'Pcd'):
1305 if Excpt
.Pcd
in GlobalData
.gPlatformOtherPcds
:
1306 Info
= GlobalData
.gPlatformOtherPcds
[Excpt
.Pcd
]
1307 EdkLogger
.error('Parser', FORMAT_INVALID
, "Cannot use this PCD (%s) in an expression as"
1308 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
1309 " of the DSC file, and it is currently defined in this section:"
1310 " %s, line #: %d." % (Excpt
.Pcd
, Info
[0], Info
[1]),
1311 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1312 Line
=self
._LineIndex
+ 1)
1314 EdkLogger
.error('Parser', FORMAT_INVALID
, "PCD (%s) is not defined in DSC file" % Excpt
.Pcd
,
1315 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1316 Line
=self
._LineIndex
+ 1)
1318 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid expression: %s" % str(Excpt
),
1319 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1320 Line
=self
._LineIndex
+ 1)
1321 except MacroException
, Excpt
:
1322 EdkLogger
.error('Parser', FORMAT_INVALID
, str(Excpt
),
1323 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1324 Line
=self
._LineIndex
+ 1)
1326 if self
._ValueList
== None:
1329 NewOwner
= self
._IdMapping
.get(Owner
, -1)
1330 self
._Enabled
= int((not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
))
1331 self
._LastItem
= self
._Store
(
1340 self
._LineIndex
+ 1,
1342 self
._LineIndex
+ 1,
1346 self
._IdMapping
[Id
] = self
._LastItem
1348 GlobalData
.gPlatformDefines
.update(self
._FileLocalMacros
)
1349 self
._PostProcessed
= True
1350 self
._Content
= None
1352 def __ProcessSectionHeader(self
):
1353 self
._SectionName
= self
._ValueList
[0]
1354 if self
._SectionName
in self
.DataType
:
1355 self
._SectionType
= self
.DataType
[self
._SectionName
]
1357 self
._SectionType
= MODEL_UNKNOWN
1359 def __ProcessSubsectionHeader(self
):
1360 self
._SubsectionName
= self
._ValueList
[0]
1361 if self
._SubsectionName
in self
.DataType
:
1362 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
1364 self
._SubsectionType
= MODEL_UNKNOWN
1366 def __RetrievePcdValue(self
):
1367 Content
= open(str(self
.MetaFile
), 'r').readlines()
1368 GlobalData
.gPlatformOtherPcds
['DSCFILE'] = str(self
.MetaFile
)
1369 for PcdType
in (MODEL_PCD_PATCHABLE_IN_MODULE
, MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_HII
,
1370 MODEL_PCD_DYNAMIC_VPD
, MODEL_PCD_DYNAMIC_EX_DEFAULT
, MODEL_PCD_DYNAMIC_EX_HII
,
1371 MODEL_PCD_DYNAMIC_EX_VPD
):
1372 Records
= self
._RawTable
.Query(PcdType
, BelongsToItem
= -1.0)
1373 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1374 Name
= TokenSpaceGuid
+ '.' + PcdName
1375 if Name
not in GlobalData
.gPlatformOtherPcds
:
1377 while not Content
[Line
- 1].lstrip().startswith(TAB_SECTION_START
):
1379 GlobalData
.gPlatformOtherPcds
[Name
] = (CleanString(Content
[Line
- 1]), PcdLine
, PcdType
)
1381 def __ProcessDefine(self
):
1382 if not self
._Enabled
:
1385 Type
, Name
, Value
= self
._ValueList
1386 Value
= ReplaceMacro(Value
, self
._Macros
, False)
1388 # If it is <Defines>, return
1390 if self
._InSubsection
:
1391 self
._ValueList
= [Type
, Name
, Value
]
1394 if self
._ItemType
== MODEL_META_DATA_DEFINE
:
1395 if self
._SectionType
== MODEL_META_DATA_HEADER
:
1396 self
._FileLocalMacros
[Name
] = Value
1398 self
._ConstructSectionMacroDict
(Name
, Value
)
1399 elif self
._ItemType
== MODEL_META_DATA_GLOBAL_DEFINE
:
1400 GlobalData
.gEdkGlobal
[Name
] = Value
1403 # Keyword in [Defines] section can be used as Macros
1405 if (self
._ItemType
== MODEL_META_DATA_HEADER
) and (self
._SectionType
== MODEL_META_DATA_HEADER
):
1406 self
._FileLocalMacros
[Name
] = Value
1408 self
._ValueList
= [Type
, Name
, Value
]
1410 def __ProcessDirective(self
):
1412 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1413 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
]:
1414 Macros
= self
._Macros
1415 Macros
.update(GlobalData
.gGlobalDefines
)
1417 Result
= ValueExpression(self
._ValueList
[1], Macros
)()
1418 except SymbolNotFound
, Exc
:
1419 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1421 except WrnExpression
, Excpt
:
1423 # Catch expression evaluation warning here. We need to report
1424 # the precise number of line and return the evaluation result
1426 EdkLogger
.warn('Parser', "Suspicious expression: %s" % str(Excpt
),
1427 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1428 Line
=self
._LineIndex
+ 1)
1429 Result
= Excpt
.result
1431 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1432 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1433 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1434 self
._DirectiveStack
.append(self
._ItemType
)
1435 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
:
1436 Result
= bool(Result
)
1438 Macro
= self
._ValueList
[1]
1439 Macro
= Macro
[2:-1] if (Macro
.startswith("$(") and Macro
.endswith(")")) else Macro
1440 Result
= Macro
in self
._Macros
1441 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
:
1443 self
._DirectiveEvalStack
.append(Result
)
1444 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
:
1445 self
._DirectiveStack
.append(self
._ItemType
)
1446 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1447 self
._DirectiveEvalStack
.append(bool(Result
))
1448 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1449 self
._DirectiveStack
.append(self
._ItemType
)
1450 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1451 self
._DirectiveEvalStack
.append(True)
1452 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1453 # Back to the nearest !if/!ifdef/!ifndef
1454 while self
._DirectiveStack
:
1455 self
._DirectiveEvalStack
.pop()
1456 Directive
= self
._DirectiveStack
.pop()
1457 if Directive
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1458 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1459 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1461 elif self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1462 # The included file must be relative to workspace or same directory as DSC file
1463 __IncludeMacros
= {}
1465 # Allow using system environment variables in path after !include
1467 __IncludeMacros
['WORKSPACE'] = GlobalData
.gGlobalDefines
['WORKSPACE']
1468 if "ECP_SOURCE" in GlobalData
.gGlobalDefines
.keys():
1469 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gGlobalDefines
['ECP_SOURCE']
1471 # During GenFds phase call DSC parser, will go into this branch.
1473 elif "ECP_SOURCE" in GlobalData
.gCommandLineDefines
.keys():
1474 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gCommandLineDefines
['ECP_SOURCE']
1476 __IncludeMacros
['EFI_SOURCE'] = GlobalData
.gGlobalDefines
['EFI_SOURCE']
1477 __IncludeMacros
['EDK_SOURCE'] = GlobalData
.gGlobalDefines
['EDK_SOURCE']
1479 # Allow using MACROs comes from [Defines] section to keep compatible.
1481 __IncludeMacros
.update(self
._Macros
)
1483 IncludedFile
= NormPath(ReplaceMacro(self
._ValueList
[1], __IncludeMacros
, RaiseError
=True))
1485 # First search the include file under the same directory as DSC file
1487 IncludedFile1
= PathClass(IncludedFile
, self
.MetaFile
.Dir
)
1488 ErrorCode
, ErrorInfo1
= IncludedFile1
.Validate()
1491 # Also search file under the WORKSPACE directory
1493 IncludedFile1
= PathClass(IncludedFile
, GlobalData
.gWorkspace
)
1494 ErrorCode
, ErrorInfo2
= IncludedFile1
.Validate()
1496 EdkLogger
.error('parser', ErrorCode
, File
=self
._FileWithError
,
1497 Line
=self
._LineIndex
+ 1, ExtraData
=ErrorInfo1
+ "\n" + ErrorInfo2
)
1499 self
._FileWithError
= IncludedFile1
1501 IncludedFileTable
= MetaFileStorage(self
._Table
.Cur
, IncludedFile1
, MODEL_FILE_DSC
, False)
1502 Owner
= self
._Content
[self
._ContentIndex
- 1][0]
1503 Parser
= DscParser(IncludedFile1
, self
._FileType
, self
._Arch
, IncludedFileTable
,
1504 Owner
=Owner
, From
=Owner
)
1506 self
.IncludedFiles
.add (IncludedFile1
)
1508 # Does not allow lower level included file to include upper level included file
1509 if Parser
._From
!= Owner
and int(Owner
) > int (Parser
._From
):
1510 EdkLogger
.error('parser', FILE_ALREADY_EXIST
, File
=self
._FileWithError
,
1511 Line
=self
._LineIndex
+ 1, ExtraData
="{0} is already included at a higher level.".format(IncludedFile1
))
1514 # set the parser status with current status
1515 Parser
._SectionName
= self
._SectionName
1516 Parser
._SectionType
= self
._SectionType
1517 Parser
._Scope
= self
._Scope
1518 Parser
._Enabled
= self
._Enabled
1519 # Parse the included file
1522 # update current status with sub-parser's status
1523 self
._SectionName
= Parser
._SectionName
1524 self
._SectionType
= Parser
._SectionType
1525 self
._Scope
= Parser
._Scope
1526 self
._Enabled
= Parser
._Enabled
1528 # Insert all records in the table for the included file into dsc file table
1529 Records
= IncludedFileTable
.GetAll()
1531 self
._Content
[self
._ContentIndex
:self
._ContentIndex
] = Records
1532 self
._Content
.pop(self
._ContentIndex
- 1)
1533 self
._ValueList
= None
1534 self
._ContentIndex
-= 1
1536 def __ProcessSkuId(self
):
1537 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=True)
1538 for Value
in self
._ValueList
]
1540 def __ProcessLibraryInstance(self
):
1541 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
1543 def __ProcessLibraryClass(self
):
1544 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, RaiseError
=True)
1546 def __ProcessPcd(self
):
1547 if self
._ItemType
not in [MODEL_PCD_FEATURE_FLAG
, MODEL_PCD_FIXED_AT_BUILD
]:
1548 self
._ValueList
[2] = ReplaceMacro(self
._ValueList
[2], self
._Macros
, RaiseError
=True)
1551 ValList
, Valid
, Index
= AnalyzeDscPcd(self
._ValueList
[2], self
._ItemType
)
1553 EdkLogger
.error('build', FORMAT_INVALID
, "Pcd format incorrect.", File
=self
._FileWithError
, Line
=self
._LineIndex
+ 1,
1554 ExtraData
="%s.%s|%s" % (self
._ValueList
[0], self
._ValueList
[1], self
._ValueList
[2]))
1555 PcdValue
= ValList
[Index
]
1558 ValList
[Index
] = ValueExpression(PcdValue
, self
._Macros
)(True)
1559 except WrnExpression
, Value
:
1560 ValList
[Index
] = Value
.result
1562 if ValList
[Index
] == 'True':
1563 ValList
[Index
] = '1'
1564 if ValList
[Index
] == 'False':
1565 ValList
[Index
] = '0'
1567 if (not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
):
1568 GlobalData
.gPlatformPcds
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = PcdValue
1569 self
._Symbols
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = PcdValue
1570 self
._ValueList
[2] = '|'.join(ValList
)
1572 def __ProcessComponent(self
):
1573 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1575 def __ProcessSourceOverridePath(self
):
1576 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1578 def __ProcessBuildOption(self
):
1579 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=False)
1580 for Value
in self
._ValueList
]
1583 MODEL_META_DATA_HEADER
: _DefineParser
,
1584 MODEL_EFI_SKU_ID
: _SkuIdParser
,
1585 MODEL_EFI_LIBRARY_INSTANCE
: _LibraryInstanceParser
,
1586 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
1587 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1588 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1589 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1590 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
1591 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
1592 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
1593 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
1594 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
1595 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
1596 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
1597 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: _CompponentSourceOverridePathParser
,
1598 MODEL_META_DATA_BUILD_OPTION
: _BuildOptionParser
,
1599 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1600 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
1601 MODEL_META_DATA_SECTION_HEADER
: MetaFileParser
._SectionHeaderParser
,
1602 MODEL_META_DATA_SUBSECTION_HEADER
: _SubsectionHeaderParser
,
1605 _Macros
= property(_GetMacros
)
1607 ## DEC file parser class
1609 # @param FilePath The path of platform description file
1610 # @param FileType The raw data of DSC file
1611 # @param Table Database used to retrieve module/package information
1612 # @param Macros Macros used for replacement in file
1614 class DecParser(MetaFileParser
):
1615 # DEC file supported data types (one type per section)
1617 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1618 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
1619 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1620 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1621 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1622 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1623 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1624 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1625 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1626 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1627 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1628 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1629 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
,
1632 ## Constructor of DecParser
1634 # Initialize object of DecParser
1636 # @param FilePath The path of platform description file
1637 # @param FileType The raw data of DSC file
1638 # @param Arch Default Arch value for filtering sections
1639 # @param Table Database used to retrieve module/package information
1641 def __init__(self
, FilePath
, FileType
, Arch
, Table
):
1642 # prevent re-initialization
1643 if hasattr(self
, "_Table"):
1645 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Arch
, Table
, -1)
1647 self
._Version
= 0x00010005 # Only EDK2 dec file is supported
1648 self
._AllPCDs
= [] # Only for check duplicate PCD
1649 self
._AllPcdDict
= {}
1655 Content
= open(str(self
.MetaFile
), 'r').readlines()
1657 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1659 self
._DefinesCount
= 0
1660 for Index
in range(0, len(Content
)):
1661 Line
, Comment
= CleanString2(Content
[Index
])
1662 self
._CurrentLine
= Line
1663 self
._LineIndex
= Index
1665 # save comment for later use
1667 self
._Comments
.append((Comment
, self
._LineIndex
+ 1))
1673 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1674 self
._SectionHeaderParser
()
1675 if self
._SectionName
== TAB_DEC_DEFINES
.upper():
1676 self
._DefinesCount
+= 1
1679 if self
._SectionType
== MODEL_UNKNOWN
:
1680 EdkLogger
.error("Parser", FORMAT_INVALID
,
1682 "Not able to determine \"%s\" in which section."%self
._CurrentLine
,
1683 self
.MetaFile
, self
._LineIndex
+ 1)
1684 elif len(self
._SectionType
) == 0:
1689 self
._ValueList
= ['', '', '']
1690 self
._SectionParser
[self
._SectionType
[0]](self
)
1691 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
1697 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1698 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1700 for Arch
, ModuleType
, Type
in self
._Scope
:
1701 self
._LastItem
= self
._Store
(
1709 self
._LineIndex
+ 1,
1711 self
._LineIndex
+ 1,
1715 for Comment
, LineNo
in self
._Comments
:
1717 MODEL_META_DATA_COMMENT
,
1731 if self
._DefinesCount
> 1:
1732 EdkLogger
.error('Parser', FORMAT_INVALID
, 'Multiple [Defines] section is exist.', self
.MetaFile
)
1733 if self
._DefinesCount
== 0:
1734 EdkLogger
.error('Parser', FORMAT_INVALID
, 'No [Defines] section exist.',self
.MetaFile
)
1738 ## Section header parser
1740 # The section header is always in following format:
1742 # [section_name.arch<.platform|module_type>]
1744 def _SectionHeaderParser(self
):
1746 self
._SectionName
= ''
1747 self
._SectionType
= []
1750 Line
= self
._CurrentLine
.replace("%s%s" % (TAB_COMMA_SPLIT
, TAB_SPACE_SPLIT
), TAB_COMMA_SPLIT
)
1751 for Item
in Line
[1:-1].split(TAB_COMMA_SPLIT
):
1753 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
,
1754 "section name can NOT be empty or incorrectly use separator comma",
1755 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1756 ItemList
= Item
.split(TAB_SPLIT
)
1758 # different types of PCD are permissible in one section
1759 self
._SectionName
= ItemList
[0].upper()
1760 if self
._SectionName
== TAB_DEC_DEFINES
.upper() and (len(ItemList
) > 1 or len(Line
.split(TAB_COMMA_SPLIT
)) > 1):
1761 EdkLogger
.error("Parser", FORMAT_INVALID
, "Defines section format is invalid",
1762 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1763 if self
._SectionName
in self
.DataType
:
1764 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1765 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1767 EdkLogger
.error("Parser", FORMAT_UNKNOWN_ERROR
, "%s is not a valid section name" % Item
,
1768 self
.MetaFile
, self
._LineIndex
+ 1, self
._CurrentLine
)
1770 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1774 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1776 Line
=self
._LineIndex
+ 1,
1777 ExtraData
=self
._CurrentLine
1780 if len(ItemList
) > 1:
1781 S1
= ItemList
[1].upper()
1785 # S2 may be Platform or ModuleType
1786 if len(ItemList
) > 2:
1787 S2
= ItemList
[2].upper()
1788 # only Includes, GUIDs, PPIs, Protocols section have Private tag
1789 if self
._SectionName
in [TAB_INCLUDES
.upper(), TAB_GUIDS
.upper(), TAB_PROTOCOLS
.upper(), TAB_PPIS
.upper()]:
1791 EdkLogger
.error("Parser", FORMAT_INVALID
, 'Please use keyword "Private" as section tag modifier.',
1792 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
1796 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1797 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1799 # 'COMMON' must not be used with specific ARCHs at the same section
1800 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1801 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1802 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
1804 # It is not permissible to mix section tags without the Private attribute with section tags with the Private attribute
1805 if 'COMMON' in PrivateList
and len(PrivateList
) > 1:
1806 EdkLogger
.error('Parser', FORMAT_INVALID
, "Can't mix section tags without the Private attribute with section tags with the Private attribute",
1807 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
)
1809 ## [guids], [ppis] and [protocols] section parser
1811 def _GuidParser(self
):
1812 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1813 if len(TokenList
) < 2:
1814 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1815 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1816 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1817 if TokenList
[0] == '':
1818 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1819 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1820 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1821 if TokenList
[1] == '':
1822 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1823 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1824 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1825 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1826 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1827 ExtraData
=self
._CurrentLine
+ \
1828 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1829 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1830 self
._ValueList
[0] = TokenList
[0]
1831 self
._ValueList
[1] = TokenList
[1]
1833 ## PCD sections parser
1835 # [PcdsFixedAtBuild]
1836 # [PcdsPatchableInModule]
1842 def _PcdParser(self
):
1843 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1844 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1845 ValueRe
= re
.compile(r
'^[a-zA-Z_][a-zA-Z0-9_]*')
1846 # check PCD information
1847 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1848 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1849 ExtraData
=self
._CurrentLine
+ \
1850 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1851 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1852 # check format of token space GUID CName
1853 if not ValueRe
.match(self
._ValueList
[0]):
1854 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_]*'",
1855 ExtraData
=self
._CurrentLine
+ \
1856 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1857 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1858 # check format of PCD CName
1859 if not ValueRe
.match(self
._ValueList
[1]):
1860 EdkLogger
.error('Parser', FORMAT_INVALID
, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
1861 ExtraData
=self
._CurrentLine
+ \
1862 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1863 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1864 # check PCD datum information
1865 if len(TokenList
) < 2 or TokenList
[1] == '':
1866 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1867 ExtraData
=self
._CurrentLine
+ \
1868 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1869 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1872 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1873 PtrValue
= ValueRe
.findall(TokenList
[1])
1875 # Has VOID* type string, may contain "|" character in the string.
1876 if len(PtrValue
) != 0:
1877 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1878 ValueList
= AnalyzePcdExpression(ptrValueList
)
1879 ValueList
[0] = PtrValue
[0]
1881 ValueList
= AnalyzePcdExpression(TokenList
[1])
1884 # check if there's enough datum information given
1885 if len(ValueList
) != 3:
1886 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1887 ExtraData
=self
._CurrentLine
+ \
1888 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1889 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1890 # check default value
1891 if ValueList
[0] == '':
1892 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1893 ExtraData
=self
._CurrentLine
+ \
1894 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1895 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1897 if ValueList
[1] == '':
1898 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1899 ExtraData
=self
._CurrentLine
+ \
1900 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1901 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1902 # check token of the PCD
1903 if ValueList
[2] == '':
1904 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1905 ExtraData
=self
._CurrentLine
+ \
1906 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1907 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1909 PcdValue
= ValueList
[0]
1912 ValueList
[0] = ValueExpression(PcdValue
, self
._AllPcdDict
)(True)
1913 except WrnExpression
, Value
:
1914 ValueList
[0] = Value
.result
1916 if ValueList
[0] == 'True':
1918 if ValueList
[0] == 'False':
1921 # check format of default value against the datum type
1922 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1924 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1925 File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1927 if ValueList
[0] in ['True', 'true', 'TRUE']:
1929 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1932 # check for duplicate PCD definition
1933 if (self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]) in self
._AllPCDs
:
1934 EdkLogger
.error('Parser', FORMAT_INVALID
,
1935 "The same PCD name and GUID have been already defined",
1936 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+ 1)
1938 self
._AllPCDs
.append((self
._Scope
[0], self
._ValueList
[0], self
._ValueList
[1]))
1939 self
._AllPcdDict
[TAB_SPLIT
.join(self
._ValueList
[0:2])] = ValueList
[0]
1941 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
1944 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
1945 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
1946 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
1947 MODEL_EFI_GUID
: _GuidParser
,
1948 MODEL_EFI_PPI
: _GuidParser
,
1949 MODEL_EFI_PROTOCOL
: _GuidParser
,
1950 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1951 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1952 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1953 MODEL_PCD_DYNAMIC
: _PcdParser
,
1954 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
1955 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1956 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._SkipUserExtension
,
1961 # This acts like the main() function for the script, unless it is 'import'ed into another
1964 if __name__
== '__main__':