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