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