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