]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/UPT/Parser/InfSectionParser.py
Sync BaseTools Branch (version r2271) to EDKII main trunk.
[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, 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.InfSpecialCommentSection = InfSpecialCommentObject()
243
244 #
245 # A List for store define section content.
246 #
247 self._PcdNameList = []
248 self._SectionName = ''
249 self._SectionType = 0
250 self.RelaPath = ''
251 self.FileName = ''
252
253 #
254 # File Header content parser
255 #
256 def InfHeaderParser(self, Content, InfHeaderObject2, FileName):
257 (Abstract, Description, Copyright, License) = ParseHeaderCommentSection(Content, FileName)
258 #
259 # Not process file name now, for later usage.
260 #
261 if self.FileName:
262 pass
263
264 #
265 # Insert Abstract, Description, CopyRight, License into header object
266 #
267 InfHeaderObject2.SetAbstract(Abstract)
268 InfHeaderObject2.SetDescription(Description)
269 InfHeaderObject2.SetCopyright(Copyright)
270 InfHeaderObject2.SetLicense(License)
271
272
273
274
275 ## Section header parser
276 #
277 # The section header is always in following format:
278 #
279 # [section_name.arch<.platform|module_type>]
280 #
281 # @param String A string contained the content need to be parsed.
282 #
283 def SectionHeaderParser(self, SectionString, FileName, LineNo):
284 _Scope = []
285 _SectionName = ''
286 ArchList = set()
287 _ValueList = []
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()
293 ]
294 SectionString = SectionString.strip()
295 for Item in GetSplitValueList(SectionString[1:-1], DT.TAB_COMMA_SPLIT):
296 if Item == '':
297 Logger.Error('Parser',
298 FORMAT_INVALID,
299 ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (""),
300 File=FileName,
301 Line=LineNo,
302 ExtraData=SectionString)
303 ItemList = GetSplitValueList(Item, DT.TAB_SPLIT)
304 #
305 # different section should not mix in one section
306 # Allow different PCD type sections mixed together
307 #
308 if _SectionName.upper() not in _PcdNameList:
309 if _SectionName != '' and _SectionName.upper() != ItemList[0].upper():
310 Logger.Error('Parser',
311 FORMAT_INVALID,
312 ST.ERR_INF_PARSER_SECTION_NAME_DUPLICATE,
313 File=FileName,
314 Line=LineNo,
315 ExtraData=SectionString)
316 elif _PcdNameList[1] in [_SectionName.upper(), ItemList[0].upper()] and \
317 (_SectionName.upper()!= ItemList[0].upper()):
318 Logger.Error('Parser',
319 FORMAT_INVALID,
320 ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (""),
321 File=FileName,
322 Line=LineNo,
323 ExtraData=SectionString)
324
325 _SectionName = ItemList[0]
326 if _SectionName.upper() in gINF_SECTION_DEF:
327 self._SectionType = gINF_SECTION_DEF[_SectionName.upper()]
328 else:
329 self._SectionType = DT.MODEL_UNKNOWN
330 Logger.Error("Parser",
331 FORMAT_INVALID,
332 ST.ERR_INF_PARSER_UNKNOWN_SECTION,
333 File=FileName,
334 Line=LineNo,
335 ExtraData=SectionString)
336
337 #
338 # Get Arch
339 #
340 Str1, ArchList = GetArch(ItemList, ArchList, FileName, LineNo, SectionString)
341
342 #
343 # For [Defines] section, do special check.
344 #
345 if ItemList[0].upper() == DT.TAB_COMMON_DEFINES.upper():
346 if len(ItemList) != 1:
347 Logger.Error('Parser',
348 FORMAT_INVALID,
349 ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (SectionString),
350 File=FileName, Line=LineNo, ExtraData=SectionString)
351
352 #
353 # For [UserExtension] section, do special check.
354 #
355 if ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper():
356
357 RetValue = ProcessUseExtHeader(ItemList)
358
359 if not RetValue[0]:
360 Logger.Error('Parser',
361 FORMAT_INVALID,
362 ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (SectionString),
363 File=FileName, Line=LineNo, ExtraData=SectionString)
364 else:
365 ItemList = RetValue[1]
366
367 if len(ItemList) == 3:
368 ItemList.append('COMMON')
369
370 Str1 = ItemList[1]
371
372 #
373 # For Library classes, need to check module type.
374 #
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',
381 FORMAT_INVALID,
382 ST.ERR_INF_PARSER_DEFINE_MODULETYPE_INVALID % (Item),
383 File=FileName,
384 Line=LineNo,
385 ExtraData=SectionString)
386 #
387 # GetSpecialStr2
388 #
389 Str2 = GetSpecialStr2(ItemList, FileName, LineNo, SectionString)
390
391 _Scope.append([Str1, Str2])
392
393 _NewValueList = []
394 _AppendFlag = True
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
399 _AppendFlag = False
400 elif _SectionName.upper() == ValueItem[0].upper() and Str1.upper() in ValueItem[1].split():
401 _AppendFlag = False
402
403 _NewValueList.append(ValueItem)
404
405 _ValueList = _NewValueList
406
407 if _AppendFlag:
408 if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper():
409 _ValueList.append([_SectionName, Str1, Str2, LineNo])
410 else:
411 if len(ItemList) == 4:
412 _ValueList.append([_SectionName, Str1, Str2, ItemList[3], LineNo])
413
414 self.SectionHeaderContent = deepcopy(_ValueList)
415
416 ## GenSpecialSectionList
417 #
418 # @param SpecialSectionList: a list of list, of which item's format
419 # (Comment, LineNum)
420 # @param ContainerFile: Input value for filename of Inf file
421 #
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)
425 if self.FileName:
426 pass
427 SpecialObjectList = []
428 ArchList = []
429 if SectionType == DT.TYPE_EVENT_SECTION:
430 TokenDict = DT.EVENT_TOKENS
431 elif SectionType == DT.TYPE_HOB_SECTION:
432 TokenDict = DT.HOB_TOKENS
433 else:
434 TokenDict = DT.BOOTMODE_TOKENS
435
436 for List in SpecialSectionList:
437 #
438 # Hob has Arch attribute, need to be handled specially here
439 #
440 if SectionType == DT.TYPE_HOB_SECTION:
441
442 MatchObject = ReFindSpecialCommentRe.search(List[0][0])
443 HobSectionStr = MatchObject.group(1)
444 ArchList = []
445 for Match in ReFindHobArchRe.finditer(HobSectionStr):
446 Arch = Match.groups(1)[0].upper()
447 ArchList.append(Arch)
448 CommentSoFar = ''
449 for Index in xrange(1, len(List)):
450 Result = ParseComment(List[Index], DT.ALL_USAGE_TOKENS, TokenDict, [], False)
451 Usage = Result[0]
452 Type = Result[1]
453 HelpText = Result[3]
454
455 if Usage == DT.ITEM_UNDEFINED and Type == DT.ITEM_UNDEFINED:
456 if HelpText is None:
457 HelpText = ''
458 if not HelpText.endswith('\n'):
459 HelpText += '\n'
460 CommentSoFar += HelpText
461 else:
462 if 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)
476 else:
477 SpecialObject = InfBootModeObject()
478 SpecialObject.SetSupportedBootModes(Type)
479 SpecialObject.SetUsage(Usage)
480 SpecialObject.SetHelpString(CommentSoFar)
481
482 SpecialObjectList.append(SpecialObject)
483 CommentSoFar = ''
484 if not InfSectionObject.SetSpecialComments(SpecialObjectList,
485 SectionType):
486 Logger.Error('InfParser',
487 FORMAT_INVALID,
488 ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (SectionType),
489 ContainerFile
490 )