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