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