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