]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/Workspace/MetaFileParser.py
BaseTools: Unify long and int in Expression.py
[mirror_edk2.git] / BaseTools / Source / Python / Workspace / MetaFileParser.py
CommitLineData
f51461c8
LG
1## @file\r
2# This file is used to parse meta files\r
3#\r
e6b10112 4# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>\r
5163d893 5# (C) Copyright 2015-2018 Hewlett Packard Enterprise Development LP<BR>\r
f51461c8
LG
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
72443dd2 18from __future__ import print_function\r
1be2ed90 19import Common.LongFilePathOs as os\r
f51461c8
LG
20import re\r
21import time\r
22import copy\r
ae7b6df8 23import md5\r
f51461c8
LG
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
5a57246e 30from Common.StringUtils import *\r
726c501c 31from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData, AnalyzeDscPcd, AnalyzePcdExpression, ParseFieldValue\r
f51461c8
LG
32from Common.Expression import *\r
33from CommonDataClass.Exceptions import *\r
1be2ed90 34from Common.LongFilePathSupport import OpenLongFilePath as open\r
50874612 35from collections import defaultdict\r
f51461c8 36from MetaFileTable import MetaFileStorage\r
97fa0ee9 37from MetaFileCommentParser import CheckInfComment\r
f51461c8 38\r
3e4faa26
CJ
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
f51461c8
LG
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
0d1f5b2b 81 if isinstance(self, DscParser) and self._InDirective > -1:\r
f51461c8
LG
82 pass\r
83 else:\r
0d1f5b2b 84 if isinstance(self, DecParser):\r
f51461c8
LG
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
0d1f5b2b 95 elif not isinstance(self, DscParser):\r
f51461c8
LG
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
cdd1b5e5 153 # @param Arch Default Arch value for filtering sections\r
f51461c8 154 # @param Table Database used to retrieve module/package information\r
f51461c8
LG
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
cdd1b5e5 158 def __init__(self, FilePath, FileType, Arch, Table, Owner= -1, From= -1):\r
f51461c8
LG
159 self._Table = Table\r
160 self._RawTable = Table\r
cdd1b5e5 161 self._Arch = Arch\r
f51461c8
LG
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
50874612 167 self._SectionsMacroDict = defaultdict(dict)\r
f51461c8
LG
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
726c501c 190 self._GuidDict = {} # for Parser PCD value {GUID(gTokeSpaceGuidName)}\r
f51461c8
LG
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
cdd1b5e5
TP
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
55c84777 227 if Arch == TAB_ARCH_COMMON or Arch == FilterArch:\r
cdd1b5e5
TP
228 NewRecordList.append(Record)\r
229 return NewRecordList\r
230\r
f51461c8
LG
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
0d1f5b2b 236 if not isinstance(DataInfo, type(())):\r
f51461c8
LG
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
4231a819 249 if self._RawTable and (len(DataInfo) == 1 or DataInfo[1] is None):\r
cdd1b5e5 250 return self._FilterRecordList(self._RawTable.Query(*DataInfo), self._Arch)\r
f51461c8
LG
251\r
252 # Do post-process if necessary\r
253 if not self._PostProcessed:\r
254 self._PostProcess()\r
255\r
cdd1b5e5 256 return self._FilterRecordList(self._Table.Query(*DataInfo), DataInfo[1])\r
f51461c8
LG
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
0d1f5b2b 278 if not isinstance(self, DscParser):\r
f51461c8
LG
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
0923aa1c
HC
288 ## Skip unsupported data for UserExtension Section\r
289 def _SkipUserExtension(self):\r
290 self._ValueList[0:1] = [self._CurrentLine]\r
291\r
f51461c8
LG
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
ccaa7754 305 ItemList = GetSplitValueList(Item, TAB_SPLIT, 3)\r
f51461c8
LG
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
eece4292 314 if self._SectionName not in SECTIONS_HAVE_ITEM_AFTER_ARCH_SET and len(ItemList) > 3:\r
f51461c8
LG
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
55c84777 327 S1 = TAB_ARCH_COMMON\r
f51461c8
LG
328 ArchList.add(S1)\r
329\r
330 # S2 may be Platform or ModuleType\r
331 if len(ItemList) > 2:\r
eece4292 332 if self._SectionName.upper() in SECTIONS_HAVE_ITEM_PCD_SET:\r
f51461c8
LG
333 S2 = ItemList[2]\r
334 else:\r
335 S2 = ItemList[2].upper()\r
336 else:\r
55c84777 337 S2 = TAB_COMMON\r
8518bf0b
LG
338 if len(ItemList) > 3:\r
339 S3 = ItemList[3]\r
340 else:\r
55c84777 341 S3 = TAB_COMMON\r
8518bf0b 342 self._Scope.append([S1, S2, S3])\r
f51461c8
LG
343\r
344 # 'COMMON' must not be used with specific ARCHs at the same section\r
55c84777 345 if TAB_ARCH_COMMON in ArchList and len(ArchList) > 1:\r
f51461c8
LG
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
dc4c7707
YZ
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
f51461c8
LG
372 # Sometimes, we need to make differences between EDK and EDK2 modules \r
373 if Name == 'INF_VERSION':\r
3e4faa26 374 if hexVersionPattern.match(Value):\r
3ab1434a 375 self._Version = int(Value, 0) \r
3e4faa26 376 elif decVersionPattern.match(Value):\r
3ab1434a
YZ
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
f51461c8
LG
382 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",\r
383 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
384\r
0d1f5b2b 385 if isinstance(self, InfParser) and self._Version < 0x00010005:\r
f51461c8
LG
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
0d1f5b2b 401 if len(TokenList) == 2 and not isinstance(self, DscParser): # value\r
f51461c8
LG
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
82a6a960
BF
413 def GetValidExpression(self, TokenSpaceGuid, PcdCName):\r
414 return self._Table.GetValidExpression(TokenSpaceGuid, PcdCName)\r
f51461c8
LG
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
ccaa7754 423 ScopeKey = [(Scope[0], Scope[1], Scope[2]) for Scope in self._Scope]\r
f51461c8 424 ScopeKey = tuple(ScopeKey)\r
f51461c8
LG
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
0d1f5b2b 429 if isinstance(self, DecParser):\r
f51461c8 430 SectionDictKey = self._SectionType[0], ScopeKey\r
50874612
CJ
431 else:\r
432 SectionDictKey = self._SectionType, ScopeKey\r
433\r
434 self._SectionsMacroDict[SectionDictKey][Name] = Value\r
f51461c8
LG
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
0d1f5b2b 446 if isinstance(self, DecParser):\r
f51461c8
LG
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
ccaa7754
GL
454 Scope0, Scope1, Scope2= ActiveScope[0], ActiveScope[1], ActiveScope[2]\r
455 if(Scope0, Scope1, Scope2) not in Scope:\r
f51461c8
LG
456 break\r
457 else:\r
458 SpeSpeMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])\r
459\r
460 for ActiveScope in self._Scope:\r
ccaa7754
GL
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
f51461c8
LG
463 break\r
464 else:\r
465 ComSpeMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])\r
466\r
55c84777 467 if (TAB_COMMON, TAB_COMMON, TAB_COMMON) in Scope:\r
f51461c8
LG
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
cdd1b5e5 520 # @param Arch Default Arch value for filtering sections\r
f51461c8 521 # @param Table Database used to retrieve module/package information\r
f51461c8 522 #\r
cdd1b5e5 523 def __init__(self, FilePath, FileType, Arch, Table):\r
f51461c8
LG
524 # prevent re-initialization\r
525 if hasattr(self, "_Table"):\r
526 return\r
cdd1b5e5 527 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table)\r
f51461c8
LG
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
55c84777
CJ
575 self._Store(MODEL_META_DATA_HEADER_COMMENT, Cmt, '', '', TAB_COMMON,\r
576 TAB_COMMON, self._Owner[-1], LNo, -1, LNo, -1, 0)\r
f51461c8
LG
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
4231a819 627 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:\r
f51461c8
LG
628 self._ItemType = -1\r
629 Comments = []\r
630 continue\r
631 if Comment:\r
632 Comments.append((Comment, Index + 1))\r
97fa0ee9
YL
633 if GlobalData.gOptions and GlobalData.gOptions.CheckUsage:\r
634 CheckInfComment(self._SectionType, Comments, str(self.MetaFile), Index + 1, self._ValueList)\r
f51461c8
LG
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
ccaa7754 639 for Arch, Platform, _ in self._Scope:\r
f51461c8
LG
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
55c84777
CJ
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
f51461c8
LG
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
0923aa1c 800 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,\r
f51461c8
LG
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
8518bf0b 816 TAB_DEFAULT_STORES.upper() : MODEL_EFI_DEFAULT_STORES,\r
f51461c8
LG
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
0923aa1c 841 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION,\r
09ef8e92 842 TAB_ERROR.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR,\r
f51461c8
LG
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
82a6a960 853 "PCD_VAR_CHECK_GENERATION",\r
f51461c8
LG
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
f0dc69e6
YZ
863 "FIX_LOAD_TOP_MEMORY_ADDRESS",\r
864 "PREBUILD",\r
865 "POSTBUILD"\r
f51461c8
LG
866 ]\r
867\r
97fa0ee9
YL
868 SubSectionDefineKeywords = [\r
869 "FILE_GUID"\r
870 ]\r
871\r
f51461c8
LG
872 SymbolPattern = ValueExpression.SymbolPattern\r
873\r
c17956e0
DL
874 IncludedFiles = set()\r
875\r
f51461c8
LG
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
cdd1b5e5 882 # @param Arch Default Arch value for filtering sections\r
f51461c8 883 # @param Table Database used to retrieve module/package information\r
f51461c8
LG
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
cdd1b5e5 887 def __init__(self, FilePath, FileType, Arch, Table, Owner= -1, From= -1):\r
f51461c8 888 # prevent re-initialization\r
395f3336 889 if hasattr(self, "_Table") and self._Table is Table:\r
f51461c8 890 return\r
cdd1b5e5 891 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, Owner, From)\r
f51461c8
LG
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
50874612 940 OwnerId.clear()\r
f51461c8
LG
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
cd7bd491
YF
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
f51461c8 955 continue\r
d429fcd0 956 if Line[0] == TAB_OPTION_START and not self._InSubsection:\r
ccaa7754 957 EdkLogger.error("Parser", FILE_READ_FAILURE, "Missing the '{' before %s in Line %s" % (Line, Index+1), ExtraData=self.MetaFile)\r
f51461c8
LG
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
4231a819 967 if self._ValueList is None:\r
f51461c8
LG
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
8518bf0b 973 for Arch, ModuleType, DefaultStore in self._Scope:\r
f51461c8 974 Owner = self._Owner[-1]\r
cd7bd491 975 if self._SubsectionType != MODEL_UNKNOWN and Arch in OwnerId:\r
f51461c8
LG
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
8518bf0b 984 DefaultStore,\r
f51461c8
LG
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
55c84777 1037 Scope = [[TAB_COMMON, TAB_COMMON, TAB_COMMON]]\r
f51461c8
LG
1038 if ItemType == MODEL_META_DATA_INCLUDE:\r
1039 Scope = self._Scope\r
09ef8e92
YF
1040 elif ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR:\r
1041 Scope = self._Scope\r
f51461c8
LG
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
09ef8e92 1055 elif ItemType not in {MODEL_META_DATA_INCLUDE, MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR}:\r
f51461c8
LG
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
f51461c8
LG
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
8518bf0b 1069 for Arch, ModuleType, DefaultStore in Scope:\r
f51461c8
LG
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
8518bf0b 1077 DefaultStore,\r
f51461c8
LG
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
97fa0ee9
YL
1100 if (not self._ValueList[1] in self.DefineKeywords and\r
1101 (self._InSubsection and self._ValueList[1] not in self.SubSectionDefineKeywords)):\r
f51461c8
LG
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
97fa0ee9
YL
1107 if not self._InSubsection:\r
1108 self._Defines[self._ValueList[1]] = self._ValueList[2]\r
f51461c8
LG
1109 self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]\r
1110\r
1111 @ParseMacro\r
1112 def _SkuIdParser(self):\r
8518bf0b 1113 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
ccaa7754 1114 if len(TokenList) not in (2, 3):\r
e6b10112 1115 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>[|<UiName>]'",\r
8518bf0b
LG
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
f51461c8
LG
1120 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
1121 if len(TokenList) != 2:\r
767ddbe8 1122 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>'",\r
f51461c8
LG
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
ae7b6df8
LG
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
a0939593
LG
1154 elif len(PcdNameTockens) > 3:\r
1155 self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), ".".join(PcdNameTockens[2:])\r
f51461c8
LG
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
e651d06c 1164 # The PCD values are optional for FIXEDATBUILD, PATCHABLEINMODULE, Dynamic/DynamicEx default\r
f51461c8 1165 #\r
e651d06c 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
f51461c8
LG
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
ccaa7754 1174 if len(ValueList) > 1 and ValueList[1] in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64] \\r
f51461c8
LG
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
9f14de3b
YZ
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
ccaa7754 1182 if len(DscPcdValueList[0].replace('L', '').replace('"', '').strip()) == 0:\r
9f14de3b
YZ
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
f51461c8
LG
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
cd7bd491 1200 self._SubsectionType = MODEL_UNKNOWN\r
f51461c8
LG
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
1fa7fdf6
FY
1261 if GlobalData.BuildOptionPcd:\r
1262 for Item in GlobalData.BuildOptionPcd:\r
0d1f5b2b 1263 if isinstance(Item, tuple):\r
705ed563 1264 continue\r
1fa7fdf6 1265 PcdName, TmpValue = Item.split("=")\r
8565b582 1266 TmpValue = BuildOptionValue(TmpValue, self._GuidDict)\r
1fa7fdf6 1267 Macros[PcdName.strip()] = TmpValue\r
f51461c8
LG
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
8518bf0b 1285 MODEL_EFI_DEFAULT_STORES : self.__ProcessDefaultStores,\r
f51461c8
LG
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
0923aa1c 1301 MODEL_META_DATA_USER_EXTENSION : self._SkipUserExtension,\r
09ef8e92 1302 MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR : self._ProcessError,\r
f51461c8
LG
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
50874612 1311 self._SectionsMacroDict.clear()\r
f51461c8
LG
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
97fa0ee9 1318 self._InSubsection = False\r
f51461c8 1319 while self._ContentIndex < len(self._Content) :\r
ccaa7754 1320 Id, self._ItemType, V1, V2, V3, S1, S2, S3, Owner, self._From, \\r
f51461c8
LG
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
8518bf0b 1328 self._Scope = [[S1, S2, S3]]\r
f51461c8
LG
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
8518bf0b 1337 if LineStart == Record[10] and LineEnd == Record[12]:\r
ccaa7754
GL
1338 if [Record[5], Record[6], Record[7]] not in self._Scope:\r
1339 self._Scope.append([Record[5], Record[6], Record[7]])\r
f51461c8
LG
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
97fa0ee9
YL
1347 if Owner > 0 and Owner in self._IdMapping:\r
1348 self._InSubsection = True\r
1349 else:\r
1350 self._InSubsection = False\r
f51461c8
LG
1351 try:\r
1352 Processer[self._ItemType]()\r
5b0671c1 1353 except EvaluationException as Excpt:\r
f51461c8
LG
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
5b0671c1 1375 except MacroException as Excpt:\r
f51461c8
LG
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
4231a819 1380 if self._ValueList is None:\r
f51461c8
LG
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
8518bf0b 1392 S3,\r
f51461c8
LG
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
09ef8e92
YF
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
f51461c8
LG
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
f51461c8
LG
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
ccaa7754 1432 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, Dummy4, ID, Line in Records:\r
f51461c8
LG
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
97fa0ee9
YL
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
f51461c8
LG
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
5b0671c1 1477 except SymbolNotFound as Exc:\r
f51461c8
LG
1478 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])\r
1479 Result = False\r
5b0671c1 1480 except WrnExpression as Excpt:\r
f51461c8
LG
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
9eb87141 1527 if "ECP_SOURCE" in GlobalData.gGlobalDefines:\r
f51461c8
LG
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
9eb87141 1532 elif "ECP_SOURCE" in GlobalData.gCommandLineDefines:\r
f51461c8
LG
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
33787826 1560 FromItem = self._Content[self._ContentIndex - 1][0]\r
a802b269 1561 if self._InSubsection:\r
33787826
YF
1562 Owner = self._Content[self._ContentIndex - 1][8]\r
1563 else:\r
1564 Owner = self._Content[self._ContentIndex - 1][0]\r
395f3336 1565 IncludedFileTable = MetaFileStorage(self._Table.Cur, IncludedFile1, MODEL_FILE_DSC, False, FromItem=FromItem)\r
cdd1b5e5 1566 Parser = DscParser(IncludedFile1, self._FileType, self._Arch, IncludedFileTable,\r
33787826 1567 Owner=Owner, From=FromItem)\r
f51461c8 1568\r
c17956e0
DL
1569 self.IncludedFiles.add (IncludedFile1)\r
1570\r
f51461c8
LG
1571 # set the parser status with current status\r
1572 Parser._SectionName = self._SectionName\r
cd7bd491
YF
1573 Parser._SubsectionType = self._SubsectionType\r
1574 Parser._InSubsection = self._InSubsection\r
1575 Parser._SectionType = self._SectionType\r
f51461c8
LG
1576 Parser._Scope = self._Scope\r
1577 Parser._Enabled = self._Enabled\r
1578 # Parse the included file\r
1579 Parser.Start()\r
1580\r
f51461c8
LG
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
8518bf0b
LG
1593 def __ProcessDefaultStores(self):\r
1594 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)\r
1595 for Value in self._ValueList]\r
f51461c8
LG
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
47fea6af 1610 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self._FileWithError, Line=self._LineIndex + 1,\r
f51461c8
LG
1611 ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))\r
1612 PcdValue = ValList[Index]\r
ae7b6df8 1613 if PcdValue and "." not in self._ValueList[0]:\r
f51461c8
LG
1614 try:\r
1615 ValList[Index] = ValueExpression(PcdValue, self._Macros)(True)\r
5b0671c1 1616 except WrnExpression as Value:\r
f51461c8 1617 ValList[Index] = Value.result\r
35f613d9
YF
1618 except:\r
1619 pass\r
f51461c8
LG
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
22a99b87
YL
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
ae7b6df8
LG
1629 try:\r
1630 self._ValueList[2] = '|'.join(ValList)\r
1631 except Exception:\r
72443dd2 1632 print(ValList)\r
f51461c8
LG
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
8518bf0b 1647 MODEL_EFI_DEFAULT_STORES : _DefaultStoresParser,\r
f51461c8
LG
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
0923aa1c 1663 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,\r
f51461c8
LG
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
0923aa1c 1692 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION,\r
f51461c8
LG
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
cdd1b5e5 1701 # @param Arch Default Arch value for filtering sections\r
f51461c8 1702 # @param Table Database used to retrieve module/package information\r
f51461c8 1703 #\r
cdd1b5e5 1704 def __init__(self, FilePath, FileType, Arch, Table):\r
f51461c8
LG
1705 # prevent re-initialization\r
1706 if hasattr(self, "_Table"):\r
1707 return\r
cdd1b5e5 1708 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, -1)\r
f51461c8
LG
1709 self._Comments = []\r
1710 self._Version = 0x00010005 # Only EDK2 dec file is supported\r
1711 self._AllPCDs = [] # Only for check duplicate PCD\r
67e11e4d 1712 self._AllPcdDict = {}\r
f51461c8 1713\r
ae7b6df8
LG
1714 self._CurrentStructurePcdName = ""\r
1715 self._include_flag = False\r
1716 self._package_flag = False\r
1717\r
f51461c8
LG
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
778aad47 1726 self._DefinesCount = 0\r
f51461c8
LG
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
778aad47
YF
1742 if self._SectionName == TAB_DEC_DEFINES.upper():\r
1743 self._DefinesCount += 1\r
f51461c8
LG
1744 self._Comments = []\r
1745 continue\r
778aad47
YF
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
f51461c8
LG
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
4231a819 1758 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:\r
f51461c8
LG
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
778aad47
YF
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
ccaa7754 1801 EdkLogger.error('Parser', FORMAT_INVALID, 'No [Defines] section exist.', self.MetaFile)\r
f51461c8
LG
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
c28d2e10 1816 PrivateList = set()\r
07959205 1817 Line = re.sub(',[\s]*', TAB_COMMA_SPLIT, self._CurrentLine)\r
f51461c8
LG
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
778aad47
YF
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
f51461c8
LG
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
55c84777 1850 S1 = TAB_ARCH_COMMON\r
f51461c8
LG
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
c28d2e10
YZ
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
f51461c8 1860 else:\r
55c84777 1861 S2 = TAB_COMMON\r
c28d2e10 1862 PrivateList.add(S2)\r
f51461c8
LG
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
55c84777 1867 if TAB_ARCH_COMMON in ArchList and len(ArchList) > 1:\r
f51461c8
LG
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
c28d2e10
YZ
1870\r
1871 # It is not permissible to mix section tags without the Private attribute with section tags with the Private attribute\r
55c84777 1872 if TAB_COMMON in PrivateList and len(PrivateList) > 1:\r
c28d2e10
YZ
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
f51461c8
LG
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
726c501c
YZ
1899 if self._ValueList[0] not in self._GuidDict:\r
1900 self._GuidDict[self._ValueList[0]] = self._ValueList[1]\r
f51461c8
LG
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
ae7b6df8
LG
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
81add864 1918 self._package_flag = False\r
ae7b6df8
LG
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
81add864 1924 self._include_flag = False\r
ae7b6df8
LG
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
ae7b6df8
LG
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
81add864 1935 self._include_flag = False\r
ae7b6df8
LG
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
8e011d83 1944 if self._CurrentStructurePcdName != TAB_SPLIT.join(PcdNames[:2]):\r
ccaa7754 1945 EdkLogger.error('Parser', FORMAT_INVALID, "Pcd Name does not match: %s and %s " % (self._CurrentStructurePcdName, TAB_SPLIT.join(PcdNames[:2])),\r
8e011d83 1946 File=self.MetaFile, Line=self._LineIndex + 1)\r
a0939593 1947 self._ValueList[1] = TAB_SPLIT.join(PcdNames[2:])\r
ae7b6df8
LG
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
726c501c 2018 try:\r
9efe8d60 2019 self._GuidDict.update(self._AllPcdDict)\r
726c501c 2020 ValueList[0] = ValueExpressionEx(ValueList[0], ValueList[1], self._GuidDict)(True)\r
5b0671c1 2021 except BadExpression as Value:\r
726c501c 2022 EdkLogger.error('Parser', FORMAT_INVALID, Value, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
ae7b6df8
LG
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
f51461c8 2047\r
ae7b6df8 2048 self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()\r
f51461c8
LG
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
0923aa1c 2063 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,\r
f51461c8
LG
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