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