]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/UPT/Parser/InfSectionParser.py
727164c2c244954eac5f55f484d6c45f0ed5dc7c
[mirror_edk2.git] / BaseTools / Source / Python / UPT / Parser / InfSectionParser.py
1 ## @file
2 # This file contained the parser for sections in INF file
3 #
4 # Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
5 #
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
10 #
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.
13 #
14
15 '''
16 InfSectionParser
17 '''
18 ##
19 # Import Modules
20 #
21 from copy import deepcopy
22 import re
23
24 from Library.String import GetSplitValueList
25 from Library.CommentParsing import ParseHeaderCommentSection
26 from Library.CommentParsing import ParseComment
27
28 from Library import DataType as DT
29
30 import Logger.Log as Logger
31 from Logger import StringTable as ST
32 from Logger.ToolError import FORMAT_INVALID
33
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
61
62 ## GetSpecialStr2
63 #
64 # GetSpecialStr2
65 #
66 def GetSpecialStr2(ItemList, FileName, LineNo, SectionString):
67 Str2 = ''
68 #
69 # S2 may be Platform or ModuleType
70 #
71 if len(ItemList) == 3:
72 #
73 # Except [LibraryClass], [Depex]
74 # section can has more than 2 items in section header string,
75 # others should report error.
76 #
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()):
80 if ItemList[2] != '':
81 Logger.Error('Parser',
82 FORMAT_INVALID,
83 ST.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID % (SectionString),
84 File=FileName,
85 Line=LineNo,
86 ExtraData=SectionString)
87 Str2 = ItemList[2]
88 elif len(ItemList) == 4:
89 #
90 # Except [UserExtension]
91 # section can has 4 items in section header string,
92 # others should report error.
93 #
94 if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper() or ItemList[0].upper() == DT.TAB_DEPEX.upper():
95 if ItemList[3] != '':
96 Logger.Error('Parser', FORMAT_INVALID, ST.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID \
97 % (SectionString), File=FileName, Line=LineNo, ExtraData=SectionString)
98
99 if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper():
100 Str2 = ItemList[2] + ' | ' + ItemList[3]
101 else:
102 Str2 = ItemList[2]
103
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)
107
108 return Str2
109
110 ## ProcessUseExtHeader
111 #
112 #
113 def ProcessUseExtHeader(ItemList):
114 NewItemList = []
115 AppendContent = ''
116 CompleteFlag = False
117 for Item in ItemList:
118 if Item.startswith('\"') and not Item.endswith('\"'):
119 AppendContent = Item
120 CompleteFlag = True
121 elif Item.endswith('\"') and not Item.startswith('\"'):
122 #
123 # Should not have an userId or IdString not starts with " before but ends with ".
124 #
125 if not CompleteFlag:
126 return False, []
127 AppendContent = AppendContent + "." + Item
128 NewItemList.append(AppendContent)
129 CompleteFlag = False
130 AppendContent = ''
131 elif Item.endswith('\"') and Item.startswith('\"'):
132 #
133 # Common item, not need to combine the information
134 #
135 NewItemList.append(Item)
136 else:
137 if not CompleteFlag:
138 NewItemList.append(Item)
139 else:
140 AppendContent = AppendContent + "." + Item
141
142 if len(NewItemList) > 4:
143 return False, []
144
145 return True, NewItemList
146
147 ## GetArch
148 #
149 # GetArch
150 #
151 def GetArch(ItemList, ArchList, FileName, LineNo, SectionString):
152 #
153 # S1 is always Arch
154 #
155 if len(ItemList) > 1:
156 Arch = ItemList[1]
157 else:
158 Arch = 'COMMON'
159 ArchList.add(Arch)
160
161 #
162 # 'COMMON' must not be used with specific ARCHs at the same section
163 #
164 if 'COMMON' in ArchList and len(ArchList) > 1:
165 Logger.Error('Parser',
166 FORMAT_INVALID,
167 ST.ERR_INF_PARSER_SECTION_ARCH_CONFLICT,
168 File=FileName,
169 Line=LineNo,
170 ExtraData=SectionString)
171
172 return Arch, ArchList
173
174 ## InfSectionParser
175 #
176 # Inherit from object
177 #
178 class InfSectionParser(InfDefinSectionParser,
179 InfBuildOptionSectionParser,
180 InfSourceSectionParser,
181 InfLibrarySectionParser,
182 InfPackageSectionParser,
183 InfGuidPpiProtocolSectionParser,
184 InfBinarySectionParser,
185 InfPcdSectionParser,
186 InfDepexSectionParser):
187 #
188 # Parser objects used to implement singleton
189 #
190 MetaFiles = {}
191
192 ## Factory method
193 #
194 # One file, one parser object. This factory method makes sure that there's
195 # only one object constructed for one meta file.
196 #
197 # @param Class class object of real AutoGen class
198 # (InfParser, DecParser or DscParser)
199 # @param FilePath The path of meta file
200 #
201 def __new__(cls, FilePath, *args, **kwargs):
202 if args:
203 pass
204 if kwargs:
205 pass
206 if FilePath in cls.MetaFiles:
207 return cls.MetaFiles[FilePath]
208 else:
209 ParserObject = super(InfSectionParser, cls).__new__(cls)
210 cls.MetaFiles[FilePath] = ParserObject
211 return ParserObject
212
213 def __init__(self):
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)
223 #
224 # Initialize all objects that an INF file will generated.
225 #
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()
244
245 #
246 # A List for store define section content.
247 #
248 self._PcdNameList = []
249 self._SectionName = ''
250 self._SectionType = 0
251 self.RelaPath = ''
252 self.FileName = ''
253
254 #
255 # File Header content parser
256 #
257 def InfHeaderParser(self, Content, InfHeaderObject2, FileName, IsBinaryHeader = False):
258 if IsBinaryHeader:
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',
262 FORMAT_INVALID,
263 ST.ERR_INVALID_BINARYHEADER_FORMAT,
264 File=FileName)
265 else:
266 (Abstract, Description, Copyright, License) = ParseHeaderCommentSection(Content, FileName)
267 #
268 # Not process file name now, for later usage.
269 #
270 if self.FileName:
271 pass
272
273 #
274 # Insert Abstract, Description, CopyRight, License into header object
275 #
276 InfHeaderObject2.SetAbstract(Abstract)
277 InfHeaderObject2.SetDescription(Description)
278 InfHeaderObject2.SetCopyright(Copyright)
279 InfHeaderObject2.SetLicense(License)
280
281
282
283
284 ## Section header parser
285 #
286 # The section header is always in following format:
287 #
288 # [section_name.arch<.platform|module_type>]
289 #
290 # @param String A string contained the content need to be parsed.
291 #
292 def SectionHeaderParser(self, SectionString, FileName, LineNo):
293 _Scope = []
294 _SectionName = ''
295 ArchList = set()
296 _ValueList = []
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()
302 ]
303 SectionString = SectionString.strip()
304 for Item in GetSplitValueList(SectionString[1:-1], DT.TAB_COMMA_SPLIT):
305 if Item == '':
306 Logger.Error('Parser',
307 FORMAT_INVALID,
308 ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (""),
309 File=FileName,
310 Line=LineNo,
311 ExtraData=SectionString)
312 ItemList = GetSplitValueList(Item, DT.TAB_SPLIT)
313 #
314 # different section should not mix in one section
315 # Allow different PCD type sections mixed together
316 #
317 if _SectionName.upper() not in _PcdNameList:
318 if _SectionName != '' and _SectionName.upper() != ItemList[0].upper():
319 Logger.Error('Parser',
320 FORMAT_INVALID,
321 ST.ERR_INF_PARSER_SECTION_NAME_DUPLICATE,
322 File=FileName,
323 Line=LineNo,
324 ExtraData=SectionString)
325 elif _PcdNameList[1] in [_SectionName.upper(), ItemList[0].upper()] and \
326 (_SectionName.upper()!= ItemList[0].upper()):
327 Logger.Error('Parser',
328 FORMAT_INVALID,
329 ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (""),
330 File=FileName,
331 Line=LineNo,
332 ExtraData=SectionString)
333
334 _SectionName = ItemList[0]
335 if _SectionName.upper() in gINF_SECTION_DEF:
336 self._SectionType = gINF_SECTION_DEF[_SectionName.upper()]
337 else:
338 self._SectionType = DT.MODEL_UNKNOWN
339 Logger.Error("Parser",
340 FORMAT_INVALID,
341 ST.ERR_INF_PARSER_UNKNOWN_SECTION,
342 File=FileName,
343 Line=LineNo,
344 ExtraData=SectionString)
345
346 #
347 # Get Arch
348 #
349 Str1, ArchList = GetArch(ItemList, ArchList, FileName, LineNo, SectionString)
350
351 #
352 # For [Defines] section, do special check.
353 #
354 if ItemList[0].upper() == DT.TAB_COMMON_DEFINES.upper():
355 if len(ItemList) != 1:
356 Logger.Error('Parser',
357 FORMAT_INVALID,
358 ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (SectionString),
359 File=FileName, Line=LineNo, ExtraData=SectionString)
360
361 #
362 # For [UserExtension] section, do special check.
363 #
364 if ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper():
365
366 RetValue = ProcessUseExtHeader(ItemList)
367
368 if not RetValue[0]:
369 Logger.Error('Parser',
370 FORMAT_INVALID,
371 ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (SectionString),
372 File=FileName, Line=LineNo, ExtraData=SectionString)
373 else:
374 ItemList = RetValue[1]
375
376 if len(ItemList) == 3:
377 ItemList.append('COMMON')
378
379 Str1 = ItemList[1]
380
381 #
382 # For Library classes, need to check module type.
383 #
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',
390 FORMAT_INVALID,
391 ST.ERR_INF_PARSER_DEFINE_MODULETYPE_INVALID % (Item),
392 File=FileName,
393 Line=LineNo,
394 ExtraData=SectionString)
395 #
396 # GetSpecialStr2
397 #
398 Str2 = GetSpecialStr2(ItemList, FileName, LineNo, SectionString)
399
400 _Scope.append([Str1, Str2])
401
402 _NewValueList = []
403 _AppendFlag = True
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
408 _AppendFlag = False
409 elif _SectionName.upper() == ValueItem[0].upper() and Str1.upper() in ValueItem[1].split():
410 _AppendFlag = False
411
412 _NewValueList.append(ValueItem)
413
414 _ValueList = _NewValueList
415
416 if _AppendFlag:
417 if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper():
418 _ValueList.append([_SectionName, Str1, Str2, LineNo])
419 else:
420 if len(ItemList) == 4:
421 _ValueList.append([_SectionName, Str1, Str2, ItemList[3], LineNo])
422
423 self.SectionHeaderContent = deepcopy(_ValueList)
424
425 ## GenSpecialSectionList
426 #
427 # @param SpecialSectionList: a list of list, of which item's format
428 # (Comment, LineNum)
429 # @param ContainerFile: Input value for filename of Inf file
430 #
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)
434 if self.FileName:
435 pass
436 SpecialObjectList = []
437 ArchList = []
438 if SectionType == DT.TYPE_EVENT_SECTION:
439 TokenDict = DT.EVENT_TOKENS
440 elif SectionType == DT.TYPE_HOB_SECTION:
441 TokenDict = DT.HOB_TOKENS
442 else:
443 TokenDict = DT.BOOTMODE_TOKENS
444
445 for List in SpecialSectionList:
446 #
447 # Hob has Arch attribute, need to be handled specially here
448 #
449 if SectionType == DT.TYPE_HOB_SECTION:
450
451 MatchObject = ReFindSpecialCommentRe.search(List[0][0])
452 HobSectionStr = MatchObject.group(1)
453 ArchList = []
454 for Match in ReFindHobArchRe.finditer(HobSectionStr):
455 Arch = Match.groups(1)[0].upper()
456 ArchList.append(Arch)
457 CommentSoFar = ''
458 for Index in xrange(1, len(List)):
459 Result = ParseComment(List[Index], DT.ALL_USAGE_TOKENS, TokenDict, [], False)
460 Usage = Result[0]
461 Type = Result[1]
462 HelpText = Result[3]
463
464 if Usage == DT.ITEM_UNDEFINED and Type == DT.ITEM_UNDEFINED:
465 if HelpText is None:
466 HelpText = ''
467 if not HelpText.endswith('\n'):
468 HelpText += '\n'
469 CommentSoFar += HelpText
470 else:
471 if 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)
485 else:
486 SpecialObject = InfBootModeObject()
487 SpecialObject.SetSupportedBootModes(Type)
488 SpecialObject.SetUsage(Usage)
489 SpecialObject.SetHelpString(CommentSoFar)
490
491 SpecialObjectList.append(SpecialObject)
492 CommentSoFar = ''
493 if not InfSectionObject.SetSpecialComments(SpecialObjectList,
494 SectionType):
495 Logger.Error('InfParser',
496 FORMAT_INVALID,
497 ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (SectionType),
498 ContainerFile
499 )