]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/UPT/Parser/InfSectionParser.py
Roll back the changes for BaseTools
[mirror_edk2.git] / BaseTools / Source / Python / UPT / Parser / InfSectionParser.py
CommitLineData
4234283c
LG
1## @file\r
2# This file contained the parser for sections in INF file \r
3#\r
4# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
5#\r
6# This program and the accompanying materials are licensed and made available \r
7# under the terms and conditions of the BSD License which accompanies this \r
8# distribution. The full text of the license may be found at \r
9# http://opensource.org/licenses/bsd-license.php\r
10#\r
11# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13#\r
14\r
15'''\r
16InfSectionParser\r
17'''\r
18##\r
19# Import Modules\r
20#\r
21from copy import deepcopy\r
22import re\r
23\r
24from Library.String import GetSplitValueList\r
25from Library.CommentParsing import ParseHeaderCommentSection\r
26from Library.CommentParsing import ParseComment\r
27\r
28from Library import DataType as DT\r
29\r
30import Logger.Log as Logger\r
31from Logger import StringTable as ST\r
32from Logger.ToolError import FORMAT_INVALID\r
33\r
34from Object.Parser.InfDefineObject import InfDefObject\r
35from Object.Parser.InfBuildOptionObject import InfBuildOptionsObject\r
36from Object.Parser.InfLibraryClassesObject import InfLibraryClassObject\r
37from Object.Parser.InfPackagesObject import InfPackageObject\r
38from Object.Parser.InfPcdObject import InfPcdObject\r
39from Object.Parser.InfSoucesObject import InfSourcesObject\r
40from Object.Parser.InfUserExtensionObject import InfUserExtensionObject\r
41from Object.Parser.InfProtocolObject import InfProtocolObject\r
42from Object.Parser.InfPpiObject import InfPpiObject\r
43from Object.Parser.InfGuidObject import InfGuidObject\r
44from Object.Parser.InfDepexObject import InfDepexObject\r
45from Object.Parser.InfBinaryObject import InfBinariesObject\r
46from Object.Parser.InfHeaderObject import InfHeaderObject\r
47from Object.Parser.InfMisc import InfSpecialCommentObject\r
48from Object.Parser.InfMisc import InfHobObject\r
49from Object.Parser.InfMisc import InfBootModeObject\r
50from Object.Parser.InfMisc import InfEventObject\r
51from Parser.InfParserMisc import gINF_SECTION_DEF\r
52from Parser.InfDefineSectionParser import InfDefinSectionParser\r
53from Parser.InfBuildOptionSectionParser import InfBuildOptionSectionParser\r
54from Parser.InfSourceSectionParser import InfSourceSectionParser\r
55from Parser.InfLibrarySectionParser import InfLibrarySectionParser\r
56from Parser.InfPackageSectionParser import InfPackageSectionParser\r
57from Parser.InfGuidPpiProtocolSectionParser import InfGuidPpiProtocolSectionParser\r
58from Parser.InfBinarySectionParser import InfBinarySectionParser\r
59from Parser.InfPcdSectionParser import InfPcdSectionParser\r
60from Parser.InfDepexSectionParser import InfDepexSectionParser\r
61\r
62## GetSpecialStr2\r
63#\r
64# GetSpecialStr2\r
65#\r
66def GetSpecialStr2(ItemList, FileName, LineNo, SectionString):\r
67 Str2 = ''\r
68 #\r
69 # S2 may be Platform or ModuleType\r
70 #\r
71 if len(ItemList) == 3:\r
72 #\r
73 # Except [LibraryClass], [Depex]\r
74 # section can has more than 2 items in section header string,\r
75 # others should report error.\r
76 #\r
77 if not (ItemList[0].upper() == DT.TAB_LIBRARY_CLASSES.upper() or \\r
78 ItemList[0].upper() == DT.TAB_DEPEX.upper() or \\r
79 ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper()):\r
80 if ItemList[2] != '':\r
81 Logger.Error('Parser',\r
82 FORMAT_INVALID,\r
83 ST.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID % (SectionString),\r
84 File=FileName,\r
85 Line=LineNo,\r
86 ExtraData=SectionString)\r
87 Str2 = ItemList[2]\r
88 elif len(ItemList) == 4:\r
89 #\r
90 # Except [UserExtension]\r
91 # section can has 4 items in section header string,\r
92 # others should report error.\r
93 #\r
94 if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper() or ItemList[0].upper() == DT.TAB_DEPEX.upper():\r
95 if ItemList[3] != '':\r
96 Logger.Error('Parser', FORMAT_INVALID, ST.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID \\r
97 % (SectionString), File=FileName, Line=LineNo, ExtraData=SectionString)\r
98 \r
99 if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper():\r
100 Str2 = ItemList[2] + ' | ' + ItemList[3]\r
101 else:\r
102 Str2 = ItemList[2]\r
103\r
104 elif len(ItemList) > 4:\r
105 Logger.Error('Parser', FORMAT_INVALID, ST.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID \\r
106 % (SectionString), File=FileName, Line=LineNo, ExtraData=SectionString)\r
107\r
108 return Str2\r
109\r
110## ProcessUseExtHeader\r
111# \r
112#\r
113def ProcessUseExtHeader(ItemList):\r
114 NewItemList = []\r
115 AppendContent = ''\r
116 CompleteFlag = False\r
117 for Item in ItemList:\r
118 if Item.startswith('\"') and not Item.endswith('\"'):\r
119 AppendContent = Item\r
120 CompleteFlag = True\r
121 elif Item.endswith('\"') and not Item.startswith('\"'):\r
122 #\r
123 # Should not have an userId or IdString not starts with " before but ends with ".\r
124 #\r
125 if not CompleteFlag:\r
126 return False, []\r
127 AppendContent = AppendContent + "." + Item\r
128 NewItemList.append(AppendContent)\r
129 CompleteFlag = False\r
130 AppendContent = ''\r
131 elif Item.endswith('\"') and Item.startswith('\"'):\r
132 #\r
133 # Common item, not need to combine the information\r
134 #\r
135 NewItemList.append(Item)\r
136 else:\r
137 if not CompleteFlag:\r
138 NewItemList.append(Item)\r
139 else:\r
140 AppendContent = AppendContent + "." + Item\r
141 \r
142 if len(NewItemList) > 4:\r
143 return False, []\r
144 \r
145 return True, NewItemList\r
146 \r
147## GetArch\r
148#\r
149# GetArch\r
150#\r
151def GetArch(ItemList, ArchList, FileName, LineNo, SectionString):\r
152 #\r
153 # S1 is always Arch\r
154 #\r
155 if len(ItemList) > 1:\r
156 Arch = ItemList[1]\r
157 else:\r
158 Arch = 'COMMON'\r
159 ArchList.add(Arch)\r
160\r
161 #\r
162 # 'COMMON' must not be used with specific ARCHs at the same section\r
163 #\r
164 if 'COMMON' in ArchList and len(ArchList) > 1:\r
165 Logger.Error('Parser',\r
166 FORMAT_INVALID,\r
167 ST.ERR_INF_PARSER_SECTION_ARCH_CONFLICT,\r
168 File=FileName,\r
169 Line=LineNo,\r
170 ExtraData=SectionString)\r
171\r
172 return Arch, ArchList\r
173\r
174## InfSectionParser\r
175#\r
176# Inherit from object\r
177#\r
178class InfSectionParser(InfDefinSectionParser,\r
179 InfBuildOptionSectionParser,\r
180 InfSourceSectionParser,\r
181 InfLibrarySectionParser,\r
182 InfPackageSectionParser,\r
183 InfGuidPpiProtocolSectionParser,\r
184 InfBinarySectionParser,\r
185 InfPcdSectionParser,\r
186 InfDepexSectionParser):\r
187 #\r
188 # Parser objects used to implement singleton\r
189 #\r
190 MetaFiles = {}\r
191\r
192 ## Factory method\r
193 #\r
194 # One file, one parser object. This factory method makes sure that there's\r
195 # only one object constructed for one meta file.\r
196 #\r
197 # @param Class class object of real AutoGen class\r
198 # (InfParser, DecParser or DscParser)\r
199 # @param FilePath The path of meta file\r
200 #\r
201 def __new__(cls, FilePath, *args, **kwargs):\r
202 if args:\r
203 pass\r
204 if kwargs:\r
205 pass\r
206 if FilePath in cls.MetaFiles:\r
207 return cls.MetaFiles[FilePath]\r
208 else:\r
209 ParserObject = super(InfSectionParser, cls).__new__(cls)\r
210 cls.MetaFiles[FilePath] = ParserObject\r
211 return ParserObject\r
212\r
213 def __init__(self):\r
214 InfDefinSectionParser.__init__(self)\r
215 InfBuildOptionSectionParser.__init__(self)\r
216 InfSourceSectionParser.__init__(self)\r
217 InfLibrarySectionParser.__init__(self)\r
218 InfPackageSectionParser.__init__(self)\r
219 InfGuidPpiProtocolSectionParser.__init__(self)\r
220 InfBinarySectionParser.__init__(self)\r
221 InfPcdSectionParser.__init__(self)\r
222 InfDepexSectionParser.__init__(self)\r
223 #\r
224 # Initialize all objects that an INF file will generated.\r
225 #\r
226 self.InfDefSection = InfDefObject()\r
227 self.InfBuildOptionSection = InfBuildOptionsObject()\r
228 self.InfLibraryClassSection = InfLibraryClassObject()\r
229 self.InfPackageSection = InfPackageObject()\r
230 self.InfPcdSection = InfPcdObject(self.MetaFiles.keys()[0])\r
231 self.InfSourcesSection = InfSourcesObject()\r
232 self.InfUserExtensionSection = InfUserExtensionObject()\r
233 self.InfProtocolSection = InfProtocolObject()\r
234 self.InfPpiSection = InfPpiObject()\r
235 self.InfGuidSection = InfGuidObject()\r
236 self.InfDepexSection = InfDepexObject()\r
237 self.InfPeiDepexSection = InfDepexObject()\r
238 self.InfDxeDepexSection = InfDepexObject()\r
239 self.InfSmmDepexSection = InfDepexObject()\r
240 self.InfBinariesSection = InfBinariesObject()\r
241 self.InfHeader = InfHeaderObject()\r
242 self.InfSpecialCommentSection = InfSpecialCommentObject()\r
243\r
244 #\r
245 # A List for store define section content.\r
246 # \r
247 self._PcdNameList = []\r
248 self._SectionName = ''\r
249 self._SectionType = 0\r
250 self.RelaPath = ''\r
251 self.FileName = ''\r
252\r
253 #\r
254 # File Header content parser\r
255 # \r
256 def InfHeaderParser(self, Content, InfHeaderObject2, FileName):\r
257 (Abstract, Description, Copyright, License) = ParseHeaderCommentSection(Content, FileName)\r
258 #\r
259 # Not process file name now, for later usage.\r
260 #\r
261 if self.FileName:\r
262 pass\r
263\r
264 #\r
265 # Insert Abstract, Description, CopyRight, License into header object\r
266 # \r
267 InfHeaderObject2.SetAbstract(Abstract)\r
268 InfHeaderObject2.SetDescription(Description)\r
269 InfHeaderObject2.SetCopyright(Copyright)\r
270 InfHeaderObject2.SetLicense(License)\r
271\r
272\r
273\r
274\r
275 ## Section header parser\r
276 #\r
277 # The section header is always in following format:\r
278 #\r
279 # [section_name.arch<.platform|module_type>]\r
280 #\r
281 # @param String A string contained the content need to be parsed. \r
282 #\r
283 def SectionHeaderParser(self, SectionString, FileName, LineNo):\r
284 _Scope = []\r
285 _SectionName = ''\r
286 ArchList = set()\r
287 _ValueList = []\r
288 _PcdNameList = [DT.TAB_INF_FIXED_PCD.upper(),\r
289 DT.TAB_INF_FEATURE_PCD.upper(),\r
290 DT.TAB_INF_PATCH_PCD.upper(),\r
291 DT.TAB_INF_PCD.upper(),\r
292 DT.TAB_INF_PCD_EX.upper()\r
293 ]\r
294 SectionString = SectionString.strip()\r
295 for Item in GetSplitValueList(SectionString[1:-1], DT.TAB_COMMA_SPLIT):\r
296 if Item == '':\r
297 Logger.Error('Parser',\r
298 FORMAT_INVALID,\r
299 ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (""),\r
300 File=FileName,\r
301 Line=LineNo,\r
302 ExtraData=SectionString)\r
303 ItemList = GetSplitValueList(Item, DT.TAB_SPLIT)\r
304 #\r
305 # different section should not mix in one section\r
306 # Allow different PCD type sections mixed together\r
307 # \r
308 if _SectionName.upper() not in _PcdNameList:\r
309 if _SectionName != '' and _SectionName.upper() != ItemList[0].upper():\r
310 Logger.Error('Parser',\r
311 FORMAT_INVALID,\r
312 ST.ERR_INF_PARSER_SECTION_NAME_DUPLICATE,\r
313 File=FileName,\r
314 Line=LineNo,\r
315 ExtraData=SectionString)\r
316 elif _PcdNameList[1] in [_SectionName.upper(), ItemList[0].upper()] and \\r
317 (_SectionName.upper()!= ItemList[0].upper()):\r
318 Logger.Error('Parser',\r
319 FORMAT_INVALID,\r
320 ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (""),\r
321 File=FileName,\r
322 Line=LineNo,\r
323 ExtraData=SectionString)\r
324\r
325 _SectionName = ItemList[0]\r
326 if _SectionName.upper() in gINF_SECTION_DEF:\r
327 self._SectionType = gINF_SECTION_DEF[_SectionName.upper()]\r
328 else:\r
329 self._SectionType = DT.MODEL_UNKNOWN\r
330 Logger.Error("Parser",\r
331 FORMAT_INVALID,\r
332 ST.ERR_INF_PARSER_UNKNOWN_SECTION,\r
333 File=FileName,\r
334 Line=LineNo,\r
335 ExtraData=SectionString)\r
336\r
337 #\r
338 # Get Arch\r
339 #\r
340 Str1, ArchList = GetArch(ItemList, ArchList, FileName, LineNo, SectionString)\r
341\r
342 #\r
343 # For [Defines] section, do special check.\r
344 # \r
345 if ItemList[0].upper() == DT.TAB_COMMON_DEFINES.upper():\r
346 if len(ItemList) != 1:\r
347 Logger.Error('Parser',\r
348 FORMAT_INVALID,\r
349 ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (SectionString),\r
350 File=FileName, Line=LineNo, ExtraData=SectionString)\r
351\r
352 #\r
353 # For [UserExtension] section, do special check.\r
354 # \r
355 if ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper():\r
356 \r
357 RetValue = ProcessUseExtHeader(ItemList)\r
358 \r
359 if not RetValue[0]:\r
360 Logger.Error('Parser',\r
361 FORMAT_INVALID,\r
362 ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (SectionString),\r
363 File=FileName, Line=LineNo, ExtraData=SectionString)\r
364 else:\r
365 ItemList = RetValue[1] \r
366 \r
367 if len(ItemList) == 3:\r
368 ItemList.append('COMMON')\r
369 \r
370 Str1 = ItemList[1]\r
371\r
372 #\r
373 # For Library classes, need to check module type. \r
374 #\r
375 if ItemList[0].upper() == DT.TAB_LIBRARY_CLASSES.upper() and len(ItemList) == 3:\r
376 if ItemList[2] != '':\r
377 ModuleTypeList = GetSplitValueList(ItemList[2], DT.TAB_VALUE_SPLIT)\r
378 for Item in ModuleTypeList:\r
379 if Item.strip() not in DT.MODULE_LIST:\r
380 Logger.Error('Parser',\r
381 FORMAT_INVALID,\r
382 ST.ERR_INF_PARSER_DEFINE_MODULETYPE_INVALID % (Item),\r
383 File=FileName,\r
384 Line=LineNo,\r
385 ExtraData=SectionString)\r
386 #\r
387 # GetSpecialStr2\r
388 #\r
389 Str2 = GetSpecialStr2(ItemList, FileName, LineNo, SectionString)\r
390\r
391 _Scope.append([Str1, Str2])\r
392\r
393 _NewValueList = []\r
394 _AppendFlag = True\r
395 if _SectionName.upper() in _PcdNameList:\r
396 for ValueItem in _ValueList:\r
397 if _SectionName.upper() == ValueItem[0].upper() and Str1.upper() not in ValueItem[1].split():\r
398 ValueItem[1] = ValueItem[1] + " " + Str1\r
399 _AppendFlag = False\r
400 elif _SectionName.upper() == ValueItem[0].upper() and Str1.upper() in ValueItem[1].split():\r
401 _AppendFlag = False\r
402\r
403 _NewValueList.append(ValueItem)\r
404\r
405 _ValueList = _NewValueList\r
406\r
407 if _AppendFlag:\r
408 if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper():\r
409 _ValueList.append([_SectionName, Str1, Str2, LineNo])\r
410 else:\r
411 if len(ItemList) == 4:\r
412 _ValueList.append([_SectionName, Str1, Str2, ItemList[3], LineNo])\r
413\r
414 self.SectionHeaderContent = deepcopy(_ValueList)\r
415\r
416 ## GenSpecialSectionList\r
417 #\r
418 # @param SpecialSectionList: a list of list, of which item's format \r
419 # (Comment, LineNum)\r
420 # @param ContainerFile: Input value for filename of Inf file\r
421 # \r
422 def InfSpecialCommentParser (self, SpecialSectionList, InfSectionObject, ContainerFile, SectionType):\r
423 ReFindSpecialCommentRe = re.compile(r"""#(?:\s*)\[(.*?)\](?:.*)""", re.DOTALL)\r
424 ReFindHobArchRe = re.compile(r"""[Hh][Oo][Bb]\.([^,]*)""", re.DOTALL)\r
425 if self.FileName:\r
426 pass\r
427 SpecialObjectList = []\r
428 ArchList = []\r
429 if SectionType == DT.TYPE_EVENT_SECTION:\r
430 TokenDict = DT.EVENT_TOKENS\r
431 elif SectionType == DT.TYPE_HOB_SECTION:\r
432 TokenDict = DT.HOB_TOKENS\r
433 else:\r
434 TokenDict = DT.BOOTMODE_TOKENS\r
435\r
436 for List in SpecialSectionList:\r
437 #\r
438 # Hob has Arch attribute, need to be handled specially here\r
439 #\r
440 if SectionType == DT.TYPE_HOB_SECTION:\r
441\r
442 MatchObject = ReFindSpecialCommentRe.search(List[0][0])\r
443 HobSectionStr = MatchObject.group(1)\r
444 ArchList = []\r
445 for Match in ReFindHobArchRe.finditer(HobSectionStr):\r
446 Arch = Match.groups(1)[0].upper()\r
447 ArchList.append(Arch)\r
448 CommentSoFar = ''\r
449 for Index in xrange(1, len(List)):\r
450 Result = ParseComment(List[Index], DT.ALL_USAGE_TOKENS, TokenDict, [], False)\r
451 Usage = Result[0]\r
452 Type = Result[1]\r
453 HelpText = Result[3]\r
454\r
455 if Usage == DT.ITEM_UNDEFINED and Type == DT.ITEM_UNDEFINED:\r
456 if HelpText is None:\r
457 HelpText = ''\r
458 if not HelpText.endswith('\n'):\r
459 HelpText += '\n'\r
460 CommentSoFar += HelpText\r
461 else:\r
462 if HelpText:\r
463 CommentSoFar += HelpText\r
464 if SectionType == DT.TYPE_EVENT_SECTION:\r
465 SpecialObject = InfEventObject()\r
466 SpecialObject.SetEventType(Type)\r
467 SpecialObject.SetUsage(Usage)\r
468 SpecialObject.SetHelpString(CommentSoFar)\r
469 elif SectionType == DT.TYPE_HOB_SECTION:\r
470 SpecialObject = InfHobObject()\r
471 SpecialObject.SetHobType(Type)\r
472 SpecialObject.SetUsage(Usage)\r
473 SpecialObject.SetHelpString(CommentSoFar)\r
474 if len(ArchList) >= 1:\r
475 SpecialObject.SetSupArchList(ArchList)\r
476 else:\r
477 SpecialObject = InfBootModeObject()\r
478 SpecialObject.SetSupportedBootModes(Type)\r
479 SpecialObject.SetUsage(Usage)\r
480 SpecialObject.SetHelpString(CommentSoFar)\r
481\r
482 SpecialObjectList.append(SpecialObject)\r
483 CommentSoFar = ''\r
484 if not InfSectionObject.SetSpecialComments(SpecialObjectList,\r
485 SectionType):\r
486 Logger.Error('InfParser',\r
487 FORMAT_INVALID,\r
488 ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (SectionType),\r
489 ContainerFile\r
490 )\r