]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/Workspace/MetaFileParser.py
BaseTools: refactor class properties
[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
fcb1af1b 24from hashlib import 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
f2cc33d8 1614 if self._ItemType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE):\r
1615 if ValList[1] != TAB_VOID and ValList[2]:\r
1616 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect. Only VOID* type PCD need the maxsize info.", File=self._FileWithError,\r
1617 Line=self._LineIndex + 1, ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))\r
47fea6af 1618 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self._FileWithError, Line=self._LineIndex + 1,\r
f51461c8
LG
1619 ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))\r
1620 PcdValue = ValList[Index]\r
ae7b6df8 1621 if PcdValue and "." not in self._ValueList[0]:\r
f51461c8
LG
1622 try:\r
1623 ValList[Index] = ValueExpression(PcdValue, self._Macros)(True)\r
5b0671c1 1624 except WrnExpression as Value:\r
f51461c8 1625 ValList[Index] = Value.result\r
35f613d9
YF
1626 except:\r
1627 pass\r
f51461c8
LG
1628\r
1629 if ValList[Index] == 'True':\r
1630 ValList[Index] = '1'\r
1631 if ValList[Index] == 'False':\r
1632 ValList[Index] = '0'\r
1633\r
22a99b87
YL
1634 if (not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack):\r
1635 GlobalData.gPlatformPcds[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue\r
1636 self._Symbols[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue\r
ae7b6df8
LG
1637 try:\r
1638 self._ValueList[2] = '|'.join(ValList)\r
1639 except Exception:\r
72443dd2 1640 print(ValList)\r
f51461c8
LG
1641\r
1642 def __ProcessComponent(self):\r
1643 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)\r
1644\r
1645 def __ProcessSourceOverridePath(self):\r
1646 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)\r
1647\r
1648 def __ProcessBuildOption(self):\r
1649 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False)\r
1650 for Value in self._ValueList]\r
1651\r
1652 _SectionParser = {\r
1653 MODEL_META_DATA_HEADER : _DefineParser,\r
1654 MODEL_EFI_SKU_ID : _SkuIdParser,\r
8518bf0b 1655 MODEL_EFI_DEFAULT_STORES : _DefaultStoresParser,\r
f51461c8
LG
1656 MODEL_EFI_LIBRARY_INSTANCE : _LibraryInstanceParser,\r
1657 MODEL_EFI_LIBRARY_CLASS : _LibraryClassParser,\r
1658 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,\r
1659 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,\r
1660 MODEL_PCD_FEATURE_FLAG : _PcdParser,\r
1661 MODEL_PCD_DYNAMIC_DEFAULT : _PcdParser,\r
1662 MODEL_PCD_DYNAMIC_HII : _PcdParser,\r
1663 MODEL_PCD_DYNAMIC_VPD : _PcdParser,\r
1664 MODEL_PCD_DYNAMIC_EX_DEFAULT : _PcdParser,\r
1665 MODEL_PCD_DYNAMIC_EX_HII : _PcdParser,\r
1666 MODEL_PCD_DYNAMIC_EX_VPD : _PcdParser,\r
1667 MODEL_META_DATA_COMPONENT : _ComponentParser,\r
1668 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : _CompponentSourceOverridePathParser,\r
1669 MODEL_META_DATA_BUILD_OPTION : _BuildOptionParser,\r
1670 MODEL_UNKNOWN : MetaFileParser._Skip,\r
0923aa1c 1671 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,\r
f51461c8
LG
1672 MODEL_META_DATA_SECTION_HEADER : MetaFileParser._SectionHeaderParser,\r
1673 MODEL_META_DATA_SUBSECTION_HEADER : _SubsectionHeaderParser,\r
1674 }\r
1675\r
1676 _Macros = property(_GetMacros)\r
1677\r
1678## DEC file parser class\r
1679#\r
1680# @param FilePath The path of platform description file\r
1681# @param FileType The raw data of DSC file\r
1682# @param Table Database used to retrieve module/package information\r
1683# @param Macros Macros used for replacement in file\r
1684#\r
1685class DecParser(MetaFileParser):\r
1686 # DEC file supported data types (one type per section)\r
1687 DataType = {\r
1688 TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER,\r
1689 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,\r
1690 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,\r
1691 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,\r
1692 TAB_GUIDS.upper() : MODEL_EFI_GUID,\r
1693 TAB_PPIS.upper() : MODEL_EFI_PPI,\r
1694 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,\r
1695 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,\r
1696 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,\r
1697 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,\r
1698 TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC,\r
1699 TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX,\r
0923aa1c 1700 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION,\r
f51461c8
LG
1701 }\r
1702\r
1703 ## Constructor of DecParser\r
1704 #\r
1705 # Initialize object of DecParser\r
1706 #\r
1707 # @param FilePath The path of platform description file\r
1708 # @param FileType The raw data of DSC file\r
cdd1b5e5 1709 # @param Arch Default Arch value for filtering sections\r
f51461c8 1710 # @param Table Database used to retrieve module/package information\r
f51461c8 1711 #\r
cdd1b5e5 1712 def __init__(self, FilePath, FileType, Arch, Table):\r
f51461c8
LG
1713 # prevent re-initialization\r
1714 if hasattr(self, "_Table"):\r
1715 return\r
cdd1b5e5 1716 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, -1)\r
f51461c8
LG
1717 self._Comments = []\r
1718 self._Version = 0x00010005 # Only EDK2 dec file is supported\r
1719 self._AllPCDs = [] # Only for check duplicate PCD\r
67e11e4d 1720 self._AllPcdDict = {}\r
f51461c8 1721\r
ae7b6df8
LG
1722 self._CurrentStructurePcdName = ""\r
1723 self._include_flag = False\r
1724 self._package_flag = False\r
1725\r
f51461c8
LG
1726 ## Parser starter\r
1727 def Start(self):\r
1728 Content = ''\r
1729 try:\r
1730 Content = open(str(self.MetaFile), 'r').readlines()\r
1731 except:\r
1732 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)\r
1733\r
778aad47 1734 self._DefinesCount = 0\r
f51461c8
LG
1735 for Index in range(0, len(Content)):\r
1736 Line, Comment = CleanString2(Content[Index])\r
1737 self._CurrentLine = Line\r
1738 self._LineIndex = Index\r
1739\r
1740 # save comment for later use\r
1741 if Comment:\r
1742 self._Comments.append((Comment, self._LineIndex + 1))\r
1743 # skip empty line\r
1744 if Line == '':\r
1745 continue\r
1746\r
1747 # section header\r
1748 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:\r
1749 self._SectionHeaderParser()\r
778aad47
YF
1750 if self._SectionName == TAB_DEC_DEFINES.upper():\r
1751 self._DefinesCount += 1\r
f51461c8
LG
1752 self._Comments = []\r
1753 continue\r
778aad47
YF
1754 if self._SectionType == MODEL_UNKNOWN:\r
1755 EdkLogger.error("Parser", FORMAT_INVALID,\r
1756 ""\r
1757 "Not able to determine \"%s\" in which section."%self._CurrentLine,\r
1758 self.MetaFile, self._LineIndex + 1)\r
f51461c8
LG
1759 elif len(self._SectionType) == 0:\r
1760 self._Comments = []\r
1761 continue\r
1762\r
1763 # section content\r
1764 self._ValueList = ['', '', '']\r
1765 self._SectionParser[self._SectionType[0]](self)\r
4231a819 1766 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:\r
f51461c8
LG
1767 self._ItemType = -1\r
1768 self._Comments = []\r
1769 continue\r
1770\r
1771 #\r
1772 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,\r
1773 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1\r
1774 #\r
1775 for Arch, ModuleType, Type in self._Scope:\r
1776 self._LastItem = self._Store(\r
1777 Type,\r
1778 self._ValueList[0],\r
1779 self._ValueList[1],\r
1780 self._ValueList[2],\r
1781 Arch,\r
1782 ModuleType,\r
1783 self._Owner[-1],\r
1784 self._LineIndex + 1,\r
1785 - 1,\r
1786 self._LineIndex + 1,\r
1787 - 1,\r
1788 0\r
1789 )\r
1790 for Comment, LineNo in self._Comments:\r
1791 self._Store(\r
1792 MODEL_META_DATA_COMMENT,\r
1793 Comment,\r
1794 self._ValueList[0],\r
1795 self._ValueList[1],\r
1796 Arch,\r
1797 ModuleType,\r
1798 self._LastItem,\r
1799 LineNo,\r
1800 - 1,\r
1801 LineNo,\r
1802 - 1,\r
1803 0\r
1804 )\r
1805 self._Comments = []\r
778aad47
YF
1806 if self._DefinesCount > 1:\r
1807 EdkLogger.error('Parser', FORMAT_INVALID, 'Multiple [Defines] section is exist.', self.MetaFile )\r
1808 if self._DefinesCount == 0:\r
ccaa7754 1809 EdkLogger.error('Parser', FORMAT_INVALID, 'No [Defines] section exist.', self.MetaFile)\r
f51461c8
LG
1810 self._Done()\r
1811\r
1812\r
1813 ## Section header parser\r
1814 #\r
1815 # The section header is always in following format:\r
1816 #\r
1817 # [section_name.arch<.platform|module_type>]\r
1818 #\r
1819 def _SectionHeaderParser(self):\r
1820 self._Scope = []\r
1821 self._SectionName = ''\r
1822 self._SectionType = []\r
1823 ArchList = set()\r
c28d2e10 1824 PrivateList = set()\r
07959205 1825 Line = re.sub(',[\s]*', TAB_COMMA_SPLIT, self._CurrentLine)\r
f51461c8
LG
1826 for Item in Line[1:-1].split(TAB_COMMA_SPLIT):\r
1827 if Item == '':\r
1828 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR,\r
1829 "section name can NOT be empty or incorrectly use separator comma",\r
1830 self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
1831 ItemList = Item.split(TAB_SPLIT)\r
1832\r
1833 # different types of PCD are permissible in one section\r
1834 self._SectionName = ItemList[0].upper()\r
778aad47
YF
1835 if self._SectionName == TAB_DEC_DEFINES.upper() and (len(ItemList) > 1 or len(Line.split(TAB_COMMA_SPLIT)) > 1):\r
1836 EdkLogger.error("Parser", FORMAT_INVALID, "Defines section format is invalid",\r
1837 self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
f51461c8
LG
1838 if self._SectionName in self.DataType:\r
1839 if self.DataType[self._SectionName] not in self._SectionType:\r
1840 self._SectionType.append(self.DataType[self._SectionName])\r
1841 else:\r
1842 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,\r
1843 self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
1844\r
1845 if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:\r
1846 EdkLogger.error(\r
1847 'Parser',\r
1848 FORMAT_INVALID,\r
1849 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,\r
1850 File=self.MetaFile,\r
1851 Line=self._LineIndex + 1,\r
1852 ExtraData=self._CurrentLine\r
1853 )\r
1854 # S1 is always Arch\r
1855 if len(ItemList) > 1:\r
1856 S1 = ItemList[1].upper()\r
1857 else:\r
55c84777 1858 S1 = TAB_ARCH_COMMON\r
f51461c8
LG
1859 ArchList.add(S1)\r
1860 # S2 may be Platform or ModuleType\r
1861 if len(ItemList) > 2:\r
1862 S2 = ItemList[2].upper()\r
c28d2e10
YZ
1863 # only Includes, GUIDs, PPIs, Protocols section have Private tag\r
1864 if self._SectionName in [TAB_INCLUDES.upper(), TAB_GUIDS.upper(), TAB_PROTOCOLS.upper(), TAB_PPIS.upper()]:\r
1865 if S2 != 'PRIVATE':\r
1866 EdkLogger.error("Parser", FORMAT_INVALID, 'Please use keyword "Private" as section tag modifier.',\r
1867 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
f51461c8 1868 else:\r
55c84777 1869 S2 = TAB_COMMON\r
c28d2e10 1870 PrivateList.add(S2)\r
f51461c8
LG
1871 if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:\r
1872 self._Scope.append([S1, S2, self.DataType[self._SectionName]])\r
1873\r
1874 # 'COMMON' must not be used with specific ARCHs at the same section\r
55c84777 1875 if TAB_ARCH_COMMON in ArchList and len(ArchList) > 1:\r
f51461c8
LG
1876 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",\r
1877 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
c28d2e10
YZ
1878\r
1879 # It is not permissible to mix section tags without the Private attribute with section tags with the Private attribute\r
55c84777 1880 if TAB_COMMON in PrivateList and len(PrivateList) > 1:\r
c28d2e10
YZ
1881 EdkLogger.error('Parser', FORMAT_INVALID, "Can't mix section tags without the Private attribute with section tags with the Private attribute",\r
1882 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
f51461c8
LG
1883\r
1884 ## [guids], [ppis] and [protocols] section parser\r
1885 @ParseMacro\r
1886 def _GuidParser(self):\r
1887 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
1888 if len(TokenList) < 2:\r
1889 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",\r
1890 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1891 File=self.MetaFile, Line=self._LineIndex + 1)\r
1892 if TokenList[0] == '':\r
1893 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",\r
1894 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1895 File=self.MetaFile, Line=self._LineIndex + 1)\r
1896 if TokenList[1] == '':\r
1897 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",\r
1898 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1899 File=self.MetaFile, Line=self._LineIndex + 1)\r
1900 if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':\r
1901 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",\r
1902 ExtraData=self._CurrentLine + \\r
1903 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",\r
1904 File=self.MetaFile, Line=self._LineIndex + 1)\r
1905 self._ValueList[0] = TokenList[0]\r
1906 self._ValueList[1] = TokenList[1]\r
726c501c
YZ
1907 if self._ValueList[0] not in self._GuidDict:\r
1908 self._GuidDict[self._ValueList[0]] = self._ValueList[1]\r
f51461c8
LG
1909\r
1910 ## PCD sections parser\r
1911 #\r
1912 # [PcdsFixedAtBuild]\r
1913 # [PcdsPatchableInModule]\r
1914 # [PcdsFeatureFlag]\r
1915 # [PcdsDynamicEx\r
1916 # [PcdsDynamic]\r
1917 #\r
1918 @ParseMacro\r
1919 def _PcdParser(self):\r
ae7b6df8
LG
1920 if self._CurrentStructurePcdName:\r
1921 self._ValueList[0] = self._CurrentStructurePcdName\r
1922\r
1923 if "|" not in self._CurrentLine:\r
1924 if "<HeaderFiles>" == self._CurrentLine:\r
1925 self._include_flag = True\r
81add864 1926 self._package_flag = False\r
ae7b6df8
LG
1927 self._ValueList = None\r
1928 return\r
1929 if "<Packages>" == self._CurrentLine:\r
1930 self._package_flag = True\r
1931 self._ValueList = None\r
81add864 1932 self._include_flag = False\r
ae7b6df8
LG
1933 return\r
1934\r
1935 if self._include_flag:\r
fcb1af1b 1936 self._ValueList[1] = "<HeaderFiles>_" + md5(self._CurrentLine).hexdigest()\r
ae7b6df8 1937 self._ValueList[2] = self._CurrentLine\r
ae7b6df8 1938 if self._package_flag and "}" != self._CurrentLine:\r
fcb1af1b 1939 self._ValueList[1] = "<Packages>_" + md5(self._CurrentLine).hexdigest()\r
ae7b6df8
LG
1940 self._ValueList[2] = self._CurrentLine\r
1941 if self._CurrentLine == "}":\r
1942 self._package_flag = False\r
81add864 1943 self._include_flag = False\r
ae7b6df8
LG
1944 self._ValueList = None\r
1945 return\r
1946 else:\r
1947 PcdTockens = self._CurrentLine.split(TAB_VALUE_SPLIT)\r
1948 PcdNames = PcdTockens[0].split(TAB_SPLIT)\r
1949 if len(PcdNames) == 2:\r
1950 self._CurrentStructurePcdName = ""\r
1951 else:\r
8e011d83 1952 if self._CurrentStructurePcdName != TAB_SPLIT.join(PcdNames[:2]):\r
ccaa7754 1953 EdkLogger.error('Parser', FORMAT_INVALID, "Pcd Name does not match: %s and %s " % (self._CurrentStructurePcdName, TAB_SPLIT.join(PcdNames[:2])),\r
8e011d83 1954 File=self.MetaFile, Line=self._LineIndex + 1)\r
a0939593 1955 self._ValueList[1] = TAB_SPLIT.join(PcdNames[2:])\r
ae7b6df8
LG
1956 self._ValueList[2] = PcdTockens[1]\r
1957 if not self._CurrentStructurePcdName:\r
1958 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
1959 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
1960 ValueRe = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*')\r
1961 # check PCD information\r
1962 if self._ValueList[0] == '' or self._ValueList[1] == '':\r
1963 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
1964 ExtraData=self._CurrentLine + \\r
1965 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1966 File=self.MetaFile, Line=self._LineIndex + 1)\r
1967 # check format of token space GUID CName\r
1968 if not ValueRe.match(self._ValueList[0]):\r
1969 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
1970 ExtraData=self._CurrentLine + \\r
1971 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1972 File=self.MetaFile, Line=self._LineIndex + 1)\r
1973 # check format of PCD CName\r
1974 if not ValueRe.match(self._ValueList[1]):\r
1975 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
1976 ExtraData=self._CurrentLine + \\r
1977 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1978 File=self.MetaFile, Line=self._LineIndex + 1)\r
1979 # check PCD datum information\r
1980 if len(TokenList) < 2 or TokenList[1] == '':\r
1981 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",\r
1982 ExtraData=self._CurrentLine + \\r
1983 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1984 File=self.MetaFile, Line=self._LineIndex + 1)\r
1985\r
1986\r
1987 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')\r
1988 PtrValue = ValueRe.findall(TokenList[1])\r
1989\r
1990 # Has VOID* type string, may contain "|" character in the string.\r
1991 if len(PtrValue) != 0:\r
1992 ptrValueList = re.sub(ValueRe, '', TokenList[1])\r
1993 ValueList = AnalyzePcdExpression(ptrValueList)\r
1994 ValueList[0] = PtrValue[0]\r
1995 else:\r
1996 ValueList = AnalyzePcdExpression(TokenList[1])\r
1997\r
1998\r
1999 # check if there's enough datum information given\r
2000 if len(ValueList) != 3:\r
2001 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",\r
2002 ExtraData=self._CurrentLine + \\r
2003 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2004 File=self.MetaFile, Line=self._LineIndex + 1)\r
2005 # check default value\r
2006 if ValueList[0] == '':\r
2007 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",\r
2008 ExtraData=self._CurrentLine + \\r
2009 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2010 File=self.MetaFile, Line=self._LineIndex + 1)\r
2011 # check datum type\r
2012 if ValueList[1] == '':\r
2013 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",\r
2014 ExtraData=self._CurrentLine + \\r
2015 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2016 File=self.MetaFile, Line=self._LineIndex + 1)\r
2017 # check token of the PCD\r
2018 if ValueList[2] == '':\r
2019 EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",\r
2020 ExtraData=self._CurrentLine + \\r
2021 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2022 File=self.MetaFile, Line=self._LineIndex + 1)\r
2023\r
2024 PcdValue = ValueList[0]\r
2025 if PcdValue:\r
726c501c 2026 try:\r
9efe8d60 2027 self._GuidDict.update(self._AllPcdDict)\r
726c501c 2028 ValueList[0] = ValueExpressionEx(ValueList[0], ValueList[1], self._GuidDict)(True)\r
5b0671c1 2029 except BadExpression as Value:\r
726c501c 2030 EdkLogger.error('Parser', FORMAT_INVALID, Value, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
ae7b6df8
LG
2031 # check format of default value against the datum type\r
2032 IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])\r
2033 if not IsValid:\r
2034 EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,\r
2035 File=self.MetaFile, Line=self._LineIndex + 1)\r
2036\r
2037 if Cause == "StructurePcd":\r
2038 self._CurrentStructurePcdName = TAB_SPLIT.join(self._ValueList[0:2])\r
2039 self._ValueList[0] = self._CurrentStructurePcdName\r
2040 self._ValueList[1] = ValueList[1].strip()\r
2041\r
2042 if ValueList[0] in ['True', 'true', 'TRUE']:\r
2043 ValueList[0] = '1'\r
2044 elif ValueList[0] in ['False', 'false', 'FALSE']:\r
2045 ValueList[0] = '0'\r
2046\r
2047 # check for duplicate PCD definition\r
2048 if (self._Scope[0], self._ValueList[0], self._ValueList[1]) in self._AllPCDs:\r
2049 EdkLogger.error('Parser', FORMAT_INVALID,\r
2050 "The same PCD name and GUID have been already defined",\r
2051 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
2052 else:\r
2053 self._AllPCDs.append((self._Scope[0], self._ValueList[0], self._ValueList[1]))\r
2054 self._AllPcdDict[TAB_SPLIT.join(self._ValueList[0:2])] = ValueList[0]\r
f51461c8 2055\r
ae7b6df8 2056 self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()\r
f51461c8
LG
2057\r
2058 _SectionParser = {\r
2059 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,\r
2060 MODEL_EFI_INCLUDE : MetaFileParser._PathParser,\r
2061 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,\r
2062 MODEL_EFI_GUID : _GuidParser,\r
2063 MODEL_EFI_PPI : _GuidParser,\r
2064 MODEL_EFI_PROTOCOL : _GuidParser,\r
2065 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,\r
2066 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,\r
2067 MODEL_PCD_FEATURE_FLAG : _PcdParser,\r
2068 MODEL_PCD_DYNAMIC : _PcdParser,\r
2069 MODEL_PCD_DYNAMIC_EX : _PcdParser,\r
2070 MODEL_UNKNOWN : MetaFileParser._Skip,\r
0923aa1c 2071 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,\r
f51461c8
LG
2072 }\r
2073\r
2074##\r
2075#\r
2076# This acts like the main() function for the script, unless it is 'import'ed into another\r
2077# script.\r
2078#\r
2079if __name__ == '__main__':\r
2080 pass\r
2081\r