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