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