]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/Workspace/MetaFileParser.py
BaseTools:Define Macro in Inf file, the pcdvalue Can't convert
[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
51f52333 760 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '1', 1)\r
f51461c8 761 elif InfPcdValueList[0] in ['False', 'false', 'FALSE']:\r
51f52333
FZ
762 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '0', 1)\r
763 elif isinstance(InfPcdValueList[0], str) and InfPcdValueList[0].find('$(') >= 0:\r
764 Value = ReplaceExprMacro(InfPcdValueList[0],self._Macros)\r
765 if Value != '0':\r
766 self._ValueList[2] = Value\r
f51461c8
LG
767 if (self._ValueList[0], self._ValueList[1]) not in self.PcdsDict:\r
768 self.PcdsDict[self._ValueList[0], self._ValueList[1]] = self._SectionType\r
769 elif self.PcdsDict[self._ValueList[0], self._ValueList[1]] != self._SectionType:\r
770 EdkLogger.error('Parser', FORMAT_INVALID, "It is not permissible to list a specified PCD in different PCD type sections.",\r
771 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",\r
772 File=self.MetaFile, Line=self._LineIndex + 1)\r
773\r
774 ## [depex] section parser\r
775 @ParseMacro\r
776 def _DepexParser(self):\r
777 self._ValueList[0:1] = [self._CurrentLine]\r
778\r
779 _SectionParser = {\r
780 MODEL_UNKNOWN : MetaFileParser._Skip,\r
781 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,\r
782 MODEL_META_DATA_BUILD_OPTION : MetaFileParser._BuildOptionParser,\r
783 MODEL_EFI_INCLUDE : _IncludeParser, # for Edk.x modules\r
784 MODEL_EFI_LIBRARY_INSTANCE : MetaFileParser._CommonParser, # for Edk.x modules\r
785 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,\r
786 MODEL_META_DATA_PACKAGE : MetaFileParser._PathParser,\r
787 MODEL_META_DATA_NMAKE : _NmakeParser, # for Edk.x modules\r
788 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,\r
789 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,\r
790 MODEL_PCD_FEATURE_FLAG : _PcdParser,\r
791 MODEL_PCD_DYNAMIC_EX : _PcdParser,\r
792 MODEL_PCD_DYNAMIC : _PcdParser,\r
793 MODEL_EFI_SOURCE_FILE : _SourceFileParser,\r
794 MODEL_EFI_GUID : MetaFileParser._CommonParser,\r
795 MODEL_EFI_PROTOCOL : MetaFileParser._CommonParser,\r
796 MODEL_EFI_PPI : MetaFileParser._CommonParser,\r
797 MODEL_EFI_DEPEX : _DepexParser,\r
798 MODEL_EFI_BINARY_FILE : _BinaryFileParser,\r
0923aa1c 799 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,\r
f51461c8
LG
800 }\r
801\r
802## DSC file parser class\r
803#\r
804# @param FilePath The path of platform description file\r
805# @param FileType The raw data of DSC file\r
806# @param Table Database used to retrieve module/package information\r
807# @param Macros Macros used for replacement in file\r
808# @param Owner Owner ID (for sub-section parsing)\r
809# @param From ID from which the data comes (for !INCLUDE directive)\r
810#\r
811class DscParser(MetaFileParser):\r
812 # DSC file supported data types (one type per section)\r
813 DataType = {\r
814 TAB_SKUIDS.upper() : MODEL_EFI_SKU_ID,\r
8518bf0b 815 TAB_DEFAULT_STORES.upper() : MODEL_EFI_DEFAULT_STORES,\r
f51461c8
LG
816 TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,\r
817 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,\r
818 TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,\r
819 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,\r
820 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,\r
821 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,\r
822 TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_DEFAULT,\r
823 TAB_PCDS_DYNAMIC_HII_NULL.upper() : MODEL_PCD_DYNAMIC_HII,\r
824 TAB_PCDS_DYNAMIC_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_VPD,\r
825 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT,\r
826 TAB_PCDS_DYNAMIC_EX_HII_NULL.upper() : MODEL_PCD_DYNAMIC_EX_HII,\r
827 TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_EX_VPD,\r
828 TAB_COMPONENTS.upper() : MODEL_META_DATA_COMPONENT,\r
829 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH,\r
830 TAB_DSC_DEFINES.upper() : MODEL_META_DATA_HEADER,\r
831 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,\r
832 TAB_DSC_DEFINES_EDKGLOBAL : MODEL_META_DATA_GLOBAL_DEFINE,\r
833 TAB_INCLUDE.upper() : MODEL_META_DATA_INCLUDE,\r
834 TAB_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
835 TAB_IF_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
836 TAB_IF_N_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF,\r
837 TAB_ELSE_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF,\r
838 TAB_ELSE.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,\r
839 TAB_END_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF,\r
0923aa1c 840 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION,\r
09ef8e92 841 TAB_ERROR.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR,\r
f51461c8
LG
842 }\r
843\r
844 # Valid names in define section\r
845 DefineKeywords = [\r
846 "DSC_SPECIFICATION",\r
847 "PLATFORM_NAME",\r
848 "PLATFORM_GUID",\r
849 "PLATFORM_VERSION",\r
850 "SKUID_IDENTIFIER",\r
851 "PCD_INFO_GENERATION",\r
82a6a960 852 "PCD_VAR_CHECK_GENERATION",\r
f51461c8
LG
853 "SUPPORTED_ARCHITECTURES",\r
854 "BUILD_TARGETS",\r
855 "OUTPUT_DIRECTORY",\r
856 "FLASH_DEFINITION",\r
857 "BUILD_NUMBER",\r
858 "RFC_LANGUAGES",\r
859 "ISO_LANGUAGES",\r
860 "TIME_STAMP_FILE",\r
861 "VPD_TOOL_GUID",\r
f0dc69e6
YZ
862 "FIX_LOAD_TOP_MEMORY_ADDRESS",\r
863 "PREBUILD",\r
864 "POSTBUILD"\r
f51461c8
LG
865 ]\r
866\r
97fa0ee9
YL
867 SubSectionDefineKeywords = [\r
868 "FILE_GUID"\r
869 ]\r
870\r
f51461c8
LG
871 SymbolPattern = ValueExpression.SymbolPattern\r
872\r
c17956e0
DL
873 IncludedFiles = set()\r
874\r
f51461c8
LG
875 ## Constructor of DscParser\r
876 #\r
877 # Initialize object of DscParser\r
878 #\r
879 # @param FilePath The path of platform description file\r
880 # @param FileType The raw data of DSC file\r
cdd1b5e5 881 # @param Arch Default Arch value for filtering sections\r
f51461c8 882 # @param Table Database used to retrieve module/package information\r
f51461c8
LG
883 # @param Owner Owner ID (for sub-section parsing)\r
884 # @param From ID from which the data comes (for !INCLUDE directive)\r
885 #\r
cdd1b5e5 886 def __init__(self, FilePath, FileType, Arch, Table, Owner= -1, From= -1):\r
f51461c8 887 # prevent re-initialization\r
395f3336 888 if hasattr(self, "_Table") and self._Table is Table:\r
f51461c8 889 return\r
cdd1b5e5 890 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, Owner, From)\r
f51461c8
LG
891 self._Version = 0x00010005 # Only EDK2 dsc file is supported\r
892 # to store conditional directive evaluation result\r
893 self._DirectiveStack = []\r
894 self._DirectiveEvalStack = []\r
895 self._Enabled = 1\r
896\r
897 #\r
898 # Specify whether current line is in uncertain condition\r
899 #\r
900 self._InDirective = -1\r
901\r
902 # Final valid replacable symbols\r
903 self._Symbols = {}\r
904 #\r
905 # Map the ID between the original table and new table to track\r
906 # the owner item\r
907 #\r
908 self._IdMapping = {-1:-1}\r
909\r
72a1d776 910 self._PcdCodeValue = ""\r
911 self._PcdDataTypeCODE = False\r
912 self._CurrentPcdName = ""\r
643556fc 913 self._Content = None\r
72a1d776 914\r
f51461c8
LG
915 ## Parser starter\r
916 def Start(self):\r
917 Content = ''\r
918 try:\r
919 Content = open(str(self.MetaFile), 'r').readlines()\r
920 except:\r
921 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)\r
922\r
923 OwnerId = {}\r
72a1d776 924\r
925 Content = self.ProcessMultipleLineCODEValue(Content)\r
926\r
f51461c8
LG
927 for Index in range(0, len(Content)):\r
928 Line = CleanString(Content[Index])\r
929 # skip empty line\r
930 if Line == '':\r
931 continue\r
932\r
933 self._CurrentLine = Line\r
934 self._LineIndex = Index\r
935 if self._InSubsection and self._Owner[-1] == -1:\r
936 self._Owner.append(self._LastItem)\r
937\r
938 # section header\r
939 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:\r
940 self._SectionType = MODEL_META_DATA_SECTION_HEADER\r
941 # subsection ending\r
942 elif Line[0] == '}' and self._InSubsection:\r
943 self._InSubsection = False\r
944 self._SubsectionType = MODEL_UNKNOWN\r
945 self._SubsectionName = ''\r
946 self._Owner[-1] = -1\r
50874612 947 OwnerId.clear()\r
f51461c8
LG
948 continue\r
949 # subsection header\r
950 elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:\r
951 self._SubsectionType = MODEL_META_DATA_SUBSECTION_HEADER\r
952 # directive line\r
953 elif Line[0] == '!':\r
cd7bd491
YF
954 TokenList = GetSplitValueList(Line, ' ', 1)\r
955 if TokenList[0] == TAB_INCLUDE:\r
956 for Arch, ModuleType, DefaultStore in self._Scope:\r
957 if self._SubsectionType != MODEL_UNKNOWN and Arch in OwnerId:\r
958 self._Owner[-1] = OwnerId[Arch]\r
959 self._DirectiveParser()\r
960 else:\r
961 self._DirectiveParser()\r
f51461c8 962 continue\r
d429fcd0 963 if Line[0] == TAB_OPTION_START and not self._InSubsection:\r
ccaa7754 964 EdkLogger.error("Parser", FILE_READ_FAILURE, "Missing the '{' before %s in Line %s" % (Line, Index+1), ExtraData=self.MetaFile)\r
f51461c8
LG
965\r
966 if self._InSubsection:\r
967 SectionType = self._SubsectionType\r
968 else:\r
969 SectionType = self._SectionType\r
970 self._ItemType = SectionType\r
971\r
972 self._ValueList = ['', '', '']\r
b8920ccc
FB
973 # "SET pcd = pcd_expression" syntax is not supported in Dsc file.\r
974 if self._CurrentLine.upper().strip().startswith("SET "):\r
975 EdkLogger.error('Parser', FORMAT_INVALID, '''"SET pcd = pcd_expression" syntax is not support in Dsc file''',\r
976 ExtraData=self._CurrentLine,\r
977 File=self.MetaFile, Line=self._LineIndex + 1)\r
f51461c8 978 self._SectionParser[SectionType](self)\r
4231a819 979 if self._ValueList is None:\r
f51461c8
LG
980 continue\r
981 #\r
982 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,\r
983 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1\r
984 #\r
8518bf0b 985 for Arch, ModuleType, DefaultStore in self._Scope:\r
f51461c8 986 Owner = self._Owner[-1]\r
cd7bd491 987 if self._SubsectionType != MODEL_UNKNOWN and Arch in OwnerId:\r
f51461c8
LG
988 Owner = OwnerId[Arch]\r
989 self._LastItem = self._Store(\r
990 self._ItemType,\r
991 self._ValueList[0],\r
992 self._ValueList[1],\r
993 self._ValueList[2],\r
994 Arch,\r
995 ModuleType,\r
8518bf0b 996 DefaultStore,\r
f51461c8
LG
997 Owner,\r
998 self._From,\r
999 self._LineIndex + 1,\r
1000 - 1,\r
1001 self._LineIndex + 1,\r
1002 - 1,\r
1003 self._Enabled\r
1004 )\r
1005 if self._SubsectionType == MODEL_UNKNOWN and self._InSubsection:\r
1006 OwnerId[Arch] = self._LastItem\r
1007\r
1008 if self._DirectiveStack:\r
1009 Type, Line, Text = self._DirectiveStack[-1]\r
1010 EdkLogger.error('Parser', FORMAT_INVALID, "No matching '!endif' found",\r
1011 ExtraData=Text, File=self.MetaFile, Line=Line)\r
1012 self._Done()\r
1013\r
1014 ## <subsection_header> parser\r
1015 def _SubsectionHeaderParser(self):\r
1016 self._SubsectionName = self._CurrentLine[1:-1].upper()\r
1017 if self._SubsectionName in self.DataType:\r
1018 self._SubsectionType = self.DataType[self._SubsectionName]\r
1019 else:\r
1020 self._SubsectionType = MODEL_UNKNOWN\r
1021 EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile,\r
1022 Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
1023 self._ValueList[0] = self._SubsectionName\r
1024\r
1025 ## Directive statement parser\r
1026 def _DirectiveParser(self):\r
1027 self._ValueList = ['', '', '']\r
1028 TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)\r
1029 self._ValueList[0:len(TokenList)] = TokenList\r
1030\r
1031 # Syntax check\r
1032 DirectiveName = self._ValueList[0].upper()\r
1033 if DirectiveName not in self.DataType:\r
1034 EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName,\r
1035 File=self.MetaFile, Line=self._LineIndex + 1)\r
1036\r
1037 if DirectiveName in ['!IF', '!IFDEF', '!IFNDEF']:\r
1038 self._InDirective += 1\r
1039\r
1040 if DirectiveName in ['!ENDIF']:\r
1041 self._InDirective -= 1\r
1042\r
1043 if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '':\r
1044 EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression",\r
1045 File=self.MetaFile, Line=self._LineIndex + 1,\r
1046 ExtraData=self._CurrentLine)\r
1047\r
1048 ItemType = self.DataType[DirectiveName]\r
55c84777 1049 Scope = [[TAB_COMMON, TAB_COMMON, TAB_COMMON]]\r
f51461c8
LG
1050 if ItemType == MODEL_META_DATA_INCLUDE:\r
1051 Scope = self._Scope\r
09ef8e92
YF
1052 elif ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR:\r
1053 Scope = self._Scope\r
f51461c8
LG
1054 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:\r
1055 # Remove all directives between !if and !endif, including themselves\r
1056 while self._DirectiveStack:\r
1057 # Remove any !else or !elseif\r
1058 DirectiveInfo = self._DirectiveStack.pop()\r
1059 if DirectiveInfo[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1060 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
1061 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:\r
1062 break\r
1063 else:\r
1064 EdkLogger.error("Parser", FORMAT_INVALID, "Redundant '!endif'",\r
1065 File=self.MetaFile, Line=self._LineIndex + 1,\r
1066 ExtraData=self._CurrentLine)\r
09ef8e92 1067 elif ItemType not in {MODEL_META_DATA_INCLUDE, MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR}:\r
f51461c8
LG
1068 # Break if there's a !else is followed by a !elseif\r
1069 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF and \\r
1070 self._DirectiveStack and \\r
1071 self._DirectiveStack[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:\r
1072 EdkLogger.error("Parser", FORMAT_INVALID, "'!elseif' after '!else'",\r
1073 File=self.MetaFile, Line=self._LineIndex + 1,\r
1074 ExtraData=self._CurrentLine)\r
1075 self._DirectiveStack.append((ItemType, self._LineIndex + 1, self._CurrentLine))\r
f51461c8
LG
1076\r
1077 #\r
1078 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,\r
1079 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1\r
1080 #\r
8518bf0b 1081 for Arch, ModuleType, DefaultStore in Scope:\r
f51461c8
LG
1082 self._LastItem = self._Store(\r
1083 ItemType,\r
1084 self._ValueList[0],\r
1085 self._ValueList[1],\r
1086 self._ValueList[2],\r
1087 Arch,\r
1088 ModuleType,\r
8518bf0b 1089 DefaultStore,\r
f51461c8
LG
1090 self._Owner[-1],\r
1091 self._From,\r
1092 self._LineIndex + 1,\r
1093 - 1,\r
1094 self._LineIndex + 1,\r
1095 - 1,\r
1096 0\r
1097 )\r
1098\r
1099 ## [defines] section parser\r
1100 @ParseMacro\r
1101 def _DefineParser(self):\r
1102 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
1103 self._ValueList[1:len(TokenList)] = TokenList\r
1104\r
1105 # Syntax check\r
1106 if not self._ValueList[1]:\r
1107 EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",\r
1108 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1109 if not self._ValueList[2]:\r
1110 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",\r
1111 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
97fa0ee9
YL
1112 if (not self._ValueList[1] in self.DefineKeywords and\r
1113 (self._InSubsection and self._ValueList[1] not in self.SubSectionDefineKeywords)):\r
f51461c8
LG
1114 EdkLogger.error('Parser', FORMAT_INVALID,\r
1115 "Unknown keyword found: %s. "\r
1116 "If this is a macro you must "\r
1117 "add it as a DEFINE in the DSC" % self._ValueList[1],\r
1118 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
97fa0ee9
YL
1119 if not self._InSubsection:\r
1120 self._Defines[self._ValueList[1]] = self._ValueList[2]\r
f51461c8
LG
1121 self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]\r
1122\r
1123 @ParseMacro\r
1124 def _SkuIdParser(self):\r
8518bf0b 1125 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
ccaa7754 1126 if len(TokenList) not in (2, 3):\r
e6b10112 1127 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>[|<UiName>]'",\r
8518bf0b
LG
1128 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1129 self._ValueList[0:len(TokenList)] = TokenList\r
1130 @ParseMacro\r
1131 def _DefaultStoresParser(self):\r
f51461c8
LG
1132 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
1133 if len(TokenList) != 2:\r
767ddbe8 1134 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>'",\r
f51461c8
LG
1135 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1136 self._ValueList[0:len(TokenList)] = TokenList\r
1137\r
1138 ## Parse Edk style of library modules\r
1139 @ParseMacro\r
1140 def _LibraryInstanceParser(self):\r
1141 self._ValueList[0] = self._CurrentLine\r
1142\r
72a1d776 1143 def ProcessMultipleLineCODEValue(self,Content):\r
1144 CODEBegin = False\r
1145 CODELine = ""\r
1146 continuelinecount = 0\r
1147 newContent = []\r
1148 for Index in range(0, len(Content)):\r
1149 Line = Content[Index]\r
1150 if CODEBegin:\r
1151 CODELine = CODELine + Line\r
1152 continuelinecount +=1\r
1153 if ")}" in Line:\r
1154 newContent.append(CODELine)\r
1155 for _ in range(continuelinecount):\r
1156 newContent.append("")\r
1157 CODEBegin = False\r
1158 CODELine = ""\r
1159 continuelinecount = 0\r
1160 else:\r
1161 if not Line:\r
1162 newContent.append(Line)\r
1163 continue\r
1164 if "{CODE(" not in Line:\r
1165 newContent.append(Line)\r
1166 continue\r
1167 elif CODEPattern.findall(Line):\r
1168 newContent.append(Line)\r
1169 continue\r
1170 else:\r
1171 CODEBegin = True\r
1172 CODELine = Line\r
1173\r
1174 return newContent\r
1175\r
1176 def _DecodeCODEData(self):\r
1177 pass\r
f51461c8
LG
1178 ## PCD sections parser\r
1179 #\r
1180 # [PcdsFixedAtBuild]\r
1181 # [PcdsPatchableInModule]\r
1182 # [PcdsFeatureFlag]\r
1183 # [PcdsDynamicEx\r
1184 # [PcdsDynamicExDefault]\r
1185 # [PcdsDynamicExVpd]\r
1186 # [PcdsDynamicExHii]\r
1187 # [PcdsDynamic]\r
1188 # [PcdsDynamicDefault]\r
1189 # [PcdsDynamicVpd]\r
1190 # [PcdsDynamicHii]\r
1191 #\r
1192 @ParseMacro\r
1193 def _PcdParser(self):\r
72a1d776 1194 if self._PcdDataTypeCODE:\r
1195 self._PcdCodeValue = self._PcdCodeValue + "\n " + self._CurrentLine\r
1196 if self._CurrentLine.endswith(")}"):\r
1197 self._CurrentLine = "|".join((self._CurrentPcdName, self._PcdCodeValue))\r
1198 self._PcdDataTypeCODE = False\r
1199 self._PcdCodeValue = ""\r
1200 else:\r
1201 self._ValueList = None\r
1202 return\r
f51461c8 1203 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
72a1d776 1204 self._CurrentPcdName = TokenList[0]\r
48e89045 1205 if len(TokenList) == 2 and TokenList[1].strip().startswith("{CODE"):\r
72a1d776 1206 self._PcdDataTypeCODE = True\r
1207 self._PcdCodeValue = TokenList[1].strip()\r
1208\r
1209 if self._PcdDataTypeCODE:\r
1210 if self._CurrentLine.endswith(")}"):\r
1211 self._PcdDataTypeCODE = False\r
1212 self._PcdCodeValue = ""\r
1213 else:\r
1214 self._ValueList = None\r
1215 return\r
f51461c8 1216 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
ae7b6df8
LG
1217 PcdNameTockens = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
1218 if len(PcdNameTockens) == 2:\r
1219 self._ValueList[0], self._ValueList[1] = PcdNameTockens[0], PcdNameTockens[1]\r
1220 elif len(PcdNameTockens) == 3:\r
1221 self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), PcdNameTockens[2]\r
a0939593
LG
1222 elif len(PcdNameTockens) > 3:\r
1223 self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), ".".join(PcdNameTockens[2:])\r
f51461c8
LG
1224 if len(TokenList) == 2:\r
1225 self._ValueList[2] = TokenList[1]\r
1226 if self._ValueList[0] == '' or self._ValueList[1] == '':\r
1227 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
1228 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",\r
1229 File=self.MetaFile, Line=self._LineIndex + 1)\r
1230 if self._ValueList[2] == '':\r
1231 #\r
e651d06c 1232 # The PCD values are optional for FIXEDATBUILD, PATCHABLEINMODULE, Dynamic/DynamicEx default\r
f51461c8 1233 #\r
e651d06c 1234 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
1235 return\r
1236 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",\r
1237 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",\r
1238 File=self.MetaFile, Line=self._LineIndex + 1)\r
1239\r
1240 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD\r
1241 ValueList = GetSplitValueList(self._ValueList[2])\r
ccaa7754 1242 if len(ValueList) > 1 and ValueList[1] in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64] \\r
f51461c8
LG
1243 and self._ItemType in [MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT]:\r
1244 EdkLogger.error('Parser', FORMAT_INVALID, "The datum type '%s' of PCD is wrong" % ValueList[1],\r
1245 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1246\r
9f14de3b
YZ
1247 # Validate the VariableName of DynamicHii and DynamicExHii for PCD Entry must not be an empty string\r
1248 if self._ItemType in [MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII]:\r
1249 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)\r
ccaa7754 1250 if len(DscPcdValueList[0].replace('L', '').replace('"', '').strip()) == 0:\r
9f14de3b
YZ
1251 EdkLogger.error('Parser', FORMAT_INVALID, "The VariableName field in the HII format PCD entry must not be an empty string",\r
1252 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1253\r
f51461c8
LG
1254 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.\r
1255 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)\r
1256 if DscPcdValueList[0] in ['True', 'true', 'TRUE']:\r
1257 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1);\r
1258 elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:\r
1259 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);\r
1260\r
1261\r
1262 ## [components] section parser\r
1263 @ParseMacro\r
1264 def _ComponentParser(self):\r
1265 if self._CurrentLine[-1] == '{':\r
1266 self._ValueList[0] = self._CurrentLine[0:-1].strip()\r
1267 self._InSubsection = True\r
cd7bd491 1268 self._SubsectionType = MODEL_UNKNOWN\r
f51461c8
LG
1269 else:\r
1270 self._ValueList[0] = self._CurrentLine\r
1271\r
1272 ## [LibraryClasses] section\r
1273 @ParseMacro\r
1274 def _LibraryClassParser(self):\r
1275 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
1276 if len(TokenList) < 2:\r
1277 EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",\r
1278 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
1279 File=self.MetaFile, Line=self._LineIndex + 1)\r
1280 if TokenList[0] == '':\r
1281 EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",\r
1282 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
1283 File=self.MetaFile, Line=self._LineIndex + 1)\r
1284 if TokenList[1] == '':\r
1285 EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",\r
1286 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
1287 File=self.MetaFile, Line=self._LineIndex + 1)\r
1288\r
1289 self._ValueList[0:len(TokenList)] = TokenList\r
1290\r
1291 def _CompponentSourceOverridePathParser(self):\r
1292 self._ValueList[0] = self._CurrentLine\r
1293\r
1294 ## [BuildOptions] section parser\r
1295 @ParseMacro\r
1296 def _BuildOptionParser(self):\r
1297 self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)\r
1298 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
1299 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)\r
1300 if len(TokenList2) == 2:\r
1301 self._ValueList[0] = TokenList2[0] # toolchain family\r
1302 self._ValueList[1] = TokenList2[1] # keys\r
1303 else:\r
1304 self._ValueList[1] = TokenList[0]\r
1305 if len(TokenList) == 2: # value\r
1306 self._ValueList[2] = TokenList[1]\r
1307\r
1308 if self._ValueList[1].count('_') != 4:\r
1309 EdkLogger.error(\r
1310 'Parser',\r
1311 FORMAT_INVALID,\r
1312 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],\r
1313 ExtraData=self._CurrentLine,\r
1314 File=self.MetaFile,\r
1315 Line=self._LineIndex + 1\r
1316 )\r
1317\r
1318 ## Override parent's method since we'll do all macro replacements in parser\r
71cac3f7
CJ
1319 @property\r
1320 def _Macros(self):\r
f51461c8
LG
1321 Macros = {}\r
1322 Macros.update(self._FileLocalMacros)\r
1323 Macros.update(self._GetApplicableSectionMacro())\r
1324 Macros.update(GlobalData.gEdkGlobal)\r
1325 Macros.update(GlobalData.gPlatformDefines)\r
1326 Macros.update(GlobalData.gCommandLineDefines)\r
1327 # PCD cannot be referenced in macro definition\r
1328 if self._ItemType not in [MODEL_META_DATA_DEFINE, MODEL_META_DATA_GLOBAL_DEFINE]:\r
1329 Macros.update(self._Symbols)\r
1fa7fdf6
FY
1330 if GlobalData.BuildOptionPcd:\r
1331 for Item in GlobalData.BuildOptionPcd:\r
0d1f5b2b 1332 if isinstance(Item, tuple):\r
705ed563 1333 continue\r
1fa7fdf6 1334 PcdName, TmpValue = Item.split("=")\r
8565b582 1335 TmpValue = BuildOptionValue(TmpValue, self._GuidDict)\r
1fa7fdf6 1336 Macros[PcdName.strip()] = TmpValue\r
f51461c8
LG
1337 return Macros\r
1338\r
1339 def _PostProcess(self):\r
1340 Processer = {\r
1341 MODEL_META_DATA_SECTION_HEADER : self.__ProcessSectionHeader,\r
1342 MODEL_META_DATA_SUBSECTION_HEADER : self.__ProcessSubsectionHeader,\r
1343 MODEL_META_DATA_HEADER : self.__ProcessDefine,\r
1344 MODEL_META_DATA_DEFINE : self.__ProcessDefine,\r
1345 MODEL_META_DATA_GLOBAL_DEFINE : self.__ProcessDefine,\r
1346 MODEL_META_DATA_INCLUDE : self.__ProcessDirective,\r
1347 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF : self.__ProcessDirective,\r
1348 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE : self.__ProcessDirective,\r
1349 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF : self.__ProcessDirective,\r
1350 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF : self.__ProcessDirective,\r
1351 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF : self.__ProcessDirective,\r
1352 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF : self.__ProcessDirective,\r
1353 MODEL_EFI_SKU_ID : self.__ProcessSkuId,\r
8518bf0b 1354 MODEL_EFI_DEFAULT_STORES : self.__ProcessDefaultStores,\r
f51461c8
LG
1355 MODEL_EFI_LIBRARY_INSTANCE : self.__ProcessLibraryInstance,\r
1356 MODEL_EFI_LIBRARY_CLASS : self.__ProcessLibraryClass,\r
1357 MODEL_PCD_FIXED_AT_BUILD : self.__ProcessPcd,\r
1358 MODEL_PCD_PATCHABLE_IN_MODULE : self.__ProcessPcd,\r
1359 MODEL_PCD_FEATURE_FLAG : self.__ProcessPcd,\r
1360 MODEL_PCD_DYNAMIC_DEFAULT : self.__ProcessPcd,\r
1361 MODEL_PCD_DYNAMIC_HII : self.__ProcessPcd,\r
1362 MODEL_PCD_DYNAMIC_VPD : self.__ProcessPcd,\r
1363 MODEL_PCD_DYNAMIC_EX_DEFAULT : self.__ProcessPcd,\r
1364 MODEL_PCD_DYNAMIC_EX_HII : self.__ProcessPcd,\r
1365 MODEL_PCD_DYNAMIC_EX_VPD : self.__ProcessPcd,\r
1366 MODEL_META_DATA_COMPONENT : self.__ProcessComponent,\r
1367 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : self.__ProcessSourceOverridePath,\r
1368 MODEL_META_DATA_BUILD_OPTION : self.__ProcessBuildOption,\r
1369 MODEL_UNKNOWN : self._Skip,\r
0923aa1c 1370 MODEL_META_DATA_USER_EXTENSION : self._SkipUserExtension,\r
09ef8e92 1371 MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR : self._ProcessError,\r
f51461c8
LG
1372 }\r
1373\r
2f818ed0 1374 self._Table = MetaFileStorage(self._RawTable.DB, self.MetaFile, MODEL_FILE_DSC, True)\r
f51461c8
LG
1375 self._DirectiveStack = []\r
1376 self._DirectiveEvalStack = []\r
1377 self._FileWithError = self.MetaFile\r
1378 self._FileLocalMacros = {}\r
50874612 1379 self._SectionsMacroDict.clear()\r
f51461c8
LG
1380 GlobalData.gPlatformDefines = {}\r
1381\r
1382 # Get all macro and PCD which has straitforward value\r
1383 self.__RetrievePcdValue()\r
1384 self._Content = self._RawTable.GetAll()\r
1385 self._ContentIndex = 0\r
97fa0ee9 1386 self._InSubsection = False\r
f51461c8 1387 while self._ContentIndex < len(self._Content) :\r
ccaa7754 1388 Id, self._ItemType, V1, V2, V3, S1, S2, S3, Owner, self._From, \\r
f51461c8
LG
1389 LineStart, ColStart, LineEnd, ColEnd, Enabled = self._Content[self._ContentIndex]\r
1390\r
1391 if self._From < 0:\r
1392 self._FileWithError = self.MetaFile\r
1393\r
1394 self._ContentIndex += 1\r
1395\r
8518bf0b 1396 self._Scope = [[S1, S2, S3]]\r
f51461c8
LG
1397 #\r
1398 # For !include directive, handle it specially,\r
1399 # merge arch and module type in case of duplicate items\r
1400 #\r
1401 while self._ItemType == MODEL_META_DATA_INCLUDE:\r
1402 if self._ContentIndex >= len(self._Content):\r
1403 break\r
1404 Record = self._Content[self._ContentIndex]\r
8518bf0b 1405 if LineStart == Record[10] and LineEnd == Record[12]:\r
ccaa7754
GL
1406 if [Record[5], Record[6], Record[7]] not in self._Scope:\r
1407 self._Scope.append([Record[5], Record[6], Record[7]])\r
f51461c8
LG
1408 self._ContentIndex += 1\r
1409 else:\r
1410 break\r
1411\r
1412 self._LineIndex = LineStart - 1\r
1413 self._ValueList = [V1, V2, V3]\r
1414\r
97fa0ee9
YL
1415 if Owner > 0 and Owner in self._IdMapping:\r
1416 self._InSubsection = True\r
1417 else:\r
1418 self._InSubsection = False\r
f51461c8
LG
1419 try:\r
1420 Processer[self._ItemType]()\r
5b0671c1 1421 except EvaluationException as Excpt:\r
f7496d71 1422 #\r
f51461c8
LG
1423 # Only catch expression evaluation error here. We need to report\r
1424 # the precise number of line on which the error occurred\r
1425 #\r
1426 if hasattr(Excpt, 'Pcd'):\r
1427 if Excpt.Pcd in GlobalData.gPlatformOtherPcds:\r
1428 Info = GlobalData.gPlatformOtherPcds[Excpt.Pcd]\r
1429 EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"\r
1430 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"\r
1431 " of the DSC file, and it is currently defined in this section:"\r
1432 " %s, line #: %d." % (Excpt.Pcd, Info[0], Info[1]),\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, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,\r
1437 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1438 Line=self._LineIndex + 1)\r
1439 else:\r
1440 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),\r
1441 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1442 Line=self._LineIndex + 1)\r
5b0671c1 1443 except MacroException as Excpt:\r
f51461c8
LG
1444 EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt),\r
1445 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1446 Line=self._LineIndex + 1)\r
1447\r
4231a819 1448 if self._ValueList is None:\r
f51461c8
LG
1449 continue\r
1450\r
1451 NewOwner = self._IdMapping.get(Owner, -1)\r
1452 self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack))\r
1453 self._LastItem = self._Store(\r
1454 self._ItemType,\r
1455 self._ValueList[0],\r
1456 self._ValueList[1],\r
1457 self._ValueList[2],\r
1458 S1,\r
1459 S2,\r
8518bf0b 1460 S3,\r
f51461c8
LG
1461 NewOwner,\r
1462 self._From,\r
1463 self._LineIndex + 1,\r
1464 - 1,\r
1465 self._LineIndex + 1,\r
1466 - 1,\r
1467 self._Enabled\r
1468 )\r
1469 self._IdMapping[Id] = self._LastItem\r
1470\r
1471 GlobalData.gPlatformDefines.update(self._FileLocalMacros)\r
1472 self._PostProcessed = True\r
1473 self._Content = None\r
09ef8e92
YF
1474 def _ProcessError(self):\r
1475 if not self._Enabled:\r
1476 return\r
1477 EdkLogger.error('Parser', ERROR_STATEMENT, self._ValueList[1], File=self.MetaFile, Line=self._LineIndex + 1)\r
f51461c8
LG
1478\r
1479 def __ProcessSectionHeader(self):\r
1480 self._SectionName = self._ValueList[0]\r
1481 if self._SectionName in self.DataType:\r
1482 self._SectionType = self.DataType[self._SectionName]\r
1483 else:\r
1484 self._SectionType = MODEL_UNKNOWN\r
1485\r
1486 def __ProcessSubsectionHeader(self):\r
1487 self._SubsectionName = self._ValueList[0]\r
1488 if self._SubsectionName in self.DataType:\r
1489 self._SubsectionType = self.DataType[self._SubsectionName]\r
1490 else:\r
1491 self._SubsectionType = MODEL_UNKNOWN\r
1492\r
1493 def __RetrievePcdValue(self):\r
f51461c8
LG
1494 Content = open(str(self.MetaFile), 'r').readlines()\r
1495 GlobalData.gPlatformOtherPcds['DSCFILE'] = str(self.MetaFile)\r
1496 for PcdType in (MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_HII,\r
1497 MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_DYNAMIC_EX_HII,\r
1498 MODEL_PCD_DYNAMIC_EX_VPD):\r
1499 Records = self._RawTable.Query(PcdType, BelongsToItem= -1.0)\r
ccaa7754 1500 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, Dummy4, ID, Line in Records:\r
f51461c8
LG
1501 Name = TokenSpaceGuid + '.' + PcdName\r
1502 if Name not in GlobalData.gPlatformOtherPcds:\r
1503 PcdLine = Line\r
1504 while not Content[Line - 1].lstrip().startswith(TAB_SECTION_START):\r
1505 Line -= 1\r
1506 GlobalData.gPlatformOtherPcds[Name] = (CleanString(Content[Line - 1]), PcdLine, PcdType)\r
1507\r
1508 def __ProcessDefine(self):\r
1509 if not self._Enabled:\r
1510 return\r
1511\r
1512 Type, Name, Value = self._ValueList\r
1513 Value = ReplaceMacro(Value, self._Macros, False)\r
97fa0ee9
YL
1514 #\r
1515 # If it is <Defines>, return\r
1516 #\r
1517 if self._InSubsection:\r
1518 self._ValueList = [Type, Name, Value]\r
1519 return\r
1520\r
f51461c8
LG
1521 if self._ItemType == MODEL_META_DATA_DEFINE:\r
1522 if self._SectionType == MODEL_META_DATA_HEADER:\r
1523 self._FileLocalMacros[Name] = Value\r
1524 else:\r
1525 self._ConstructSectionMacroDict(Name, Value)\r
1526 elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE:\r
1527 GlobalData.gEdkGlobal[Name] = Value\r
1528\r
1529 #\r
1530 # Keyword in [Defines] section can be used as Macros\r
1531 #\r
1532 if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER):\r
1533 self._FileLocalMacros[Name] = Value\r
1534\r
1535 self._ValueList = [Type, Name, Value]\r
1536\r
1537 def __ProcessDirective(self):\r
1538 Result = None\r
1539 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1540 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF]:\r
1541 Macros = self._Macros\r
1542 Macros.update(GlobalData.gGlobalDefines)\r
1543 try:\r
1544 Result = ValueExpression(self._ValueList[1], Macros)()\r
5b0671c1 1545 except SymbolNotFound as Exc:\r
f51461c8
LG
1546 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])\r
1547 Result = False\r
5b0671c1 1548 except WrnExpression as Excpt:\r
f7496d71 1549 #\r
f51461c8
LG
1550 # Catch expression evaluation warning here. We need to report\r
1551 # the precise number of line and return the evaluation result\r
1552 #\r
1553 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),\r
1554 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1555 Line=self._LineIndex + 1)\r
1556 Result = Excpt.result\r
1557\r
1558 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1559 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
1560 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:\r
1561 self._DirectiveStack.append(self._ItemType)\r
1562 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF:\r
1563 Result = bool(Result)\r
1564 else:\r
1565 Macro = self._ValueList[1]\r
1566 Macro = Macro[2:-1] if (Macro.startswith("$(") and Macro.endswith(")")) else Macro\r
1567 Result = Macro in self._Macros\r
1568 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF:\r
1569 Result = not Result\r
1570 self._DirectiveEvalStack.append(Result)\r
1571 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF:\r
1572 self._DirectiveStack.append(self._ItemType)\r
1573 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]\r
1574 self._DirectiveEvalStack.append(bool(Result))\r
1575 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:\r
1576 self._DirectiveStack.append(self._ItemType)\r
1577 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]\r
1578 self._DirectiveEvalStack.append(True)\r
1579 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:\r
1580 # Back to the nearest !if/!ifdef/!ifndef\r
1581 while self._DirectiveStack:\r
1582 self._DirectiveEvalStack.pop()\r
1583 Directive = self._DirectiveStack.pop()\r
1584 if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1585 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
1586 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:\r
1587 break\r
1588 elif self._ItemType == MODEL_META_DATA_INCLUDE:\r
1589 # The included file must be relative to workspace or same directory as DSC file\r
1590 __IncludeMacros = {}\r
1591 #\r
1592 # Allow using system environment variables in path after !include\r
1593 #\r
1594 __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE']\r
f51461c8 1595 #\r
f7496d71 1596 # Allow using MACROs comes from [Defines] section to keep compatible.\r
f51461c8
LG
1597 #\r
1598 __IncludeMacros.update(self._Macros)\r
1599\r
1600 IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True))\r
1601 #\r
1602 # First search the include file under the same directory as DSC file\r
1603 #\r
1604 IncludedFile1 = PathClass(IncludedFile, self.MetaFile.Dir)\r
1605 ErrorCode, ErrorInfo1 = IncludedFile1.Validate()\r
1606 if ErrorCode != 0:\r
1607 #\r
1608 # Also search file under the WORKSPACE directory\r
1609 #\r
1610 IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)\r
1611 ErrorCode, ErrorInfo2 = IncludedFile1.Validate()\r
1612 if ErrorCode != 0:\r
1613 EdkLogger.error('parser', ErrorCode, File=self._FileWithError,\r
1614 Line=self._LineIndex + 1, ExtraData=ErrorInfo1 + "\n" + ErrorInfo2)\r
1615\r
1616 self._FileWithError = IncludedFile1\r
1617\r
33787826 1618 FromItem = self._Content[self._ContentIndex - 1][0]\r
a802b269 1619 if self._InSubsection:\r
33787826
YF
1620 Owner = self._Content[self._ContentIndex - 1][8]\r
1621 else:\r
1622 Owner = self._Content[self._ContentIndex - 1][0]\r
2f818ed0 1623 IncludedFileTable = MetaFileStorage(self._RawTable.DB, IncludedFile1, MODEL_FILE_DSC, False, FromItem=FromItem)\r
cdd1b5e5 1624 Parser = DscParser(IncludedFile1, self._FileType, self._Arch, IncludedFileTable,\r
33787826 1625 Owner=Owner, From=FromItem)\r
f51461c8 1626\r
c17956e0
DL
1627 self.IncludedFiles.add (IncludedFile1)\r
1628\r
f51461c8
LG
1629 # set the parser status with current status\r
1630 Parser._SectionName = self._SectionName\r
cd7bd491
YF
1631 Parser._SubsectionType = self._SubsectionType\r
1632 Parser._InSubsection = self._InSubsection\r
1633 Parser._SectionType = self._SectionType\r
f51461c8
LG
1634 Parser._Scope = self._Scope\r
1635 Parser._Enabled = self._Enabled\r
1636 # Parse the included file\r
643556fc 1637 Parser.StartParse()\r
f51461c8
LG
1638 # Insert all records in the table for the included file into dsc file table\r
1639 Records = IncludedFileTable.GetAll()\r
1640 if Records:\r
1641 self._Content[self._ContentIndex:self._ContentIndex] = Records\r
1642 self._Content.pop(self._ContentIndex - 1)\r
1643 self._ValueList = None\r
1644 self._ContentIndex -= 1\r
1645\r
1646 def __ProcessSkuId(self):\r
1647 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)\r
1648 for Value in self._ValueList]\r
8518bf0b
LG
1649 def __ProcessDefaultStores(self):\r
1650 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)\r
1651 for Value in self._ValueList]\r
f51461c8
LG
1652\r
1653 def __ProcessLibraryInstance(self):\r
1654 self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]\r
1655\r
1656 def __ProcessLibraryClass(self):\r
1657 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True)\r
1658\r
1659 def __ProcessPcd(self):\r
1660 if self._ItemType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:\r
1661 self._ValueList[2] = ReplaceMacro(self._ValueList[2], self._Macros, RaiseError=True)\r
1662 return\r
1663\r
1664 ValList, Valid, Index = AnalyzeDscPcd(self._ValueList[2], self._ItemType)\r
1665 if not Valid:\r
f2cc33d8 1666 if self._ItemType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE):\r
ff4d0f85
YZ
1667 if ValList[1] != TAB_VOID and StructPattern.match(ValList[1]) is None and ValList[2]:\r
1668 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect. The datum type info should be VOID* or a valid struct name.", File=self._FileWithError,\r
f2cc33d8 1669 Line=self._LineIndex + 1, ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))\r
47fea6af 1670 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self._FileWithError, Line=self._LineIndex + 1,\r
f51461c8
LG
1671 ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))\r
1672 PcdValue = ValList[Index]\r
ae7b6df8 1673 if PcdValue and "." not in self._ValueList[0]:\r
f51461c8
LG
1674 try:\r
1675 ValList[Index] = ValueExpression(PcdValue, self._Macros)(True)\r
5b0671c1 1676 except WrnExpression as Value:\r
f51461c8 1677 ValList[Index] = Value.result\r
35f613d9
YF
1678 except:\r
1679 pass\r
f51461c8
LG
1680\r
1681 if ValList[Index] == 'True':\r
1682 ValList[Index] = '1'\r
1683 if ValList[Index] == 'False':\r
1684 ValList[Index] = '0'\r
1685\r
22a99b87
YL
1686 if (not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack):\r
1687 GlobalData.gPlatformPcds[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue\r
1688 self._Symbols[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue\r
ae7b6df8
LG
1689 try:\r
1690 self._ValueList[2] = '|'.join(ValList)\r
1691 except Exception:\r
72443dd2 1692 print(ValList)\r
f51461c8
LG
1693\r
1694 def __ProcessComponent(self):\r
1695 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)\r
1696\r
1697 def __ProcessSourceOverridePath(self):\r
1698 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)\r
1699\r
1700 def __ProcessBuildOption(self):\r
1701 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False)\r
1702 for Value in self._ValueList]\r
1703\r
5bc96263
FB
1704 def DisableOverrideComponent(self,module_id):\r
1705 for ori_id in self._IdMapping:\r
1706 if self._IdMapping[ori_id] == module_id:\r
1707 self._RawTable.DisableComponent(ori_id)\r
1708\r
f51461c8
LG
1709 _SectionParser = {\r
1710 MODEL_META_DATA_HEADER : _DefineParser,\r
1711 MODEL_EFI_SKU_ID : _SkuIdParser,\r
8518bf0b 1712 MODEL_EFI_DEFAULT_STORES : _DefaultStoresParser,\r
f51461c8
LG
1713 MODEL_EFI_LIBRARY_INSTANCE : _LibraryInstanceParser,\r
1714 MODEL_EFI_LIBRARY_CLASS : _LibraryClassParser,\r
1715 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,\r
1716 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,\r
1717 MODEL_PCD_FEATURE_FLAG : _PcdParser,\r
1718 MODEL_PCD_DYNAMIC_DEFAULT : _PcdParser,\r
1719 MODEL_PCD_DYNAMIC_HII : _PcdParser,\r
1720 MODEL_PCD_DYNAMIC_VPD : _PcdParser,\r
1721 MODEL_PCD_DYNAMIC_EX_DEFAULT : _PcdParser,\r
1722 MODEL_PCD_DYNAMIC_EX_HII : _PcdParser,\r
1723 MODEL_PCD_DYNAMIC_EX_VPD : _PcdParser,\r
1724 MODEL_META_DATA_COMPONENT : _ComponentParser,\r
1725 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : _CompponentSourceOverridePathParser,\r
1726 MODEL_META_DATA_BUILD_OPTION : _BuildOptionParser,\r
1727 MODEL_UNKNOWN : MetaFileParser._Skip,\r
0923aa1c 1728 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,\r
f51461c8
LG
1729 MODEL_META_DATA_SECTION_HEADER : MetaFileParser._SectionHeaderParser,\r
1730 MODEL_META_DATA_SUBSECTION_HEADER : _SubsectionHeaderParser,\r
1731 }\r
1732\r
f51461c8
LG
1733## DEC file parser class\r
1734#\r
1735# @param FilePath The path of platform description file\r
1736# @param FileType The raw data of DSC file\r
1737# @param Table Database used to retrieve module/package information\r
1738# @param Macros Macros used for replacement in file\r
1739#\r
1740class DecParser(MetaFileParser):\r
1741 # DEC file supported data types (one type per section)\r
1742 DataType = {\r
1743 TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER,\r
1744 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,\r
1745 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,\r
1746 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,\r
1747 TAB_GUIDS.upper() : MODEL_EFI_GUID,\r
1748 TAB_PPIS.upper() : MODEL_EFI_PPI,\r
1749 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,\r
1750 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,\r
1751 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,\r
1752 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,\r
1753 TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC,\r
1754 TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX,\r
0923aa1c 1755 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION,\r
f51461c8
LG
1756 }\r
1757\r
1758 ## Constructor of DecParser\r
1759 #\r
1760 # Initialize object of DecParser\r
1761 #\r
1762 # @param FilePath The path of platform description file\r
1763 # @param FileType The raw data of DSC file\r
cdd1b5e5 1764 # @param Arch Default Arch value for filtering sections\r
f51461c8 1765 # @param Table Database used to retrieve module/package information\r
f51461c8 1766 #\r
cdd1b5e5 1767 def __init__(self, FilePath, FileType, Arch, Table):\r
f51461c8
LG
1768 # prevent re-initialization\r
1769 if hasattr(self, "_Table"):\r
1770 return\r
cdd1b5e5 1771 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, -1)\r
f51461c8
LG
1772 self._Comments = []\r
1773 self._Version = 0x00010005 # Only EDK2 dec file is supported\r
1774 self._AllPCDs = [] # Only for check duplicate PCD\r
67e11e4d 1775 self._AllPcdDict = {}\r
f51461c8 1776\r
ae7b6df8
LG
1777 self._CurrentStructurePcdName = ""\r
1778 self._include_flag = False\r
1779 self._package_flag = False\r
1780\r
f51461c8
LG
1781 ## Parser starter\r
1782 def Start(self):\r
1783 Content = ''\r
1784 try:\r
1785 Content = open(str(self.MetaFile), 'r').readlines()\r
1786 except:\r
1787 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)\r
1788\r
778aad47 1789 self._DefinesCount = 0\r
f51461c8
LG
1790 for Index in range(0, len(Content)):\r
1791 Line, Comment = CleanString2(Content[Index])\r
1792 self._CurrentLine = Line\r
1793 self._LineIndex = Index\r
1794\r
1795 # save comment for later use\r
1796 if Comment:\r
1797 self._Comments.append((Comment, self._LineIndex + 1))\r
1798 # skip empty line\r
1799 if Line == '':\r
1800 continue\r
1801\r
1802 # section header\r
1803 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:\r
1804 self._SectionHeaderParser()\r
778aad47
YF
1805 if self._SectionName == TAB_DEC_DEFINES.upper():\r
1806 self._DefinesCount += 1\r
f51461c8
LG
1807 self._Comments = []\r
1808 continue\r
778aad47
YF
1809 if self._SectionType == MODEL_UNKNOWN:\r
1810 EdkLogger.error("Parser", FORMAT_INVALID,\r
1811 ""\r
1812 "Not able to determine \"%s\" in which section."%self._CurrentLine,\r
1813 self.MetaFile, self._LineIndex + 1)\r
f51461c8
LG
1814 elif len(self._SectionType) == 0:\r
1815 self._Comments = []\r
1816 continue\r
1817\r
1818 # section content\r
1819 self._ValueList = ['', '', '']\r
1820 self._SectionParser[self._SectionType[0]](self)\r
4231a819 1821 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:\r
f51461c8
LG
1822 self._ItemType = -1\r
1823 self._Comments = []\r
1824 continue\r
1825\r
1826 #\r
1827 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,\r
1828 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1\r
1829 #\r
1830 for Arch, ModuleType, Type in self._Scope:\r
1831 self._LastItem = self._Store(\r
1832 Type,\r
1833 self._ValueList[0],\r
1834 self._ValueList[1],\r
1835 self._ValueList[2],\r
1836 Arch,\r
1837 ModuleType,\r
1838 self._Owner[-1],\r
1839 self._LineIndex + 1,\r
1840 - 1,\r
1841 self._LineIndex + 1,\r
1842 - 1,\r
1843 0\r
1844 )\r
1845 for Comment, LineNo in self._Comments:\r
1846 self._Store(\r
1847 MODEL_META_DATA_COMMENT,\r
1848 Comment,\r
1849 self._ValueList[0],\r
1850 self._ValueList[1],\r
1851 Arch,\r
1852 ModuleType,\r
1853 self._LastItem,\r
1854 LineNo,\r
1855 - 1,\r
1856 LineNo,\r
1857 - 1,\r
1858 0\r
1859 )\r
1860 self._Comments = []\r
778aad47
YF
1861 if self._DefinesCount > 1:\r
1862 EdkLogger.error('Parser', FORMAT_INVALID, 'Multiple [Defines] section is exist.', self.MetaFile )\r
1863 if self._DefinesCount == 0:\r
ccaa7754 1864 EdkLogger.error('Parser', FORMAT_INVALID, 'No [Defines] section exist.', self.MetaFile)\r
f51461c8
LG
1865 self._Done()\r
1866\r
1867\r
1868 ## Section header parser\r
1869 #\r
1870 # The section header is always in following format:\r
1871 #\r
1872 # [section_name.arch<.platform|module_type>]\r
1873 #\r
1874 def _SectionHeaderParser(self):\r
1875 self._Scope = []\r
1876 self._SectionName = ''\r
1877 self._SectionType = []\r
1878 ArchList = set()\r
c28d2e10 1879 PrivateList = set()\r
07959205 1880 Line = re.sub(',[\s]*', TAB_COMMA_SPLIT, self._CurrentLine)\r
f51461c8
LG
1881 for Item in Line[1:-1].split(TAB_COMMA_SPLIT):\r
1882 if Item == '':\r
1883 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR,\r
1884 "section name can NOT be empty or incorrectly use separator comma",\r
1885 self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
1886 ItemList = Item.split(TAB_SPLIT)\r
1887\r
1888 # different types of PCD are permissible in one section\r
1889 self._SectionName = ItemList[0].upper()\r
778aad47
YF
1890 if self._SectionName == TAB_DEC_DEFINES.upper() and (len(ItemList) > 1 or len(Line.split(TAB_COMMA_SPLIT)) > 1):\r
1891 EdkLogger.error("Parser", FORMAT_INVALID, "Defines section format is invalid",\r
1892 self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
f51461c8
LG
1893 if self._SectionName in self.DataType:\r
1894 if self.DataType[self._SectionName] not in self._SectionType:\r
1895 self._SectionType.append(self.DataType[self._SectionName])\r
1896 else:\r
1897 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,\r
1898 self.MetaFile, self._LineIndex + 1, self._CurrentLine)\r
1899\r
1900 if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:\r
1901 EdkLogger.error(\r
1902 'Parser',\r
1903 FORMAT_INVALID,\r
1904 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,\r
1905 File=self.MetaFile,\r
1906 Line=self._LineIndex + 1,\r
1907 ExtraData=self._CurrentLine\r
1908 )\r
1909 # S1 is always Arch\r
1910 if len(ItemList) > 1:\r
1911 S1 = ItemList[1].upper()\r
1912 else:\r
55c84777 1913 S1 = TAB_ARCH_COMMON\r
f51461c8
LG
1914 ArchList.add(S1)\r
1915 # S2 may be Platform or ModuleType\r
1916 if len(ItemList) > 2:\r
1917 S2 = ItemList[2].upper()\r
c28d2e10
YZ
1918 # only Includes, GUIDs, PPIs, Protocols section have Private tag\r
1919 if self._SectionName in [TAB_INCLUDES.upper(), TAB_GUIDS.upper(), TAB_PROTOCOLS.upper(), TAB_PPIS.upper()]:\r
1920 if S2 != 'PRIVATE':\r
1921 EdkLogger.error("Parser", FORMAT_INVALID, 'Please use keyword "Private" as section tag modifier.',\r
1922 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
f51461c8 1923 else:\r
55c84777 1924 S2 = TAB_COMMON\r
c28d2e10 1925 PrivateList.add(S2)\r
f51461c8
LG
1926 if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:\r
1927 self._Scope.append([S1, S2, self.DataType[self._SectionName]])\r
1928\r
1929 # 'COMMON' must not be used with specific ARCHs at the same section\r
55c84777 1930 if TAB_ARCH_COMMON in ArchList and len(ArchList) > 1:\r
f51461c8
LG
1931 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",\r
1932 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
c28d2e10
YZ
1933\r
1934 # It is not permissible to mix section tags without the Private attribute with section tags with the Private attribute\r
55c84777 1935 if TAB_COMMON in PrivateList and len(PrivateList) > 1:\r
c28d2e10
YZ
1936 EdkLogger.error('Parser', FORMAT_INVALID, "Can't mix section tags without the Private attribute with section tags with the Private attribute",\r
1937 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)\r
f51461c8
LG
1938\r
1939 ## [guids], [ppis] and [protocols] section parser\r
1940 @ParseMacro\r
1941 def _GuidParser(self):\r
1942 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
1943 if len(TokenList) < 2:\r
1944 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",\r
1945 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1946 File=self.MetaFile, Line=self._LineIndex + 1)\r
1947 if TokenList[0] == '':\r
1948 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",\r
1949 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1950 File=self.MetaFile, Line=self._LineIndex + 1)\r
1951 if TokenList[1] == '':\r
1952 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",\r
1953 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1954 File=self.MetaFile, Line=self._LineIndex + 1)\r
1955 if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':\r
1956 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",\r
1957 ExtraData=self._CurrentLine + \\r
1958 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",\r
1959 File=self.MetaFile, Line=self._LineIndex + 1)\r
1960 self._ValueList[0] = TokenList[0]\r
1961 self._ValueList[1] = TokenList[1]\r
726c501c
YZ
1962 if self._ValueList[0] not in self._GuidDict:\r
1963 self._GuidDict[self._ValueList[0]] = self._ValueList[1]\r
f51461c8 1964\r
72a1d776 1965 def ParsePcdName(self,namelist):\r
1966 if "[" in namelist[1]:\r
1967 pcdname = namelist[1][:namelist[1].index("[")]\r
1968 arrayindex = namelist[1][namelist[1].index("["):]\r
1969 namelist[1] = pcdname\r
1970 if len(namelist) == 2:\r
1971 namelist.append(arrayindex)\r
1972 else:\r
1973 namelist[2] = ".".join((arrayindex,namelist[2]))\r
1974 return namelist\r
1975\r
f51461c8
LG
1976 ## PCD sections parser\r
1977 #\r
1978 # [PcdsFixedAtBuild]\r
1979 # [PcdsPatchableInModule]\r
1980 # [PcdsFeatureFlag]\r
1981 # [PcdsDynamicEx\r
1982 # [PcdsDynamic]\r
1983 #\r
1984 @ParseMacro\r
1985 def _PcdParser(self):\r
ae7b6df8
LG
1986 if self._CurrentStructurePcdName:\r
1987 self._ValueList[0] = self._CurrentStructurePcdName\r
1988\r
1989 if "|" not in self._CurrentLine:\r
1990 if "<HeaderFiles>" == self._CurrentLine:\r
1991 self._include_flag = True\r
81add864 1992 self._package_flag = False\r
ae7b6df8
LG
1993 self._ValueList = None\r
1994 return\r
1995 if "<Packages>" == self._CurrentLine:\r
1996 self._package_flag = True\r
1997 self._ValueList = None\r
81add864 1998 self._include_flag = False\r
ae7b6df8
LG
1999 return\r
2000\r
2001 if self._include_flag:\r
1ccc4d89 2002 self._ValueList[1] = "<HeaderFiles>_" + md5(self._CurrentLine).hexdigest()\r
ae7b6df8 2003 self._ValueList[2] = self._CurrentLine\r
ae7b6df8 2004 if self._package_flag and "}" != self._CurrentLine:\r
1ccc4d89 2005 self._ValueList[1] = "<Packages>_" + md5(self._CurrentLine).hexdigest()\r
ae7b6df8
LG
2006 self._ValueList[2] = self._CurrentLine\r
2007 if self._CurrentLine == "}":\r
2008 self._package_flag = False\r
81add864 2009 self._include_flag = False\r
ae7b6df8
LG
2010 self._ValueList = None\r
2011 return\r
2012 else:\r
2013 PcdTockens = self._CurrentLine.split(TAB_VALUE_SPLIT)\r
72a1d776 2014 PcdNames = self.ParsePcdName(PcdTockens[0].split(TAB_SPLIT))\r
ae7b6df8 2015 if len(PcdNames) == 2:\r
72a1d776 2016 if PcdNames[1].strip().endswith("]"):\r
2017 PcdName = PcdNames[1][:PcdNames[1].index('[')]\r
2018 Index = PcdNames[1][PcdNames[1].index('['):]\r
2019 self._ValueList[0] = TAB_SPLIT.join((PcdNames[0],PcdName))\r
2020 self._ValueList[1] = Index\r
2021 self._ValueList[2] = PcdTockens[1]\r
2022 else:\r
2023 self._CurrentStructurePcdName = ""\r
ae7b6df8 2024 else:\r
8e011d83 2025 if self._CurrentStructurePcdName != TAB_SPLIT.join(PcdNames[:2]):\r
ccaa7754 2026 EdkLogger.error('Parser', FORMAT_INVALID, "Pcd Name does not match: %s and %s " % (self._CurrentStructurePcdName, TAB_SPLIT.join(PcdNames[:2])),\r
8e011d83 2027 File=self.MetaFile, Line=self._LineIndex + 1)\r
a0939593 2028 self._ValueList[1] = TAB_SPLIT.join(PcdNames[2:])\r
ae7b6df8
LG
2029 self._ValueList[2] = PcdTockens[1]\r
2030 if not self._CurrentStructurePcdName:\r
2031 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
2032 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
2033 ValueRe = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*')\r
2034 # check PCD information\r
2035 if self._ValueList[0] == '' or self._ValueList[1] == '':\r
2036 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
2037 ExtraData=self._CurrentLine + \\r
2038 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2039 File=self.MetaFile, Line=self._LineIndex + 1)\r
2040 # check format of token space GUID CName\r
2041 if not ValueRe.match(self._ValueList[0]):\r
2042 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
2043 ExtraData=self._CurrentLine + \\r
2044 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2045 File=self.MetaFile, Line=self._LineIndex + 1)\r
2046 # check format of PCD CName\r
2047 if not ValueRe.match(self._ValueList[1]):\r
2048 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
2049 ExtraData=self._CurrentLine + \\r
2050 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2051 File=self.MetaFile, Line=self._LineIndex + 1)\r
2052 # check PCD datum information\r
2053 if len(TokenList) < 2 or TokenList[1] == '':\r
2054 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",\r
2055 ExtraData=self._CurrentLine + \\r
2056 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2057 File=self.MetaFile, Line=self._LineIndex + 1)\r
2058\r
2059\r
2060 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')\r
2061 PtrValue = ValueRe.findall(TokenList[1])\r
2062\r
2063 # Has VOID* type string, may contain "|" character in the string.\r
2064 if len(PtrValue) != 0:\r
2065 ptrValueList = re.sub(ValueRe, '', TokenList[1])\r
2066 ValueList = AnalyzePcdExpression(ptrValueList)\r
2067 ValueList[0] = PtrValue[0]\r
2068 else:\r
2069 ValueList = AnalyzePcdExpression(TokenList[1])\r
2070\r
2071\r
2072 # check if there's enough datum information given\r
2073 if len(ValueList) != 3:\r
2074 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",\r
2075 ExtraData=self._CurrentLine + \\r
2076 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2077 File=self.MetaFile, Line=self._LineIndex + 1)\r
2078 # check default value\r
2079 if ValueList[0] == '':\r
2080 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",\r
2081 ExtraData=self._CurrentLine + \\r
2082 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2083 File=self.MetaFile, Line=self._LineIndex + 1)\r
2084 # check datum type\r
2085 if ValueList[1] == '':\r
2086 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",\r
2087 ExtraData=self._CurrentLine + \\r
2088 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2089 File=self.MetaFile, Line=self._LineIndex + 1)\r
2090 # check token of the PCD\r
2091 if ValueList[2] == '':\r
2092 EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",\r
2093 ExtraData=self._CurrentLine + \\r
2094 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
2095 File=self.MetaFile, Line=self._LineIndex + 1)\r
2096\r
2097 PcdValue = ValueList[0]\r
2098 if PcdValue:\r
726c501c 2099 try:\r
9efe8d60 2100 self._GuidDict.update(self._AllPcdDict)\r
726c501c 2101 ValueList[0] = ValueExpressionEx(ValueList[0], ValueList[1], self._GuidDict)(True)\r
5b0671c1 2102 except BadExpression as Value:\r
726c501c 2103 EdkLogger.error('Parser', FORMAT_INVALID, Value, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
ae7b6df8
LG
2104 # check format of default value against the datum type\r
2105 IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])\r
2106 if not IsValid:\r
2107 EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,\r
2108 File=self.MetaFile, Line=self._LineIndex + 1)\r
2109\r
2110 if Cause == "StructurePcd":\r
2111 self._CurrentStructurePcdName = TAB_SPLIT.join(self._ValueList[0:2])\r
2112 self._ValueList[0] = self._CurrentStructurePcdName\r
2113 self._ValueList[1] = ValueList[1].strip()\r
2114\r
2115 if ValueList[0] in ['True', 'true', 'TRUE']:\r
2116 ValueList[0] = '1'\r
2117 elif ValueList[0] in ['False', 'false', 'FALSE']:\r
2118 ValueList[0] = '0'\r
2119\r
2120 # check for duplicate PCD definition\r
2121 if (self._Scope[0], self._ValueList[0], self._ValueList[1]) in self._AllPCDs:\r
2122 EdkLogger.error('Parser', FORMAT_INVALID,\r
2123 "The same PCD name and GUID have been already defined",\r
2124 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
2125 else:\r
2126 self._AllPCDs.append((self._Scope[0], self._ValueList[0], self._ValueList[1]))\r
2127 self._AllPcdDict[TAB_SPLIT.join(self._ValueList[0:2])] = ValueList[0]\r
f51461c8 2128\r
ae7b6df8 2129 self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()\r
f51461c8
LG
2130\r
2131 _SectionParser = {\r
2132 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,\r
2133 MODEL_EFI_INCLUDE : MetaFileParser._PathParser,\r
2134 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,\r
2135 MODEL_EFI_GUID : _GuidParser,\r
2136 MODEL_EFI_PPI : _GuidParser,\r
2137 MODEL_EFI_PROTOCOL : _GuidParser,\r
2138 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,\r
2139 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,\r
2140 MODEL_PCD_FEATURE_FLAG : _PcdParser,\r
2141 MODEL_PCD_DYNAMIC : _PcdParser,\r
2142 MODEL_PCD_DYNAMIC_EX : _PcdParser,\r
2143 MODEL_UNKNOWN : MetaFileParser._Skip,\r
0923aa1c 2144 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,\r
f51461c8
LG
2145 }\r
2146\r
2147##\r
2148#\r
2149# This acts like the main() function for the script, unless it is 'import'ed into another\r
2150# script.\r
2151#\r
2152if __name__ == '__main__':\r
2153 pass\r
2154\r