]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - BaseTools/Source/Python/Workspace/MetaFileParser.py
MdeModulePkg/PerformanceMeasurement.h: Correct the license
[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 isinstance(self, DscParser) and self._InDirective > -1:\r
82 pass\r
83 else:\r
84 if isinstance(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 not isinstance(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 not isinstance(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 not isinstance(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 isinstance(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 not isinstance(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 isinstance(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 isinstance(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") and self._Table is 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 TokenList = GetSplitValueList(Line, ' ', 1)\r
948 if TokenList[0] == TAB_INCLUDE:\r
949 for Arch, ModuleType, DefaultStore in self._Scope:\r
950 if self._SubsectionType != MODEL_UNKNOWN and Arch in OwnerId:\r
951 self._Owner[-1] = OwnerId[Arch]\r
952 self._DirectiveParser()\r
953 else:\r
954 self._DirectiveParser()\r
955 continue\r
956 if Line[0] == TAB_OPTION_START and not self._InSubsection:\r
957 EdkLogger.error("Parser", FILE_READ_FAILURE, "Missing the '{' before %s in Line %s" % (Line, Index+1), ExtraData=self.MetaFile)\r
958\r
959 if self._InSubsection:\r
960 SectionType = self._SubsectionType\r
961 else:\r
962 SectionType = self._SectionType\r
963 self._ItemType = SectionType\r
964\r
965 self._ValueList = ['', '', '']\r
966 self._SectionParser[SectionType](self)\r
967 if self._ValueList is None:\r
968 continue\r
969 #\r
970 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,\r
971 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1\r
972 #\r
973 for Arch, ModuleType, DefaultStore in self._Scope:\r
974 Owner = self._Owner[-1]\r
975 if self._SubsectionType != MODEL_UNKNOWN and Arch in OwnerId:\r
976 Owner = OwnerId[Arch]\r
977 self._LastItem = self._Store(\r
978 self._ItemType,\r
979 self._ValueList[0],\r
980 self._ValueList[1],\r
981 self._ValueList[2],\r
982 Arch,\r
983 ModuleType,\r
984 DefaultStore,\r
985 Owner,\r
986 self._From,\r
987 self._LineIndex + 1,\r
988 - 1,\r
989 self._LineIndex + 1,\r
990 - 1,\r
991 self._Enabled\r
992 )\r
993 if self._SubsectionType == MODEL_UNKNOWN and self._InSubsection:\r
994 OwnerId[Arch] = self._LastItem\r
995\r
996 if self._DirectiveStack:\r
997 Type, Line, Text = self._DirectiveStack[-1]\r
998 EdkLogger.error('Parser', FORMAT_INVALID, "No matching '!endif' found",\r
999 ExtraData=Text, File=self.MetaFile, Line=Line)\r
1000 self._Done()\r
1001\r
1002 ## <subsection_header> parser\r
1003 def _SubsectionHeaderParser(self):\r
1004 self._SubsectionName = self._CurrentLine[1:-1].upper()\r
1005 if self._SubsectionName in self.DataType:\r
1006 self._SubsectionType = self.DataType[self._SubsectionName]\r
1007 else:\r
1008 self._SubsectionType = MODEL_UNKNOWN\r
1009 EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile,\r
1010 Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
1011 self._ValueList[0] = self._SubsectionName\r
1012\r
1013 ## Directive statement parser\r
1014 def _DirectiveParser(self):\r
1015 self._ValueList = ['', '', '']\r
1016 TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)\r
1017 self._ValueList[0:len(TokenList)] = TokenList\r
1018\r
1019 # Syntax check\r
1020 DirectiveName = self._ValueList[0].upper()\r
1021 if DirectiveName not in self.DataType:\r
1022 EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName,\r
1023 File=self.MetaFile, Line=self._LineIndex + 1)\r
1024\r
1025 if DirectiveName in ['!IF', '!IFDEF', '!IFNDEF']:\r
1026 self._InDirective += 1\r
1027\r
1028 if DirectiveName in ['!ENDIF']:\r
1029 self._InDirective -= 1\r
1030\r
1031 if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '':\r
1032 EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression",\r
1033 File=self.MetaFile, Line=self._LineIndex + 1,\r
1034 ExtraData=self._CurrentLine)\r
1035\r
1036 ItemType = self.DataType[DirectiveName]\r
1037 Scope = [[TAB_COMMON, TAB_COMMON, TAB_COMMON]]\r
1038 if ItemType == MODEL_META_DATA_INCLUDE:\r
1039 Scope = self._Scope\r
1040 elif ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR:\r
1041 Scope = self._Scope\r
1042 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:\r
1043 # Remove all directives between !if and !endif, including themselves\r
1044 while self._DirectiveStack:\r
1045 # Remove any !else or !elseif\r
1046 DirectiveInfo = self._DirectiveStack.pop()\r
1047 if DirectiveInfo[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1048 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
1049 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:\r
1050 break\r
1051 else:\r
1052 EdkLogger.error("Parser", FORMAT_INVALID, "Redundant '!endif'",\r
1053 File=self.MetaFile, Line=self._LineIndex + 1,\r
1054 ExtraData=self._CurrentLine)\r
1055 elif ItemType not in {MODEL_META_DATA_INCLUDE, MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR}:\r
1056 # Break if there's a !else is followed by a !elseif\r
1057 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF and \\r
1058 self._DirectiveStack and \\r
1059 self._DirectiveStack[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:\r
1060 EdkLogger.error("Parser", FORMAT_INVALID, "'!elseif' after '!else'",\r
1061 File=self.MetaFile, Line=self._LineIndex + 1,\r
1062 ExtraData=self._CurrentLine)\r
1063 self._DirectiveStack.append((ItemType, self._LineIndex + 1, self._CurrentLine))\r
1064\r
1065 #\r
1066 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,\r
1067 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1\r
1068 #\r
1069 for Arch, ModuleType, DefaultStore in Scope:\r
1070 self._LastItem = self._Store(\r
1071 ItemType,\r
1072 self._ValueList[0],\r
1073 self._ValueList[1],\r
1074 self._ValueList[2],\r
1075 Arch,\r
1076 ModuleType,\r
1077 DefaultStore,\r
1078 self._Owner[-1],\r
1079 self._From,\r
1080 self._LineIndex + 1,\r
1081 - 1,\r
1082 self._LineIndex + 1,\r
1083 - 1,\r
1084 0\r
1085 )\r
1086\r
1087 ## [defines] section parser\r
1088 @ParseMacro\r
1089 def _DefineParser(self):\r
1090 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
1091 self._ValueList[1:len(TokenList)] = TokenList\r
1092\r
1093 # Syntax check\r
1094 if not self._ValueList[1]:\r
1095 EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",\r
1096 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1097 if not self._ValueList[2]:\r
1098 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",\r
1099 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1100 if (not self._ValueList[1] in self.DefineKeywords and\r
1101 (self._InSubsection and self._ValueList[1] not in self.SubSectionDefineKeywords)):\r
1102 EdkLogger.error('Parser', FORMAT_INVALID,\r
1103 "Unknown keyword found: %s. "\r
1104 "If this is a macro you must "\r
1105 "add it as a DEFINE in the DSC" % self._ValueList[1],\r
1106 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1107 if not self._InSubsection:\r
1108 self._Defines[self._ValueList[1]] = self._ValueList[2]\r
1109 self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]\r
1110\r
1111 @ParseMacro\r
1112 def _SkuIdParser(self):\r
1113 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
1114 if len(TokenList) not in (2, 3):\r
1115 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>[|<UiName>]'",\r
1116 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1117 self._ValueList[0:len(TokenList)] = TokenList\r
1118 @ParseMacro\r
1119 def _DefaultStoresParser(self):\r
1120 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
1121 if len(TokenList) != 2:\r
1122 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>'",\r
1123 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1124 self._ValueList[0:len(TokenList)] = TokenList\r
1125\r
1126 ## Parse Edk style of library modules\r
1127 @ParseMacro\r
1128 def _LibraryInstanceParser(self):\r
1129 self._ValueList[0] = self._CurrentLine\r
1130\r
1131 ## PCD sections parser\r
1132 #\r
1133 # [PcdsFixedAtBuild]\r
1134 # [PcdsPatchableInModule]\r
1135 # [PcdsFeatureFlag]\r
1136 # [PcdsDynamicEx\r
1137 # [PcdsDynamicExDefault]\r
1138 # [PcdsDynamicExVpd]\r
1139 # [PcdsDynamicExHii]\r
1140 # [PcdsDynamic]\r
1141 # [PcdsDynamicDefault]\r
1142 # [PcdsDynamicVpd]\r
1143 # [PcdsDynamicHii]\r
1144 #\r
1145 @ParseMacro\r
1146 def _PcdParser(self):\r
1147 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
1148 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
1149 PcdNameTockens = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
1150 if len(PcdNameTockens) == 2:\r
1151 self._ValueList[0], self._ValueList[1] = PcdNameTockens[0], PcdNameTockens[1]\r
1152 elif len(PcdNameTockens) == 3:\r
1153 self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), PcdNameTockens[2]\r
1154 elif len(PcdNameTockens) > 3:\r
1155 self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), ".".join(PcdNameTockens[2:])\r
1156 if len(TokenList) == 2:\r
1157 self._ValueList[2] = TokenList[1]\r
1158 if self._ValueList[0] == '' or self._ValueList[1] == '':\r
1159 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
1160 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",\r
1161 File=self.MetaFile, Line=self._LineIndex + 1)\r
1162 if self._ValueList[2] == '':\r
1163 #\r
1164 # The PCD values are optional for FIXEDATBUILD, PATCHABLEINMODULE, Dynamic/DynamicEx default\r
1165 #\r
1166 if self._SectionType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):\r
1167 return\r
1168 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",\r
1169 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",\r
1170 File=self.MetaFile, Line=self._LineIndex + 1)\r
1171\r
1172 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD\r
1173 ValueList = GetSplitValueList(self._ValueList[2])\r
1174 if len(ValueList) > 1 and ValueList[1] in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64] \\r
1175 and self._ItemType in [MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT]:\r
1176 EdkLogger.error('Parser', FORMAT_INVALID, "The datum type '%s' of PCD is wrong" % ValueList[1],\r
1177 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1178\r
1179 # Validate the VariableName of DynamicHii and DynamicExHii for PCD Entry must not be an empty string\r
1180 if self._ItemType in [MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII]:\r
1181 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)\r
1182 if len(DscPcdValueList[0].replace('L', '').replace('"', '').strip()) == 0:\r
1183 EdkLogger.error('Parser', FORMAT_INVALID, "The VariableName field in the HII format PCD entry must not be an empty string",\r
1184 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1185\r
1186 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.\r
1187 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)\r
1188 if DscPcdValueList[0] in ['True', 'true', 'TRUE']:\r
1189 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1);\r
1190 elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:\r
1191 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);\r
1192\r
1193\r
1194 ## [components] section parser\r
1195 @ParseMacro\r
1196 def _ComponentParser(self):\r
1197 if self._CurrentLine[-1] == '{':\r
1198 self._ValueList[0] = self._CurrentLine[0:-1].strip()\r
1199 self._InSubsection = True\r
1200 self._SubsectionType = MODEL_UNKNOWN\r
1201 else:\r
1202 self._ValueList[0] = self._CurrentLine\r
1203\r
1204 ## [LibraryClasses] section\r
1205 @ParseMacro\r
1206 def _LibraryClassParser(self):\r
1207 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
1208 if len(TokenList) < 2:\r
1209 EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",\r
1210 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
1211 File=self.MetaFile, Line=self._LineIndex + 1)\r
1212 if TokenList[0] == '':\r
1213 EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",\r
1214 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
1215 File=self.MetaFile, Line=self._LineIndex + 1)\r
1216 if TokenList[1] == '':\r
1217 EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",\r
1218 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
1219 File=self.MetaFile, Line=self._LineIndex + 1)\r
1220\r
1221 self._ValueList[0:len(TokenList)] = TokenList\r
1222\r
1223 def _CompponentSourceOverridePathParser(self):\r
1224 self._ValueList[0] = self._CurrentLine\r
1225\r
1226 ## [BuildOptions] section parser\r
1227 @ParseMacro\r
1228 def _BuildOptionParser(self):\r
1229 self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)\r
1230 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
1231 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)\r
1232 if len(TokenList2) == 2:\r
1233 self._ValueList[0] = TokenList2[0] # toolchain family\r
1234 self._ValueList[1] = TokenList2[1] # keys\r
1235 else:\r
1236 self._ValueList[1] = TokenList[0]\r
1237 if len(TokenList) == 2: # value\r
1238 self._ValueList[2] = TokenList[1]\r
1239\r
1240 if self._ValueList[1].count('_') != 4:\r
1241 EdkLogger.error(\r
1242 'Parser',\r
1243 FORMAT_INVALID,\r
1244 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],\r
1245 ExtraData=self._CurrentLine,\r
1246 File=self.MetaFile,\r
1247 Line=self._LineIndex + 1\r
1248 )\r
1249\r
1250 ## Override parent's method since we'll do all macro replacements in parser\r
1251 def _GetMacros(self):\r
1252 Macros = {}\r
1253 Macros.update(self._FileLocalMacros)\r
1254 Macros.update(self._GetApplicableSectionMacro())\r
1255 Macros.update(GlobalData.gEdkGlobal)\r
1256 Macros.update(GlobalData.gPlatformDefines)\r
1257 Macros.update(GlobalData.gCommandLineDefines)\r
1258 # PCD cannot be referenced in macro definition\r
1259 if self._ItemType not in [MODEL_META_DATA_DEFINE, MODEL_META_DATA_GLOBAL_DEFINE]:\r
1260 Macros.update(self._Symbols)\r
1261 if GlobalData.BuildOptionPcd:\r
1262 for Item in GlobalData.BuildOptionPcd:\r
1263 if isinstance(Item, tuple):\r
1264 continue\r
1265 PcdName, TmpValue = Item.split("=")\r
1266 TmpValue = BuildOptionValue(TmpValue, self._GuidDict)\r
1267 Macros[PcdName.strip()] = TmpValue\r
1268 return Macros\r
1269\r
1270 def _PostProcess(self):\r
1271 Processer = {\r
1272 MODEL_META_DATA_SECTION_HEADER : self.__ProcessSectionHeader,\r
1273 MODEL_META_DATA_SUBSECTION_HEADER : self.__ProcessSubsectionHeader,\r
1274 MODEL_META_DATA_HEADER : self.__ProcessDefine,\r
1275 MODEL_META_DATA_DEFINE : self.__ProcessDefine,\r
1276 MODEL_META_DATA_GLOBAL_DEFINE : self.__ProcessDefine,\r
1277 MODEL_META_DATA_INCLUDE : self.__ProcessDirective,\r
1278 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF : self.__ProcessDirective,\r
1279 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE : self.__ProcessDirective,\r
1280 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF : self.__ProcessDirective,\r
1281 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF : self.__ProcessDirective,\r
1282 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF : self.__ProcessDirective,\r
1283 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF : self.__ProcessDirective,\r
1284 MODEL_EFI_SKU_ID : self.__ProcessSkuId,\r
1285 MODEL_EFI_DEFAULT_STORES : self.__ProcessDefaultStores,\r
1286 MODEL_EFI_LIBRARY_INSTANCE : self.__ProcessLibraryInstance,\r
1287 MODEL_EFI_LIBRARY_CLASS : self.__ProcessLibraryClass,\r
1288 MODEL_PCD_FIXED_AT_BUILD : self.__ProcessPcd,\r
1289 MODEL_PCD_PATCHABLE_IN_MODULE : self.__ProcessPcd,\r
1290 MODEL_PCD_FEATURE_FLAG : self.__ProcessPcd,\r
1291 MODEL_PCD_DYNAMIC_DEFAULT : self.__ProcessPcd,\r
1292 MODEL_PCD_DYNAMIC_HII : self.__ProcessPcd,\r
1293 MODEL_PCD_DYNAMIC_VPD : self.__ProcessPcd,\r
1294 MODEL_PCD_DYNAMIC_EX_DEFAULT : self.__ProcessPcd,\r
1295 MODEL_PCD_DYNAMIC_EX_HII : self.__ProcessPcd,\r
1296 MODEL_PCD_DYNAMIC_EX_VPD : self.__ProcessPcd,\r
1297 MODEL_META_DATA_COMPONENT : self.__ProcessComponent,\r
1298 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : self.__ProcessSourceOverridePath,\r
1299 MODEL_META_DATA_BUILD_OPTION : self.__ProcessBuildOption,\r
1300 MODEL_UNKNOWN : self._Skip,\r
1301 MODEL_META_DATA_USER_EXTENSION : self._SkipUserExtension,\r
1302 MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR : self._ProcessError,\r
1303 }\r
1304\r
1305 self._Table = MetaFileStorage(self._RawTable.Cur, self.MetaFile, MODEL_FILE_DSC, True)\r
1306 self._Table.Create()\r
1307 self._DirectiveStack = []\r
1308 self._DirectiveEvalStack = []\r
1309 self._FileWithError = self.MetaFile\r
1310 self._FileLocalMacros = {}\r
1311 self._SectionsMacroDict.clear()\r
1312 GlobalData.gPlatformDefines = {}\r
1313\r
1314 # Get all macro and PCD which has straitforward value\r
1315 self.__RetrievePcdValue()\r
1316 self._Content = self._RawTable.GetAll()\r
1317 self._ContentIndex = 0\r
1318 self._InSubsection = False\r
1319 while self._ContentIndex < len(self._Content) :\r
1320 Id, self._ItemType, V1, V2, V3, S1, S2, S3, Owner, self._From, \\r
1321 LineStart, ColStart, LineEnd, ColEnd, Enabled = self._Content[self._ContentIndex]\r
1322\r
1323 if self._From < 0:\r
1324 self._FileWithError = self.MetaFile\r
1325\r
1326 self._ContentIndex += 1\r
1327\r
1328 self._Scope = [[S1, S2, S3]]\r
1329 #\r
1330 # For !include directive, handle it specially,\r
1331 # merge arch and module type in case of duplicate items\r
1332 #\r
1333 while self._ItemType == MODEL_META_DATA_INCLUDE:\r
1334 if self._ContentIndex >= len(self._Content):\r
1335 break\r
1336 Record = self._Content[self._ContentIndex]\r
1337 if LineStart == Record[10] and LineEnd == Record[12]:\r
1338 if [Record[5], Record[6], Record[7]] not in self._Scope:\r
1339 self._Scope.append([Record[5], Record[6], Record[7]])\r
1340 self._ContentIndex += 1\r
1341 else:\r
1342 break\r
1343\r
1344 self._LineIndex = LineStart - 1\r
1345 self._ValueList = [V1, V2, V3]\r
1346\r
1347 if Owner > 0 and Owner in self._IdMapping:\r
1348 self._InSubsection = True\r
1349 else:\r
1350 self._InSubsection = False\r
1351 try:\r
1352 Processer[self._ItemType]()\r
1353 except EvaluationException as Excpt:\r
1354 #\r
1355 # Only catch expression evaluation error here. We need to report\r
1356 # the precise number of line on which the error occurred\r
1357 #\r
1358 if hasattr(Excpt, 'Pcd'):\r
1359 if Excpt.Pcd in GlobalData.gPlatformOtherPcds:\r
1360 Info = GlobalData.gPlatformOtherPcds[Excpt.Pcd]\r
1361 EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"\r
1362 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"\r
1363 " of the DSC file, and it is currently defined in this section:"\r
1364 " %s, line #: %d." % (Excpt.Pcd, Info[0], Info[1]),\r
1365 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1366 Line=self._LineIndex + 1)\r
1367 else:\r
1368 EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,\r
1369 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1370 Line=self._LineIndex + 1)\r
1371 else:\r
1372 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),\r
1373 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1374 Line=self._LineIndex + 1)\r
1375 except MacroException as Excpt:\r
1376 EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt),\r
1377 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1378 Line=self._LineIndex + 1)\r
1379\r
1380 if self._ValueList is None:\r
1381 continue\r
1382\r
1383 NewOwner = self._IdMapping.get(Owner, -1)\r
1384 self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack))\r
1385 self._LastItem = self._Store(\r
1386 self._ItemType,\r
1387 self._ValueList[0],\r
1388 self._ValueList[1],\r
1389 self._ValueList[2],\r
1390 S1,\r
1391 S2,\r
1392 S3,\r
1393 NewOwner,\r
1394 self._From,\r
1395 self._LineIndex + 1,\r
1396 - 1,\r
1397 self._LineIndex + 1,\r
1398 - 1,\r
1399 self._Enabled\r
1400 )\r
1401 self._IdMapping[Id] = self._LastItem\r
1402\r
1403 GlobalData.gPlatformDefines.update(self._FileLocalMacros)\r
1404 self._PostProcessed = True\r
1405 self._Content = None\r
1406 def _ProcessError(self):\r
1407 if not self._Enabled:\r
1408 return\r
1409 EdkLogger.error('Parser', ERROR_STATEMENT, self._ValueList[1], File=self.MetaFile, Line=self._LineIndex + 1)\r
1410\r
1411 def __ProcessSectionHeader(self):\r
1412 self._SectionName = self._ValueList[0]\r
1413 if self._SectionName in self.DataType:\r
1414 self._SectionType = self.DataType[self._SectionName]\r
1415 else:\r
1416 self._SectionType = MODEL_UNKNOWN\r
1417\r
1418 def __ProcessSubsectionHeader(self):\r
1419 self._SubsectionName = self._ValueList[0]\r
1420 if self._SubsectionName in self.DataType:\r
1421 self._SubsectionType = self.DataType[self._SubsectionName]\r
1422 else:\r
1423 self._SubsectionType = MODEL_UNKNOWN\r
1424\r
1425 def __RetrievePcdValue(self):\r
1426 Content = open(str(self.MetaFile), 'r').readlines()\r
1427 GlobalData.gPlatformOtherPcds['DSCFILE'] = str(self.MetaFile)\r
1428 for PcdType in (MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_HII,\r
1429 MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_DYNAMIC_EX_HII,\r
1430 MODEL_PCD_DYNAMIC_EX_VPD):\r
1431 Records = self._RawTable.Query(PcdType, BelongsToItem= -1.0)\r
1432 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, Dummy4, ID, Line in Records:\r
1433 Name = TokenSpaceGuid + '.' + PcdName\r
1434 if Name not in GlobalData.gPlatformOtherPcds:\r
1435 PcdLine = Line\r
1436 while not Content[Line - 1].lstrip().startswith(TAB_SECTION_START):\r
1437 Line -= 1\r
1438 GlobalData.gPlatformOtherPcds[Name] = (CleanString(Content[Line - 1]), PcdLine, PcdType)\r
1439\r
1440 def __ProcessDefine(self):\r
1441 if not self._Enabled:\r
1442 return\r
1443\r
1444 Type, Name, Value = self._ValueList\r
1445 Value = ReplaceMacro(Value, self._Macros, False)\r
1446 #\r
1447 # If it is <Defines>, return\r
1448 #\r
1449 if self._InSubsection:\r
1450 self._ValueList = [Type, Name, Value]\r
1451 return\r
1452\r
1453 if self._ItemType == MODEL_META_DATA_DEFINE:\r
1454 if self._SectionType == MODEL_META_DATA_HEADER:\r
1455 self._FileLocalMacros[Name] = Value\r
1456 else:\r
1457 self._ConstructSectionMacroDict(Name, Value)\r
1458 elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE:\r
1459 GlobalData.gEdkGlobal[Name] = Value\r
1460\r
1461 #\r
1462 # Keyword in [Defines] section can be used as Macros\r
1463 #\r
1464 if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER):\r
1465 self._FileLocalMacros[Name] = Value\r
1466\r
1467 self._ValueList = [Type, Name, Value]\r
1468\r
1469 def __ProcessDirective(self):\r
1470 Result = None\r
1471 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1472 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF]:\r
1473 Macros = self._Macros\r
1474 Macros.update(GlobalData.gGlobalDefines)\r
1475 try:\r
1476 Result = ValueExpression(self._ValueList[1], Macros)()\r
1477 except SymbolNotFound as Exc:\r
1478 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])\r
1479 Result = False\r
1480 except WrnExpression as Excpt:\r
1481 #\r
1482 # Catch expression evaluation warning here. We need to report\r
1483 # the precise number of line and return the evaluation result\r
1484 #\r
1485 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),\r
1486 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1487 Line=self._LineIndex + 1)\r
1488 Result = Excpt.result\r
1489\r
1490 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1491 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
1492 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:\r
1493 self._DirectiveStack.append(self._ItemType)\r
1494 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF:\r
1495 Result = bool(Result)\r
1496 else:\r
1497 Macro = self._ValueList[1]\r
1498 Macro = Macro[2:-1] if (Macro.startswith("$(") and Macro.endswith(")")) else Macro\r
1499 Result = Macro in self._Macros\r
1500 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF:\r
1501 Result = not Result\r
1502 self._DirectiveEvalStack.append(Result)\r
1503 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF:\r
1504 self._DirectiveStack.append(self._ItemType)\r
1505 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]\r
1506 self._DirectiveEvalStack.append(bool(Result))\r
1507 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:\r
1508 self._DirectiveStack.append(self._ItemType)\r
1509 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]\r
1510 self._DirectiveEvalStack.append(True)\r
1511 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:\r
1512 # Back to the nearest !if/!ifdef/!ifndef\r
1513 while self._DirectiveStack:\r
1514 self._DirectiveEvalStack.pop()\r
1515 Directive = self._DirectiveStack.pop()\r
1516 if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1517 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
1518 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:\r
1519 break\r
1520 elif self._ItemType == MODEL_META_DATA_INCLUDE:\r
1521 # The included file must be relative to workspace or same directory as DSC file\r
1522 __IncludeMacros = {}\r
1523 #\r
1524 # Allow using system environment variables in path after !include\r
1525 #\r
1526 __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE']\r
1527 if "ECP_SOURCE" in GlobalData.gGlobalDefines:\r
1528 __IncludeMacros['ECP_SOURCE'] = GlobalData.gGlobalDefines['ECP_SOURCE']\r
1529 #\r
1530 # During GenFds phase call DSC parser, will go into this branch.\r
1531 #\r
1532 elif "ECP_SOURCE" in GlobalData.gCommandLineDefines:\r
1533 __IncludeMacros['ECP_SOURCE'] = GlobalData.gCommandLineDefines['ECP_SOURCE']\r
1534\r
1535 __IncludeMacros['EFI_SOURCE'] = GlobalData.gGlobalDefines['EFI_SOURCE']\r
1536 __IncludeMacros['EDK_SOURCE'] = GlobalData.gGlobalDefines['EDK_SOURCE']\r
1537 #\r
1538 # Allow using MACROs comes from [Defines] section to keep compatible.\r
1539 #\r
1540 __IncludeMacros.update(self._Macros)\r
1541\r
1542 IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True))\r
1543 #\r
1544 # First search the include file under the same directory as DSC file\r
1545 #\r
1546 IncludedFile1 = PathClass(IncludedFile, self.MetaFile.Dir)\r
1547 ErrorCode, ErrorInfo1 = IncludedFile1.Validate()\r
1548 if ErrorCode != 0:\r
1549 #\r
1550 # Also search file under the WORKSPACE directory\r
1551 #\r
1552 IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)\r
1553 ErrorCode, ErrorInfo2 = IncludedFile1.Validate()\r
1554 if ErrorCode != 0:\r
1555 EdkLogger.error('parser', ErrorCode, File=self._FileWithError,\r
1556 Line=self._LineIndex + 1, ExtraData=ErrorInfo1 + "\n" + ErrorInfo2)\r
1557\r
1558 self._FileWithError = IncludedFile1\r
1559\r
1560 FromItem = self._Content[self._ContentIndex - 1][0]\r
1561 if self._InSubsection:\r
1562 Owner = self._Content[self._ContentIndex - 1][8]\r
1563 else:\r
1564 Owner = self._Content[self._ContentIndex - 1][0]\r
1565 IncludedFileTable = MetaFileStorage(self._Table.Cur, IncludedFile1, MODEL_FILE_DSC, False, FromItem=FromItem)\r
1566 Parser = DscParser(IncludedFile1, self._FileType, self._Arch, IncludedFileTable,\r
1567 Owner=Owner, From=FromItem)\r
1568\r
1569 self.IncludedFiles.add (IncludedFile1)\r
1570\r
1571 # set the parser status with current status\r
1572 Parser._SectionName = self._SectionName\r
1573 Parser._SubsectionType = self._SubsectionType\r
1574 Parser._InSubsection = self._InSubsection\r
1575 Parser._SectionType = self._SectionType\r
1576 Parser._Scope = self._Scope\r
1577 Parser._Enabled = self._Enabled\r
1578 # Parse the included file\r
1579 Parser.Start()\r
1580\r
1581\r
1582 # Insert all records in the table for the included file into dsc file table\r
1583 Records = IncludedFileTable.GetAll()\r
1584 if Records:\r
1585 self._Content[self._ContentIndex:self._ContentIndex] = Records\r
1586 self._Content.pop(self._ContentIndex - 1)\r
1587 self._ValueList = None\r
1588 self._ContentIndex -= 1\r
1589\r
1590 def __ProcessSkuId(self):\r
1591 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)\r
1592 for Value in self._ValueList]\r
1593 def __ProcessDefaultStores(self):\r
1594 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)\r
1595 for Value in self._ValueList]\r
1596\r
1597 def __ProcessLibraryInstance(self):\r
1598 self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]\r
1599\r
1600 def __ProcessLibraryClass(self):\r
1601 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True)\r
1602\r
1603 def __ProcessPcd(self):\r
1604 if self._ItemType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:\r
1605 self._ValueList[2] = ReplaceMacro(self._ValueList[2], self._Macros, RaiseError=True)\r
1606 return\r
1607\r
1608 ValList, Valid, Index = AnalyzeDscPcd(self._ValueList[2], self._ItemType)\r
1609 if not Valid:\r
1610 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self._FileWithError, Line=self._LineIndex + 1,\r
1611 ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))\r
1612 PcdValue = ValList[Index]\r
1613 if PcdValue and "." not in self._ValueList[0]:\r
1614 try:\r
1615 ValList[Index] = ValueExpression(PcdValue, self._Macros)(True)\r
1616 except WrnExpression as Value:\r
1617 ValList[Index] = Value.result\r
1618 except:\r
1619 pass\r
1620\r
1621 if ValList[Index] == 'True':\r
1622 ValList[Index] = '1'\r
1623 if ValList[Index] == 'False':\r
1624 ValList[Index] = '0'\r
1625\r
1626 if (not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack):\r
1627 GlobalData.gPlatformPcds[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue\r
1628 self._Symbols[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue\r
1629 try:\r
1630 self._ValueList[2] = '|'.join(ValList)\r
1631 except Exception:\r
1632 print(ValList)\r
1633\r
1634 def __ProcessComponent(self):\r
1635 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)\r
1636\r
1637 def __ProcessSourceOverridePath(self):\r
1638 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)\r
1639\r
1640 def __ProcessBuildOption(self):\r
1641 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False)\r
1642 for Value in self._ValueList]\r
1643\r
1644 _SectionParser = {\r
1645 MODEL_META_DATA_HEADER : _DefineParser,\r
1646 MODEL_EFI_SKU_ID : _SkuIdParser,\r
1647 MODEL_EFI_DEFAULT_STORES : _DefaultStoresParser,\r
1648 MODEL_EFI_LIBRARY_INSTANCE : _LibraryInstanceParser,\r
1649 MODEL_EFI_LIBRARY_CLASS : _LibraryClassParser,\r
1650 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,\r
1651 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,\r
1652 MODEL_PCD_FEATURE_FLAG : _PcdParser,\r
1653 MODEL_PCD_DYNAMIC_DEFAULT : _PcdParser,\r
1654 MODEL_PCD_DYNAMIC_HII : _PcdParser,\r
1655 MODEL_PCD_DYNAMIC_VPD : _PcdParser,\r
1656 MODEL_PCD_DYNAMIC_EX_DEFAULT : _PcdParser,\r
1657 MODEL_PCD_DYNAMIC_EX_HII : _PcdParser,\r
1658 MODEL_PCD_DYNAMIC_EX_VPD : _PcdParser,\r
1659 MODEL_META_DATA_COMPONENT : _ComponentParser,\r
1660 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : _CompponentSourceOverridePathParser,\r
1661 MODEL_META_DATA_BUILD_OPTION : _BuildOptionParser,\r
1662 MODEL_UNKNOWN : MetaFileParser._Skip,\r
1663 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,\r
1664 MODEL_META_DATA_SECTION_HEADER : MetaFileParser._SectionHeaderParser,\r
1665 MODEL_META_DATA_SUBSECTION_HEADER : _SubsectionHeaderParser,\r
1666 }\r
1667\r
1668 _Macros = property(_GetMacros)\r
1669\r
1670## DEC file parser class\r
1671#\r
1672# @param FilePath The path of platform description file\r
1673# @param FileType The raw data of DSC file\r
1674# @param Table Database used to retrieve module/package information\r
1675# @param Macros Macros used for replacement in file\r
1676#\r
1677class DecParser(MetaFileParser):\r
1678 # DEC file supported data types (one type per section)\r
1679 DataType = {\r
1680 TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER,\r
1681 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,\r
1682 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,\r
1683 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,\r
1684 TAB_GUIDS.upper() : MODEL_EFI_GUID,\r
1685 TAB_PPIS.upper() : MODEL_EFI_PPI,\r
1686 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,\r
1687 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,\r
1688 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,\r
1689 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,\r
1690 TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC,\r
1691 TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX,\r
1692 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION,\r
1693 }\r
1694\r
1695 ## Constructor of DecParser\r
1696 #\r
1697 # Initialize object of DecParser\r
1698 #\r
1699 # @param FilePath The path of platform description file\r
1700 # @param FileType The raw data of DSC file\r
1701 # @param Arch Default Arch value for filtering sections\r
1702 # @param Table Database used to retrieve module/package information\r
1703 #\r
1704 def __init__(self, FilePath, FileType, Arch, Table):\r
1705 # prevent re-initialization\r
1706 if hasattr(self, "_Table"):\r
1707 return\r
1708 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, -1)\r
1709 self._Comments = []\r
1710 self._Version = 0x00010005 # Only EDK2 dec file is supported\r
1711 self._AllPCDs = [] # Only for check duplicate PCD\r
1712 self._AllPcdDict = {}\r
1713\r
1714 self._CurrentStructurePcdName = ""\r
1715 self._include_flag = False\r
1716 self._package_flag = False\r
1717\r
1718 ## Parser starter\r
1719 def Start(self):\r
1720 Content = ''\r
1721 try:\r
1722 Content = open(str(self.MetaFile), 'r').readlines()\r
1723 except:\r
1724 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)\r
1725\r
1726 self._DefinesCount = 0\r
1727 for Index in range(0, len(Content)):\r
1728 Line, Comment = CleanString2(Content[Index])\r
1729 self._CurrentLine = Line\r
1730 self._LineIndex = Index\r
1731\r
1732 # save comment for later use\r
1733 if Comment:\r
1734 self._Comments.append((Comment, self._LineIndex + 1))\r
1735 # skip empty line\r
1736 if Line == '':\r
1737 continue\r
1738\r
1739 # section header\r
1740 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:\r
1741 self._SectionHeaderParser()\r
1742 if self._SectionName == TAB_DEC_DEFINES.upper():\r
1743 self._DefinesCount += 1\r
1744 self._Comments = []\r
1745 continue\r
1746 if self._SectionType == MODEL_UNKNOWN:\r
1747 EdkLogger.error("Parser", FORMAT_INVALID,\r
1748 ""\r
1749 "Not able to determine \"%s\" in which section."%self._CurrentLine,\r
1750 self.MetaFile, self._LineIndex + 1)\r
1751 elif len(self._SectionType) == 0:\r
1752 self._Comments = []\r
1753 continue\r
1754\r
1755 # section content\r
1756 self._ValueList = ['', '', '']\r
1757 self._SectionParser[self._SectionType[0]](self)\r
1758 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:\r
1759 self._ItemType = -1\r
1760 self._Comments = []\r
1761 continue\r
1762\r
1763 #\r
1764 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,\r
1765 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1\r
1766 #\r
1767 for Arch, ModuleType, Type in self._Scope:\r
1768 self._LastItem = self._Store(\r
1769 Type,\r
1770 self._ValueList[0],\r
1771 self._ValueList[1],\r
1772 self._ValueList[2],\r
1773 Arch,\r
1774 ModuleType,\r
1775 self._Owner[-1],\r
1776 self._LineIndex + 1,\r
1777 - 1,\r
1778 self._LineIndex + 1,\r
1779 - 1,\r
1780 0\r
1781 )\r
1782 for Comment, LineNo in self._Comments:\r
1783 self._Store(\r
1784 MODEL_META_DATA_COMMENT,\r
1785 Comment,\r
1786 self._ValueList[0],\r
1787 self._ValueList[1],\r
1788 Arch,\r
1789 ModuleType,\r
1790 self._LastItem,\r
1791 LineNo,\r
1792 - 1,\r
1793 LineNo,\r
1794 - 1,\r
1795 0\r
1796 )\r
1797 self._Comments = []\r
1798 if self._DefinesCount > 1:\r
1799 EdkLogger.error('Parser', FORMAT_INVALID, 'Multiple [Defines] section is exist.', self.MetaFile )\r
1800 if self._DefinesCount == 0:\r
1801 EdkLogger.error('Parser', FORMAT_INVALID, 'No [Defines] section exist.', self.MetaFile)\r
1802 self._Done()\r
1803\r
1804\r
1805 ## Section header parser\r
1806 #\r
1807 # The section header is always in following format:\r
1808 #\r
1809 # [section_name.arch<.platform|module_type>]\r
1810 #\r
1811 def _SectionHeaderParser(self):\r
1812 self._Scope = []\r
1813 self._SectionName = ''\r
1814 self._SectionType = []\r
1815 ArchList = set()\r
1816 PrivateList = set()\r
1817 Line = re.sub(',[\s]*', TAB_COMMA_SPLIT, self._CurrentLine)\r
1818 for Item in Line[1:-1].split(TAB_COMMA_SPLIT):\r
1819 if Item == '':\r
1820 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR,\r
1821 "section name can NOT be empty or incorrectly use separator comma",\r
1822 self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
1823 ItemList = Item.split(TAB_SPLIT)\r
1824\r
1825 # different types of PCD are permissible in one section\r
1826 self._SectionName = ItemList[0].upper()\r
1827 if self._SectionName == TAB_DEC_DEFINES.upper() and (len(ItemList) > 1 or len(Line.split(TAB_COMMA_SPLIT)) > 1):\r
1828 EdkLogger.error("Parser", FORMAT_INVALID, "Defines section format is invalid",\r
1829 self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
1830 if self._SectionName in self.DataType:\r
1831 if self.DataType[self._SectionName] not in self._SectionType:\r
1832 self._SectionType.append(self.DataType[self._SectionName])\r
1833 else:\r
1834 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,\r
1835 self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
1836\r
1837 if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:\r
1838 EdkLogger.error(\r
1839 'Parser',\r
1840 FORMAT_INVALID,\r
1841 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,\r
1842 File=self.MetaFile,\r
1843 Line=self._LineIndex + 1,\r
1844 ExtraData=self._CurrentLine\r
1845 )\r
1846 # S1 is always Arch\r
1847 if len(ItemList) > 1:\r
1848 S1 = ItemList[1].upper()\r
1849 else:\r
1850 S1 = TAB_ARCH_COMMON\r
1851 ArchList.add(S1)\r
1852 # S2 may be Platform or ModuleType\r
1853 if len(ItemList) > 2:\r
1854 S2 = ItemList[2].upper()\r
1855 # only Includes, GUIDs, PPIs, Protocols section have Private tag\r
1856 if self._SectionName in [TAB_INCLUDES.upper(), TAB_GUIDS.upper(), TAB_PROTOCOLS.upper(), TAB_PPIS.upper()]:\r
1857 if S2 != 'PRIVATE':\r
1858 EdkLogger.error("Parser", FORMAT_INVALID, 'Please use keyword "Private" as section tag modifier.',\r
1859 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
1860 else:\r
1861 S2 = TAB_COMMON\r
1862 PrivateList.add(S2)\r
1863 if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:\r
1864 self._Scope.append([S1, S2, self.DataType[self._SectionName]])\r
1865\r
1866 # 'COMMON' must not be used with specific ARCHs at the same section\r
1867 if TAB_ARCH_COMMON in ArchList and len(ArchList) > 1:\r
1868 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",\r
1869 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
1870\r
1871 # It is not permissible to mix section tags without the Private attribute with section tags with the Private attribute\r
1872 if TAB_COMMON in PrivateList and len(PrivateList) > 1:\r
1873 EdkLogger.error('Parser', FORMAT_INVALID, "Can't mix section tags without the Private attribute with section tags with the Private attribute",\r
1874 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
1875\r
1876 ## [guids], [ppis] and [protocols] section parser\r
1877 @ParseMacro\r
1878 def _GuidParser(self):\r
1879 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
1880 if len(TokenList) < 2:\r
1881 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",\r
1882 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1883 File=self.MetaFile, Line=self._LineIndex + 1)\r
1884 if TokenList[0] == '':\r
1885 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",\r
1886 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1887 File=self.MetaFile, Line=self._LineIndex + 1)\r
1888 if TokenList[1] == '':\r
1889 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",\r
1890 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1891 File=self.MetaFile, Line=self._LineIndex + 1)\r
1892 if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':\r
1893 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",\r
1894 ExtraData=self._CurrentLine + \\r
1895 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",\r
1896 File=self.MetaFile, Line=self._LineIndex + 1)\r
1897 self._ValueList[0] = TokenList[0]\r
1898 self._ValueList[1] = TokenList[1]\r
1899 if self._ValueList[0] not in self._GuidDict:\r
1900 self._GuidDict[self._ValueList[0]] = self._ValueList[1]\r
1901\r
1902 ## PCD sections parser\r
1903 #\r
1904 # [PcdsFixedAtBuild]\r
1905 # [PcdsPatchableInModule]\r
1906 # [PcdsFeatureFlag]\r
1907 # [PcdsDynamicEx\r
1908 # [PcdsDynamic]\r
1909 #\r
1910 @ParseMacro\r
1911 def _PcdParser(self):\r
1912 if self._CurrentStructurePcdName:\r
1913 self._ValueList[0] = self._CurrentStructurePcdName\r
1914\r
1915 if "|" not in self._CurrentLine:\r
1916 if "<HeaderFiles>" == self._CurrentLine:\r
1917 self._include_flag = True\r
1918 self._package_flag = False\r
1919 self._ValueList = None\r
1920 return\r
1921 if "<Packages>" == self._CurrentLine:\r
1922 self._package_flag = True\r
1923 self._ValueList = None\r
1924 self._include_flag = False\r
1925 return\r
1926\r
1927 if self._include_flag:\r
1928 self._ValueList[1] = "<HeaderFiles>_" + md5.new(self._CurrentLine).hexdigest()\r
1929 self._ValueList[2] = self._CurrentLine\r
1930 if self._package_flag and "}" != self._CurrentLine:\r
1931 self._ValueList[1] = "<Packages>_" + md5.new(self._CurrentLine).hexdigest()\r
1932 self._ValueList[2] = self._CurrentLine\r
1933 if self._CurrentLine == "}":\r
1934 self._package_flag = False\r
1935 self._include_flag = False\r
1936 self._ValueList = None\r
1937 return\r
1938 else:\r
1939 PcdTockens = self._CurrentLine.split(TAB_VALUE_SPLIT)\r
1940 PcdNames = PcdTockens[0].split(TAB_SPLIT)\r
1941 if len(PcdNames) == 2:\r
1942 self._CurrentStructurePcdName = ""\r
1943 else:\r
1944 if self._CurrentStructurePcdName != TAB_SPLIT.join(PcdNames[:2]):\r
1945 EdkLogger.error('Parser', FORMAT_INVALID, "Pcd Name does not match: %s and %s " % (self._CurrentStructurePcdName, TAB_SPLIT.join(PcdNames[:2])),\r
1946 File=self.MetaFile, Line=self._LineIndex + 1)\r
1947 self._ValueList[1] = TAB_SPLIT.join(PcdNames[2:])\r
1948 self._ValueList[2] = PcdTockens[1]\r
1949 if not self._CurrentStructurePcdName:\r
1950 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
1951 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
1952 ValueRe = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*')\r
1953 # check PCD information\r
1954 if self._ValueList[0] == '' or self._ValueList[1] == '':\r
1955 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
1956 ExtraData=self._CurrentLine + \\r
1957 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1958 File=self.MetaFile, Line=self._LineIndex + 1)\r
1959 # check format of token space GUID CName\r
1960 if not ValueRe.match(self._ValueList[0]):\r
1961 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
1962 ExtraData=self._CurrentLine + \\r
1963 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1964 File=self.MetaFile, Line=self._LineIndex + 1)\r
1965 # check format of PCD CName\r
1966 if not ValueRe.match(self._ValueList[1]):\r
1967 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
1968 ExtraData=self._CurrentLine + \\r
1969 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1970 File=self.MetaFile, Line=self._LineIndex + 1)\r
1971 # check PCD datum information\r
1972 if len(TokenList) < 2 or TokenList[1] == '':\r
1973 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",\r
1974 ExtraData=self._CurrentLine + \\r
1975 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1976 File=self.MetaFile, Line=self._LineIndex + 1)\r
1977\r
1978\r
1979 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')\r
1980 PtrValue = ValueRe.findall(TokenList[1])\r
1981\r
1982 # Has VOID* type string, may contain "|" character in the string.\r
1983 if len(PtrValue) != 0:\r
1984 ptrValueList = re.sub(ValueRe, '', TokenList[1])\r
1985 ValueList = AnalyzePcdExpression(ptrValueList)\r
1986 ValueList[0] = PtrValue[0]\r
1987 else:\r
1988 ValueList = AnalyzePcdExpression(TokenList[1])\r
1989\r
1990\r
1991 # check if there's enough datum information given\r
1992 if len(ValueList) != 3:\r
1993 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",\r
1994 ExtraData=self._CurrentLine + \\r
1995 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1996 File=self.MetaFile, Line=self._LineIndex + 1)\r
1997 # check default value\r
1998 if ValueList[0] == '':\r
1999 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",\r
2000 ExtraData=self._CurrentLine + \\r
2001 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2002 File=self.MetaFile, Line=self._LineIndex + 1)\r
2003 # check datum type\r
2004 if ValueList[1] == '':\r
2005 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",\r
2006 ExtraData=self._CurrentLine + \\r
2007 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2008 File=self.MetaFile, Line=self._LineIndex + 1)\r
2009 # check token of the PCD\r
2010 if ValueList[2] == '':\r
2011 EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",\r
2012 ExtraData=self._CurrentLine + \\r
2013 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2014 File=self.MetaFile, Line=self._LineIndex + 1)\r
2015\r
2016 PcdValue = ValueList[0]\r
2017 if PcdValue:\r
2018 try:\r
2019 self._GuidDict.update(self._AllPcdDict)\r
2020 ValueList[0] = ValueExpressionEx(ValueList[0], ValueList[1], self._GuidDict)(True)\r
2021 except BadExpression as Value:\r
2022 EdkLogger.error('Parser', FORMAT_INVALID, Value, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
2023 # check format of default value against the datum type\r
2024 IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])\r
2025 if not IsValid:\r
2026 EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,\r
2027 File=self.MetaFile, Line=self._LineIndex + 1)\r
2028\r
2029 if Cause == "StructurePcd":\r
2030 self._CurrentStructurePcdName = TAB_SPLIT.join(self._ValueList[0:2])\r
2031 self._ValueList[0] = self._CurrentStructurePcdName\r
2032 self._ValueList[1] = ValueList[1].strip()\r
2033\r
2034 if ValueList[0] in ['True', 'true', 'TRUE']:\r
2035 ValueList[0] = '1'\r
2036 elif ValueList[0] in ['False', 'false', 'FALSE']:\r
2037 ValueList[0] = '0'\r
2038\r
2039 # check for duplicate PCD definition\r
2040 if (self._Scope[0], self._ValueList[0], self._ValueList[1]) in self._AllPCDs:\r
2041 EdkLogger.error('Parser', FORMAT_INVALID,\r
2042 "The same PCD name and GUID have been already defined",\r
2043 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
2044 else:\r
2045 self._AllPCDs.append((self._Scope[0], self._ValueList[0], self._ValueList[1]))\r
2046 self._AllPcdDict[TAB_SPLIT.join(self._ValueList[0:2])] = ValueList[0]\r
2047\r
2048 self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()\r
2049\r
2050 _SectionParser = {\r
2051 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,\r
2052 MODEL_EFI_INCLUDE : MetaFileParser._PathParser,\r
2053 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,\r
2054 MODEL_EFI_GUID : _GuidParser,\r
2055 MODEL_EFI_PPI : _GuidParser,\r
2056 MODEL_EFI_PROTOCOL : _GuidParser,\r
2057 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,\r
2058 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,\r
2059 MODEL_PCD_FEATURE_FLAG : _PcdParser,\r
2060 MODEL_PCD_DYNAMIC : _PcdParser,\r
2061 MODEL_PCD_DYNAMIC_EX : _PcdParser,\r
2062 MODEL_UNKNOWN : MetaFileParser._Skip,\r
2063 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,\r
2064 }\r
2065\r
2066##\r
2067#\r
2068# This acts like the main() function for the script, unless it is 'import'ed into another\r
2069# script.\r
2070#\r
2071if __name__ == '__main__':\r
2072 pass\r
2073\r