]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/Workspace/MetaFileParser.py
MdeModulePkg/NonDiscoverablePciDevice: Remove the redundant check
[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
643556fc 209 self._Table.SetEndFlag()\r
f51461c8
LG
210\r
211 def _PostProcess(self):\r
212 self._PostProcessed = True\r
213\r
214 ## Get the parse complete flag\r
71cac3f7
CJ
215 @property\r
216 def Finished(self):\r
f51461c8
LG
217 return self._Finished\r
218\r
219 ## Set the complete flag\r
71cac3f7
CJ
220 @Finished.setter\r
221 def Finished(self, Value):\r
f51461c8
LG
222 self._Finished = Value\r
223\r
cdd1b5e5
TP
224 ## Remove records that do not match given Filter Arch\r
225 def _FilterRecordList(self, RecordList, FilterArch):\r
226 NewRecordList = []\r
227 for Record in RecordList:\r
228 Arch = Record[3]\r
55c84777 229 if Arch == TAB_ARCH_COMMON or Arch == FilterArch:\r
cdd1b5e5
TP
230 NewRecordList.append(Record)\r
231 return NewRecordList\r
232\r
f51461c8
LG
233 ## Use [] style to query data in table, just for readability\r
234 #\r
235 # DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]\r
236 #\r
237 def __getitem__(self, DataInfo):\r
0d1f5b2b 238 if not isinstance(DataInfo, type(())):\r
f51461c8
LG
239 DataInfo = (DataInfo,)\r
240\r
241 # Parse the file first, if necessary\r
643556fc 242 self.StartParse()\r
f51461c8
LG
243\r
244 # No specific ARCH or Platform given, use raw data\r
4231a819 245 if self._RawTable and (len(DataInfo) == 1 or DataInfo[1] is None):\r
cdd1b5e5 246 return self._FilterRecordList(self._RawTable.Query(*DataInfo), self._Arch)\r
f51461c8
LG
247\r
248 # Do post-process if necessary\r
249 if not self._PostProcessed:\r
250 self._PostProcess()\r
251\r
cdd1b5e5 252 return self._FilterRecordList(self._Table.Query(*DataInfo), DataInfo[1])\r
f51461c8 253\r
643556fc
FB
254 def StartParse(self):\r
255 if not self._Finished:\r
256 if self._RawTable.IsIntegrity():\r
257 self._Finished = True\r
258 else:\r
259 self._Table = self._RawTable\r
260 self._PostProcessed = False\r
261 self.Start()\r
f51461c8
LG
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
643556fc 920 self._Content = None\r
72a1d776 921\r
f51461c8
LG
922 ## Parser starter\r
923 def Start(self):\r
924 Content = ''\r
925 try:\r
926 Content = open(str(self.MetaFile), 'r').readlines()\r
927 except:\r
928 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)\r
929\r
930 OwnerId = {}\r
72a1d776 931\r
932 Content = self.ProcessMultipleLineCODEValue(Content)\r
933\r
f51461c8
LG
934 for Index in range(0, len(Content)):\r
935 Line = CleanString(Content[Index])\r
936 # skip empty line\r
937 if Line == '':\r
938 continue\r
939\r
940 self._CurrentLine = Line\r
941 self._LineIndex = Index\r
942 if self._InSubsection and self._Owner[-1] == -1:\r
943 self._Owner.append(self._LastItem)\r
944\r
945 # section header\r
946 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:\r
947 self._SectionType = MODEL_META_DATA_SECTION_HEADER\r
948 # subsection ending\r
949 elif Line[0] == '}' and self._InSubsection:\r
950 self._InSubsection = False\r
951 self._SubsectionType = MODEL_UNKNOWN\r
952 self._SubsectionName = ''\r
953 self._Owner[-1] = -1\r
50874612 954 OwnerId.clear()\r
f51461c8
LG
955 continue\r
956 # subsection header\r
957 elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:\r
958 self._SubsectionType = MODEL_META_DATA_SUBSECTION_HEADER\r
959 # directive line\r
960 elif Line[0] == '!':\r
cd7bd491
YF
961 TokenList = GetSplitValueList(Line, ' ', 1)\r
962 if TokenList[0] == TAB_INCLUDE:\r
963 for Arch, ModuleType, DefaultStore in self._Scope:\r
964 if self._SubsectionType != MODEL_UNKNOWN and Arch in OwnerId:\r
965 self._Owner[-1] = OwnerId[Arch]\r
966 self._DirectiveParser()\r
967 else:\r
968 self._DirectiveParser()\r
f51461c8 969 continue\r
d429fcd0 970 if Line[0] == TAB_OPTION_START and not self._InSubsection:\r
ccaa7754 971 EdkLogger.error("Parser", FILE_READ_FAILURE, "Missing the '{' before %s in Line %s" % (Line, Index+1), ExtraData=self.MetaFile)\r
f51461c8
LG
972\r
973 if self._InSubsection:\r
974 SectionType = self._SubsectionType\r
975 else:\r
976 SectionType = self._SectionType\r
977 self._ItemType = SectionType\r
978\r
979 self._ValueList = ['', '', '']\r
980 self._SectionParser[SectionType](self)\r
4231a819 981 if self._ValueList is None:\r
f51461c8
LG
982 continue\r
983 #\r
984 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,\r
985 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1\r
986 #\r
8518bf0b 987 for Arch, ModuleType, DefaultStore in self._Scope:\r
f51461c8 988 Owner = self._Owner[-1]\r
cd7bd491 989 if self._SubsectionType != MODEL_UNKNOWN and Arch in OwnerId:\r
f51461c8
LG
990 Owner = OwnerId[Arch]\r
991 self._LastItem = self._Store(\r
992 self._ItemType,\r
993 self._ValueList[0],\r
994 self._ValueList[1],\r
995 self._ValueList[2],\r
996 Arch,\r
997 ModuleType,\r
8518bf0b 998 DefaultStore,\r
f51461c8
LG
999 Owner,\r
1000 self._From,\r
1001 self._LineIndex + 1,\r
1002 - 1,\r
1003 self._LineIndex + 1,\r
1004 - 1,\r
1005 self._Enabled\r
1006 )\r
1007 if self._SubsectionType == MODEL_UNKNOWN and self._InSubsection:\r
1008 OwnerId[Arch] = self._LastItem\r
1009\r
1010 if self._DirectiveStack:\r
1011 Type, Line, Text = self._DirectiveStack[-1]\r
1012 EdkLogger.error('Parser', FORMAT_INVALID, "No matching '!endif' found",\r
1013 ExtraData=Text, File=self.MetaFile, Line=Line)\r
1014 self._Done()\r
1015\r
1016 ## <subsection_header> parser\r
1017 def _SubsectionHeaderParser(self):\r
1018 self._SubsectionName = self._CurrentLine[1:-1].upper()\r
1019 if self._SubsectionName in self.DataType:\r
1020 self._SubsectionType = self.DataType[self._SubsectionName]\r
1021 else:\r
1022 self._SubsectionType = MODEL_UNKNOWN\r
1023 EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile,\r
1024 Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
1025 self._ValueList[0] = self._SubsectionName\r
1026\r
1027 ## Directive statement parser\r
1028 def _DirectiveParser(self):\r
1029 self._ValueList = ['', '', '']\r
1030 TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)\r
1031 self._ValueList[0:len(TokenList)] = TokenList\r
1032\r
1033 # Syntax check\r
1034 DirectiveName = self._ValueList[0].upper()\r
1035 if DirectiveName not in self.DataType:\r
1036 EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName,\r
1037 File=self.MetaFile, Line=self._LineIndex + 1)\r
1038\r
1039 if DirectiveName in ['!IF', '!IFDEF', '!IFNDEF']:\r
1040 self._InDirective += 1\r
1041\r
1042 if DirectiveName in ['!ENDIF']:\r
1043 self._InDirective -= 1\r
1044\r
1045 if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '':\r
1046 EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression",\r
1047 File=self.MetaFile, Line=self._LineIndex + 1,\r
1048 ExtraData=self._CurrentLine)\r
1049\r
1050 ItemType = self.DataType[DirectiveName]\r
55c84777 1051 Scope = [[TAB_COMMON, TAB_COMMON, TAB_COMMON]]\r
f51461c8
LG
1052 if ItemType == MODEL_META_DATA_INCLUDE:\r
1053 Scope = self._Scope\r
09ef8e92
YF
1054 elif ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR:\r
1055 Scope = self._Scope\r
f51461c8
LG
1056 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:\r
1057 # Remove all directives between !if and !endif, including themselves\r
1058 while self._DirectiveStack:\r
1059 # Remove any !else or !elseif\r
1060 DirectiveInfo = self._DirectiveStack.pop()\r
1061 if DirectiveInfo[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1062 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
1063 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:\r
1064 break\r
1065 else:\r
1066 EdkLogger.error("Parser", FORMAT_INVALID, "Redundant '!endif'",\r
1067 File=self.MetaFile, Line=self._LineIndex + 1,\r
1068 ExtraData=self._CurrentLine)\r
09ef8e92 1069 elif ItemType not in {MODEL_META_DATA_INCLUDE, MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR}:\r
f51461c8
LG
1070 # Break if there's a !else is followed by a !elseif\r
1071 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF and \\r
1072 self._DirectiveStack and \\r
1073 self._DirectiveStack[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:\r
1074 EdkLogger.error("Parser", FORMAT_INVALID, "'!elseif' after '!else'",\r
1075 File=self.MetaFile, Line=self._LineIndex + 1,\r
1076 ExtraData=self._CurrentLine)\r
1077 self._DirectiveStack.append((ItemType, self._LineIndex + 1, self._CurrentLine))\r
f51461c8
LG
1078\r
1079 #\r
1080 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,\r
1081 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1\r
1082 #\r
8518bf0b 1083 for Arch, ModuleType, DefaultStore in Scope:\r
f51461c8
LG
1084 self._LastItem = self._Store(\r
1085 ItemType,\r
1086 self._ValueList[0],\r
1087 self._ValueList[1],\r
1088 self._ValueList[2],\r
1089 Arch,\r
1090 ModuleType,\r
8518bf0b 1091 DefaultStore,\r
f51461c8
LG
1092 self._Owner[-1],\r
1093 self._From,\r
1094 self._LineIndex + 1,\r
1095 - 1,\r
1096 self._LineIndex + 1,\r
1097 - 1,\r
1098 0\r
1099 )\r
1100\r
1101 ## [defines] section parser\r
1102 @ParseMacro\r
1103 def _DefineParser(self):\r
1104 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
1105 self._ValueList[1:len(TokenList)] = TokenList\r
1106\r
1107 # Syntax check\r
1108 if not self._ValueList[1]:\r
1109 EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",\r
1110 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1111 if not self._ValueList[2]:\r
1112 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",\r
1113 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
97fa0ee9
YL
1114 if (not self._ValueList[1] in self.DefineKeywords and\r
1115 (self._InSubsection and self._ValueList[1] not in self.SubSectionDefineKeywords)):\r
f51461c8
LG
1116 EdkLogger.error('Parser', FORMAT_INVALID,\r
1117 "Unknown keyword found: %s. "\r
1118 "If this is a macro you must "\r
1119 "add it as a DEFINE in the DSC" % self._ValueList[1],\r
1120 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
97fa0ee9
YL
1121 if not self._InSubsection:\r
1122 self._Defines[self._ValueList[1]] = self._ValueList[2]\r
f51461c8
LG
1123 self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]\r
1124\r
1125 @ParseMacro\r
1126 def _SkuIdParser(self):\r
8518bf0b 1127 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
ccaa7754 1128 if len(TokenList) not in (2, 3):\r
e6b10112 1129 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>[|<UiName>]'",\r
8518bf0b
LG
1130 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1131 self._ValueList[0:len(TokenList)] = TokenList\r
1132 @ParseMacro\r
1133 def _DefaultStoresParser(self):\r
f51461c8
LG
1134 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
1135 if len(TokenList) != 2:\r
767ddbe8 1136 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>'",\r
f51461c8
LG
1137 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1138 self._ValueList[0:len(TokenList)] = TokenList\r
1139\r
1140 ## Parse Edk style of library modules\r
1141 @ParseMacro\r
1142 def _LibraryInstanceParser(self):\r
1143 self._ValueList[0] = self._CurrentLine\r
1144\r
72a1d776 1145 def ProcessMultipleLineCODEValue(self,Content):\r
1146 CODEBegin = False\r
1147 CODELine = ""\r
1148 continuelinecount = 0\r
1149 newContent = []\r
1150 for Index in range(0, len(Content)):\r
1151 Line = Content[Index]\r
1152 if CODEBegin:\r
1153 CODELine = CODELine + Line\r
1154 continuelinecount +=1\r
1155 if ")}" in Line:\r
1156 newContent.append(CODELine)\r
1157 for _ in range(continuelinecount):\r
1158 newContent.append("")\r
1159 CODEBegin = False\r
1160 CODELine = ""\r
1161 continuelinecount = 0\r
1162 else:\r
1163 if not Line:\r
1164 newContent.append(Line)\r
1165 continue\r
1166 if "{CODE(" not in Line:\r
1167 newContent.append(Line)\r
1168 continue\r
1169 elif CODEPattern.findall(Line):\r
1170 newContent.append(Line)\r
1171 continue\r
1172 else:\r
1173 CODEBegin = True\r
1174 CODELine = Line\r
1175\r
1176 return newContent\r
1177\r
1178 def _DecodeCODEData(self):\r
1179 pass\r
f51461c8
LG
1180 ## PCD sections parser\r
1181 #\r
1182 # [PcdsFixedAtBuild]\r
1183 # [PcdsPatchableInModule]\r
1184 # [PcdsFeatureFlag]\r
1185 # [PcdsDynamicEx\r
1186 # [PcdsDynamicExDefault]\r
1187 # [PcdsDynamicExVpd]\r
1188 # [PcdsDynamicExHii]\r
1189 # [PcdsDynamic]\r
1190 # [PcdsDynamicDefault]\r
1191 # [PcdsDynamicVpd]\r
1192 # [PcdsDynamicHii]\r
1193 #\r
1194 @ParseMacro\r
1195 def _PcdParser(self):\r
72a1d776 1196 if self._PcdDataTypeCODE:\r
1197 self._PcdCodeValue = self._PcdCodeValue + "\n " + self._CurrentLine\r
1198 if self._CurrentLine.endswith(")}"):\r
1199 self._CurrentLine = "|".join((self._CurrentPcdName, self._PcdCodeValue))\r
1200 self._PcdDataTypeCODE = False\r
1201 self._PcdCodeValue = ""\r
1202 else:\r
1203 self._ValueList = None\r
1204 return\r
f51461c8 1205 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
72a1d776 1206 self._CurrentPcdName = TokenList[0]\r
48e89045 1207 if len(TokenList) == 2 and TokenList[1].strip().startswith("{CODE"):\r
72a1d776 1208 self._PcdDataTypeCODE = True\r
1209 self._PcdCodeValue = TokenList[1].strip()\r
1210\r
1211 if self._PcdDataTypeCODE:\r
1212 if self._CurrentLine.endswith(")}"):\r
1213 self._PcdDataTypeCODE = False\r
1214 self._PcdCodeValue = ""\r
1215 else:\r
1216 self._ValueList = None\r
1217 return\r
f51461c8 1218 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
ae7b6df8
LG
1219 PcdNameTockens = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
1220 if len(PcdNameTockens) == 2:\r
1221 self._ValueList[0], self._ValueList[1] = PcdNameTockens[0], PcdNameTockens[1]\r
1222 elif len(PcdNameTockens) == 3:\r
1223 self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), PcdNameTockens[2]\r
a0939593
LG
1224 elif len(PcdNameTockens) > 3:\r
1225 self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), ".".join(PcdNameTockens[2:])\r
f51461c8
LG
1226 if len(TokenList) == 2:\r
1227 self._ValueList[2] = TokenList[1]\r
1228 if self._ValueList[0] == '' or self._ValueList[1] == '':\r
1229 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
1230 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",\r
1231 File=self.MetaFile, Line=self._LineIndex + 1)\r
1232 if self._ValueList[2] == '':\r
1233 #\r
e651d06c 1234 # The PCD values are optional for FIXEDATBUILD, PATCHABLEINMODULE, Dynamic/DynamicEx default\r
f51461c8 1235 #\r
e651d06c 1236 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
1237 return\r
1238 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",\r
1239 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",\r
1240 File=self.MetaFile, Line=self._LineIndex + 1)\r
1241\r
1242 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD\r
1243 ValueList = GetSplitValueList(self._ValueList[2])\r
ccaa7754 1244 if len(ValueList) > 1 and ValueList[1] in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64] \\r
f51461c8
LG
1245 and self._ItemType in [MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT]:\r
1246 EdkLogger.error('Parser', FORMAT_INVALID, "The datum type '%s' of PCD is wrong" % ValueList[1],\r
1247 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1248\r
9f14de3b
YZ
1249 # Validate the VariableName of DynamicHii and DynamicExHii for PCD Entry must not be an empty string\r
1250 if self._ItemType in [MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII]:\r
1251 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)\r
ccaa7754 1252 if len(DscPcdValueList[0].replace('L', '').replace('"', '').strip()) == 0:\r
9f14de3b
YZ
1253 EdkLogger.error('Parser', FORMAT_INVALID, "The VariableName field in the HII format PCD entry must not be an empty string",\r
1254 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1255\r
f51461c8
LG
1256 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.\r
1257 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)\r
1258 if DscPcdValueList[0] in ['True', 'true', 'TRUE']:\r
1259 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1);\r
1260 elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:\r
1261 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);\r
1262\r
1263\r
1264 ## [components] section parser\r
1265 @ParseMacro\r
1266 def _ComponentParser(self):\r
1267 if self._CurrentLine[-1] == '{':\r
1268 self._ValueList[0] = self._CurrentLine[0:-1].strip()\r
1269 self._InSubsection = True\r
cd7bd491 1270 self._SubsectionType = MODEL_UNKNOWN\r
f51461c8
LG
1271 else:\r
1272 self._ValueList[0] = self._CurrentLine\r
1273\r
1274 ## [LibraryClasses] section\r
1275 @ParseMacro\r
1276 def _LibraryClassParser(self):\r
1277 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
1278 if len(TokenList) < 2:\r
1279 EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",\r
1280 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
1281 File=self.MetaFile, Line=self._LineIndex + 1)\r
1282 if TokenList[0] == '':\r
1283 EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",\r
1284 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
1285 File=self.MetaFile, Line=self._LineIndex + 1)\r
1286 if TokenList[1] == '':\r
1287 EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",\r
1288 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
1289 File=self.MetaFile, Line=self._LineIndex + 1)\r
1290\r
1291 self._ValueList[0:len(TokenList)] = TokenList\r
1292\r
1293 def _CompponentSourceOverridePathParser(self):\r
1294 self._ValueList[0] = self._CurrentLine\r
1295\r
1296 ## [BuildOptions] section parser\r
1297 @ParseMacro\r
1298 def _BuildOptionParser(self):\r
1299 self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)\r
1300 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
1301 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)\r
1302 if len(TokenList2) == 2:\r
1303 self._ValueList[0] = TokenList2[0] # toolchain family\r
1304 self._ValueList[1] = TokenList2[1] # keys\r
1305 else:\r
1306 self._ValueList[1] = TokenList[0]\r
1307 if len(TokenList) == 2: # value\r
1308 self._ValueList[2] = TokenList[1]\r
1309\r
1310 if self._ValueList[1].count('_') != 4:\r
1311 EdkLogger.error(\r
1312 'Parser',\r
1313 FORMAT_INVALID,\r
1314 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],\r
1315 ExtraData=self._CurrentLine,\r
1316 File=self.MetaFile,\r
1317 Line=self._LineIndex + 1\r
1318 )\r
1319\r
1320 ## Override parent's method since we'll do all macro replacements in parser\r
71cac3f7
CJ
1321 @property\r
1322 def _Macros(self):\r
f51461c8
LG
1323 Macros = {}\r
1324 Macros.update(self._FileLocalMacros)\r
1325 Macros.update(self._GetApplicableSectionMacro())\r
1326 Macros.update(GlobalData.gEdkGlobal)\r
1327 Macros.update(GlobalData.gPlatformDefines)\r
1328 Macros.update(GlobalData.gCommandLineDefines)\r
1329 # PCD cannot be referenced in macro definition\r
1330 if self._ItemType not in [MODEL_META_DATA_DEFINE, MODEL_META_DATA_GLOBAL_DEFINE]:\r
1331 Macros.update(self._Symbols)\r
1fa7fdf6
FY
1332 if GlobalData.BuildOptionPcd:\r
1333 for Item in GlobalData.BuildOptionPcd:\r
0d1f5b2b 1334 if isinstance(Item, tuple):\r
705ed563 1335 continue\r
1fa7fdf6 1336 PcdName, TmpValue = Item.split("=")\r
8565b582 1337 TmpValue = BuildOptionValue(TmpValue, self._GuidDict)\r
1fa7fdf6 1338 Macros[PcdName.strip()] = TmpValue\r
f51461c8
LG
1339 return Macros\r
1340\r
1341 def _PostProcess(self):\r
1342 Processer = {\r
1343 MODEL_META_DATA_SECTION_HEADER : self.__ProcessSectionHeader,\r
1344 MODEL_META_DATA_SUBSECTION_HEADER : self.__ProcessSubsectionHeader,\r
1345 MODEL_META_DATA_HEADER : self.__ProcessDefine,\r
1346 MODEL_META_DATA_DEFINE : self.__ProcessDefine,\r
1347 MODEL_META_DATA_GLOBAL_DEFINE : self.__ProcessDefine,\r
1348 MODEL_META_DATA_INCLUDE : self.__ProcessDirective,\r
1349 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF : self.__ProcessDirective,\r
1350 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE : self.__ProcessDirective,\r
1351 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF : self.__ProcessDirective,\r
1352 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF : self.__ProcessDirective,\r
1353 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF : self.__ProcessDirective,\r
1354 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF : self.__ProcessDirective,\r
1355 MODEL_EFI_SKU_ID : self.__ProcessSkuId,\r
8518bf0b 1356 MODEL_EFI_DEFAULT_STORES : self.__ProcessDefaultStores,\r
f51461c8
LG
1357 MODEL_EFI_LIBRARY_INSTANCE : self.__ProcessLibraryInstance,\r
1358 MODEL_EFI_LIBRARY_CLASS : self.__ProcessLibraryClass,\r
1359 MODEL_PCD_FIXED_AT_BUILD : self.__ProcessPcd,\r
1360 MODEL_PCD_PATCHABLE_IN_MODULE : self.__ProcessPcd,\r
1361 MODEL_PCD_FEATURE_FLAG : self.__ProcessPcd,\r
1362 MODEL_PCD_DYNAMIC_DEFAULT : self.__ProcessPcd,\r
1363 MODEL_PCD_DYNAMIC_HII : self.__ProcessPcd,\r
1364 MODEL_PCD_DYNAMIC_VPD : self.__ProcessPcd,\r
1365 MODEL_PCD_DYNAMIC_EX_DEFAULT : self.__ProcessPcd,\r
1366 MODEL_PCD_DYNAMIC_EX_HII : self.__ProcessPcd,\r
1367 MODEL_PCD_DYNAMIC_EX_VPD : self.__ProcessPcd,\r
1368 MODEL_META_DATA_COMPONENT : self.__ProcessComponent,\r
1369 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : self.__ProcessSourceOverridePath,\r
1370 MODEL_META_DATA_BUILD_OPTION : self.__ProcessBuildOption,\r
1371 MODEL_UNKNOWN : self._Skip,\r
0923aa1c 1372 MODEL_META_DATA_USER_EXTENSION : self._SkipUserExtension,\r
09ef8e92 1373 MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR : self._ProcessError,\r
f51461c8
LG
1374 }\r
1375\r
2f818ed0 1376 self._Table = MetaFileStorage(self._RawTable.DB, self.MetaFile, MODEL_FILE_DSC, True)\r
f51461c8
LG
1377 self._DirectiveStack = []\r
1378 self._DirectiveEvalStack = []\r
1379 self._FileWithError = self.MetaFile\r
1380 self._FileLocalMacros = {}\r
50874612 1381 self._SectionsMacroDict.clear()\r
f51461c8
LG
1382 GlobalData.gPlatformDefines = {}\r
1383\r
1384 # Get all macro and PCD which has straitforward value\r
1385 self.__RetrievePcdValue()\r
1386 self._Content = self._RawTable.GetAll()\r
1387 self._ContentIndex = 0\r
97fa0ee9 1388 self._InSubsection = False\r
f51461c8 1389 while self._ContentIndex < len(self._Content) :\r
ccaa7754 1390 Id, self._ItemType, V1, V2, V3, S1, S2, S3, Owner, self._From, \\r
f51461c8
LG
1391 LineStart, ColStart, LineEnd, ColEnd, Enabled = self._Content[self._ContentIndex]\r
1392\r
1393 if self._From < 0:\r
1394 self._FileWithError = self.MetaFile\r
1395\r
1396 self._ContentIndex += 1\r
1397\r
8518bf0b 1398 self._Scope = [[S1, S2, S3]]\r
f51461c8
LG
1399 #\r
1400 # For !include directive, handle it specially,\r
1401 # merge arch and module type in case of duplicate items\r
1402 #\r
1403 while self._ItemType == MODEL_META_DATA_INCLUDE:\r
1404 if self._ContentIndex >= len(self._Content):\r
1405 break\r
1406 Record = self._Content[self._ContentIndex]\r
8518bf0b 1407 if LineStart == Record[10] and LineEnd == Record[12]:\r
ccaa7754
GL
1408 if [Record[5], Record[6], Record[7]] not in self._Scope:\r
1409 self._Scope.append([Record[5], Record[6], Record[7]])\r
f51461c8
LG
1410 self._ContentIndex += 1\r
1411 else:\r
1412 break\r
1413\r
1414 self._LineIndex = LineStart - 1\r
1415 self._ValueList = [V1, V2, V3]\r
1416\r
97fa0ee9
YL
1417 if Owner > 0 and Owner in self._IdMapping:\r
1418 self._InSubsection = True\r
1419 else:\r
1420 self._InSubsection = False\r
f51461c8
LG
1421 try:\r
1422 Processer[self._ItemType]()\r
5b0671c1 1423 except EvaluationException as Excpt:\r
f7496d71 1424 #\r
f51461c8
LG
1425 # Only catch expression evaluation error here. We need to report\r
1426 # the precise number of line on which the error occurred\r
1427 #\r
1428 if hasattr(Excpt, 'Pcd'):\r
1429 if Excpt.Pcd in GlobalData.gPlatformOtherPcds:\r
1430 Info = GlobalData.gPlatformOtherPcds[Excpt.Pcd]\r
1431 EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"\r
1432 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"\r
1433 " of the DSC file, and it is currently defined in this section:"\r
1434 " %s, line #: %d." % (Excpt.Pcd, Info[0], Info[1]),\r
1435 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1436 Line=self._LineIndex + 1)\r
1437 else:\r
1438 EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,\r
1439 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1440 Line=self._LineIndex + 1)\r
1441 else:\r
1442 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),\r
1443 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1444 Line=self._LineIndex + 1)\r
5b0671c1 1445 except MacroException as Excpt:\r
f51461c8
LG
1446 EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt),\r
1447 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1448 Line=self._LineIndex + 1)\r
1449\r
4231a819 1450 if self._ValueList is None:\r
f51461c8
LG
1451 continue\r
1452\r
1453 NewOwner = self._IdMapping.get(Owner, -1)\r
1454 self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack))\r
1455 self._LastItem = self._Store(\r
1456 self._ItemType,\r
1457 self._ValueList[0],\r
1458 self._ValueList[1],\r
1459 self._ValueList[2],\r
1460 S1,\r
1461 S2,\r
8518bf0b 1462 S3,\r
f51461c8
LG
1463 NewOwner,\r
1464 self._From,\r
1465 self._LineIndex + 1,\r
1466 - 1,\r
1467 self._LineIndex + 1,\r
1468 - 1,\r
1469 self._Enabled\r
1470 )\r
1471 self._IdMapping[Id] = self._LastItem\r
1472\r
1473 GlobalData.gPlatformDefines.update(self._FileLocalMacros)\r
1474 self._PostProcessed = True\r
1475 self._Content = None\r
09ef8e92
YF
1476 def _ProcessError(self):\r
1477 if not self._Enabled:\r
1478 return\r
1479 EdkLogger.error('Parser', ERROR_STATEMENT, self._ValueList[1], File=self.MetaFile, Line=self._LineIndex + 1)\r
f51461c8
LG
1480\r
1481 def __ProcessSectionHeader(self):\r
1482 self._SectionName = self._ValueList[0]\r
1483 if self._SectionName in self.DataType:\r
1484 self._SectionType = self.DataType[self._SectionName]\r
1485 else:\r
1486 self._SectionType = MODEL_UNKNOWN\r
1487\r
1488 def __ProcessSubsectionHeader(self):\r
1489 self._SubsectionName = self._ValueList[0]\r
1490 if self._SubsectionName in self.DataType:\r
1491 self._SubsectionType = self.DataType[self._SubsectionName]\r
1492 else:\r
1493 self._SubsectionType = MODEL_UNKNOWN\r
1494\r
1495 def __RetrievePcdValue(self):\r
f51461c8
LG
1496 Content = open(str(self.MetaFile), 'r').readlines()\r
1497 GlobalData.gPlatformOtherPcds['DSCFILE'] = str(self.MetaFile)\r
1498 for PcdType in (MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_HII,\r
1499 MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_DYNAMIC_EX_HII,\r
1500 MODEL_PCD_DYNAMIC_EX_VPD):\r
1501 Records = self._RawTable.Query(PcdType, BelongsToItem= -1.0)\r
ccaa7754 1502 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, Dummy4, ID, Line in Records:\r
f51461c8
LG
1503 Name = TokenSpaceGuid + '.' + PcdName\r
1504 if Name not in GlobalData.gPlatformOtherPcds:\r
1505 PcdLine = Line\r
1506 while not Content[Line - 1].lstrip().startswith(TAB_SECTION_START):\r
1507 Line -= 1\r
1508 GlobalData.gPlatformOtherPcds[Name] = (CleanString(Content[Line - 1]), PcdLine, PcdType)\r
1509\r
1510 def __ProcessDefine(self):\r
1511 if not self._Enabled:\r
1512 return\r
1513\r
1514 Type, Name, Value = self._ValueList\r
1515 Value = ReplaceMacro(Value, self._Macros, False)\r
97fa0ee9
YL
1516 #\r
1517 # If it is <Defines>, return\r
1518 #\r
1519 if self._InSubsection:\r
1520 self._ValueList = [Type, Name, Value]\r
1521 return\r
1522\r
f51461c8
LG
1523 if self._ItemType == MODEL_META_DATA_DEFINE:\r
1524 if self._SectionType == MODEL_META_DATA_HEADER:\r
1525 self._FileLocalMacros[Name] = Value\r
1526 else:\r
1527 self._ConstructSectionMacroDict(Name, Value)\r
1528 elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE:\r
1529 GlobalData.gEdkGlobal[Name] = Value\r
1530\r
1531 #\r
1532 # Keyword in [Defines] section can be used as Macros\r
1533 #\r
1534 if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER):\r
1535 self._FileLocalMacros[Name] = Value\r
1536\r
1537 self._ValueList = [Type, Name, Value]\r
1538\r
1539 def __ProcessDirective(self):\r
1540 Result = None\r
1541 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1542 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF]:\r
1543 Macros = self._Macros\r
1544 Macros.update(GlobalData.gGlobalDefines)\r
1545 try:\r
1546 Result = ValueExpression(self._ValueList[1], Macros)()\r
5b0671c1 1547 except SymbolNotFound as Exc:\r
f51461c8
LG
1548 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])\r
1549 Result = False\r
5b0671c1 1550 except WrnExpression as Excpt:\r
f7496d71 1551 #\r
f51461c8
LG
1552 # Catch expression evaluation warning here. We need to report\r
1553 # the precise number of line and return the evaluation result\r
1554 #\r
1555 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),\r
1556 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1557 Line=self._LineIndex + 1)\r
1558 Result = Excpt.result\r
1559\r
1560 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1561 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
1562 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:\r
1563 self._DirectiveStack.append(self._ItemType)\r
1564 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF:\r
1565 Result = bool(Result)\r
1566 else:\r
1567 Macro = self._ValueList[1]\r
1568 Macro = Macro[2:-1] if (Macro.startswith("$(") and Macro.endswith(")")) else Macro\r
1569 Result = Macro in self._Macros\r
1570 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF:\r
1571 Result = not Result\r
1572 self._DirectiveEvalStack.append(Result)\r
1573 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF:\r
1574 self._DirectiveStack.append(self._ItemType)\r
1575 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]\r
1576 self._DirectiveEvalStack.append(bool(Result))\r
1577 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:\r
1578 self._DirectiveStack.append(self._ItemType)\r
1579 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]\r
1580 self._DirectiveEvalStack.append(True)\r
1581 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:\r
1582 # Back to the nearest !if/!ifdef/!ifndef\r
1583 while self._DirectiveStack:\r
1584 self._DirectiveEvalStack.pop()\r
1585 Directive = self._DirectiveStack.pop()\r
1586 if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1587 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
1588 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:\r
1589 break\r
1590 elif self._ItemType == MODEL_META_DATA_INCLUDE:\r
1591 # The included file must be relative to workspace or same directory as DSC file\r
1592 __IncludeMacros = {}\r
1593 #\r
1594 # Allow using system environment variables in path after !include\r
1595 #\r
1596 __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE']\r
9eb87141 1597 if "ECP_SOURCE" in GlobalData.gGlobalDefines:\r
f51461c8
LG
1598 __IncludeMacros['ECP_SOURCE'] = GlobalData.gGlobalDefines['ECP_SOURCE']\r
1599 #\r
1600 # During GenFds phase call DSC parser, will go into this branch.\r
1601 #\r
9eb87141 1602 elif "ECP_SOURCE" in GlobalData.gCommandLineDefines:\r
f51461c8
LG
1603 __IncludeMacros['ECP_SOURCE'] = GlobalData.gCommandLineDefines['ECP_SOURCE']\r
1604\r
1605 __IncludeMacros['EFI_SOURCE'] = GlobalData.gGlobalDefines['EFI_SOURCE']\r
1606 __IncludeMacros['EDK_SOURCE'] = GlobalData.gGlobalDefines['EDK_SOURCE']\r
1607 #\r
f7496d71 1608 # Allow using MACROs comes from [Defines] section to keep compatible.\r
f51461c8
LG
1609 #\r
1610 __IncludeMacros.update(self._Macros)\r
1611\r
1612 IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True))\r
1613 #\r
1614 # First search the include file under the same directory as DSC file\r
1615 #\r
1616 IncludedFile1 = PathClass(IncludedFile, self.MetaFile.Dir)\r
1617 ErrorCode, ErrorInfo1 = IncludedFile1.Validate()\r
1618 if ErrorCode != 0:\r
1619 #\r
1620 # Also search file under the WORKSPACE directory\r
1621 #\r
1622 IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)\r
1623 ErrorCode, ErrorInfo2 = IncludedFile1.Validate()\r
1624 if ErrorCode != 0:\r
1625 EdkLogger.error('parser', ErrorCode, File=self._FileWithError,\r
1626 Line=self._LineIndex + 1, ExtraData=ErrorInfo1 + "\n" + ErrorInfo2)\r
1627\r
1628 self._FileWithError = IncludedFile1\r
1629\r
33787826 1630 FromItem = self._Content[self._ContentIndex - 1][0]\r
a802b269 1631 if self._InSubsection:\r
33787826
YF
1632 Owner = self._Content[self._ContentIndex - 1][8]\r
1633 else:\r
1634 Owner = self._Content[self._ContentIndex - 1][0]\r
2f818ed0 1635 IncludedFileTable = MetaFileStorage(self._RawTable.DB, IncludedFile1, MODEL_FILE_DSC, False, FromItem=FromItem)\r
cdd1b5e5 1636 Parser = DscParser(IncludedFile1, self._FileType, self._Arch, IncludedFileTable,\r
33787826 1637 Owner=Owner, From=FromItem)\r
f51461c8 1638\r
c17956e0
DL
1639 self.IncludedFiles.add (IncludedFile1)\r
1640\r
f51461c8
LG
1641 # set the parser status with current status\r
1642 Parser._SectionName = self._SectionName\r
cd7bd491
YF
1643 Parser._SubsectionType = self._SubsectionType\r
1644 Parser._InSubsection = self._InSubsection\r
1645 Parser._SectionType = self._SectionType\r
f51461c8
LG
1646 Parser._Scope = self._Scope\r
1647 Parser._Enabled = self._Enabled\r
1648 # Parse the included file\r
643556fc 1649 Parser.StartParse()\r
f51461c8
LG
1650 # Insert all records in the table for the included file into dsc file table\r
1651 Records = IncludedFileTable.GetAll()\r
1652 if Records:\r
1653 self._Content[self._ContentIndex:self._ContentIndex] = Records\r
1654 self._Content.pop(self._ContentIndex - 1)\r
1655 self._ValueList = None\r
1656 self._ContentIndex -= 1\r
1657\r
1658 def __ProcessSkuId(self):\r
1659 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)\r
1660 for Value in self._ValueList]\r
8518bf0b
LG
1661 def __ProcessDefaultStores(self):\r
1662 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)\r
1663 for Value in self._ValueList]\r
f51461c8
LG
1664\r
1665 def __ProcessLibraryInstance(self):\r
1666 self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]\r
1667\r
1668 def __ProcessLibraryClass(self):\r
1669 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True)\r
1670\r
1671 def __ProcessPcd(self):\r
1672 if self._ItemType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:\r
1673 self._ValueList[2] = ReplaceMacro(self._ValueList[2], self._Macros, RaiseError=True)\r
1674 return\r
1675\r
1676 ValList, Valid, Index = AnalyzeDscPcd(self._ValueList[2], self._ItemType)\r
1677 if not Valid:\r
f2cc33d8 1678 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
1679 if ValList[1] != TAB_VOID and StructPattern.match(ValList[1]) is None and ValList[2]:\r
1680 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 1681 Line=self._LineIndex + 1, ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))\r
47fea6af 1682 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self._FileWithError, Line=self._LineIndex + 1,\r
f51461c8
LG
1683 ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))\r
1684 PcdValue = ValList[Index]\r
ae7b6df8 1685 if PcdValue and "." not in self._ValueList[0]:\r
f51461c8
LG
1686 try:\r
1687 ValList[Index] = ValueExpression(PcdValue, self._Macros)(True)\r
5b0671c1 1688 except WrnExpression as Value:\r
f51461c8 1689 ValList[Index] = Value.result\r
35f613d9
YF
1690 except:\r
1691 pass\r
f51461c8
LG
1692\r
1693 if ValList[Index] == 'True':\r
1694 ValList[Index] = '1'\r
1695 if ValList[Index] == 'False':\r
1696 ValList[Index] = '0'\r
1697\r
22a99b87
YL
1698 if (not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack):\r
1699 GlobalData.gPlatformPcds[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue\r
1700 self._Symbols[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue\r
ae7b6df8
LG
1701 try:\r
1702 self._ValueList[2] = '|'.join(ValList)\r
1703 except Exception:\r
72443dd2 1704 print(ValList)\r
f51461c8
LG
1705\r
1706 def __ProcessComponent(self):\r
1707 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)\r
1708\r
1709 def __ProcessSourceOverridePath(self):\r
1710 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)\r
1711\r
1712 def __ProcessBuildOption(self):\r
1713 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False)\r
1714 for Value in self._ValueList]\r
1715\r
1716 _SectionParser = {\r
1717 MODEL_META_DATA_HEADER : _DefineParser,\r
1718 MODEL_EFI_SKU_ID : _SkuIdParser,\r
8518bf0b 1719 MODEL_EFI_DEFAULT_STORES : _DefaultStoresParser,\r
f51461c8
LG
1720 MODEL_EFI_LIBRARY_INSTANCE : _LibraryInstanceParser,\r
1721 MODEL_EFI_LIBRARY_CLASS : _LibraryClassParser,\r
1722 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,\r
1723 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,\r
1724 MODEL_PCD_FEATURE_FLAG : _PcdParser,\r
1725 MODEL_PCD_DYNAMIC_DEFAULT : _PcdParser,\r
1726 MODEL_PCD_DYNAMIC_HII : _PcdParser,\r
1727 MODEL_PCD_DYNAMIC_VPD : _PcdParser,\r
1728 MODEL_PCD_DYNAMIC_EX_DEFAULT : _PcdParser,\r
1729 MODEL_PCD_DYNAMIC_EX_HII : _PcdParser,\r
1730 MODEL_PCD_DYNAMIC_EX_VPD : _PcdParser,\r
1731 MODEL_META_DATA_COMPONENT : _ComponentParser,\r
1732 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : _CompponentSourceOverridePathParser,\r
1733 MODEL_META_DATA_BUILD_OPTION : _BuildOptionParser,\r
1734 MODEL_UNKNOWN : MetaFileParser._Skip,\r
0923aa1c 1735 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,\r
f51461c8
LG
1736 MODEL_META_DATA_SECTION_HEADER : MetaFileParser._SectionHeaderParser,\r
1737 MODEL_META_DATA_SUBSECTION_HEADER : _SubsectionHeaderParser,\r
1738 }\r
1739\r
f51461c8
LG
1740## DEC file parser class\r
1741#\r
1742# @param FilePath The path of platform description file\r
1743# @param FileType The raw data of DSC file\r
1744# @param Table Database used to retrieve module/package information\r
1745# @param Macros Macros used for replacement in file\r
1746#\r
1747class DecParser(MetaFileParser):\r
1748 # DEC file supported data types (one type per section)\r
1749 DataType = {\r
1750 TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER,\r
1751 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,\r
1752 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,\r
1753 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,\r
1754 TAB_GUIDS.upper() : MODEL_EFI_GUID,\r
1755 TAB_PPIS.upper() : MODEL_EFI_PPI,\r
1756 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,\r
1757 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,\r
1758 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,\r
1759 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,\r
1760 TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC,\r
1761 TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX,\r
0923aa1c 1762 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION,\r
f51461c8
LG
1763 }\r
1764\r
1765 ## Constructor of DecParser\r
1766 #\r
1767 # Initialize object of DecParser\r
1768 #\r
1769 # @param FilePath The path of platform description file\r
1770 # @param FileType The raw data of DSC file\r
cdd1b5e5 1771 # @param Arch Default Arch value for filtering sections\r
f51461c8 1772 # @param Table Database used to retrieve module/package information\r
f51461c8 1773 #\r
cdd1b5e5 1774 def __init__(self, FilePath, FileType, Arch, Table):\r
f51461c8
LG
1775 # prevent re-initialization\r
1776 if hasattr(self, "_Table"):\r
1777 return\r
cdd1b5e5 1778 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, -1)\r
f51461c8
LG
1779 self._Comments = []\r
1780 self._Version = 0x00010005 # Only EDK2 dec file is supported\r
1781 self._AllPCDs = [] # Only for check duplicate PCD\r
67e11e4d 1782 self._AllPcdDict = {}\r
f51461c8 1783\r
ae7b6df8
LG
1784 self._CurrentStructurePcdName = ""\r
1785 self._include_flag = False\r
1786 self._package_flag = False\r
1787\r
f51461c8
LG
1788 ## Parser starter\r
1789 def Start(self):\r
1790 Content = ''\r
1791 try:\r
1792 Content = open(str(self.MetaFile), 'r').readlines()\r
1793 except:\r
1794 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)\r
1795\r
778aad47 1796 self._DefinesCount = 0\r
f51461c8
LG
1797 for Index in range(0, len(Content)):\r
1798 Line, Comment = CleanString2(Content[Index])\r
1799 self._CurrentLine = Line\r
1800 self._LineIndex = Index\r
1801\r
1802 # save comment for later use\r
1803 if Comment:\r
1804 self._Comments.append((Comment, self._LineIndex + 1))\r
1805 # skip empty line\r
1806 if Line == '':\r
1807 continue\r
1808\r
1809 # section header\r
1810 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:\r
1811 self._SectionHeaderParser()\r
778aad47
YF
1812 if self._SectionName == TAB_DEC_DEFINES.upper():\r
1813 self._DefinesCount += 1\r
f51461c8
LG
1814 self._Comments = []\r
1815 continue\r
778aad47
YF
1816 if self._SectionType == MODEL_UNKNOWN:\r
1817 EdkLogger.error("Parser", FORMAT_INVALID,\r
1818 ""\r
1819 "Not able to determine \"%s\" in which section."%self._CurrentLine,\r
1820 self.MetaFile, self._LineIndex + 1)\r
f51461c8
LG
1821 elif len(self._SectionType) == 0:\r
1822 self._Comments = []\r
1823 continue\r
1824\r
1825 # section content\r
1826 self._ValueList = ['', '', '']\r
1827 self._SectionParser[self._SectionType[0]](self)\r
4231a819 1828 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:\r
f51461c8
LG
1829 self._ItemType = -1\r
1830 self._Comments = []\r
1831 continue\r
1832\r
1833 #\r
1834 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,\r
1835 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1\r
1836 #\r
1837 for Arch, ModuleType, Type in self._Scope:\r
1838 self._LastItem = self._Store(\r
1839 Type,\r
1840 self._ValueList[0],\r
1841 self._ValueList[1],\r
1842 self._ValueList[2],\r
1843 Arch,\r
1844 ModuleType,\r
1845 self._Owner[-1],\r
1846 self._LineIndex + 1,\r
1847 - 1,\r
1848 self._LineIndex + 1,\r
1849 - 1,\r
1850 0\r
1851 )\r
1852 for Comment, LineNo in self._Comments:\r
1853 self._Store(\r
1854 MODEL_META_DATA_COMMENT,\r
1855 Comment,\r
1856 self._ValueList[0],\r
1857 self._ValueList[1],\r
1858 Arch,\r
1859 ModuleType,\r
1860 self._LastItem,\r
1861 LineNo,\r
1862 - 1,\r
1863 LineNo,\r
1864 - 1,\r
1865 0\r
1866 )\r
1867 self._Comments = []\r
778aad47
YF
1868 if self._DefinesCount > 1:\r
1869 EdkLogger.error('Parser', FORMAT_INVALID, 'Multiple [Defines] section is exist.', self.MetaFile )\r
1870 if self._DefinesCount == 0:\r
ccaa7754 1871 EdkLogger.error('Parser', FORMAT_INVALID, 'No [Defines] section exist.', self.MetaFile)\r
f51461c8
LG
1872 self._Done()\r
1873\r
1874\r
1875 ## Section header parser\r
1876 #\r
1877 # The section header is always in following format:\r
1878 #\r
1879 # [section_name.arch<.platform|module_type>]\r
1880 #\r
1881 def _SectionHeaderParser(self):\r
1882 self._Scope = []\r
1883 self._SectionName = ''\r
1884 self._SectionType = []\r
1885 ArchList = set()\r
c28d2e10 1886 PrivateList = set()\r
07959205 1887 Line = re.sub(',[\s]*', TAB_COMMA_SPLIT, self._CurrentLine)\r
f51461c8
LG
1888 for Item in Line[1:-1].split(TAB_COMMA_SPLIT):\r
1889 if Item == '':\r
1890 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR,\r
1891 "section name can NOT be empty or incorrectly use separator comma",\r
1892 self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
1893 ItemList = Item.split(TAB_SPLIT)\r
1894\r
1895 # different types of PCD are permissible in one section\r
1896 self._SectionName = ItemList[0].upper()\r
778aad47
YF
1897 if self._SectionName == TAB_DEC_DEFINES.upper() and (len(ItemList) > 1 or len(Line.split(TAB_COMMA_SPLIT)) > 1):\r
1898 EdkLogger.error("Parser", FORMAT_INVALID, "Defines section format is invalid",\r
1899 self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
f51461c8
LG
1900 if self._SectionName in self.DataType:\r
1901 if self.DataType[self._SectionName] not in self._SectionType:\r
1902 self._SectionType.append(self.DataType[self._SectionName])\r
1903 else:\r
1904 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,\r
1905 self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
1906\r
1907 if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:\r
1908 EdkLogger.error(\r
1909 'Parser',\r
1910 FORMAT_INVALID,\r
1911 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,\r
1912 File=self.MetaFile,\r
1913 Line=self._LineIndex + 1,\r
1914 ExtraData=self._CurrentLine\r
1915 )\r
1916 # S1 is always Arch\r
1917 if len(ItemList) > 1:\r
1918 S1 = ItemList[1].upper()\r
1919 else:\r
55c84777 1920 S1 = TAB_ARCH_COMMON\r
f51461c8
LG
1921 ArchList.add(S1)\r
1922 # S2 may be Platform or ModuleType\r
1923 if len(ItemList) > 2:\r
1924 S2 = ItemList[2].upper()\r
c28d2e10
YZ
1925 # only Includes, GUIDs, PPIs, Protocols section have Private tag\r
1926 if self._SectionName in [TAB_INCLUDES.upper(), TAB_GUIDS.upper(), TAB_PROTOCOLS.upper(), TAB_PPIS.upper()]:\r
1927 if S2 != 'PRIVATE':\r
1928 EdkLogger.error("Parser", FORMAT_INVALID, 'Please use keyword "Private" as section tag modifier.',\r
1929 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
f51461c8 1930 else:\r
55c84777 1931 S2 = TAB_COMMON\r
c28d2e10 1932 PrivateList.add(S2)\r
f51461c8
LG
1933 if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:\r
1934 self._Scope.append([S1, S2, self.DataType[self._SectionName]])\r
1935\r
1936 # 'COMMON' must not be used with specific ARCHs at the same section\r
55c84777 1937 if TAB_ARCH_COMMON in ArchList and len(ArchList) > 1:\r
f51461c8
LG
1938 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",\r
1939 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
c28d2e10
YZ
1940\r
1941 # It is not permissible to mix section tags without the Private attribute with section tags with the Private attribute\r
55c84777 1942 if TAB_COMMON in PrivateList and len(PrivateList) > 1:\r
c28d2e10
YZ
1943 EdkLogger.error('Parser', FORMAT_INVALID, "Can't mix section tags without the Private attribute with section tags with the Private attribute",\r
1944 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
f51461c8
LG
1945\r
1946 ## [guids], [ppis] and [protocols] section parser\r
1947 @ParseMacro\r
1948 def _GuidParser(self):\r
1949 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
1950 if len(TokenList) < 2:\r
1951 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",\r
1952 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1953 File=self.MetaFile, Line=self._LineIndex + 1)\r
1954 if TokenList[0] == '':\r
1955 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",\r
1956 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1957 File=self.MetaFile, Line=self._LineIndex + 1)\r
1958 if TokenList[1] == '':\r
1959 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",\r
1960 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1961 File=self.MetaFile, Line=self._LineIndex + 1)\r
1962 if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':\r
1963 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",\r
1964 ExtraData=self._CurrentLine + \\r
1965 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",\r
1966 File=self.MetaFile, Line=self._LineIndex + 1)\r
1967 self._ValueList[0] = TokenList[0]\r
1968 self._ValueList[1] = TokenList[1]\r
726c501c
YZ
1969 if self._ValueList[0] not in self._GuidDict:\r
1970 self._GuidDict[self._ValueList[0]] = self._ValueList[1]\r
f51461c8 1971\r
72a1d776 1972 def ParsePcdName(self,namelist):\r
1973 if "[" in namelist[1]:\r
1974 pcdname = namelist[1][:namelist[1].index("[")]\r
1975 arrayindex = namelist[1][namelist[1].index("["):]\r
1976 namelist[1] = pcdname\r
1977 if len(namelist) == 2:\r
1978 namelist.append(arrayindex)\r
1979 else:\r
1980 namelist[2] = ".".join((arrayindex,namelist[2]))\r
1981 return namelist\r
1982\r
f51461c8
LG
1983 ## PCD sections parser\r
1984 #\r
1985 # [PcdsFixedAtBuild]\r
1986 # [PcdsPatchableInModule]\r
1987 # [PcdsFeatureFlag]\r
1988 # [PcdsDynamicEx\r
1989 # [PcdsDynamic]\r
1990 #\r
1991 @ParseMacro\r
1992 def _PcdParser(self):\r
ae7b6df8
LG
1993 if self._CurrentStructurePcdName:\r
1994 self._ValueList[0] = self._CurrentStructurePcdName\r
1995\r
1996 if "|" not in self._CurrentLine:\r
1997 if "<HeaderFiles>" == self._CurrentLine:\r
1998 self._include_flag = True\r
81add864 1999 self._package_flag = False\r
ae7b6df8
LG
2000 self._ValueList = None\r
2001 return\r
2002 if "<Packages>" == self._CurrentLine:\r
2003 self._package_flag = True\r
2004 self._ValueList = None\r
81add864 2005 self._include_flag = False\r
ae7b6df8
LG
2006 return\r
2007\r
2008 if self._include_flag:\r
1ccc4d89 2009 self._ValueList[1] = "<HeaderFiles>_" + md5(self._CurrentLine).hexdigest()\r
ae7b6df8 2010 self._ValueList[2] = self._CurrentLine\r
ae7b6df8 2011 if self._package_flag and "}" != self._CurrentLine:\r
1ccc4d89 2012 self._ValueList[1] = "<Packages>_" + md5(self._CurrentLine).hexdigest()\r
ae7b6df8
LG
2013 self._ValueList[2] = self._CurrentLine\r
2014 if self._CurrentLine == "}":\r
2015 self._package_flag = False\r
81add864 2016 self._include_flag = False\r
ae7b6df8
LG
2017 self._ValueList = None\r
2018 return\r
2019 else:\r
2020 PcdTockens = self._CurrentLine.split(TAB_VALUE_SPLIT)\r
72a1d776 2021 PcdNames = self.ParsePcdName(PcdTockens[0].split(TAB_SPLIT))\r
ae7b6df8 2022 if len(PcdNames) == 2:\r
72a1d776 2023 if PcdNames[1].strip().endswith("]"):\r
2024 PcdName = PcdNames[1][:PcdNames[1].index('[')]\r
2025 Index = PcdNames[1][PcdNames[1].index('['):]\r
2026 self._ValueList[0] = TAB_SPLIT.join((PcdNames[0],PcdName))\r
2027 self._ValueList[1] = Index\r
2028 self._ValueList[2] = PcdTockens[1]\r
2029 else:\r
2030 self._CurrentStructurePcdName = ""\r
ae7b6df8 2031 else:\r
8e011d83 2032 if self._CurrentStructurePcdName != TAB_SPLIT.join(PcdNames[:2]):\r
ccaa7754 2033 EdkLogger.error('Parser', FORMAT_INVALID, "Pcd Name does not match: %s and %s " % (self._CurrentStructurePcdName, TAB_SPLIT.join(PcdNames[:2])),\r
8e011d83 2034 File=self.MetaFile, Line=self._LineIndex + 1)\r
a0939593 2035 self._ValueList[1] = TAB_SPLIT.join(PcdNames[2:])\r
ae7b6df8
LG
2036 self._ValueList[2] = PcdTockens[1]\r
2037 if not self._CurrentStructurePcdName:\r
2038 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
2039 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
2040 ValueRe = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*')\r
2041 # check PCD information\r
2042 if self._ValueList[0] == '' or self._ValueList[1] == '':\r
2043 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
2044 ExtraData=self._CurrentLine + \\r
2045 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2046 File=self.MetaFile, Line=self._LineIndex + 1)\r
2047 # check format of token space GUID CName\r
2048 if not ValueRe.match(self._ValueList[0]):\r
2049 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
2050 ExtraData=self._CurrentLine + \\r
2051 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2052 File=self.MetaFile, Line=self._LineIndex + 1)\r
2053 # check format of PCD CName\r
2054 if not ValueRe.match(self._ValueList[1]):\r
2055 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
2056 ExtraData=self._CurrentLine + \\r
2057 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2058 File=self.MetaFile, Line=self._LineIndex + 1)\r
2059 # check PCD datum information\r
2060 if len(TokenList) < 2 or TokenList[1] == '':\r
2061 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",\r
2062 ExtraData=self._CurrentLine + \\r
2063 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2064 File=self.MetaFile, Line=self._LineIndex + 1)\r
2065\r
2066\r
2067 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')\r
2068 PtrValue = ValueRe.findall(TokenList[1])\r
2069\r
2070 # Has VOID* type string, may contain "|" character in the string.\r
2071 if len(PtrValue) != 0:\r
2072 ptrValueList = re.sub(ValueRe, '', TokenList[1])\r
2073 ValueList = AnalyzePcdExpression(ptrValueList)\r
2074 ValueList[0] = PtrValue[0]\r
2075 else:\r
2076 ValueList = AnalyzePcdExpression(TokenList[1])\r
2077\r
2078\r
2079 # check if there's enough datum information given\r
2080 if len(ValueList) != 3:\r
2081 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",\r
2082 ExtraData=self._CurrentLine + \\r
2083 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2084 File=self.MetaFile, Line=self._LineIndex + 1)\r
2085 # check default value\r
2086 if ValueList[0] == '':\r
2087 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",\r
2088 ExtraData=self._CurrentLine + \\r
2089 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2090 File=self.MetaFile, Line=self._LineIndex + 1)\r
2091 # check datum type\r
2092 if ValueList[1] == '':\r
2093 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",\r
2094 ExtraData=self._CurrentLine + \\r
2095 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2096 File=self.MetaFile, Line=self._LineIndex + 1)\r
2097 # check token of the PCD\r
2098 if ValueList[2] == '':\r
2099 EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",\r
2100 ExtraData=self._CurrentLine + \\r
2101 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2102 File=self.MetaFile, Line=self._LineIndex + 1)\r
2103\r
2104 PcdValue = ValueList[0]\r
2105 if PcdValue:\r
726c501c 2106 try:\r
9efe8d60 2107 self._GuidDict.update(self._AllPcdDict)\r
726c501c 2108 ValueList[0] = ValueExpressionEx(ValueList[0], ValueList[1], self._GuidDict)(True)\r
5b0671c1 2109 except BadExpression as Value:\r
726c501c 2110 EdkLogger.error('Parser', FORMAT_INVALID, Value, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
ae7b6df8
LG
2111 # check format of default value against the datum type\r
2112 IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])\r
2113 if not IsValid:\r
2114 EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,\r
2115 File=self.MetaFile, Line=self._LineIndex + 1)\r
2116\r
2117 if Cause == "StructurePcd":\r
2118 self._CurrentStructurePcdName = TAB_SPLIT.join(self._ValueList[0:2])\r
2119 self._ValueList[0] = self._CurrentStructurePcdName\r
2120 self._ValueList[1] = ValueList[1].strip()\r
2121\r
2122 if ValueList[0] in ['True', 'true', 'TRUE']:\r
2123 ValueList[0] = '1'\r
2124 elif ValueList[0] in ['False', 'false', 'FALSE']:\r
2125 ValueList[0] = '0'\r
2126\r
2127 # check for duplicate PCD definition\r
2128 if (self._Scope[0], self._ValueList[0], self._ValueList[1]) in self._AllPCDs:\r
2129 EdkLogger.error('Parser', FORMAT_INVALID,\r
2130 "The same PCD name and GUID have been already defined",\r
2131 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
2132 else:\r
2133 self._AllPCDs.append((self._Scope[0], self._ValueList[0], self._ValueList[1]))\r
2134 self._AllPcdDict[TAB_SPLIT.join(self._ValueList[0:2])] = ValueList[0]\r
f51461c8 2135\r
ae7b6df8 2136 self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()\r
f51461c8
LG
2137\r
2138 _SectionParser = {\r
2139 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,\r
2140 MODEL_EFI_INCLUDE : MetaFileParser._PathParser,\r
2141 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,\r
2142 MODEL_EFI_GUID : _GuidParser,\r
2143 MODEL_EFI_PPI : _GuidParser,\r
2144 MODEL_EFI_PROTOCOL : _GuidParser,\r
2145 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,\r
2146 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,\r
2147 MODEL_PCD_FEATURE_FLAG : _PcdParser,\r
2148 MODEL_PCD_DYNAMIC : _PcdParser,\r
2149 MODEL_PCD_DYNAMIC_EX : _PcdParser,\r
2150 MODEL_UNKNOWN : MetaFileParser._Skip,\r
0923aa1c 2151 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,\r
f51461c8
LG
2152 }\r
2153\r
2154##\r
2155#\r
2156# This acts like the main() function for the script, unless it is 'import'ed into another\r
2157# script.\r
2158#\r
2159if __name__ == '__main__':\r
2160 pass\r
2161\r