2 # This file contained the parser for sections in INF file
4 # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
6 # SPDX-License-Identifier: BSD-2-Clause-Patent
15 from copy
import deepcopy
18 from Library
.StringUtils
import GetSplitValueList
19 from Library
.CommentParsing
import ParseHeaderCommentSection
20 from Library
.CommentParsing
import ParseComment
22 from Library
import DataType
as DT
24 import Logger
.Log
as Logger
25 from Logger
import StringTable
as ST
26 from Logger
.ToolError
import FORMAT_INVALID
28 from Object
.Parser
.InfDefineObject
import InfDefObject
29 from Object
.Parser
.InfBuildOptionObject
import InfBuildOptionsObject
30 from Object
.Parser
.InfLibraryClassesObject
import InfLibraryClassObject
31 from Object
.Parser
.InfPackagesObject
import InfPackageObject
32 from Object
.Parser
.InfPcdObject
import InfPcdObject
33 from Object
.Parser
.InfSoucesObject
import InfSourcesObject
34 from Object
.Parser
.InfUserExtensionObject
import InfUserExtensionObject
35 from Object
.Parser
.InfProtocolObject
import InfProtocolObject
36 from Object
.Parser
.InfPpiObject
import InfPpiObject
37 from Object
.Parser
.InfGuidObject
import InfGuidObject
38 from Object
.Parser
.InfDepexObject
import InfDepexObject
39 from Object
.Parser
.InfBinaryObject
import InfBinariesObject
40 from Object
.Parser
.InfHeaderObject
import InfHeaderObject
41 from Object
.Parser
.InfMisc
import InfSpecialCommentObject
42 from Object
.Parser
.InfMisc
import InfHobObject
43 from Object
.Parser
.InfMisc
import InfBootModeObject
44 from Object
.Parser
.InfMisc
import InfEventObject
45 from Parser
.InfParserMisc
import gINF_SECTION_DEF
46 from Parser
.InfDefineSectionParser
import InfDefinSectionParser
47 from Parser
.InfBuildOptionSectionParser
import InfBuildOptionSectionParser
48 from Parser
.InfSourceSectionParser
import InfSourceSectionParser
49 from Parser
.InfLibrarySectionParser
import InfLibrarySectionParser
50 from Parser
.InfPackageSectionParser
import InfPackageSectionParser
51 from Parser
.InfGuidPpiProtocolSectionParser
import InfGuidPpiProtocolSectionParser
52 from Parser
.InfBinarySectionParser
import InfBinarySectionParser
53 from Parser
.InfPcdSectionParser
import InfPcdSectionParser
54 from Parser
.InfDepexSectionParser
import InfDepexSectionParser
60 def GetSpecialStr2(ItemList
, FileName
, LineNo
, SectionString
):
63 # S2 may be Platform or ModuleType
65 if len(ItemList
) == 3:
67 # Except [LibraryClass], [Depex]
68 # section can has more than 2 items in section header string,
69 # others should report error.
71 if not (ItemList
[0].upper() == DT
.TAB_LIBRARY_CLASSES
.upper() or \
72 ItemList
[0].upper() == DT
.TAB_DEPEX
.upper() or \
73 ItemList
[0].upper() == DT
.TAB_USER_EXTENSIONS
.upper()):
75 Logger
.Error('Parser',
77 ST
.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID
% (SectionString
),
80 ExtraData
=SectionString
)
82 elif len(ItemList
) == 4:
84 # Except [UserExtension]
85 # section can has 4 items in section header string,
86 # others should report error.
88 if not ItemList
[0].upper() == DT
.TAB_USER_EXTENSIONS
.upper() or ItemList
[0].upper() == DT
.TAB_DEPEX
.upper():
90 Logger
.Error('Parser', FORMAT_INVALID
, ST
.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID \
91 % (SectionString
), File
=FileName
, Line
=LineNo
, ExtraData
=SectionString
)
93 if not ItemList
[0].upper() == DT
.TAB_USER_EXTENSIONS
.upper():
94 Str2
= ItemList
[2] + ' | ' + ItemList
[3]
98 elif len(ItemList
) > 4:
99 Logger
.Error('Parser', FORMAT_INVALID
, ST
.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID \
100 % (SectionString
), File
=FileName
, Line
=LineNo
, ExtraData
=SectionString
)
104 ## ProcessUseExtHeader
107 def ProcessUseExtHeader(ItemList
):
111 for Item
in ItemList
:
112 if Item
.startswith('\"') and not Item
.endswith('\"'):
115 elif Item
.endswith('\"') and not Item
.startswith('\"'):
117 # Should not have an userId or IdString not starts with " before but ends with ".
121 AppendContent
= AppendContent
+ "." + Item
122 NewItemList
.append(AppendContent
)
125 elif Item
.endswith('\"') and Item
.startswith('\"'):
127 # Common item, not need to combine the information
129 NewItemList
.append(Item
)
132 NewItemList
.append(Item
)
134 AppendContent
= AppendContent
+ "." + Item
136 if len(NewItemList
) > 4:
139 return True, NewItemList
145 def GetArch(ItemList
, ArchList
, FileName
, LineNo
, SectionString
):
149 if len(ItemList
) > 1:
156 # 'COMMON' must not be used with specific ARCHs at the same section
158 if 'COMMON' in ArchList
and len(ArchList
) > 1:
159 Logger
.Error('Parser',
161 ST
.ERR_INF_PARSER_SECTION_ARCH_CONFLICT
,
164 ExtraData
=SectionString
)
166 return Arch
, ArchList
170 # Inherit from object
172 class InfSectionParser(InfDefinSectionParser
,
173 InfBuildOptionSectionParser
,
174 InfSourceSectionParser
,
175 InfLibrarySectionParser
,
176 InfPackageSectionParser
,
177 InfGuidPpiProtocolSectionParser
,
178 InfBinarySectionParser
,
180 InfDepexSectionParser
):
182 # Parser objects used to implement singleton
188 # One file, one parser object. This factory method makes sure that there's
189 # only one object constructed for one meta file.
191 # @param Class class object of real AutoGen class
192 # (InfParser, DecParser or DscParser)
193 # @param FilePath The path of meta file
195 def __new__(cls
, FilePath
, *args
, **kwargs
):
200 if FilePath
in cls
.MetaFiles
:
201 return cls
.MetaFiles
[FilePath
]
203 ParserObject
= super(InfSectionParser
, cls
).__new
__(cls
)
204 cls
.MetaFiles
[FilePath
] = ParserObject
208 InfDefinSectionParser
.__init
__(self
)
209 InfBuildOptionSectionParser
.__init
__(self
)
210 InfSourceSectionParser
.__init
__(self
)
211 InfLibrarySectionParser
.__init
__(self
)
212 InfPackageSectionParser
.__init
__(self
)
213 InfGuidPpiProtocolSectionParser
.__init
__(self
)
214 InfBinarySectionParser
.__init
__(self
)
215 InfPcdSectionParser
.__init
__(self
)
216 InfDepexSectionParser
.__init
__(self
)
218 # Initialize all objects that an INF file will generated.
220 self
.InfDefSection
= InfDefObject()
221 self
.InfBuildOptionSection
= InfBuildOptionsObject()
222 self
.InfLibraryClassSection
= InfLibraryClassObject()
223 self
.InfPackageSection
= InfPackageObject()
224 self
.InfPcdSection
= InfPcdObject(list(self
.MetaFiles
.keys())[0])
225 self
.InfSourcesSection
= InfSourcesObject()
226 self
.InfUserExtensionSection
= InfUserExtensionObject()
227 self
.InfProtocolSection
= InfProtocolObject()
228 self
.InfPpiSection
= InfPpiObject()
229 self
.InfGuidSection
= InfGuidObject()
230 self
.InfDepexSection
= InfDepexObject()
231 self
.InfPeiDepexSection
= InfDepexObject()
232 self
.InfDxeDepexSection
= InfDepexObject()
233 self
.InfSmmDepexSection
= InfDepexObject()
234 self
.InfBinariesSection
= InfBinariesObject()
235 self
.InfHeader
= InfHeaderObject()
236 self
.InfBinaryHeader
= InfHeaderObject()
237 self
.InfSpecialCommentSection
= InfSpecialCommentObject()
240 # A List for store define section content.
242 self
._PcdNameList
= []
243 self
._SectionName
= ''
244 self
._SectionType
= 0
249 # File Header content parser
251 def InfHeaderParser(self
, Content
, InfHeaderObject2
, FileName
, IsBinaryHeader
= False):
253 (Abstract
, Description
, Copyright
, License
) = ParseHeaderCommentSection(Content
, FileName
, True)
254 if not Abstract
or not Description
or not Copyright
or not License
:
255 Logger
.Error('Parser',
257 ST
.ERR_INVALID_BINARYHEADER_FORMAT
,
260 (Abstract
, Description
, Copyright
, License
) = ParseHeaderCommentSection(Content
, FileName
)
262 # Not process file name now, for later usage.
268 # Insert Abstract, Description, CopyRight, License into header object
270 InfHeaderObject2
.SetAbstract(Abstract
)
271 InfHeaderObject2
.SetDescription(Description
)
272 InfHeaderObject2
.SetCopyright(Copyright
)
273 InfHeaderObject2
.SetLicense(License
)
278 ## Section header parser
280 # The section header is always in following format:
282 # [section_name.arch<.platform|module_type>]
284 # @param String A string contained the content need to be parsed.
286 def SectionHeaderParser(self
, SectionString
, FileName
, LineNo
):
291 _PcdNameList
= [DT
.TAB_INF_FIXED_PCD
.upper(),
292 DT
.TAB_INF_FEATURE_PCD
.upper(),
293 DT
.TAB_INF_PATCH_PCD
.upper(),
294 DT
.TAB_INF_PCD
.upper(),
295 DT
.TAB_INF_PCD_EX
.upper()
297 SectionString
= SectionString
.strip()
298 for Item
in GetSplitValueList(SectionString
[1:-1], DT
.TAB_COMMA_SPLIT
):
300 Logger
.Error('Parser',
302 ST
.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR
% (""),
305 ExtraData
=SectionString
)
306 ItemList
= GetSplitValueList(Item
, DT
.TAB_SPLIT
)
308 # different section should not mix in one section
309 # Allow different PCD type sections mixed together
311 if _SectionName
.upper() not in _PcdNameList
:
312 if _SectionName
!= '' and _SectionName
.upper() != ItemList
[0].upper():
313 Logger
.Error('Parser',
315 ST
.ERR_INF_PARSER_SECTION_NAME_DUPLICATE
,
318 ExtraData
=SectionString
)
319 elif _PcdNameList
[1] in [_SectionName
.upper(), ItemList
[0].upper()] and \
320 (_SectionName
.upper()!= ItemList
[0].upper()):
321 Logger
.Error('Parser',
323 ST
.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR
% (""),
326 ExtraData
=SectionString
)
328 _SectionName
= ItemList
[0]
329 if _SectionName
.upper() in gINF_SECTION_DEF
:
330 self
._SectionType
= gINF_SECTION_DEF
[_SectionName
.upper()]
332 self
._SectionType
= DT
.MODEL_UNKNOWN
333 Logger
.Error("Parser",
335 ST
.ERR_INF_PARSER_UNKNOWN_SECTION
,
338 ExtraData
=SectionString
)
343 Str1
, ArchList
= GetArch(ItemList
, ArchList
, FileName
, LineNo
, SectionString
)
346 # For [Defines] section, do special check.
348 if ItemList
[0].upper() == DT
.TAB_COMMON_DEFINES
.upper():
349 if len(ItemList
) != 1:
350 Logger
.Error('Parser',
352 ST
.ERR_INF_PARSER_DEFINE_FROMAT_INVALID
% (SectionString
),
353 File
=FileName
, Line
=LineNo
, ExtraData
=SectionString
)
356 # For [UserExtension] section, do special check.
358 if ItemList
[0].upper() == DT
.TAB_USER_EXTENSIONS
.upper():
360 RetValue
= ProcessUseExtHeader(ItemList
)
363 Logger
.Error('Parser',
365 ST
.ERR_INF_PARSER_DEFINE_FROMAT_INVALID
% (SectionString
),
366 File
=FileName
, Line
=LineNo
, ExtraData
=SectionString
)
368 ItemList
= RetValue
[1]
370 if len(ItemList
) == 3:
371 ItemList
.append('COMMON')
376 # For Library classes, need to check module type.
378 if ItemList
[0].upper() == DT
.TAB_LIBRARY_CLASSES
.upper() and len(ItemList
) == 3:
379 if ItemList
[2] != '':
380 ModuleTypeList
= GetSplitValueList(ItemList
[2], DT
.TAB_VALUE_SPLIT
)
381 for Item
in ModuleTypeList
:
382 if Item
.strip() not in DT
.MODULE_LIST
:
383 Logger
.Error('Parser',
385 ST
.ERR_INF_PARSER_DEFINE_MODULETYPE_INVALID
% (Item
),
388 ExtraData
=SectionString
)
392 Str2
= GetSpecialStr2(ItemList
, FileName
, LineNo
, SectionString
)
394 _Scope
.append([Str1
, Str2
])
398 if _SectionName
.upper() in _PcdNameList
:
399 for ValueItem
in _ValueList
:
400 if _SectionName
.upper() == ValueItem
[0].upper() and Str1
.upper() not in ValueItem
[1].split():
401 ValueItem
[1] = ValueItem
[1] + " " + Str1
403 elif _SectionName
.upper() == ValueItem
[0].upper() and Str1
.upper() in ValueItem
[1].split():
406 _NewValueList
.append(ValueItem
)
408 _ValueList
= _NewValueList
411 if not ItemList
[0].upper() == DT
.TAB_USER_EXTENSIONS
.upper():
412 _ValueList
.append([_SectionName
, Str1
, Str2
, LineNo
])
414 if len(ItemList
) == 4:
415 _ValueList
.append([_SectionName
, Str1
, Str2
, ItemList
[3], LineNo
])
417 self
.SectionHeaderContent
= deepcopy(_ValueList
)
419 ## GenSpecialSectionList
421 # @param SpecialSectionList: a list of list, of which item's format
423 # @param ContainerFile: Input value for filename of Inf file
425 def InfSpecialCommentParser (self
, SpecialSectionList
, InfSectionObject
, ContainerFile
, SectionType
):
426 ReFindSpecialCommentRe
= re
.compile(r
"""#(?:\s*)\[(.*?)\](?:.*)""", re
.DOTALL
)
427 ReFindHobArchRe
= re
.compile(r
"""[Hh][Oo][Bb]\.([^,]*)""", re
.DOTALL
)
430 SpecialObjectList
= []
432 if SectionType
== DT
.TYPE_EVENT_SECTION
:
433 TokenDict
= DT
.EVENT_TOKENS
434 elif SectionType
== DT
.TYPE_HOB_SECTION
:
435 TokenDict
= DT
.HOB_TOKENS
437 TokenDict
= DT
.BOOTMODE_TOKENS
439 for List
in SpecialSectionList
:
441 # Hob has Arch attribute, need to be handled specially here
443 if SectionType
== DT
.TYPE_HOB_SECTION
:
445 MatchObject
= ReFindSpecialCommentRe
.search(List
[0][0])
446 HobSectionStr
= MatchObject
.group(1)
448 for Match
in ReFindHobArchRe
.finditer(HobSectionStr
):
449 Arch
= Match
.groups(1)[0].upper()
450 ArchList
.append(Arch
)
452 for Index
in range(1, len(List
)):
453 Result
= ParseComment(List
[Index
], DT
.ALL_USAGE_TOKENS
, TokenDict
, [], False)
458 if Usage
== DT
.ITEM_UNDEFINED
and Type
== DT
.ITEM_UNDEFINED
:
461 if not HelpText
.endswith('\n'):
463 CommentSoFar
+= HelpText
466 CommentSoFar
+= HelpText
467 if SectionType
== DT
.TYPE_EVENT_SECTION
:
468 SpecialObject
= InfEventObject()
469 SpecialObject
.SetEventType(Type
)
470 SpecialObject
.SetUsage(Usage
)
471 SpecialObject
.SetHelpString(CommentSoFar
)
472 elif SectionType
== DT
.TYPE_HOB_SECTION
:
473 SpecialObject
= InfHobObject()
474 SpecialObject
.SetHobType(Type
)
475 SpecialObject
.SetUsage(Usage
)
476 SpecialObject
.SetHelpString(CommentSoFar
)
477 if len(ArchList
) >= 1:
478 SpecialObject
.SetSupArchList(ArchList
)
480 SpecialObject
= InfBootModeObject()
481 SpecialObject
.SetSupportedBootModes(Type
)
482 SpecialObject
.SetUsage(Usage
)
483 SpecialObject
.SetHelpString(CommentSoFar
)
485 SpecialObjectList
.append(SpecialObject
)
487 if not InfSectionObject
.SetSpecialComments(SpecialObjectList
,
489 Logger
.Error('InfParser',
491 ST
.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR
% (SectionType
),