2 # This file contained the parser for sections in INF file
4 # Copyright (c) 2011, 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
.String
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
.InfSpecialCommentSection
= InfSpecialCommentObject()
245 # A List for store define section content.
247 self
._PcdNameList
= []
248 self
._SectionName
= ''
249 self
._SectionType
= 0
254 # File Header content parser
256 def InfHeaderParser(self
, Content
, InfHeaderObject2
, FileName
):
257 (Abstract
, Description
, Copyright
, License
) = ParseHeaderCommentSection(Content
, FileName
)
259 # Not process file name now, for later usage.
265 # Insert Abstract, Description, CopyRight, License into header object
267 InfHeaderObject2
.SetAbstract(Abstract
)
268 InfHeaderObject2
.SetDescription(Description
)
269 InfHeaderObject2
.SetCopyright(Copyright
)
270 InfHeaderObject2
.SetLicense(License
)
275 ## Section header parser
277 # The section header is always in following format:
279 # [section_name.arch<.platform|module_type>]
281 # @param String A string contained the content need to be parsed.
283 def SectionHeaderParser(self
, SectionString
, FileName
, LineNo
):
288 _PcdNameList
= [DT
.TAB_INF_FIXED_PCD
.upper(),
289 DT
.TAB_INF_FEATURE_PCD
.upper(),
290 DT
.TAB_INF_PATCH_PCD
.upper(),
291 DT
.TAB_INF_PCD
.upper(),
292 DT
.TAB_INF_PCD_EX
.upper()
294 SectionString
= SectionString
.strip()
295 for Item
in GetSplitValueList(SectionString
[1:-1], DT
.TAB_COMMA_SPLIT
):
297 Logger
.Error('Parser',
299 ST
.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR
% (""),
302 ExtraData
=SectionString
)
303 ItemList
= GetSplitValueList(Item
, DT
.TAB_SPLIT
)
305 # different section should not mix in one section
306 # Allow different PCD type sections mixed together
308 if _SectionName
.upper() not in _PcdNameList
:
309 if _SectionName
!= '' and _SectionName
.upper() != ItemList
[0].upper():
310 Logger
.Error('Parser',
312 ST
.ERR_INF_PARSER_SECTION_NAME_DUPLICATE
,
315 ExtraData
=SectionString
)
316 elif _PcdNameList
[1] in [_SectionName
.upper(), ItemList
[0].upper()] and \
317 (_SectionName
.upper()!= ItemList
[0].upper()):
318 Logger
.Error('Parser',
320 ST
.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR
% (""),
323 ExtraData
=SectionString
)
325 _SectionName
= ItemList
[0]
326 if _SectionName
.upper() in gINF_SECTION_DEF
:
327 self
._SectionType
= gINF_SECTION_DEF
[_SectionName
.upper()]
329 self
._SectionType
= DT
.MODEL_UNKNOWN
330 Logger
.Error("Parser",
332 ST
.ERR_INF_PARSER_UNKNOWN_SECTION
,
335 ExtraData
=SectionString
)
340 Str1
, ArchList
= GetArch(ItemList
, ArchList
, FileName
, LineNo
, SectionString
)
343 # For [Defines] section, do special check.
345 if ItemList
[0].upper() == DT
.TAB_COMMON_DEFINES
.upper():
346 if len(ItemList
) != 1:
347 Logger
.Error('Parser',
349 ST
.ERR_INF_PARSER_DEFINE_FROMAT_INVALID
% (SectionString
),
350 File
=FileName
, Line
=LineNo
, ExtraData
=SectionString
)
353 # For [UserExtension] section, do special check.
355 if ItemList
[0].upper() == DT
.TAB_USER_EXTENSIONS
.upper():
357 RetValue
= ProcessUseExtHeader(ItemList
)
360 Logger
.Error('Parser',
362 ST
.ERR_INF_PARSER_DEFINE_FROMAT_INVALID
% (SectionString
),
363 File
=FileName
, Line
=LineNo
, ExtraData
=SectionString
)
365 ItemList
= RetValue
[1]
367 if len(ItemList
) == 3:
368 ItemList
.append('COMMON')
373 # For Library classes, need to check module type.
375 if ItemList
[0].upper() == DT
.TAB_LIBRARY_CLASSES
.upper() and len(ItemList
) == 3:
376 if ItemList
[2] != '':
377 ModuleTypeList
= GetSplitValueList(ItemList
[2], DT
.TAB_VALUE_SPLIT
)
378 for Item
in ModuleTypeList
:
379 if Item
.strip() not in DT
.MODULE_LIST
:
380 Logger
.Error('Parser',
382 ST
.ERR_INF_PARSER_DEFINE_MODULETYPE_INVALID
% (Item
),
385 ExtraData
=SectionString
)
389 Str2
= GetSpecialStr2(ItemList
, FileName
, LineNo
, SectionString
)
391 _Scope
.append([Str1
, Str2
])
395 if _SectionName
.upper() in _PcdNameList
:
396 for ValueItem
in _ValueList
:
397 if _SectionName
.upper() == ValueItem
[0].upper() and Str1
.upper() not in ValueItem
[1].split():
398 ValueItem
[1] = ValueItem
[1] + " " + Str1
400 elif _SectionName
.upper() == ValueItem
[0].upper() and Str1
.upper() in ValueItem
[1].split():
403 _NewValueList
.append(ValueItem
)
405 _ValueList
= _NewValueList
408 if not ItemList
[0].upper() == DT
.TAB_USER_EXTENSIONS
.upper():
409 _ValueList
.append([_SectionName
, Str1
, Str2
, LineNo
])
411 if len(ItemList
) == 4:
412 _ValueList
.append([_SectionName
, Str1
, Str2
, ItemList
[3], LineNo
])
414 self
.SectionHeaderContent
= deepcopy(_ValueList
)
416 ## GenSpecialSectionList
418 # @param SpecialSectionList: a list of list, of which item's format
420 # @param ContainerFile: Input value for filename of Inf file
422 def InfSpecialCommentParser (self
, SpecialSectionList
, InfSectionObject
, ContainerFile
, SectionType
):
423 ReFindSpecialCommentRe
= re
.compile(r
"""#(?:\s*)\[(.*?)\](?:.*)""", re
.DOTALL
)
424 ReFindHobArchRe
= re
.compile(r
"""[Hh][Oo][Bb]\.([^,]*)""", re
.DOTALL
)
427 SpecialObjectList
= []
429 if SectionType
== DT
.TYPE_EVENT_SECTION
:
430 TokenDict
= DT
.EVENT_TOKENS
431 elif SectionType
== DT
.TYPE_HOB_SECTION
:
432 TokenDict
= DT
.HOB_TOKENS
434 TokenDict
= DT
.BOOTMODE_TOKENS
436 for List
in SpecialSectionList
:
438 # Hob has Arch attribute, need to be handled specially here
440 if SectionType
== DT
.TYPE_HOB_SECTION
:
442 MatchObject
= ReFindSpecialCommentRe
.search(List
[0][0])
443 HobSectionStr
= MatchObject
.group(1)
445 for Match
in ReFindHobArchRe
.finditer(HobSectionStr
):
446 Arch
= Match
.groups(1)[0].upper()
447 ArchList
.append(Arch
)
449 for Index
in xrange(1, len(List
)):
450 Result
= ParseComment(List
[Index
], DT
.ALL_USAGE_TOKENS
, TokenDict
, [], False)
455 if Usage
== DT
.ITEM_UNDEFINED
and Type
== DT
.ITEM_UNDEFINED
:
458 if not HelpText
.endswith('\n'):
460 CommentSoFar
+= HelpText
463 CommentSoFar
+= HelpText
464 if SectionType
== DT
.TYPE_EVENT_SECTION
:
465 SpecialObject
= InfEventObject()
466 SpecialObject
.SetEventType(Type
)
467 SpecialObject
.SetUsage(Usage
)
468 SpecialObject
.SetHelpString(CommentSoFar
)
469 elif SectionType
== DT
.TYPE_HOB_SECTION
:
470 SpecialObject
= InfHobObject()
471 SpecialObject
.SetHobType(Type
)
472 SpecialObject
.SetUsage(Usage
)
473 SpecialObject
.SetHelpString(CommentSoFar
)
474 if len(ArchList
) >= 1:
475 SpecialObject
.SetSupArchList(ArchList
)
477 SpecialObject
= InfBootModeObject()
478 SpecialObject
.SetSupportedBootModes(Type
)
479 SpecialObject
.SetUsage(Usage
)
480 SpecialObject
.SetHelpString(CommentSoFar
)
482 SpecialObjectList
.append(SpecialObject
)
484 if not InfSectionObject
.SetSpecialComments(SpecialObjectList
,
486 Logger
.Error('InfParser',
488 ST
.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR
% (SectionType
),