2 # This file contained the parser for sections in INF file
4 # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
6 # This program and the accompanying materials are licensed and made available
7 # under the terms and conditions of the BSD License which accompanies this
8 # 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.
21 from copy
import deepcopy
24 from Library
.StringUtils
import GetSplitValueList
25 from Library
.CommentParsing
import ParseHeaderCommentSection
26 from Library
.CommentParsing
import ParseComment
28 from Library
import DataType
as DT
30 import Logger
.Log
as Logger
31 from Logger
import StringTable
as ST
32 from Logger
.ToolError
import FORMAT_INVALID
34 from Object
.Parser
.InfDefineObject
import InfDefObject
35 from Object
.Parser
.InfBuildOptionObject
import InfBuildOptionsObject
36 from Object
.Parser
.InfLibraryClassesObject
import InfLibraryClassObject
37 from Object
.Parser
.InfPackagesObject
import InfPackageObject
38 from Object
.Parser
.InfPcdObject
import InfPcdObject
39 from Object
.Parser
.InfSoucesObject
import InfSourcesObject
40 from Object
.Parser
.InfUserExtensionObject
import InfUserExtensionObject
41 from Object
.Parser
.InfProtocolObject
import InfProtocolObject
42 from Object
.Parser
.InfPpiObject
import InfPpiObject
43 from Object
.Parser
.InfGuidObject
import InfGuidObject
44 from Object
.Parser
.InfDepexObject
import InfDepexObject
45 from Object
.Parser
.InfBinaryObject
import InfBinariesObject
46 from Object
.Parser
.InfHeaderObject
import InfHeaderObject
47 from Object
.Parser
.InfMisc
import InfSpecialCommentObject
48 from Object
.Parser
.InfMisc
import InfHobObject
49 from Object
.Parser
.InfMisc
import InfBootModeObject
50 from Object
.Parser
.InfMisc
import InfEventObject
51 from Parser
.InfParserMisc
import gINF_SECTION_DEF
52 from Parser
.InfDefineSectionParser
import InfDefinSectionParser
53 from Parser
.InfBuildOptionSectionParser
import InfBuildOptionSectionParser
54 from Parser
.InfSourceSectionParser
import InfSourceSectionParser
55 from Parser
.InfLibrarySectionParser
import InfLibrarySectionParser
56 from Parser
.InfPackageSectionParser
import InfPackageSectionParser
57 from Parser
.InfGuidPpiProtocolSectionParser
import InfGuidPpiProtocolSectionParser
58 from Parser
.InfBinarySectionParser
import InfBinarySectionParser
59 from Parser
.InfPcdSectionParser
import InfPcdSectionParser
60 from Parser
.InfDepexSectionParser
import InfDepexSectionParser
66 def GetSpecialStr2(ItemList
, FileName
, LineNo
, SectionString
):
69 # S2 may be Platform or ModuleType
71 if len(ItemList
) == 3:
73 # Except [LibraryClass], [Depex]
74 # section can has more than 2 items in section header string,
75 # others should report error.
77 if not (ItemList
[0].upper() == DT
.TAB_LIBRARY_CLASSES
.upper() or \
78 ItemList
[0].upper() == DT
.TAB_DEPEX
.upper() or \
79 ItemList
[0].upper() == DT
.TAB_USER_EXTENSIONS
.upper()):
81 Logger
.Error('Parser',
83 ST
.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID
% (SectionString
),
86 ExtraData
=SectionString
)
88 elif len(ItemList
) == 4:
90 # Except [UserExtension]
91 # section can has 4 items in section header string,
92 # others should report error.
94 if not ItemList
[0].upper() == DT
.TAB_USER_EXTENSIONS
.upper() or ItemList
[0].upper() == DT
.TAB_DEPEX
.upper():
96 Logger
.Error('Parser', FORMAT_INVALID
, ST
.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID \
97 % (SectionString
), File
=FileName
, Line
=LineNo
, ExtraData
=SectionString
)
99 if not ItemList
[0].upper() == DT
.TAB_USER_EXTENSIONS
.upper():
100 Str2
= ItemList
[2] + ' | ' + ItemList
[3]
104 elif len(ItemList
) > 4:
105 Logger
.Error('Parser', FORMAT_INVALID
, ST
.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID \
106 % (SectionString
), File
=FileName
, Line
=LineNo
, ExtraData
=SectionString
)
110 ## ProcessUseExtHeader
113 def ProcessUseExtHeader(ItemList
):
117 for Item
in ItemList
:
118 if Item
.startswith('\"') and not Item
.endswith('\"'):
121 elif Item
.endswith('\"') and not Item
.startswith('\"'):
123 # Should not have an userId or IdString not starts with " before but ends with ".
127 AppendContent
= AppendContent
+ "." + Item
128 NewItemList
.append(AppendContent
)
131 elif Item
.endswith('\"') and Item
.startswith('\"'):
133 # Common item, not need to combine the information
135 NewItemList
.append(Item
)
138 NewItemList
.append(Item
)
140 AppendContent
= AppendContent
+ "." + Item
142 if len(NewItemList
) > 4:
145 return True, NewItemList
151 def GetArch(ItemList
, ArchList
, FileName
, LineNo
, SectionString
):
155 if len(ItemList
) > 1:
162 # 'COMMON' must not be used with specific ARCHs at the same section
164 if 'COMMON' in ArchList
and len(ArchList
) > 1:
165 Logger
.Error('Parser',
167 ST
.ERR_INF_PARSER_SECTION_ARCH_CONFLICT
,
170 ExtraData
=SectionString
)
172 return Arch
, ArchList
176 # Inherit from object
178 class InfSectionParser(InfDefinSectionParser
,
179 InfBuildOptionSectionParser
,
180 InfSourceSectionParser
,
181 InfLibrarySectionParser
,
182 InfPackageSectionParser
,
183 InfGuidPpiProtocolSectionParser
,
184 InfBinarySectionParser
,
186 InfDepexSectionParser
):
188 # Parser objects used to implement singleton
194 # One file, one parser object. This factory method makes sure that there's
195 # only one object constructed for one meta file.
197 # @param Class class object of real AutoGen class
198 # (InfParser, DecParser or DscParser)
199 # @param FilePath The path of meta file
201 def __new__(cls
, FilePath
, *args
, **kwargs
):
206 if FilePath
in cls
.MetaFiles
:
207 return cls
.MetaFiles
[FilePath
]
209 ParserObject
= super(InfSectionParser
, cls
).__new
__(cls
)
210 cls
.MetaFiles
[FilePath
] = ParserObject
214 InfDefinSectionParser
.__init
__(self
)
215 InfBuildOptionSectionParser
.__init
__(self
)
216 InfSourceSectionParser
.__init
__(self
)
217 InfLibrarySectionParser
.__init
__(self
)
218 InfPackageSectionParser
.__init
__(self
)
219 InfGuidPpiProtocolSectionParser
.__init
__(self
)
220 InfBinarySectionParser
.__init
__(self
)
221 InfPcdSectionParser
.__init
__(self
)
222 InfDepexSectionParser
.__init
__(self
)
224 # Initialize all objects that an INF file will generated.
226 self
.InfDefSection
= InfDefObject()
227 self
.InfBuildOptionSection
= InfBuildOptionsObject()
228 self
.InfLibraryClassSection
= InfLibraryClassObject()
229 self
.InfPackageSection
= InfPackageObject()
230 self
.InfPcdSection
= InfPcdObject(self
.MetaFiles
.keys()[0])
231 self
.InfSourcesSection
= InfSourcesObject()
232 self
.InfUserExtensionSection
= InfUserExtensionObject()
233 self
.InfProtocolSection
= InfProtocolObject()
234 self
.InfPpiSection
= InfPpiObject()
235 self
.InfGuidSection
= InfGuidObject()
236 self
.InfDepexSection
= InfDepexObject()
237 self
.InfPeiDepexSection
= InfDepexObject()
238 self
.InfDxeDepexSection
= InfDepexObject()
239 self
.InfSmmDepexSection
= InfDepexObject()
240 self
.InfBinariesSection
= InfBinariesObject()
241 self
.InfHeader
= InfHeaderObject()
242 self
.InfBinaryHeader
= InfHeaderObject()
243 self
.InfSpecialCommentSection
= InfSpecialCommentObject()
246 # A List for store define section content.
248 self
._PcdNameList
= []
249 self
._SectionName
= ''
250 self
._SectionType
= 0
255 # File Header content parser
257 def InfHeaderParser(self
, Content
, InfHeaderObject2
, FileName
, IsBinaryHeader
= False):
259 (Abstract
, Description
, Copyright
, License
) = ParseHeaderCommentSection(Content
, FileName
, True)
260 if not Abstract
or not Description
or not Copyright
or not License
:
261 Logger
.Error('Parser',
263 ST
.ERR_INVALID_BINARYHEADER_FORMAT
,
266 (Abstract
, Description
, Copyright
, License
) = ParseHeaderCommentSection(Content
, FileName
)
268 # Not process file name now, for later usage.
274 # Insert Abstract, Description, CopyRight, License into header object
276 InfHeaderObject2
.SetAbstract(Abstract
)
277 InfHeaderObject2
.SetDescription(Description
)
278 InfHeaderObject2
.SetCopyright(Copyright
)
279 InfHeaderObject2
.SetLicense(License
)
284 ## Section header parser
286 # The section header is always in following format:
288 # [section_name.arch<.platform|module_type>]
290 # @param String A string contained the content need to be parsed.
292 def SectionHeaderParser(self
, SectionString
, FileName
, LineNo
):
297 _PcdNameList
= [DT
.TAB_INF_FIXED_PCD
.upper(),
298 DT
.TAB_INF_FEATURE_PCD
.upper(),
299 DT
.TAB_INF_PATCH_PCD
.upper(),
300 DT
.TAB_INF_PCD
.upper(),
301 DT
.TAB_INF_PCD_EX
.upper()
303 SectionString
= SectionString
.strip()
304 for Item
in GetSplitValueList(SectionString
[1:-1], DT
.TAB_COMMA_SPLIT
):
306 Logger
.Error('Parser',
308 ST
.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR
% (""),
311 ExtraData
=SectionString
)
312 ItemList
= GetSplitValueList(Item
, DT
.TAB_SPLIT
)
314 # different section should not mix in one section
315 # Allow different PCD type sections mixed together
317 if _SectionName
.upper() not in _PcdNameList
:
318 if _SectionName
!= '' and _SectionName
.upper() != ItemList
[0].upper():
319 Logger
.Error('Parser',
321 ST
.ERR_INF_PARSER_SECTION_NAME_DUPLICATE
,
324 ExtraData
=SectionString
)
325 elif _PcdNameList
[1] in [_SectionName
.upper(), ItemList
[0].upper()] and \
326 (_SectionName
.upper()!= ItemList
[0].upper()):
327 Logger
.Error('Parser',
329 ST
.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR
% (""),
332 ExtraData
=SectionString
)
334 _SectionName
= ItemList
[0]
335 if _SectionName
.upper() in gINF_SECTION_DEF
:
336 self
._SectionType
= gINF_SECTION_DEF
[_SectionName
.upper()]
338 self
._SectionType
= DT
.MODEL_UNKNOWN
339 Logger
.Error("Parser",
341 ST
.ERR_INF_PARSER_UNKNOWN_SECTION
,
344 ExtraData
=SectionString
)
349 Str1
, ArchList
= GetArch(ItemList
, ArchList
, FileName
, LineNo
, SectionString
)
352 # For [Defines] section, do special check.
354 if ItemList
[0].upper() == DT
.TAB_COMMON_DEFINES
.upper():
355 if len(ItemList
) != 1:
356 Logger
.Error('Parser',
358 ST
.ERR_INF_PARSER_DEFINE_FROMAT_INVALID
% (SectionString
),
359 File
=FileName
, Line
=LineNo
, ExtraData
=SectionString
)
362 # For [UserExtension] section, do special check.
364 if ItemList
[0].upper() == DT
.TAB_USER_EXTENSIONS
.upper():
366 RetValue
= ProcessUseExtHeader(ItemList
)
369 Logger
.Error('Parser',
371 ST
.ERR_INF_PARSER_DEFINE_FROMAT_INVALID
% (SectionString
),
372 File
=FileName
, Line
=LineNo
, ExtraData
=SectionString
)
374 ItemList
= RetValue
[1]
376 if len(ItemList
) == 3:
377 ItemList
.append('COMMON')
382 # For Library classes, need to check module type.
384 if ItemList
[0].upper() == DT
.TAB_LIBRARY_CLASSES
.upper() and len(ItemList
) == 3:
385 if ItemList
[2] != '':
386 ModuleTypeList
= GetSplitValueList(ItemList
[2], DT
.TAB_VALUE_SPLIT
)
387 for Item
in ModuleTypeList
:
388 if Item
.strip() not in DT
.MODULE_LIST
:
389 Logger
.Error('Parser',
391 ST
.ERR_INF_PARSER_DEFINE_MODULETYPE_INVALID
% (Item
),
394 ExtraData
=SectionString
)
398 Str2
= GetSpecialStr2(ItemList
, FileName
, LineNo
, SectionString
)
400 _Scope
.append([Str1
, Str2
])
404 if _SectionName
.upper() in _PcdNameList
:
405 for ValueItem
in _ValueList
:
406 if _SectionName
.upper() == ValueItem
[0].upper() and Str1
.upper() not in ValueItem
[1].split():
407 ValueItem
[1] = ValueItem
[1] + " " + Str1
409 elif _SectionName
.upper() == ValueItem
[0].upper() and Str1
.upper() in ValueItem
[1].split():
412 _NewValueList
.append(ValueItem
)
414 _ValueList
= _NewValueList
417 if not ItemList
[0].upper() == DT
.TAB_USER_EXTENSIONS
.upper():
418 _ValueList
.append([_SectionName
, Str1
, Str2
, LineNo
])
420 if len(ItemList
) == 4:
421 _ValueList
.append([_SectionName
, Str1
, Str2
, ItemList
[3], LineNo
])
423 self
.SectionHeaderContent
= deepcopy(_ValueList
)
425 ## GenSpecialSectionList
427 # @param SpecialSectionList: a list of list, of which item's format
429 # @param ContainerFile: Input value for filename of Inf file
431 def InfSpecialCommentParser (self
, SpecialSectionList
, InfSectionObject
, ContainerFile
, SectionType
):
432 ReFindSpecialCommentRe
= re
.compile(r
"""#(?:\s*)\[(.*?)\](?:.*)""", re
.DOTALL
)
433 ReFindHobArchRe
= re
.compile(r
"""[Hh][Oo][Bb]\.([^,]*)""", re
.DOTALL
)
436 SpecialObjectList
= []
438 if SectionType
== DT
.TYPE_EVENT_SECTION
:
439 TokenDict
= DT
.EVENT_TOKENS
440 elif SectionType
== DT
.TYPE_HOB_SECTION
:
441 TokenDict
= DT
.HOB_TOKENS
443 TokenDict
= DT
.BOOTMODE_TOKENS
445 for List
in SpecialSectionList
:
447 # Hob has Arch attribute, need to be handled specially here
449 if SectionType
== DT
.TYPE_HOB_SECTION
:
451 MatchObject
= ReFindSpecialCommentRe
.search(List
[0][0])
452 HobSectionStr
= MatchObject
.group(1)
454 for Match
in ReFindHobArchRe
.finditer(HobSectionStr
):
455 Arch
= Match
.groups(1)[0].upper()
456 ArchList
.append(Arch
)
458 for Index
in xrange(1, len(List
)):
459 Result
= ParseComment(List
[Index
], DT
.ALL_USAGE_TOKENS
, TokenDict
, [], False)
464 if Usage
== DT
.ITEM_UNDEFINED
and Type
== DT
.ITEM_UNDEFINED
:
467 if not HelpText
.endswith('\n'):
469 CommentSoFar
+= HelpText
472 CommentSoFar
+= HelpText
473 if SectionType
== DT
.TYPE_EVENT_SECTION
:
474 SpecialObject
= InfEventObject()
475 SpecialObject
.SetEventType(Type
)
476 SpecialObject
.SetUsage(Usage
)
477 SpecialObject
.SetHelpString(CommentSoFar
)
478 elif SectionType
== DT
.TYPE_HOB_SECTION
:
479 SpecialObject
= InfHobObject()
480 SpecialObject
.SetHobType(Type
)
481 SpecialObject
.SetUsage(Usage
)
482 SpecialObject
.SetHelpString(CommentSoFar
)
483 if len(ArchList
) >= 1:
484 SpecialObject
.SetSupArchList(ArchList
)
486 SpecialObject
= InfBootModeObject()
487 SpecialObject
.SetSupportedBootModes(Type
)
488 SpecialObject
.SetUsage(Usage
)
489 SpecialObject
.SetHelpString(CommentSoFar
)
491 SpecialObjectList
.append(SpecialObject
)
493 if not InfSectionObject
.SetSpecialComments(SpecialObjectList
,
495 Logger
.Error('InfParser',
497 ST
.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR
% (SectionType
),