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