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