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