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