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