]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - BaseTools/Source/Python/Workspace/MetaFileParser.py
BaseTools: Replace StandardError with Expression
[mirror_edk2.git] / BaseTools / Source / Python / Workspace / MetaFileParser.py
... / ...
CommitLineData
1## @file\r
2# This file is used to parse meta files\r
3#\r
4# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>\r
5# (C) Copyright 2015-2018 Hewlett Packard Enterprise Development LP<BR>\r
6# This program and the accompanying materials\r
7# are licensed and made available under the terms and conditions of the BSD License\r
8# which accompanies this 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
16# Import Modules\r
17#\r
18from __future__ import print_function\r
19import Common.LongFilePathOs as os\r
20import re\r
21import time\r
22import copy\r
23import md5\r
24\r
25import Common.EdkLogger as EdkLogger\r
26import Common.GlobalData as GlobalData\r
27\r
28from CommonDataClass.DataClass import *\r
29from Common.DataType import *\r
30from Common.StringUtils import *\r
31from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData, AnalyzeDscPcd, AnalyzePcdExpression, ParseFieldValue\r
32from Common.Expression import *\r
33from CommonDataClass.Exceptions import *\r
34from Common.LongFilePathSupport import OpenLongFilePath as open\r
35from collections import defaultdict\r
36from MetaFileTable import MetaFileStorage\r
37from MetaFileCommentParser import CheckInfComment\r
38\r
39## RegEx for finding file versions\r
40hexVersionPattern = re.compile(r'0[xX][\da-f-A-F]{5,8}')\r
41decVersionPattern = re.compile(r'\d+\.\d+')\r
42\r
43## A decorator used to parse macro definition\r
44def ParseMacro(Parser):\r
45 def MacroParser(self):\r
46 Match = gMacroDefPattern.match(self._CurrentLine)\r
47 if not Match:\r
48 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method\r
49 Parser(self)\r
50 return\r
51\r
52 TokenList = GetSplitValueList(self._CurrentLine[Match.end(1):], TAB_EQUAL_SPLIT, 1)\r
53 # Syntax check\r
54 if not TokenList[0]:\r
55 EdkLogger.error('Parser', FORMAT_INVALID, "No macro name given",\r
56 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
57 if len(TokenList) < 2:\r
58 TokenList.append('')\r
59\r
60 Type = Match.group(1)\r
61 Name, Value = TokenList\r
62 # Global macros can be only defined via environment variable\r
63 if Name in GlobalData.gGlobalDefines:\r
64 EdkLogger.error('Parser', FORMAT_INVALID, "%s can only be defined via environment variable" % Name,\r
65 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
66 # Only upper case letters, digit and '_' are allowed\r
67 if not gMacroNamePattern.match(Name):\r
68 EdkLogger.error('Parser', FORMAT_INVALID, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",\r
69 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
70\r
71 Value = ReplaceMacro(Value, self._Macros)\r
72 if Type in self.DataType:\r
73 self._ItemType = self.DataType[Type]\r
74 else:\r
75 self._ItemType = MODEL_META_DATA_DEFINE\r
76 # DEFINE defined macros\r
77 if Type == TAB_DSC_DEFINES_DEFINE:\r
78 #\r
79 # First judge whether this DEFINE is in conditional directive statements or not.\r
80 #\r
81 if type(self) == DscParser and self._InDirective > -1:\r
82 pass\r
83 else:\r
84 if type(self) == DecParser:\r
85 if MODEL_META_DATA_HEADER in self._SectionType:\r
86 self._FileLocalMacros[Name] = Value\r
87 else:\r
88 self._ConstructSectionMacroDict(Name, Value)\r
89 elif self._SectionType == MODEL_META_DATA_HEADER:\r
90 self._FileLocalMacros[Name] = Value\r
91 else:\r
92 self._ConstructSectionMacroDict(Name, Value)\r
93\r
94 # EDK_GLOBAL defined macros\r
95 elif type(self) != DscParser:\r
96 EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used in .dsc file",\r
97 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
98 elif self._SectionType != MODEL_META_DATA_HEADER:\r
99 EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used under [Defines] section",\r
100 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
101 elif (Name in self._FileLocalMacros) and (self._FileLocalMacros[Name] != Value):\r
102 EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",\r
103 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
104\r
105 self._ValueList = [Type, Name, Value]\r
106\r
107 return MacroParser\r
108\r
109## Base class of parser\r
110#\r
111# This class is used for derivation purpose. The specific parser for one kind\r
112# type file must derive this class and implement some public interfaces.\r
113#\r
114# @param FilePath The path of platform description file\r
115# @param FileType The raw data of DSC file\r
116# @param Table Database used to retrieve module/package information\r
117# @param Macros Macros used for replacement in file\r
118# @param Owner Owner ID (for sub-section parsing)\r
119# @param From ID from which the data comes (for !INCLUDE directive)\r
120#\r
121class MetaFileParser(object):\r
122 # data type (file content) for specific file type\r
123 DataType = {}\r
124\r
125 # Parser objects used to implement singleton\r
126 MetaFiles = {}\r
127\r
128 ## Factory method\r
129 #\r
130 # One file, one parser object. This factory method makes sure that there's\r
131 # only one object constructed for one meta file.\r
132 #\r
133 # @param Class class object of real AutoGen class\r
134 # (InfParser, DecParser or DscParser)\r
135 # @param FilePath The path of meta file\r
136 # @param *args The specific class related parameters\r
137 # @param **kwargs The specific class related dict parameters\r
138 #\r
139 def __new__(Class, FilePath, *args, **kwargs):\r
140 if FilePath in Class.MetaFiles:\r
141 return Class.MetaFiles[FilePath]\r
142 else:\r
143 ParserObject = super(MetaFileParser, Class).__new__(Class)\r
144 Class.MetaFiles[FilePath] = ParserObject\r
145 return ParserObject\r
146\r
147 ## Constructor of MetaFileParser\r
148 #\r
149 # Initialize object of MetaFileParser\r
150 #\r
151 # @param FilePath The path of platform description file\r
152 # @param FileType The raw data of DSC file\r
153 # @param Arch Default Arch value for filtering sections\r
154 # @param Table Database used to retrieve module/package information\r
155 # @param Owner Owner ID (for sub-section parsing)\r
156 # @param From ID from which the data comes (for !INCLUDE directive)\r
157 #\r
158 def __init__(self, FilePath, FileType, Arch, Table, Owner= -1, From= -1):\r
159 self._Table = Table\r
160 self._RawTable = Table\r
161 self._Arch = Arch\r
162 self._FileType = FileType\r
163 self.MetaFile = FilePath\r
164 self._FileDir = self.MetaFile.Dir\r
165 self._Defines = {}\r
166 self._FileLocalMacros = {}\r
167 self._SectionsMacroDict = defaultdict(dict)\r
168\r
169 # for recursive parsing\r
170 self._Owner = [Owner]\r
171 self._From = From\r
172\r
173 # parsr status for parsing\r
174 self._ValueList = ['', '', '', '', '']\r
175 self._Scope = []\r
176 self._LineIndex = 0\r
177 self._CurrentLine = ''\r
178 self._SectionType = MODEL_UNKNOWN\r
179 self._SectionName = ''\r
180 self._InSubsection = False\r
181 self._SubsectionType = MODEL_UNKNOWN\r
182 self._SubsectionName = ''\r
183 self._ItemType = MODEL_UNKNOWN\r
184 self._LastItem = -1\r
185 self._Enabled = 0\r
186 self._Finished = False\r
187 self._PostProcessed = False\r
188 # Different version of meta-file has different way to parse.\r
189 self._Version = 0\r
190 self._GuidDict = {} # for Parser PCD value {GUID(gTokeSpaceGuidName)}\r
191\r
192 ## Store the parsed data in table\r
193 def _Store(self, *Args):\r
194 return self._Table.Insert(*Args)\r
195\r
196 ## Virtual method for starting parse\r
197 def Start(self):\r
198 raise NotImplementedError\r
199\r
200 ## Notify a post-process is needed\r
201 def DoPostProcess(self):\r
202 self._PostProcessed = False\r
203\r
204 ## Set parsing complete flag in both class and table\r
205 def _Done(self):\r
206 self._Finished = True\r
207 ## Do not set end flag when processing included files\r
208 if self._From == -1:\r
209 self._Table.SetEndFlag()\r
210\r
211 def _PostProcess(self):\r
212 self._PostProcessed = True\r
213\r
214 ## Get the parse complete flag\r
215 def _GetFinished(self):\r
216 return self._Finished\r
217\r
218 ## Set the complete flag\r
219 def _SetFinished(self, Value):\r
220 self._Finished = Value\r
221\r
222 ## Remove records that do not match given Filter Arch\r
223 def _FilterRecordList(self, RecordList, FilterArch):\r
224 NewRecordList = []\r
225 for Record in RecordList:\r
226 Arch = Record[3]\r
227 if Arch == TAB_ARCH_COMMON or Arch == FilterArch:\r
228 NewRecordList.append(Record)\r
229 return NewRecordList\r
230\r
231 ## Use [] style to query data in table, just for readability\r
232 #\r
233 # DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]\r
234 #\r
235 def __getitem__(self, DataInfo):\r
236 if type(DataInfo) != type(()):\r
237 DataInfo = (DataInfo,)\r
238\r
239 # Parse the file first, if necessary\r
240 if not self._Finished:\r
241 if self._RawTable.IsIntegrity():\r
242 self._Finished = True\r
243 else:\r
244 self._Table = self._RawTable\r
245 self._PostProcessed = False\r
246 self.Start()\r
247\r
248 # No specific ARCH or Platform given, use raw data\r
249 if self._RawTable and (len(DataInfo) == 1 or DataInfo[1] is None):\r
250 return self._FilterRecordList(self._RawTable.Query(*DataInfo), self._Arch)\r
251\r
252 # Do post-process if necessary\r
253 if not self._PostProcessed:\r
254 self._PostProcess()\r
255\r
256 return self._FilterRecordList(self._Table.Query(*DataInfo), DataInfo[1])\r
257\r
258 ## Data parser for the common format in different type of file\r
259 #\r
260 # The common format in the meatfile is like\r
261 #\r
262 # xxx1 | xxx2 | xxx3\r
263 #\r
264 @ParseMacro\r
265 def _CommonParser(self):\r
266 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
267 self._ValueList[0:len(TokenList)] = TokenList\r
268\r
269 ## Data parser for the format in which there's path\r
270 #\r
271 # Only path can have macro used. So we need to replace them before use.\r
272 #\r
273 @ParseMacro\r
274 def _PathParser(self):\r
275 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
276 self._ValueList[0:len(TokenList)] = TokenList\r
277 # Don't do macro replacement for dsc file at this point\r
278 if type(self) != DscParser:\r
279 Macros = self._Macros\r
280 self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]\r
281\r
282 ## Skip unsupported data\r
283 def _Skip(self):\r
284 EdkLogger.warn("Parser", "Unrecognized content", File=self.MetaFile,\r
285 Line=self._LineIndex + 1, ExtraData=self._CurrentLine);\r
286 self._ValueList[0:1] = [self._CurrentLine]\r
287\r
288 ## Skip unsupported data for UserExtension Section\r
289 def _SkipUserExtension(self):\r
290 self._ValueList[0:1] = [self._CurrentLine]\r
291\r
292 ## Section header parser\r
293 #\r
294 # The section header is always in following format:\r
295 #\r
296 # [section_name.arch<.platform|module_type>]\r
297 #\r
298 def _SectionHeaderParser(self):\r
299 self._Scope = []\r
300 self._SectionName = ''\r
301 ArchList = set()\r
302 for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):\r
303 if Item == '':\r
304 continue\r
305 ItemList = GetSplitValueList(Item, TAB_SPLIT,3)\r
306 # different section should not mix in one section\r
307 if self._SectionName != '' and self._SectionName != ItemList[0].upper():\r
308 EdkLogger.error('Parser', FORMAT_INVALID, "Different section names in the same section",\r
309 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
310 self._SectionName = ItemList[0].upper()\r
311 if self._SectionName in self.DataType:\r
312 self._SectionType = self.DataType[self._SectionName]\r
313 # Check if the section name is valid\r
314 if self._SectionName not in SECTIONS_HAVE_ITEM_AFTER_ARCH_SET and len(ItemList) > 3:\r
315 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,\r
316 self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
317 elif self._Version >= 0x00010005:\r
318 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,\r
319 self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
320 else:\r
321 self._SectionType = MODEL_UNKNOWN\r
322\r
323 # S1 is always Arch\r
324 if len(ItemList) > 1:\r
325 S1 = ItemList[1].upper()\r
326 else:\r
327 S1 = TAB_ARCH_COMMON\r
328 ArchList.add(S1)\r
329\r
330 # S2 may be Platform or ModuleType\r
331 if len(ItemList) > 2:\r
332 if self._SectionName.upper() in SECTIONS_HAVE_ITEM_PCD_SET:\r
333 S2 = ItemList[2]\r
334 else:\r
335 S2 = ItemList[2].upper()\r
336 else:\r
337 S2 = TAB_COMMON\r
338 if len(ItemList) > 3:\r
339 S3 = ItemList[3]\r
340 else:\r
341 S3 = TAB_COMMON\r
342 self._Scope.append([S1, S2, S3])\r
343\r
344 # 'COMMON' must not be used with specific ARCHs at the same section\r
345 if TAB_ARCH_COMMON in ArchList and len(ArchList) > 1:\r
346 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",\r
347 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
348 # If the section information is needed later, it should be stored in database\r
349 self._ValueList[0] = self._SectionName\r
350\r
351 ## [defines] section parser\r
352 @ParseMacro\r
353 def _DefineParser(self):\r
354 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
355 self._ValueList[1:len(TokenList)] = TokenList\r
356 if not self._ValueList[1]:\r
357 EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",\r
358 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
359 if not self._ValueList[2]:\r
360 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",\r
361 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
362\r
363 self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]\r
364 Name, Value = self._ValueList[1], self._ValueList[2]\r
365 MacroUsed = GlobalData.gMacroRefPattern.findall(Value)\r
366 if len(MacroUsed) != 0:\r
367 for Macro in MacroUsed:\r
368 if Macro in GlobalData.gGlobalDefines:\r
369 EdkLogger.error("Parser", FORMAT_INVALID, "Global macro %s is not permitted." % (Macro), ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
370 else:\r
371 EdkLogger.error("Parser", FORMAT_INVALID, "%s not defined" % (Macro), ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
372 # Sometimes, we need to make differences between EDK and EDK2 modules \r
373 if Name == 'INF_VERSION':\r
374 if hexVersionPattern.match(Value):\r
375 self._Version = int(Value, 0) \r
376 elif decVersionPattern.match(Value):\r
377 ValueList = Value.split('.')\r
378 Major = '%04o' % int(ValueList[0], 0)\r
379 Minor = '%04o' % int(ValueList[1], 0)\r
380 self._Version = int('0x' + Major + Minor, 0)\r
381 else:\r
382 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",\r
383 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
384\r
385 if type(self) == InfParser and self._Version < 0x00010005:\r
386 # EDK module allows using defines as macros\r
387 self._FileLocalMacros[Name] = Value\r
388 self._Defines[Name] = Value\r
389\r
390 ## [BuildOptions] section parser\r
391 @ParseMacro\r
392 def _BuildOptionParser(self):\r
393 self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)\r
394 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
395 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)\r
396 if len(TokenList2) == 2:\r
397 self._ValueList[0] = TokenList2[0] # toolchain family\r
398 self._ValueList[1] = TokenList2[1] # keys\r
399 else:\r
400 self._ValueList[1] = TokenList[0]\r
401 if len(TokenList) == 2 and type(self) != DscParser: # value\r
402 self._ValueList[2] = ReplaceMacro(TokenList[1], self._Macros)\r
403\r
404 if self._ValueList[1].count('_') != 4:\r
405 EdkLogger.error(\r
406 'Parser',\r
407 FORMAT_INVALID,\r
408 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],\r
409 ExtraData=self._CurrentLine,\r
410 File=self.MetaFile,\r
411 Line=self._LineIndex + 1\r
412 )\r
413 def GetValidExpression(self, TokenSpaceGuid, PcdCName):\r
414 return self._Table.GetValidExpression(TokenSpaceGuid, PcdCName)\r
415 def _GetMacros(self):\r
416 Macros = {}\r
417 Macros.update(self._FileLocalMacros)\r
418 Macros.update(self._GetApplicableSectionMacro())\r
419 return Macros\r
420\r
421 ## Construct section Macro dict \r
422 def _ConstructSectionMacroDict(self, Name, Value):\r
423 ScopeKey = [(Scope[0], Scope[1],Scope[2]) for Scope in self._Scope]\r
424 ScopeKey = tuple(ScopeKey)\r
425 #\r
426 # DecParser SectionType is a list, will contain more than one item only in Pcd Section\r
427 # As Pcd section macro usage is not alllowed, so here it is safe\r
428 #\r
429 if type(self) == DecParser:\r
430 SectionDictKey = self._SectionType[0], ScopeKey\r
431 else:\r
432 SectionDictKey = self._SectionType, ScopeKey\r
433\r
434 self._SectionsMacroDict[SectionDictKey][Name] = Value\r
435\r
436 ## Get section Macros that are applicable to current line, which may come from other sections \r
437 ## that share the same name while scope is wider\r
438 def _GetApplicableSectionMacro(self):\r
439 Macros = {}\r
440\r
441 ComComMacroDict = {}\r
442 ComSpeMacroDict = {}\r
443 SpeSpeMacroDict = {}\r
444\r
445 ActiveSectionType = self._SectionType\r
446 if type(self) == DecParser:\r
447 ActiveSectionType = self._SectionType[0]\r
448\r
449 for (SectionType, Scope) in self._SectionsMacroDict:\r
450 if SectionType != ActiveSectionType:\r
451 continue\r
452\r
453 for ActiveScope in self._Scope:\r
454 Scope0, Scope1 ,Scope2= ActiveScope[0], ActiveScope[1],ActiveScope[2]\r
455 if(Scope0, Scope1,Scope2) not in Scope:\r
456 break\r
457 else:\r
458 SpeSpeMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])\r
459\r
460 for ActiveScope in self._Scope:\r
461 Scope0, Scope1,Scope2 = ActiveScope[0], ActiveScope[1],ActiveScope[2]\r
462 if(Scope0, Scope1,Scope2) not in Scope and (Scope0, TAB_COMMON, TAB_COMMON) not in Scope and (TAB_COMMON, Scope1, TAB_COMMON) not in Scope:\r
463 break\r
464 else:\r
465 ComSpeMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])\r
466\r
467 if (TAB_COMMON, TAB_COMMON, TAB_COMMON) in Scope:\r
468 ComComMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])\r
469\r
470 Macros.update(ComComMacroDict)\r
471 Macros.update(ComSpeMacroDict)\r
472 Macros.update(SpeSpeMacroDict)\r
473\r
474 return Macros\r
475\r
476 _SectionParser = {}\r
477 Finished = property(_GetFinished, _SetFinished)\r
478 _Macros = property(_GetMacros)\r
479\r
480\r
481## INF file parser class\r
482#\r
483# @param FilePath The path of platform description file\r
484# @param FileType The raw data of DSC file\r
485# @param Table Database used to retrieve module/package information\r
486# @param Macros Macros used for replacement in file\r
487#\r
488class InfParser(MetaFileParser):\r
489 # INF file supported data types (one type per section)\r
490 DataType = {\r
491 TAB_UNKNOWN.upper() : MODEL_UNKNOWN,\r
492 TAB_INF_DEFINES.upper() : MODEL_META_DATA_HEADER,\r
493 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,\r
494 TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,\r
495 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,\r
496 TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,\r
497 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,\r
498 TAB_PACKAGES.upper() : MODEL_META_DATA_PACKAGE,\r
499 TAB_NMAKE.upper() : MODEL_META_DATA_NMAKE,\r
500 TAB_INF_FIXED_PCD.upper() : MODEL_PCD_FIXED_AT_BUILD,\r
501 TAB_INF_PATCH_PCD.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,\r
502 TAB_INF_FEATURE_PCD.upper() : MODEL_PCD_FEATURE_FLAG,\r
503 TAB_INF_PCD_EX.upper() : MODEL_PCD_DYNAMIC_EX,\r
504 TAB_INF_PCD.upper() : MODEL_PCD_DYNAMIC,\r
505 TAB_SOURCES.upper() : MODEL_EFI_SOURCE_FILE,\r
506 TAB_GUIDS.upper() : MODEL_EFI_GUID,\r
507 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,\r
508 TAB_PPIS.upper() : MODEL_EFI_PPI,\r
509 TAB_DEPEX.upper() : MODEL_EFI_DEPEX,\r
510 TAB_BINARIES.upper() : MODEL_EFI_BINARY_FILE,\r
511 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION\r
512 }\r
513\r
514 ## Constructor of InfParser\r
515 #\r
516 # Initialize object of InfParser\r
517 #\r
518 # @param FilePath The path of module description file\r
519 # @param FileType The raw data of DSC file\r
520 # @param Arch Default Arch value for filtering sections\r
521 # @param Table Database used to retrieve module/package information\r
522 #\r
523 def __init__(self, FilePath, FileType, Arch, Table):\r
524 # prevent re-initialization\r
525 if hasattr(self, "_Table"):\r
526 return\r
527 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table)\r
528 self.PcdsDict = {}\r
529\r
530 ## Parser starter\r
531 def Start(self):\r
532 NmakeLine = ''\r
533 Content = ''\r
534 try:\r
535 Content = open(str(self.MetaFile), 'r').readlines()\r
536 except:\r
537 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)\r
538\r
539 # parse the file line by line\r
540 IsFindBlockComment = False\r
541 GetHeaderComment = False\r
542 TailComments = []\r
543 SectionComments = []\r
544 Comments = []\r
545\r
546 for Index in range(0, len(Content)):\r
547 # skip empty, commented, block commented lines\r
548 Line, Comment = CleanString2(Content[Index], AllowCppStyleComment=True)\r
549 NextLine = ''\r
550 if Index + 1 < len(Content):\r
551 NextLine, NextComment = CleanString2(Content[Index + 1])\r
552 if Line == '':\r
553 if Comment:\r
554 Comments.append((Comment, Index + 1))\r
555 elif GetHeaderComment:\r
556 SectionComments.extend(Comments)\r
557 Comments = []\r
558 continue\r
559 if Line.find(DataType.TAB_COMMENT_EDK_START) > -1:\r
560 IsFindBlockComment = True\r
561 continue\r
562 if Line.find(DataType.TAB_COMMENT_EDK_END) > -1:\r
563 IsFindBlockComment = False\r
564 continue\r
565 if IsFindBlockComment:\r
566 continue\r
567\r
568 self._LineIndex = Index\r
569 self._CurrentLine = Line\r
570\r
571 # section header\r
572 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:\r
573 if not GetHeaderComment:\r
574 for Cmt, LNo in Comments:\r
575 self._Store(MODEL_META_DATA_HEADER_COMMENT, Cmt, '', '', TAB_COMMON,\r
576 TAB_COMMON, self._Owner[-1], LNo, -1, LNo, -1, 0)\r
577 GetHeaderComment = True\r
578 else:\r
579 TailComments.extend(SectionComments + Comments)\r
580 Comments = []\r
581 self._SectionHeaderParser()\r
582 # Check invalid sections\r
583 if self._Version < 0x00010005:\r
584 if self._SectionType in [MODEL_META_DATA_BUILD_OPTION,\r
585 MODEL_EFI_LIBRARY_CLASS,\r
586 MODEL_META_DATA_PACKAGE,\r
587 MODEL_PCD_FIXED_AT_BUILD,\r
588 MODEL_PCD_PATCHABLE_IN_MODULE,\r
589 MODEL_PCD_FEATURE_FLAG,\r
590 MODEL_PCD_DYNAMIC_EX,\r
591 MODEL_PCD_DYNAMIC,\r
592 MODEL_EFI_GUID,\r
593 MODEL_EFI_PROTOCOL,\r
594 MODEL_EFI_PPI,\r
595 MODEL_META_DATA_USER_EXTENSION]:\r
596 EdkLogger.error('Parser', FORMAT_INVALID,\r
597 "Section [%s] is not allowed in inf file without version" % (self._SectionName),\r
598 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
599 elif self._SectionType in [MODEL_EFI_INCLUDE,\r
600 MODEL_EFI_LIBRARY_INSTANCE,\r
601 MODEL_META_DATA_NMAKE]:\r
602 EdkLogger.error('Parser', FORMAT_INVALID,\r
603 "Section [%s] is not allowed in inf file with version 0x%08x" % (self._SectionName, self._Version),\r
604 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
605 continue\r
606 # merge two lines specified by '\' in section NMAKE\r
607 elif self._SectionType == MODEL_META_DATA_NMAKE:\r
608 if Line[-1] == '\\':\r
609 if NextLine == '':\r
610 self._CurrentLine = NmakeLine + Line[0:-1]\r
611 NmakeLine = ''\r
612 else:\r
613 if NextLine[0] == TAB_SECTION_START and NextLine[-1] == TAB_SECTION_END:\r
614 self._CurrentLine = NmakeLine + Line[0:-1]\r
615 NmakeLine = ''\r
616 else:\r
617 NmakeLine = NmakeLine + ' ' + Line[0:-1]\r
618 continue\r
619 else:\r
620 self._CurrentLine = NmakeLine + Line\r
621 NmakeLine = ''\r
622\r
623 # section content\r
624 self._ValueList = ['', '', '']\r
625 # parse current line, result will be put in self._ValueList\r
626 self._SectionParser[self._SectionType](self)\r
627 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:\r
628 self._ItemType = -1\r
629 Comments = []\r
630 continue\r
631 if Comment:\r
632 Comments.append((Comment, Index + 1))\r
633 if GlobalData.gOptions and GlobalData.gOptions.CheckUsage:\r
634 CheckInfComment(self._SectionType, Comments, str(self.MetaFile), Index + 1, self._ValueList)\r
635 #\r
636 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,\r
637 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1\r
638 #\r
639 for Arch, Platform,_ in self._Scope:\r
640 LastItem = self._Store(self._SectionType,\r
641 self._ValueList[0],\r
642 self._ValueList[1],\r
643 self._ValueList[2],\r
644 Arch,\r
645 Platform,\r
646 self._Owner[-1],\r
647 self._LineIndex + 1,\r
648 - 1,\r
649 self._LineIndex + 1,\r
650 - 1,\r
651 0\r
652 )\r
653 for Comment, LineNo in Comments:\r
654 self._Store(MODEL_META_DATA_COMMENT, Comment, '', '', Arch, Platform,\r
655 LastItem, LineNo, -1, LineNo, -1, 0)\r
656 Comments = []\r
657 SectionComments = []\r
658 TailComments.extend(SectionComments + Comments)\r
659 if IsFindBlockComment:\r
660 EdkLogger.error("Parser", FORMAT_INVALID, "Open block comments (starting with /*) are expected to end with */",\r
661 File=self.MetaFile)\r
662\r
663 # If there are tail comments in INF file, save to database whatever the comments are\r
664 for Comment in TailComments:\r
665 self._Store(MODEL_META_DATA_TAIL_COMMENT, Comment[0], '', '', TAB_COMMON,\r
666 TAB_COMMON, self._Owner[-1], -1, -1, -1, -1, 0)\r
667 self._Done()\r
668\r
669 ## Data parser for the format in which there's path\r
670 #\r
671 # Only path can have macro used. So we need to replace them before use.\r
672 #\r
673 def _IncludeParser(self):\r
674 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
675 self._ValueList[0:len(TokenList)] = TokenList\r
676 Macros = self._Macros\r
677 if Macros:\r
678 for Index in range(0, len(self._ValueList)):\r
679 Value = self._ValueList[Index]\r
680 if not Value:\r
681 continue\r
682\r
683 if Value.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:\r
684 Value = '$(EDK_SOURCE)' + Value[17:]\r
685 if Value.find('$(EFI_SOURCE)') > -1 or Value.find('$(EDK_SOURCE)') > -1:\r
686 pass\r
687 elif Value.startswith('.'):\r
688 pass\r
689 elif Value.startswith('$('):\r
690 pass\r
691 else:\r
692 Value = '$(EFI_SOURCE)/' + Value\r
693\r
694 self._ValueList[Index] = ReplaceMacro(Value, Macros)\r
695\r
696 ## Parse [Sources] section\r
697 #\r
698 # Only path can have macro used. So we need to replace them before use.\r
699 #\r
700 @ParseMacro\r
701 def _SourceFileParser(self):\r
702 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
703 self._ValueList[0:len(TokenList)] = TokenList\r
704 Macros = self._Macros\r
705 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'\r
706 if 'COMPONENT_TYPE' in Macros:\r
707 if self._Defines['COMPONENT_TYPE'].upper() == 'ACPITABLE':\r
708 self._ValueList[0] = GetSplitValueList(self._ValueList[0], ' ', 1)[0]\r
709 if self._Defines['BASE_NAME'] == 'Microcode':\r
710 pass\r
711 self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]\r
712\r
713 ## Parse [Binaries] section\r
714 #\r
715 # Only path can have macro used. So we need to replace them before use.\r
716 #\r
717 @ParseMacro\r
718 def _BinaryFileParser(self):\r
719 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 2)\r
720 if len(TokenList) < 2:\r
721 EdkLogger.error('Parser', FORMAT_INVALID, "No file type or path specified",\r
722 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",\r
723 File=self.MetaFile, Line=self._LineIndex + 1)\r
724 if not TokenList[0]:\r
725 EdkLogger.error('Parser', FORMAT_INVALID, "No file type specified",\r
726 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",\r
727 File=self.MetaFile, Line=self._LineIndex + 1)\r
728 if not TokenList[1]:\r
729 EdkLogger.error('Parser', FORMAT_INVALID, "No file path specified",\r
730 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",\r
731 File=self.MetaFile, Line=self._LineIndex + 1)\r
732 self._ValueList[0:len(TokenList)] = TokenList\r
733 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)\r
734\r
735 ## [nmake] section parser (Edk.x style only)\r
736 def _NmakeParser(self):\r
737 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
738 self._ValueList[0:len(TokenList)] = TokenList\r
739 # remove macros\r
740 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)\r
741 # remove self-reference in macro setting\r
742 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})\r
743\r
744 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser\r
745 @ParseMacro\r
746 def _PcdParser(self):\r
747 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
748 ValueList = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
749 if len(ValueList) != 2:\r
750 EdkLogger.error('Parser', FORMAT_INVALID, "Illegal token space GUID and PCD name format",\r
751 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",\r
752 File=self.MetaFile, Line=self._LineIndex + 1)\r
753 self._ValueList[0:1] = ValueList\r
754 if len(TokenList) > 1:\r
755 self._ValueList[2] = TokenList[1]\r
756 if self._ValueList[0] == '' or self._ValueList[1] == '':\r
757 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
758 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",\r
759 File=self.MetaFile, Line=self._LineIndex + 1)\r
760\r
761 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.\r
762 if self._ValueList[2] != '':\r
763 InfPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)\r
764 if InfPcdValueList[0] in ['True', 'true', 'TRUE']:\r
765 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '1', 1);\r
766 elif InfPcdValueList[0] in ['False', 'false', 'FALSE']:\r
767 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '0', 1);\r
768 if (self._ValueList[0], self._ValueList[1]) not in self.PcdsDict:\r
769 self.PcdsDict[self._ValueList[0], self._ValueList[1]] = self._SectionType\r
770 elif self.PcdsDict[self._ValueList[0], self._ValueList[1]] != self._SectionType:\r
771 EdkLogger.error('Parser', FORMAT_INVALID, "It is not permissible to list a specified PCD in different PCD type sections.",\r
772 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",\r
773 File=self.MetaFile, Line=self._LineIndex + 1)\r
774\r
775 ## [depex] section parser\r
776 @ParseMacro\r
777 def _DepexParser(self):\r
778 self._ValueList[0:1] = [self._CurrentLine]\r
779\r
780 _SectionParser = {\r
781 MODEL_UNKNOWN : MetaFileParser._Skip,\r
782 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,\r
783 MODEL_META_DATA_BUILD_OPTION : MetaFileParser._BuildOptionParser,\r
784 MODEL_EFI_INCLUDE : _IncludeParser, # for Edk.x modules\r
785 MODEL_EFI_LIBRARY_INSTANCE : MetaFileParser._CommonParser, # for Edk.x modules\r
786 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,\r
787 MODEL_META_DATA_PACKAGE : MetaFileParser._PathParser,\r
788 MODEL_META_DATA_NMAKE : _NmakeParser, # for Edk.x modules\r
789 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,\r
790 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,\r
791 MODEL_PCD_FEATURE_FLAG : _PcdParser,\r
792 MODEL_PCD_DYNAMIC_EX : _PcdParser,\r
793 MODEL_PCD_DYNAMIC : _PcdParser,\r
794 MODEL_EFI_SOURCE_FILE : _SourceFileParser,\r
795 MODEL_EFI_GUID : MetaFileParser._CommonParser,\r
796 MODEL_EFI_PROTOCOL : MetaFileParser._CommonParser,\r
797 MODEL_EFI_PPI : MetaFileParser._CommonParser,\r
798 MODEL_EFI_DEPEX : _DepexParser,\r
799 MODEL_EFI_BINARY_FILE : _BinaryFileParser,\r
800 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,\r
801 }\r
802\r
803## DSC file parser class\r
804#\r
805# @param FilePath The path of platform description file\r
806# @param FileType The raw data of DSC file\r
807# @param Table Database used to retrieve module/package information\r
808# @param Macros Macros used for replacement in file\r
809# @param Owner Owner ID (for sub-section parsing)\r
810# @param From ID from which the data comes (for !INCLUDE directive)\r
811#\r
812class DscParser(MetaFileParser):\r
813 # DSC file supported data types (one type per section)\r
814 DataType = {\r
815 TAB_SKUIDS.upper() : MODEL_EFI_SKU_ID,\r
816 TAB_DEFAULT_STORES.upper() : MODEL_EFI_DEFAULT_STORES,\r
817 TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,\r
818 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,\r
819 TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,\r
820 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,\r
821 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,\r
822 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,\r
823 TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_DEFAULT,\r
824 TAB_PCDS_DYNAMIC_HII_NULL.upper() : MODEL_PCD_DYNAMIC_HII,\r
825 TAB_PCDS_DYNAMIC_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_VPD,\r
826 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT,\r
827 TAB_PCDS_DYNAMIC_EX_HII_NULL.upper() : MODEL_PCD_DYNAMIC_EX_HII,\r
828 TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_EX_VPD,\r
829 TAB_COMPONENTS.upper() : MODEL_META_DATA_COMPONENT,\r
830 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH,\r
831 TAB_DSC_DEFINES.upper() : MODEL_META_DATA_HEADER,\r
832 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,\r
833 TAB_DSC_DEFINES_EDKGLOBAL : MODEL_META_DATA_GLOBAL_DEFINE,\r
834 TAB_INCLUDE.upper() : MODEL_META_DATA_INCLUDE,\r
835 TAB_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
836 TAB_IF_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
837 TAB_IF_N_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF,\r
838 TAB_ELSE_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF,\r
839 TAB_ELSE.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,\r
840 TAB_END_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF,\r
841 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION,\r
842 TAB_ERROR.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR,\r
843 }\r
844\r
845 # Valid names in define section\r
846 DefineKeywords = [\r
847 "DSC_SPECIFICATION",\r
848 "PLATFORM_NAME",\r
849 "PLATFORM_GUID",\r
850 "PLATFORM_VERSION",\r
851 "SKUID_IDENTIFIER",\r
852 "PCD_INFO_GENERATION",\r
853 "PCD_VAR_CHECK_GENERATION",\r
854 "SUPPORTED_ARCHITECTURES",\r
855 "BUILD_TARGETS",\r
856 "OUTPUT_DIRECTORY",\r
857 "FLASH_DEFINITION",\r
858 "BUILD_NUMBER",\r
859 "RFC_LANGUAGES",\r
860 "ISO_LANGUAGES",\r
861 "TIME_STAMP_FILE",\r
862 "VPD_TOOL_GUID",\r
863 "FIX_LOAD_TOP_MEMORY_ADDRESS",\r
864 "PREBUILD",\r
865 "POSTBUILD"\r
866 ]\r
867\r
868 SubSectionDefineKeywords = [\r
869 "FILE_GUID"\r
870 ]\r
871\r
872 SymbolPattern = ValueExpression.SymbolPattern\r
873\r
874 IncludedFiles = set()\r
875\r
876 ## Constructor of DscParser\r
877 #\r
878 # Initialize object of DscParser\r
879 #\r
880 # @param FilePath The path of platform description file\r
881 # @param FileType The raw data of DSC file\r
882 # @param Arch Default Arch value for filtering sections\r
883 # @param Table Database used to retrieve module/package information\r
884 # @param Owner Owner ID (for sub-section parsing)\r
885 # @param From ID from which the data comes (for !INCLUDE directive)\r
886 #\r
887 def __init__(self, FilePath, FileType, Arch, Table, Owner= -1, From= -1):\r
888 # prevent re-initialization\r
889 if hasattr(self, "_Table"):\r
890 return\r
891 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, Owner, From)\r
892 self._Version = 0x00010005 # Only EDK2 dsc file is supported\r
893 # to store conditional directive evaluation result\r
894 self._DirectiveStack = []\r
895 self._DirectiveEvalStack = []\r
896 self._Enabled = 1\r
897\r
898 #\r
899 # Specify whether current line is in uncertain condition\r
900 #\r
901 self._InDirective = -1\r
902\r
903 # Final valid replacable symbols\r
904 self._Symbols = {}\r
905 #\r
906 # Map the ID between the original table and new table to track\r
907 # the owner item\r
908 #\r
909 self._IdMapping = {-1:-1}\r
910\r
911 ## Parser starter\r
912 def Start(self):\r
913 Content = ''\r
914 try:\r
915 Content = open(str(self.MetaFile), 'r').readlines()\r
916 except:\r
917 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)\r
918\r
919 OwnerId = {}\r
920 for Index in range(0, len(Content)):\r
921 Line = CleanString(Content[Index])\r
922 # skip empty line\r
923 if Line == '':\r
924 continue\r
925\r
926 self._CurrentLine = Line\r
927 self._LineIndex = Index\r
928 if self._InSubsection and self._Owner[-1] == -1:\r
929 self._Owner.append(self._LastItem)\r
930\r
931 # section header\r
932 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:\r
933 self._SectionType = MODEL_META_DATA_SECTION_HEADER\r
934 # subsection ending\r
935 elif Line[0] == '}' and self._InSubsection:\r
936 self._InSubsection = False\r
937 self._SubsectionType = MODEL_UNKNOWN\r
938 self._SubsectionName = ''\r
939 self._Owner[-1] = -1\r
940 OwnerId.clear()\r
941 continue\r
942 # subsection header\r
943 elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:\r
944 self._SubsectionType = MODEL_META_DATA_SUBSECTION_HEADER\r
945 # directive line\r
946 elif Line[0] == '!':\r
947 self._DirectiveParser()\r
948 continue\r
949 if Line[0] == TAB_OPTION_START and not self._InSubsection:\r
950 EdkLogger.error("Parser", FILE_READ_FAILURE, "Missing the '{' before %s in Line %s" % (Line, Index+1),ExtraData=self.MetaFile)\r
951\r
952 if self._InSubsection:\r
953 SectionType = self._SubsectionType\r
954 else:\r
955 SectionType = self._SectionType\r
956 self._ItemType = SectionType\r
957\r
958 self._ValueList = ['', '', '']\r
959 self._SectionParser[SectionType](self)\r
960 if self._ValueList is None:\r
961 continue\r
962 #\r
963 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,\r
964 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1\r
965 #\r
966 for Arch, ModuleType, DefaultStore in self._Scope:\r
967 Owner = self._Owner[-1]\r
968 if self._SubsectionType != MODEL_UNKNOWN:\r
969 Owner = OwnerId[Arch]\r
970 self._LastItem = self._Store(\r
971 self._ItemType,\r
972 self._ValueList[0],\r
973 self._ValueList[1],\r
974 self._ValueList[2],\r
975 Arch,\r
976 ModuleType,\r
977 DefaultStore,\r
978 Owner,\r
979 self._From,\r
980 self._LineIndex + 1,\r
981 - 1,\r
982 self._LineIndex + 1,\r
983 - 1,\r
984 self._Enabled\r
985 )\r
986 if self._SubsectionType == MODEL_UNKNOWN and self._InSubsection:\r
987 OwnerId[Arch] = self._LastItem\r
988\r
989 if self._DirectiveStack:\r
990 Type, Line, Text = self._DirectiveStack[-1]\r
991 EdkLogger.error('Parser', FORMAT_INVALID, "No matching '!endif' found",\r
992 ExtraData=Text, File=self.MetaFile, Line=Line)\r
993 self._Done()\r
994\r
995 ## <subsection_header> parser\r
996 def _SubsectionHeaderParser(self):\r
997 self._SubsectionName = self._CurrentLine[1:-1].upper()\r
998 if self._SubsectionName in self.DataType:\r
999 self._SubsectionType = self.DataType[self._SubsectionName]\r
1000 else:\r
1001 self._SubsectionType = MODEL_UNKNOWN\r
1002 EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile,\r
1003 Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
1004 self._ValueList[0] = self._SubsectionName\r
1005\r
1006 ## Directive statement parser\r
1007 def _DirectiveParser(self):\r
1008 self._ValueList = ['', '', '']\r
1009 TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)\r
1010 self._ValueList[0:len(TokenList)] = TokenList\r
1011\r
1012 # Syntax check\r
1013 DirectiveName = self._ValueList[0].upper()\r
1014 if DirectiveName not in self.DataType:\r
1015 EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName,\r
1016 File=self.MetaFile, Line=self._LineIndex + 1)\r
1017\r
1018 if DirectiveName in ['!IF', '!IFDEF', '!IFNDEF']:\r
1019 self._InDirective += 1\r
1020\r
1021 if DirectiveName in ['!ENDIF']:\r
1022 self._InDirective -= 1\r
1023\r
1024 if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '':\r
1025 EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression",\r
1026 File=self.MetaFile, Line=self._LineIndex + 1,\r
1027 ExtraData=self._CurrentLine)\r
1028\r
1029 ItemType = self.DataType[DirectiveName]\r
1030 Scope = [[TAB_COMMON, TAB_COMMON, TAB_COMMON]]\r
1031 if ItemType == MODEL_META_DATA_INCLUDE:\r
1032 Scope = self._Scope\r
1033 elif ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR:\r
1034 Scope = self._Scope\r
1035 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:\r
1036 # Remove all directives between !if and !endif, including themselves\r
1037 while self._DirectiveStack:\r
1038 # Remove any !else or !elseif\r
1039 DirectiveInfo = self._DirectiveStack.pop()\r
1040 if DirectiveInfo[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1041 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
1042 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:\r
1043 break\r
1044 else:\r
1045 EdkLogger.error("Parser", FORMAT_INVALID, "Redundant '!endif'",\r
1046 File=self.MetaFile, Line=self._LineIndex + 1,\r
1047 ExtraData=self._CurrentLine)\r
1048 elif ItemType not in {MODEL_META_DATA_INCLUDE, MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR}:\r
1049 # Break if there's a !else is followed by a !elseif\r
1050 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF and \\r
1051 self._DirectiveStack and \\r
1052 self._DirectiveStack[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:\r
1053 EdkLogger.error("Parser", FORMAT_INVALID, "'!elseif' after '!else'",\r
1054 File=self.MetaFile, Line=self._LineIndex + 1,\r
1055 ExtraData=self._CurrentLine)\r
1056 self._DirectiveStack.append((ItemType, self._LineIndex + 1, self._CurrentLine))\r
1057\r
1058 #\r
1059 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,\r
1060 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1\r
1061 #\r
1062 for Arch, ModuleType, DefaultStore in Scope:\r
1063 self._LastItem = self._Store(\r
1064 ItemType,\r
1065 self._ValueList[0],\r
1066 self._ValueList[1],\r
1067 self._ValueList[2],\r
1068 Arch,\r
1069 ModuleType,\r
1070 DefaultStore,\r
1071 self._Owner[-1],\r
1072 self._From,\r
1073 self._LineIndex + 1,\r
1074 - 1,\r
1075 self._LineIndex + 1,\r
1076 - 1,\r
1077 0\r
1078 )\r
1079\r
1080 ## [defines] section parser\r
1081 @ParseMacro\r
1082 def _DefineParser(self):\r
1083 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
1084 self._ValueList[1:len(TokenList)] = TokenList\r
1085\r
1086 # Syntax check\r
1087 if not self._ValueList[1]:\r
1088 EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",\r
1089 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1090 if not self._ValueList[2]:\r
1091 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",\r
1092 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1093 if (not self._ValueList[1] in self.DefineKeywords and\r
1094 (self._InSubsection and self._ValueList[1] not in self.SubSectionDefineKeywords)):\r
1095 EdkLogger.error('Parser', FORMAT_INVALID,\r
1096 "Unknown keyword found: %s. "\r
1097 "If this is a macro you must "\r
1098 "add it as a DEFINE in the DSC" % self._ValueList[1],\r
1099 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1100 if not self._InSubsection:\r
1101 self._Defines[self._ValueList[1]] = self._ValueList[2]\r
1102 self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]\r
1103\r
1104 @ParseMacro\r
1105 def _SkuIdParser(self):\r
1106 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
1107 if len(TokenList) not in (2,3):\r
1108 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>[|<UiName>]'",\r
1109 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1110 self._ValueList[0:len(TokenList)] = TokenList\r
1111 @ParseMacro\r
1112 def _DefaultStoresParser(self):\r
1113 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
1114 if len(TokenList) != 2:\r
1115 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>'",\r
1116 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1117 self._ValueList[0:len(TokenList)] = TokenList\r
1118\r
1119 ## Parse Edk style of library modules\r
1120 @ParseMacro\r
1121 def _LibraryInstanceParser(self):\r
1122 self._ValueList[0] = self._CurrentLine\r
1123\r
1124 ## PCD sections parser\r
1125 #\r
1126 # [PcdsFixedAtBuild]\r
1127 # [PcdsPatchableInModule]\r
1128 # [PcdsFeatureFlag]\r
1129 # [PcdsDynamicEx\r
1130 # [PcdsDynamicExDefault]\r
1131 # [PcdsDynamicExVpd]\r
1132 # [PcdsDynamicExHii]\r
1133 # [PcdsDynamic]\r
1134 # [PcdsDynamicDefault]\r
1135 # [PcdsDynamicVpd]\r
1136 # [PcdsDynamicHii]\r
1137 #\r
1138 @ParseMacro\r
1139 def _PcdParser(self):\r
1140 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
1141 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
1142 PcdNameTockens = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
1143 if len(PcdNameTockens) == 2:\r
1144 self._ValueList[0], self._ValueList[1] = PcdNameTockens[0], PcdNameTockens[1]\r
1145 elif len(PcdNameTockens) == 3:\r
1146 self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), PcdNameTockens[2]\r
1147 elif len(PcdNameTockens) > 3:\r
1148 self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), ".".join(PcdNameTockens[2:])\r
1149 if len(TokenList) == 2:\r
1150 self._ValueList[2] = TokenList[1]\r
1151 if self._ValueList[0] == '' or self._ValueList[1] == '':\r
1152 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
1153 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",\r
1154 File=self.MetaFile, Line=self._LineIndex + 1)\r
1155 if self._ValueList[2] == '':\r
1156 #\r
1157 # The PCD values are optional for FIXEDATBUILD, PATCHABLEINMODULE, Dynamic/DynamicEx default\r
1158 #\r
1159 if self._SectionType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):\r
1160 return\r
1161 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",\r
1162 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",\r
1163 File=self.MetaFile, Line=self._LineIndex + 1)\r
1164\r
1165 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD\r
1166 ValueList = GetSplitValueList(self._ValueList[2])\r
1167 if len(ValueList) > 1 and ValueList[1] in [TAB_UINT8 , TAB_UINT16, TAB_UINT32 , TAB_UINT64] \\r
1168 and self._ItemType in [MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT]:\r
1169 EdkLogger.error('Parser', FORMAT_INVALID, "The datum type '%s' of PCD is wrong" % ValueList[1],\r
1170 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1171\r
1172 # Validate the VariableName of DynamicHii and DynamicExHii for PCD Entry must not be an empty string\r
1173 if self._ItemType in [MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII]:\r
1174 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)\r
1175 if len(DscPcdValueList[0].replace('L','').replace('"','').strip()) == 0:\r
1176 EdkLogger.error('Parser', FORMAT_INVALID, "The VariableName field in the HII format PCD entry must not be an empty string",\r
1177 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1178\r
1179 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.\r
1180 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)\r
1181 if DscPcdValueList[0] in ['True', 'true', 'TRUE']:\r
1182 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1);\r
1183 elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:\r
1184 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);\r
1185\r
1186\r
1187 ## [components] section parser\r
1188 @ParseMacro\r
1189 def _ComponentParser(self):\r
1190 if self._CurrentLine[-1] == '{':\r
1191 self._ValueList[0] = self._CurrentLine[0:-1].strip()\r
1192 self._InSubsection = True\r
1193 else:\r
1194 self._ValueList[0] = self._CurrentLine\r
1195\r
1196 ## [LibraryClasses] section\r
1197 @ParseMacro\r
1198 def _LibraryClassParser(self):\r
1199 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
1200 if len(TokenList) < 2:\r
1201 EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",\r
1202 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
1203 File=self.MetaFile, Line=self._LineIndex + 1)\r
1204 if TokenList[0] == '':\r
1205 EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",\r
1206 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
1207 File=self.MetaFile, Line=self._LineIndex + 1)\r
1208 if TokenList[1] == '':\r
1209 EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",\r
1210 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
1211 File=self.MetaFile, Line=self._LineIndex + 1)\r
1212\r
1213 self._ValueList[0:len(TokenList)] = TokenList\r
1214\r
1215 def _CompponentSourceOverridePathParser(self):\r
1216 self._ValueList[0] = self._CurrentLine\r
1217\r
1218 ## [BuildOptions] section parser\r
1219 @ParseMacro\r
1220 def _BuildOptionParser(self):\r
1221 self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)\r
1222 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
1223 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)\r
1224 if len(TokenList2) == 2:\r
1225 self._ValueList[0] = TokenList2[0] # toolchain family\r
1226 self._ValueList[1] = TokenList2[1] # keys\r
1227 else:\r
1228 self._ValueList[1] = TokenList[0]\r
1229 if len(TokenList) == 2: # value\r
1230 self._ValueList[2] = TokenList[1]\r
1231\r
1232 if self._ValueList[1].count('_') != 4:\r
1233 EdkLogger.error(\r
1234 'Parser',\r
1235 FORMAT_INVALID,\r
1236 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],\r
1237 ExtraData=self._CurrentLine,\r
1238 File=self.MetaFile,\r
1239 Line=self._LineIndex + 1\r
1240 )\r
1241\r
1242 ## Override parent's method since we'll do all macro replacements in parser\r
1243 def _GetMacros(self):\r
1244 Macros = {}\r
1245 Macros.update(self._FileLocalMacros)\r
1246 Macros.update(self._GetApplicableSectionMacro())\r
1247 Macros.update(GlobalData.gEdkGlobal)\r
1248 Macros.update(GlobalData.gPlatformDefines)\r
1249 Macros.update(GlobalData.gCommandLineDefines)\r
1250 # PCD cannot be referenced in macro definition\r
1251 if self._ItemType not in [MODEL_META_DATA_DEFINE, MODEL_META_DATA_GLOBAL_DEFINE]:\r
1252 Macros.update(self._Symbols)\r
1253 if GlobalData.BuildOptionPcd:\r
1254 for Item in GlobalData.BuildOptionPcd:\r
1255 if type(Item) is tuple:\r
1256 continue\r
1257 PcdName, TmpValue = Item.split("=")\r
1258 TmpValue = BuildOptionValue(TmpValue, self._GuidDict)\r
1259 Macros[PcdName.strip()] = TmpValue\r
1260 return Macros\r
1261\r
1262 def _PostProcess(self):\r
1263 Processer = {\r
1264 MODEL_META_DATA_SECTION_HEADER : self.__ProcessSectionHeader,\r
1265 MODEL_META_DATA_SUBSECTION_HEADER : self.__ProcessSubsectionHeader,\r
1266 MODEL_META_DATA_HEADER : self.__ProcessDefine,\r
1267 MODEL_META_DATA_DEFINE : self.__ProcessDefine,\r
1268 MODEL_META_DATA_GLOBAL_DEFINE : self.__ProcessDefine,\r
1269 MODEL_META_DATA_INCLUDE : self.__ProcessDirective,\r
1270 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF : self.__ProcessDirective,\r
1271 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE : self.__ProcessDirective,\r
1272 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF : self.__ProcessDirective,\r
1273 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF : self.__ProcessDirective,\r
1274 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF : self.__ProcessDirective,\r
1275 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF : self.__ProcessDirective,\r
1276 MODEL_EFI_SKU_ID : self.__ProcessSkuId,\r
1277 MODEL_EFI_DEFAULT_STORES : self.__ProcessDefaultStores,\r
1278 MODEL_EFI_LIBRARY_INSTANCE : self.__ProcessLibraryInstance,\r
1279 MODEL_EFI_LIBRARY_CLASS : self.__ProcessLibraryClass,\r
1280 MODEL_PCD_FIXED_AT_BUILD : self.__ProcessPcd,\r
1281 MODEL_PCD_PATCHABLE_IN_MODULE : self.__ProcessPcd,\r
1282 MODEL_PCD_FEATURE_FLAG : self.__ProcessPcd,\r
1283 MODEL_PCD_DYNAMIC_DEFAULT : self.__ProcessPcd,\r
1284 MODEL_PCD_DYNAMIC_HII : self.__ProcessPcd,\r
1285 MODEL_PCD_DYNAMIC_VPD : self.__ProcessPcd,\r
1286 MODEL_PCD_DYNAMIC_EX_DEFAULT : self.__ProcessPcd,\r
1287 MODEL_PCD_DYNAMIC_EX_HII : self.__ProcessPcd,\r
1288 MODEL_PCD_DYNAMIC_EX_VPD : self.__ProcessPcd,\r
1289 MODEL_META_DATA_COMPONENT : self.__ProcessComponent,\r
1290 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : self.__ProcessSourceOverridePath,\r
1291 MODEL_META_DATA_BUILD_OPTION : self.__ProcessBuildOption,\r
1292 MODEL_UNKNOWN : self._Skip,\r
1293 MODEL_META_DATA_USER_EXTENSION : self._SkipUserExtension,\r
1294 MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR : self._ProcessError,\r
1295 }\r
1296\r
1297 self._Table = MetaFileStorage(self._RawTable.Cur, self.MetaFile, MODEL_FILE_DSC, True)\r
1298 self._Table.Create()\r
1299 self._DirectiveStack = []\r
1300 self._DirectiveEvalStack = []\r
1301 self._FileWithError = self.MetaFile\r
1302 self._FileLocalMacros = {}\r
1303 self._SectionsMacroDict.clear()\r
1304 GlobalData.gPlatformDefines = {}\r
1305\r
1306 # Get all macro and PCD which has straitforward value\r
1307 self.__RetrievePcdValue()\r
1308 self._Content = self._RawTable.GetAll()\r
1309 self._ContentIndex = 0\r
1310 self._InSubsection = False\r
1311 while self._ContentIndex < len(self._Content) :\r
1312 Id, self._ItemType, V1, V2, V3, S1, S2, S3,Owner, self._From, \\r
1313 LineStart, ColStart, LineEnd, ColEnd, Enabled = self._Content[self._ContentIndex]\r
1314\r
1315 if self._From < 0:\r
1316 self._FileWithError = self.MetaFile\r
1317\r
1318 self._ContentIndex += 1\r
1319\r
1320 self._Scope = [[S1, S2, S3]]\r
1321 #\r
1322 # For !include directive, handle it specially,\r
1323 # merge arch and module type in case of duplicate items\r
1324 #\r
1325 while self._ItemType == MODEL_META_DATA_INCLUDE:\r
1326 if self._ContentIndex >= len(self._Content):\r
1327 break\r
1328 Record = self._Content[self._ContentIndex]\r
1329 if LineStart == Record[10] and LineEnd == Record[12]:\r
1330 if [Record[5], Record[6],Record[7]] not in self._Scope:\r
1331 self._Scope.append([Record[5], Record[6],Record[7]])\r
1332 self._ContentIndex += 1\r
1333 else:\r
1334 break\r
1335\r
1336 self._LineIndex = LineStart - 1\r
1337 self._ValueList = [V1, V2, V3]\r
1338\r
1339 if Owner > 0 and Owner in self._IdMapping:\r
1340 self._InSubsection = True\r
1341 else:\r
1342 self._InSubsection = False\r
1343 try:\r
1344 Processer[self._ItemType]()\r
1345 except EvaluationException as Excpt:\r
1346 # \r
1347 # Only catch expression evaluation error here. We need to report\r
1348 # the precise number of line on which the error occurred\r
1349 #\r
1350 if hasattr(Excpt, 'Pcd'):\r
1351 if Excpt.Pcd in GlobalData.gPlatformOtherPcds:\r
1352 Info = GlobalData.gPlatformOtherPcds[Excpt.Pcd]\r
1353 EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"\r
1354 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"\r
1355 " of the DSC file, and it is currently defined in this section:"\r
1356 " %s, line #: %d." % (Excpt.Pcd, Info[0], Info[1]),\r
1357 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1358 Line=self._LineIndex + 1)\r
1359 else:\r
1360 EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,\r
1361 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1362 Line=self._LineIndex + 1)\r
1363 else:\r
1364 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),\r
1365 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1366 Line=self._LineIndex + 1)\r
1367 except MacroException as Excpt:\r
1368 EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt),\r
1369 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1370 Line=self._LineIndex + 1)\r
1371\r
1372 if self._ValueList is None:\r
1373 continue\r
1374\r
1375 NewOwner = self._IdMapping.get(Owner, -1)\r
1376 self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack))\r
1377 self._LastItem = self._Store(\r
1378 self._ItemType,\r
1379 self._ValueList[0],\r
1380 self._ValueList[1],\r
1381 self._ValueList[2],\r
1382 S1,\r
1383 S2,\r
1384 S3,\r
1385 NewOwner,\r
1386 self._From,\r
1387 self._LineIndex + 1,\r
1388 - 1,\r
1389 self._LineIndex + 1,\r
1390 - 1,\r
1391 self._Enabled\r
1392 )\r
1393 self._IdMapping[Id] = self._LastItem\r
1394\r
1395 GlobalData.gPlatformDefines.update(self._FileLocalMacros)\r
1396 self._PostProcessed = True\r
1397 self._Content = None\r
1398 def _ProcessError(self):\r
1399 if not self._Enabled:\r
1400 return\r
1401 EdkLogger.error('Parser', ERROR_STATEMENT, self._ValueList[1], File=self.MetaFile, Line=self._LineIndex + 1)\r
1402\r
1403 def __ProcessSectionHeader(self):\r
1404 self._SectionName = self._ValueList[0]\r
1405 if self._SectionName in self.DataType:\r
1406 self._SectionType = self.DataType[self._SectionName]\r
1407 else:\r
1408 self._SectionType = MODEL_UNKNOWN\r
1409\r
1410 def __ProcessSubsectionHeader(self):\r
1411 self._SubsectionName = self._ValueList[0]\r
1412 if self._SubsectionName in self.DataType:\r
1413 self._SubsectionType = self.DataType[self._SubsectionName]\r
1414 else:\r
1415 self._SubsectionType = MODEL_UNKNOWN\r
1416\r
1417 def __RetrievePcdValue(self):\r
1418 Content = open(str(self.MetaFile), 'r').readlines()\r
1419 GlobalData.gPlatformOtherPcds['DSCFILE'] = str(self.MetaFile)\r
1420 for PcdType in (MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_HII,\r
1421 MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_DYNAMIC_EX_HII,\r
1422 MODEL_PCD_DYNAMIC_EX_VPD):\r
1423 Records = self._RawTable.Query(PcdType, BelongsToItem= -1.0)\r
1424 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, Dummy4,ID, Line in Records:\r
1425 Name = TokenSpaceGuid + '.' + PcdName\r
1426 if Name not in GlobalData.gPlatformOtherPcds:\r
1427 PcdLine = Line\r
1428 while not Content[Line - 1].lstrip().startswith(TAB_SECTION_START):\r
1429 Line -= 1\r
1430 GlobalData.gPlatformOtherPcds[Name] = (CleanString(Content[Line - 1]), PcdLine, PcdType)\r
1431\r
1432 def __ProcessDefine(self):\r
1433 if not self._Enabled:\r
1434 return\r
1435\r
1436 Type, Name, Value = self._ValueList\r
1437 Value = ReplaceMacro(Value, self._Macros, False)\r
1438 #\r
1439 # If it is <Defines>, return\r
1440 #\r
1441 if self._InSubsection:\r
1442 self._ValueList = [Type, Name, Value]\r
1443 return\r
1444\r
1445 if self._ItemType == MODEL_META_DATA_DEFINE:\r
1446 if self._SectionType == MODEL_META_DATA_HEADER:\r
1447 self._FileLocalMacros[Name] = Value\r
1448 else:\r
1449 self._ConstructSectionMacroDict(Name, Value)\r
1450 elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE:\r
1451 GlobalData.gEdkGlobal[Name] = Value\r
1452\r
1453 #\r
1454 # Keyword in [Defines] section can be used as Macros\r
1455 #\r
1456 if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER):\r
1457 self._FileLocalMacros[Name] = Value\r
1458\r
1459 self._ValueList = [Type, Name, Value]\r
1460\r
1461 def __ProcessDirective(self):\r
1462 Result = None\r
1463 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1464 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF]:\r
1465 Macros = self._Macros\r
1466 Macros.update(GlobalData.gGlobalDefines)\r
1467 try:\r
1468 Result = ValueExpression(self._ValueList[1], Macros)()\r
1469 except SymbolNotFound as Exc:\r
1470 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])\r
1471 Result = False\r
1472 except WrnExpression as Excpt:\r
1473 # \r
1474 # Catch expression evaluation warning here. We need to report\r
1475 # the precise number of line and return the evaluation result\r
1476 #\r
1477 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),\r
1478 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1479 Line=self._LineIndex + 1)\r
1480 Result = Excpt.result\r
1481\r
1482 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1483 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
1484 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:\r
1485 self._DirectiveStack.append(self._ItemType)\r
1486 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF:\r
1487 Result = bool(Result)\r
1488 else:\r
1489 Macro = self._ValueList[1]\r
1490 Macro = Macro[2:-1] if (Macro.startswith("$(") and Macro.endswith(")")) else Macro\r
1491 Result = Macro in self._Macros\r
1492 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF:\r
1493 Result = not Result\r
1494 self._DirectiveEvalStack.append(Result)\r
1495 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF:\r
1496 self._DirectiveStack.append(self._ItemType)\r
1497 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]\r
1498 self._DirectiveEvalStack.append(bool(Result))\r
1499 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:\r
1500 self._DirectiveStack.append(self._ItemType)\r
1501 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]\r
1502 self._DirectiveEvalStack.append(True)\r
1503 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:\r
1504 # Back to the nearest !if/!ifdef/!ifndef\r
1505 while self._DirectiveStack:\r
1506 self._DirectiveEvalStack.pop()\r
1507 Directive = self._DirectiveStack.pop()\r
1508 if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1509 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
1510 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:\r
1511 break\r
1512 elif self._ItemType == MODEL_META_DATA_INCLUDE:\r
1513 # The included file must be relative to workspace or same directory as DSC file\r
1514 __IncludeMacros = {}\r
1515 #\r
1516 # Allow using system environment variables in path after !include\r
1517 #\r
1518 __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE']\r
1519 if "ECP_SOURCE" in GlobalData.gGlobalDefines:\r
1520 __IncludeMacros['ECP_SOURCE'] = GlobalData.gGlobalDefines['ECP_SOURCE']\r
1521 #\r
1522 # During GenFds phase call DSC parser, will go into this branch.\r
1523 #\r
1524 elif "ECP_SOURCE" in GlobalData.gCommandLineDefines:\r
1525 __IncludeMacros['ECP_SOURCE'] = GlobalData.gCommandLineDefines['ECP_SOURCE']\r
1526\r
1527 __IncludeMacros['EFI_SOURCE'] = GlobalData.gGlobalDefines['EFI_SOURCE']\r
1528 __IncludeMacros['EDK_SOURCE'] = GlobalData.gGlobalDefines['EDK_SOURCE']\r
1529 #\r
1530 # Allow using MACROs comes from [Defines] section to keep compatible. \r
1531 #\r
1532 __IncludeMacros.update(self._Macros)\r
1533\r
1534 IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True))\r
1535 #\r
1536 # First search the include file under the same directory as DSC file\r
1537 #\r
1538 IncludedFile1 = PathClass(IncludedFile, self.MetaFile.Dir)\r
1539 ErrorCode, ErrorInfo1 = IncludedFile1.Validate()\r
1540 if ErrorCode != 0:\r
1541 #\r
1542 # Also search file under the WORKSPACE directory\r
1543 #\r
1544 IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)\r
1545 ErrorCode, ErrorInfo2 = IncludedFile1.Validate()\r
1546 if ErrorCode != 0:\r
1547 EdkLogger.error('parser', ErrorCode, File=self._FileWithError,\r
1548 Line=self._LineIndex + 1, ExtraData=ErrorInfo1 + "\n" + ErrorInfo2)\r
1549\r
1550 self._FileWithError = IncludedFile1\r
1551\r
1552 IncludedFileTable = MetaFileStorage(self._Table.Cur, IncludedFile1, MODEL_FILE_DSC, False)\r
1553 FromItem = self._Content[self._ContentIndex - 1][0]\r
1554 if self._InSubsection:\r
1555 Owner = self._Content[self._ContentIndex - 1][8]\r
1556 else:\r
1557 Owner = self._Content[self._ContentIndex - 1][0]\r
1558 Parser = DscParser(IncludedFile1, self._FileType, self._Arch, IncludedFileTable,\r
1559 Owner=Owner, From=FromItem)\r
1560\r
1561 self.IncludedFiles.add (IncludedFile1)\r
1562\r
1563 # set the parser status with current status\r
1564 Parser._SectionName = self._SectionName\r
1565 if self._InSubsection:\r
1566 Parser._SectionType = self._SubsectionType\r
1567 else:\r
1568 Parser._SectionType = self._SectionType\r
1569 Parser._Scope = self._Scope\r
1570 Parser._Enabled = self._Enabled\r
1571 # Parse the included file\r
1572 Parser.Start()\r
1573\r
1574 # update current status with sub-parser's status\r
1575 self._SectionName = Parser._SectionName\r
1576 if not self._InSubsection:\r
1577 self._SectionType = Parser._SectionType\r
1578 self._SubsectionType = Parser._SubsectionType\r
1579 self._InSubsection = Parser._InSubsection\r
1580\r
1581 self._Scope = Parser._Scope\r
1582 self._Enabled = Parser._Enabled\r
1583\r
1584 # Insert all records in the table for the included file into dsc file table\r
1585 Records = IncludedFileTable.GetAll()\r
1586 if Records:\r
1587 self._Content[self._ContentIndex:self._ContentIndex] = Records\r
1588 self._Content.pop(self._ContentIndex - 1)\r
1589 self._ValueList = None\r
1590 self._ContentIndex -= 1\r
1591\r
1592 def __ProcessSkuId(self):\r
1593 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)\r
1594 for Value in self._ValueList]\r
1595 def __ProcessDefaultStores(self):\r
1596 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)\r
1597 for Value in self._ValueList]\r
1598\r
1599 def __ProcessLibraryInstance(self):\r
1600 self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]\r
1601\r
1602 def __ProcessLibraryClass(self):\r
1603 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True)\r
1604\r
1605 def __ProcessPcd(self):\r
1606 if self._ItemType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:\r
1607 self._ValueList[2] = ReplaceMacro(self._ValueList[2], self._Macros, RaiseError=True)\r
1608 return\r
1609\r
1610 ValList, Valid, Index = AnalyzeDscPcd(self._ValueList[2], self._ItemType)\r
1611 if not Valid:\r
1612 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self._FileWithError, Line=self._LineIndex + 1,\r
1613 ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))\r
1614 PcdValue = ValList[Index]\r
1615 if PcdValue and "." not in self._ValueList[0]:\r
1616 try:\r
1617 ValList[Index] = ValueExpression(PcdValue, self._Macros)(True)\r
1618 except WrnExpression as Value:\r
1619 ValList[Index] = Value.result\r
1620 except:\r
1621 pass\r
1622\r
1623 if ValList[Index] == 'True':\r
1624 ValList[Index] = '1'\r
1625 if ValList[Index] == 'False':\r
1626 ValList[Index] = '0'\r
1627\r
1628 if (not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack):\r
1629 GlobalData.gPlatformPcds[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue\r
1630 self._Symbols[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue\r
1631 try:\r
1632 self._ValueList[2] = '|'.join(ValList)\r
1633 except Exception:\r
1634 print(ValList)\r
1635\r
1636 def __ProcessComponent(self):\r
1637 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)\r
1638\r
1639 def __ProcessSourceOverridePath(self):\r
1640 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)\r
1641\r
1642 def __ProcessBuildOption(self):\r
1643 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False)\r
1644 for Value in self._ValueList]\r
1645\r
1646 _SectionParser = {\r
1647 MODEL_META_DATA_HEADER : _DefineParser,\r
1648 MODEL_EFI_SKU_ID : _SkuIdParser,\r
1649 MODEL_EFI_DEFAULT_STORES : _DefaultStoresParser,\r
1650 MODEL_EFI_LIBRARY_INSTANCE : _LibraryInstanceParser,\r
1651 MODEL_EFI_LIBRARY_CLASS : _LibraryClassParser,\r
1652 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,\r
1653 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,\r
1654 MODEL_PCD_FEATURE_FLAG : _PcdParser,\r
1655 MODEL_PCD_DYNAMIC_DEFAULT : _PcdParser,\r
1656 MODEL_PCD_DYNAMIC_HII : _PcdParser,\r
1657 MODEL_PCD_DYNAMIC_VPD : _PcdParser,\r
1658 MODEL_PCD_DYNAMIC_EX_DEFAULT : _PcdParser,\r
1659 MODEL_PCD_DYNAMIC_EX_HII : _PcdParser,\r
1660 MODEL_PCD_DYNAMIC_EX_VPD : _PcdParser,\r
1661 MODEL_META_DATA_COMPONENT : _ComponentParser,\r
1662 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : _CompponentSourceOverridePathParser,\r
1663 MODEL_META_DATA_BUILD_OPTION : _BuildOptionParser,\r
1664 MODEL_UNKNOWN : MetaFileParser._Skip,\r
1665 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,\r
1666 MODEL_META_DATA_SECTION_HEADER : MetaFileParser._SectionHeaderParser,\r
1667 MODEL_META_DATA_SUBSECTION_HEADER : _SubsectionHeaderParser,\r
1668 }\r
1669\r
1670 _Macros = property(_GetMacros)\r
1671\r
1672## DEC file parser class\r
1673#\r
1674# @param FilePath The path of platform description file\r
1675# @param FileType The raw data of DSC file\r
1676# @param Table Database used to retrieve module/package information\r
1677# @param Macros Macros used for replacement in file\r
1678#\r
1679class DecParser(MetaFileParser):\r
1680 # DEC file supported data types (one type per section)\r
1681 DataType = {\r
1682 TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER,\r
1683 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,\r
1684 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,\r
1685 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,\r
1686 TAB_GUIDS.upper() : MODEL_EFI_GUID,\r
1687 TAB_PPIS.upper() : MODEL_EFI_PPI,\r
1688 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,\r
1689 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,\r
1690 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,\r
1691 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,\r
1692 TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC,\r
1693 TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX,\r
1694 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION,\r
1695 }\r
1696\r
1697 ## Constructor of DecParser\r
1698 #\r
1699 # Initialize object of DecParser\r
1700 #\r
1701 # @param FilePath The path of platform description file\r
1702 # @param FileType The raw data of DSC file\r
1703 # @param Arch Default Arch value for filtering sections\r
1704 # @param Table Database used to retrieve module/package information\r
1705 #\r
1706 def __init__(self, FilePath, FileType, Arch, Table):\r
1707 # prevent re-initialization\r
1708 if hasattr(self, "_Table"):\r
1709 return\r
1710 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, -1)\r
1711 self._Comments = []\r
1712 self._Version = 0x00010005 # Only EDK2 dec file is supported\r
1713 self._AllPCDs = [] # Only for check duplicate PCD\r
1714 self._AllPcdDict = {}\r
1715\r
1716 self._CurrentStructurePcdName = ""\r
1717 self._include_flag = False\r
1718 self._package_flag = False\r
1719\r
1720 ## Parser starter\r
1721 def Start(self):\r
1722 Content = ''\r
1723 try:\r
1724 Content = open(str(self.MetaFile), 'r').readlines()\r
1725 except:\r
1726 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)\r
1727\r
1728 self._DefinesCount = 0\r
1729 for Index in range(0, len(Content)):\r
1730 Line, Comment = CleanString2(Content[Index])\r
1731 self._CurrentLine = Line\r
1732 self._LineIndex = Index\r
1733\r
1734 # save comment for later use\r
1735 if Comment:\r
1736 self._Comments.append((Comment, self._LineIndex + 1))\r
1737 # skip empty line\r
1738 if Line == '':\r
1739 continue\r
1740\r
1741 # section header\r
1742 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:\r
1743 self._SectionHeaderParser()\r
1744 if self._SectionName == TAB_DEC_DEFINES.upper():\r
1745 self._DefinesCount += 1\r
1746 self._Comments = []\r
1747 continue\r
1748 if self._SectionType == MODEL_UNKNOWN:\r
1749 EdkLogger.error("Parser", FORMAT_INVALID,\r
1750 ""\r
1751 "Not able to determine \"%s\" in which section."%self._CurrentLine,\r
1752 self.MetaFile, self._LineIndex + 1)\r
1753 elif len(self._SectionType) == 0:\r
1754 self._Comments = []\r
1755 continue\r
1756\r
1757 # section content\r
1758 self._ValueList = ['', '', '']\r
1759 self._SectionParser[self._SectionType[0]](self)\r
1760 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:\r
1761 self._ItemType = -1\r
1762 self._Comments = []\r
1763 continue\r
1764\r
1765 #\r
1766 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,\r
1767 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1\r
1768 #\r
1769 for Arch, ModuleType, Type in self._Scope:\r
1770 self._LastItem = self._Store(\r
1771 Type,\r
1772 self._ValueList[0],\r
1773 self._ValueList[1],\r
1774 self._ValueList[2],\r
1775 Arch,\r
1776 ModuleType,\r
1777 self._Owner[-1],\r
1778 self._LineIndex + 1,\r
1779 - 1,\r
1780 self._LineIndex + 1,\r
1781 - 1,\r
1782 0\r
1783 )\r
1784 for Comment, LineNo in self._Comments:\r
1785 self._Store(\r
1786 MODEL_META_DATA_COMMENT,\r
1787 Comment,\r
1788 self._ValueList[0],\r
1789 self._ValueList[1],\r
1790 Arch,\r
1791 ModuleType,\r
1792 self._LastItem,\r
1793 LineNo,\r
1794 - 1,\r
1795 LineNo,\r
1796 - 1,\r
1797 0\r
1798 )\r
1799 self._Comments = []\r
1800 if self._DefinesCount > 1:\r
1801 EdkLogger.error('Parser', FORMAT_INVALID, 'Multiple [Defines] section is exist.', self.MetaFile )\r
1802 if self._DefinesCount == 0:\r
1803 EdkLogger.error('Parser', FORMAT_INVALID, 'No [Defines] section exist.',self.MetaFile)\r
1804 self._Done()\r
1805\r
1806\r
1807 ## Section header parser\r
1808 #\r
1809 # The section header is always in following format:\r
1810 #\r
1811 # [section_name.arch<.platform|module_type>]\r
1812 #\r
1813 def _SectionHeaderParser(self):\r
1814 self._Scope = []\r
1815 self._SectionName = ''\r
1816 self._SectionType = []\r
1817 ArchList = set()\r
1818 PrivateList = set()\r
1819 Line = re.sub(',[\s]*', TAB_COMMA_SPLIT, self._CurrentLine)\r
1820 for Item in Line[1:-1].split(TAB_COMMA_SPLIT):\r
1821 if Item == '':\r
1822 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR,\r
1823 "section name can NOT be empty or incorrectly use separator comma",\r
1824 self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
1825 ItemList = Item.split(TAB_SPLIT)\r
1826\r
1827 # different types of PCD are permissible in one section\r
1828 self._SectionName = ItemList[0].upper()\r
1829 if self._SectionName == TAB_DEC_DEFINES.upper() and (len(ItemList) > 1 or len(Line.split(TAB_COMMA_SPLIT)) > 1):\r
1830 EdkLogger.error("Parser", FORMAT_INVALID, "Defines section format is invalid",\r
1831 self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
1832 if self._SectionName in self.DataType:\r
1833 if self.DataType[self._SectionName] not in self._SectionType:\r
1834 self._SectionType.append(self.DataType[self._SectionName])\r
1835 else:\r
1836 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,\r
1837 self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
1838\r
1839 if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:\r
1840 EdkLogger.error(\r
1841 'Parser',\r
1842 FORMAT_INVALID,\r
1843 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,\r
1844 File=self.MetaFile,\r
1845 Line=self._LineIndex + 1,\r
1846 ExtraData=self._CurrentLine\r
1847 )\r
1848 # S1 is always Arch\r
1849 if len(ItemList) > 1:\r
1850 S1 = ItemList[1].upper()\r
1851 else:\r
1852 S1 = TAB_ARCH_COMMON\r
1853 ArchList.add(S1)\r
1854 # S2 may be Platform or ModuleType\r
1855 if len(ItemList) > 2:\r
1856 S2 = ItemList[2].upper()\r
1857 # only Includes, GUIDs, PPIs, Protocols section have Private tag\r
1858 if self._SectionName in [TAB_INCLUDES.upper(), TAB_GUIDS.upper(), TAB_PROTOCOLS.upper(), TAB_PPIS.upper()]:\r
1859 if S2 != 'PRIVATE':\r
1860 EdkLogger.error("Parser", FORMAT_INVALID, 'Please use keyword "Private" as section tag modifier.',\r
1861 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
1862 else:\r
1863 S2 = TAB_COMMON\r
1864 PrivateList.add(S2)\r
1865 if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:\r
1866 self._Scope.append([S1, S2, self.DataType[self._SectionName]])\r
1867\r
1868 # 'COMMON' must not be used with specific ARCHs at the same section\r
1869 if TAB_ARCH_COMMON in ArchList and len(ArchList) > 1:\r
1870 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",\r
1871 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
1872\r
1873 # It is not permissible to mix section tags without the Private attribute with section tags with the Private attribute\r
1874 if TAB_COMMON in PrivateList and len(PrivateList) > 1:\r
1875 EdkLogger.error('Parser', FORMAT_INVALID, "Can't mix section tags without the Private attribute with section tags with the Private attribute",\r
1876 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
1877\r
1878 ## [guids], [ppis] and [protocols] section parser\r
1879 @ParseMacro\r
1880 def _GuidParser(self):\r
1881 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
1882 if len(TokenList) < 2:\r
1883 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",\r
1884 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1885 File=self.MetaFile, Line=self._LineIndex + 1)\r
1886 if TokenList[0] == '':\r
1887 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",\r
1888 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1889 File=self.MetaFile, Line=self._LineIndex + 1)\r
1890 if TokenList[1] == '':\r
1891 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",\r
1892 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1893 File=self.MetaFile, Line=self._LineIndex + 1)\r
1894 if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':\r
1895 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",\r
1896 ExtraData=self._CurrentLine + \\r
1897 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",\r
1898 File=self.MetaFile, Line=self._LineIndex + 1)\r
1899 self._ValueList[0] = TokenList[0]\r
1900 self._ValueList[1] = TokenList[1]\r
1901 if self._ValueList[0] not in self._GuidDict:\r
1902 self._GuidDict[self._ValueList[0]] = self._ValueList[1]\r
1903\r
1904 ## PCD sections parser\r
1905 #\r
1906 # [PcdsFixedAtBuild]\r
1907 # [PcdsPatchableInModule]\r
1908 # [PcdsFeatureFlag]\r
1909 # [PcdsDynamicEx\r
1910 # [PcdsDynamic]\r
1911 #\r
1912 @ParseMacro\r
1913 def _PcdParser(self):\r
1914 if self._CurrentStructurePcdName:\r
1915 self._ValueList[0] = self._CurrentStructurePcdName\r
1916\r
1917 if "|" not in self._CurrentLine:\r
1918 if "<HeaderFiles>" == self._CurrentLine:\r
1919 self._include_flag = True\r
1920 self._package_flag = False\r
1921 self._ValueList = None\r
1922 return\r
1923 if "<Packages>" == self._CurrentLine:\r
1924 self._package_flag = True\r
1925 self._ValueList = None\r
1926 self._include_flag = False\r
1927 return\r
1928\r
1929 if self._include_flag:\r
1930 self._ValueList[1] = "<HeaderFiles>_" + md5.new(self._CurrentLine).hexdigest()\r
1931 self._ValueList[2] = self._CurrentLine\r
1932 if self._package_flag and "}" != self._CurrentLine:\r
1933 self._ValueList[1] = "<Packages>_" + md5.new(self._CurrentLine).hexdigest()\r
1934 self._ValueList[2] = self._CurrentLine\r
1935 if self._CurrentLine == "}":\r
1936 self._package_flag = False\r
1937 self._include_flag = False\r
1938 self._ValueList = None\r
1939 return\r
1940 else:\r
1941 PcdTockens = self._CurrentLine.split(TAB_VALUE_SPLIT)\r
1942 PcdNames = PcdTockens[0].split(TAB_SPLIT)\r
1943 if len(PcdNames) == 2:\r
1944 self._CurrentStructurePcdName = ""\r
1945 else:\r
1946 if self._CurrentStructurePcdName != TAB_SPLIT.join(PcdNames[:2]):\r
1947 EdkLogger.error('Parser', FORMAT_INVALID, "Pcd Name does not match: %s and %s " % (self._CurrentStructurePcdName , TAB_SPLIT.join(PcdNames[:2])),\r
1948 File=self.MetaFile, Line=self._LineIndex + 1)\r
1949 self._ValueList[1] = TAB_SPLIT.join(PcdNames[2:])\r
1950 self._ValueList[2] = PcdTockens[1]\r
1951 if not self._CurrentStructurePcdName:\r
1952 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
1953 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
1954 ValueRe = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*')\r
1955 # check PCD information\r
1956 if self._ValueList[0] == '' or self._ValueList[1] == '':\r
1957 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
1958 ExtraData=self._CurrentLine + \\r
1959 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1960 File=self.MetaFile, Line=self._LineIndex + 1)\r
1961 # check format of token space GUID CName\r
1962 if not ValueRe.match(self._ValueList[0]):\r
1963 EdkLogger.error('Parser', FORMAT_INVALID, "The format of the token space GUID CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",\r
1964 ExtraData=self._CurrentLine + \\r
1965 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1966 File=self.MetaFile, Line=self._LineIndex + 1)\r
1967 # check format of PCD CName\r
1968 if not ValueRe.match(self._ValueList[1]):\r
1969 EdkLogger.error('Parser', FORMAT_INVALID, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",\r
1970 ExtraData=self._CurrentLine + \\r
1971 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1972 File=self.MetaFile, Line=self._LineIndex + 1)\r
1973 # check PCD datum information\r
1974 if len(TokenList) < 2 or TokenList[1] == '':\r
1975 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",\r
1976 ExtraData=self._CurrentLine + \\r
1977 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1978 File=self.MetaFile, Line=self._LineIndex + 1)\r
1979\r
1980\r
1981 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')\r
1982 PtrValue = ValueRe.findall(TokenList[1])\r
1983\r
1984 # Has VOID* type string, may contain "|" character in the string.\r
1985 if len(PtrValue) != 0:\r
1986 ptrValueList = re.sub(ValueRe, '', TokenList[1])\r
1987 ValueList = AnalyzePcdExpression(ptrValueList)\r
1988 ValueList[0] = PtrValue[0]\r
1989 else:\r
1990 ValueList = AnalyzePcdExpression(TokenList[1])\r
1991\r
1992\r
1993 # check if there's enough datum information given\r
1994 if len(ValueList) != 3:\r
1995 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",\r
1996 ExtraData=self._CurrentLine + \\r
1997 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1998 File=self.MetaFile, Line=self._LineIndex + 1)\r
1999 # check default value\r
2000 if ValueList[0] == '':\r
2001 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",\r
2002 ExtraData=self._CurrentLine + \\r
2003 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2004 File=self.MetaFile, Line=self._LineIndex + 1)\r
2005 # check datum type\r
2006 if ValueList[1] == '':\r
2007 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",\r
2008 ExtraData=self._CurrentLine + \\r
2009 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2010 File=self.MetaFile, Line=self._LineIndex + 1)\r
2011 # check token of the PCD\r
2012 if ValueList[2] == '':\r
2013 EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",\r
2014 ExtraData=self._CurrentLine + \\r
2015 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2016 File=self.MetaFile, Line=self._LineIndex + 1)\r
2017\r
2018 PcdValue = ValueList[0]\r
2019 if PcdValue:\r
2020 try:\r
2021 self._GuidDict.update(self._AllPcdDict)\r
2022 ValueList[0] = ValueExpressionEx(ValueList[0], ValueList[1], self._GuidDict)(True)\r
2023 except BadExpression as Value:\r
2024 EdkLogger.error('Parser', FORMAT_INVALID, Value, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
2025 # check format of default value against the datum type\r
2026 IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])\r
2027 if not IsValid:\r
2028 EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,\r
2029 File=self.MetaFile, Line=self._LineIndex + 1)\r
2030\r
2031 if Cause == "StructurePcd":\r
2032 self._CurrentStructurePcdName = TAB_SPLIT.join(self._ValueList[0:2])\r
2033 self._ValueList[0] = self._CurrentStructurePcdName\r
2034 self._ValueList[1] = ValueList[1].strip()\r
2035\r
2036 if ValueList[0] in ['True', 'true', 'TRUE']:\r
2037 ValueList[0] = '1'\r
2038 elif ValueList[0] in ['False', 'false', 'FALSE']:\r
2039 ValueList[0] = '0'\r
2040\r
2041 # check for duplicate PCD definition\r
2042 if (self._Scope[0], self._ValueList[0], self._ValueList[1]) in self._AllPCDs:\r
2043 EdkLogger.error('Parser', FORMAT_INVALID,\r
2044 "The same PCD name and GUID have been already defined",\r
2045 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
2046 else:\r
2047 self._AllPCDs.append((self._Scope[0], self._ValueList[0], self._ValueList[1]))\r
2048 self._AllPcdDict[TAB_SPLIT.join(self._ValueList[0:2])] = ValueList[0]\r
2049\r
2050 self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()\r
2051\r
2052 _SectionParser = {\r
2053 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,\r
2054 MODEL_EFI_INCLUDE : MetaFileParser._PathParser,\r
2055 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,\r
2056 MODEL_EFI_GUID : _GuidParser,\r
2057 MODEL_EFI_PPI : _GuidParser,\r
2058 MODEL_EFI_PROTOCOL : _GuidParser,\r
2059 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,\r
2060 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,\r
2061 MODEL_PCD_FEATURE_FLAG : _PcdParser,\r
2062 MODEL_PCD_DYNAMIC : _PcdParser,\r
2063 MODEL_PCD_DYNAMIC_EX : _PcdParser,\r
2064 MODEL_UNKNOWN : MetaFileParser._Skip,\r
2065 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,\r
2066 }\r
2067\r
2068##\r
2069#\r
2070# This acts like the main() function for the script, unless it is 'import'ed into another\r
2071# script.\r
2072#\r
2073if __name__ == '__main__':\r
2074 pass\r
2075\r