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