]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/Ecc/MetaFileWorkspace/MetaFileParser.py
BaseTools: Remove the logic SourceOverridePath
[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
855698fb 25import Ecc.EccGlobalData as EccGlobalData\r
26import Ecc.EccToolError as 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
855698fb 35from Ecc.MetaFileWorkspace.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
938cf4c3 43 Match = GlobalData.gMacroDefPattern.match(self._CurrentLine)\r
f51461c8
LG
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
938cf4c3 64 if not GlobalData.gMacroNamePattern.match(Name):\r
f51461c8
LG
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
f51461c8
LG
613 self._ValueList[Index] = ReplaceMacro(Value, Macros)\r
614\r
615 ## Parse [Sources] section\r
616 #\r
617 # Only path can have macro used. So we need to replace them before use.\r
618 #\r
619 @ParseMacro\r
620 def _SourceFileParser(self):\r
621 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
622 self._ValueList[0:len(TokenList)] = TokenList\r
623 Macros = self._Macros\r
624 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'\r
625 if 'COMPONENT_TYPE' in Macros:\r
626 if self._Defines['COMPONENT_TYPE'].upper() == 'ACPITABLE':\r
627 self._ValueList[0] = GetSplitValueList(self._ValueList[0], ' ', 1)[0]\r
628 if self._Defines['BASE_NAME'] == 'Microcode':\r
629 pass\r
630 self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]\r
631\r
632 ## Parse [Binaries] section\r
633 #\r
634 # Only path can have macro used. So we need to replace them before use.\r
635 #\r
636 @ParseMacro\r
637 def _BinaryFileParser(self):\r
638 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 2)\r
639 if len(TokenList) < 2:\r
640 EdkLogger.error('Parser', FORMAT_INVALID, "No file type or path specified",\r
641 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",\r
642 File=self.MetaFile, Line=self._LineIndex+1)\r
643 if not TokenList[0]:\r
644 EdkLogger.error('Parser', FORMAT_INVALID, "No file type specified",\r
645 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",\r
646 File=self.MetaFile, Line=self._LineIndex+1)\r
647 if not TokenList[1]:\r
648 EdkLogger.error('Parser', FORMAT_INVALID, "No file path specified",\r
649 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",\r
650 File=self.MetaFile, Line=self._LineIndex+1)\r
651 self._ValueList[0:len(TokenList)] = TokenList\r
652 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)\r
653\r
654 ## [nmake] section parser (Edk.x style only)\r
655 def _NmakeParser(self):\r
656 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
657 self._ValueList[0:len(TokenList)] = TokenList\r
658 # remove macros\r
659 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)\r
660 # remove self-reference in macro setting\r
661 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})\r
662\r
663 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser\r
664 @ParseMacro\r
665 def _PcdParser(self):\r
666 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
667 ValueList = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
668 if len(ValueList) != 2:\r
669 EdkLogger.error('Parser', FORMAT_INVALID, "Illegal token space GUID and PCD name format",\r
670 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",\r
671 File=self.MetaFile, Line=self._LineIndex+1)\r
672 self._ValueList[0:1] = ValueList\r
673 if len(TokenList) > 1:\r
674 self._ValueList[2] = TokenList[1]\r
675 if self._ValueList[0] == '' or self._ValueList[1] == '':\r
676 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
677 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",\r
678 File=self.MetaFile, Line=self._LineIndex+1)\r
679\r
680 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.\r
681 if self._ValueList[2] != '':\r
682 InfPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)\r
683 if InfPcdValueList[0] in ['True', 'true', 'TRUE']:\r
684 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '1', 1);\r
685 elif InfPcdValueList[0] in ['False', 'false', 'FALSE']:\r
686 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '0', 1);\r
687\r
688 ## [depex] section parser\r
689 @ParseMacro\r
690 def _DepexParser(self):\r
691 self._ValueList[0:1] = [self._CurrentLine]\r
692\r
693 _SectionParser = {\r
694 MODEL_UNKNOWN : MetaFileParser._Skip,\r
695 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,\r
696 MODEL_META_DATA_BUILD_OPTION : MetaFileParser._BuildOptionParser,\r
697 MODEL_EFI_INCLUDE : _IncludeParser, # for Edk.x modules\r
698 MODEL_EFI_LIBRARY_INSTANCE : MetaFileParser._CommonParser, # for Edk.x modules\r
699 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,\r
700 MODEL_META_DATA_PACKAGE : MetaFileParser._PathParser,\r
701 MODEL_META_DATA_NMAKE : _NmakeParser, # for Edk.x modules\r
702 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,\r
703 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,\r
704 MODEL_PCD_FEATURE_FLAG : _PcdParser,\r
705 MODEL_PCD_DYNAMIC_EX : _PcdParser,\r
706 MODEL_PCD_DYNAMIC : _PcdParser,\r
707 MODEL_EFI_SOURCE_FILE : _SourceFileParser,\r
708 MODEL_EFI_GUID : MetaFileParser._CommonParser,\r
709 MODEL_EFI_PROTOCOL : MetaFileParser._CommonParser,\r
710 MODEL_EFI_PPI : MetaFileParser._CommonParser,\r
711 MODEL_EFI_DEPEX : _DepexParser,\r
712 MODEL_EFI_BINARY_FILE : _BinaryFileParser,\r
713 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip,\r
714 }\r
715\r
716## DSC file parser class\r
717#\r
718# @param FilePath The path of platform description file\r
719# @param FileType The raw data of DSC file\r
720# @param Table Database used to retrieve module/package information\r
721# @param Macros Macros used for replacement in file\r
722# @param Owner Owner ID (for sub-section parsing)\r
723# @param From ID from which the data comes (for !INCLUDE directive)\r
724#\r
725class DscParser(MetaFileParser):\r
726 # DSC file supported data types (one type per section)\r
727 DataType = {\r
728 TAB_SKUIDS.upper() : MODEL_EFI_SKU_ID,\r
729 TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,\r
730 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,\r
731 TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,\r
732 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,\r
733 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,\r
734 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,\r
735 TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_DEFAULT,\r
736 TAB_PCDS_DYNAMIC_HII_NULL.upper() : MODEL_PCD_DYNAMIC_HII,\r
737 TAB_PCDS_DYNAMIC_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_VPD,\r
738 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT,\r
739 TAB_PCDS_DYNAMIC_EX_HII_NULL.upper() : MODEL_PCD_DYNAMIC_EX_HII,\r
740 TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_EX_VPD,\r
741 TAB_COMPONENTS.upper() : MODEL_META_DATA_COMPONENT,\r
f51461c8
LG
742 TAB_DSC_DEFINES.upper() : MODEL_META_DATA_HEADER,\r
743 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,\r
744 TAB_DSC_DEFINES_EDKGLOBAL : MODEL_META_DATA_GLOBAL_DEFINE,\r
745 TAB_INCLUDE.upper() : MODEL_META_DATA_INCLUDE,\r
746 TAB_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
747 TAB_IF_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
748 TAB_IF_N_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF,\r
749 TAB_ELSE_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF,\r
750 TAB_ELSE.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,\r
751 TAB_END_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF,\r
8d62ae35 752 TAB_ERROR.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR,\r
f51461c8
LG
753 }\r
754\r
755 # Valid names in define section\r
756 DefineKeywords = [\r
757 "DSC_SPECIFICATION",\r
758 "PLATFORM_NAME",\r
759 "PLATFORM_GUID",\r
760 "PLATFORM_VERSION",\r
761 "SKUID_IDENTIFIER",\r
762 "PCD_INFO_GENERATION",\r
763 "SUPPORTED_ARCHITECTURES",\r
764 "BUILD_TARGETS",\r
765 "OUTPUT_DIRECTORY",\r
766 "FLASH_DEFINITION",\r
767 "BUILD_NUMBER",\r
768 "RFC_LANGUAGES",\r
769 "ISO_LANGUAGES",\r
770 "TIME_STAMP_FILE",\r
771 "VPD_TOOL_GUID",\r
772 "FIX_LOAD_TOP_MEMORY_ADDRESS"\r
773 ]\r
774\r
f05c2e9f
HC
775 SubSectionDefineKeywords = [\r
776 "FILE_GUID"\r
777 ]\r
778\r
f51461c8
LG
779 SymbolPattern = ValueExpression.SymbolPattern\r
780\r
781 ## Constructor of DscParser\r
782 #\r
783 # Initialize object of DscParser\r
784 #\r
785 # @param FilePath The path of platform description file\r
786 # @param FileType The raw data of DSC file\r
787 # @param Table Database used to retrieve module/package information\r
788 # @param Macros Macros used for replacement in file\r
789 # @param Owner Owner ID (for sub-section parsing)\r
790 # @param From ID from which the data comes (for !INCLUDE directive)\r
791 #\r
792 def __init__(self, FilePath, FileType, Table, Owner=-1, From=-1):\r
793 # prevent re-initialization\r
794 if hasattr(self, "_Table"):\r
795 return\r
796 MetaFileParser.__init__(self, FilePath, FileType, Table, Owner, From)\r
797 self._Version = 0x00010005 # Only EDK2 dsc file is supported\r
798 # to store conditional directive evaluation result\r
799 self._DirectiveStack = []\r
800 self._DirectiveEvalStack = []\r
801 self._Enabled = 1\r
802\r
803 # Final valid replacable symbols\r
804 self._Symbols = {}\r
805 #\r
806 # Map the ID between the original table and new table to track\r
807 # the owner item\r
808 #\r
809 self._IdMapping = {-1:-1}\r
f7496d71 810\r
f51461c8
LG
811 self.TblFile = EccGlobalData.gDb.TblFile\r
812 self.FileID = -1\r
813\r
814 ## Parser starter\r
815 def Start(self):\r
816 Content = ''\r
817 try:\r
818 Content = open(str(self.MetaFile.Path), 'r').readlines()\r
819 except:\r
820 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)\r
821 #\r
822 # Insert a record for file\r
823 #\r
824 Filename = NormPath(self.MetaFile.Path)\r
825 FileID = self.TblFile.GetFileId(Filename)\r
826 if FileID:\r
827 self.FileID = FileID\r
828 else:\r
829 self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_DSC)\r
f7496d71
LG
830\r
831\r
f51461c8
LG
832 for Index in range(0, len(Content)):\r
833 Line = CleanString(Content[Index])\r
834 # skip empty line\r
835 if Line == '':\r
836 continue\r
837\r
838 self._CurrentLine = Line\r
839 self._LineIndex = Index\r
840 if self._InSubsection and self._Owner[-1] == -1:\r
841 self._Owner.append(self._LastItem)\r
f7496d71 842\r
f51461c8
LG
843 # section header\r
844 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:\r
845 self._SectionType = MODEL_META_DATA_SECTION_HEADER\r
846 # subsection ending\r
847 elif Line[0] == '}' and self._InSubsection:\r
848 self._InSubsection = False\r
849 self._SubsectionType = MODEL_UNKNOWN\r
850 self._SubsectionName = ''\r
851 self._Owner[-1] = -1\r
852 continue\r
853 # subsection header\r
854 elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:\r
855 self._SubsectionType = MODEL_META_DATA_SUBSECTION_HEADER\r
856 # directive line\r
857 elif Line[0] == '!':\r
858 self._DirectiveParser()\r
859 continue\r
860\r
861 if self._InSubsection:\r
862 SectionType = self._SubsectionType\r
863 else:\r
864 SectionType = self._SectionType\r
865 self._ItemType = SectionType\r
866\r
867 self._ValueList = ['', '', '']\r
868 self._SectionParser[SectionType](self)\r
4231a819 869 if self._ValueList is None:\r
f51461c8
LG
870 continue\r
871 #\r
872 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,\r
873 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1\r
874 #\r
875 for Arch, ModuleType in self._Scope:\r
876 self._LastItem = self._Store(\r
877 self._ItemType,\r
878 self._ValueList[0],\r
879 self._ValueList[1],\r
880 self._ValueList[2],\r
881 Arch,\r
882 ModuleType,\r
883 self._Owner[-1],\r
884 self.FileID,\r
885 self._From,\r
886 self._LineIndex+1,\r
887 -1,\r
888 self._LineIndex+1,\r
889 -1,\r
890 self._Enabled\r
891 )\r
892\r
893 if self._DirectiveStack:\r
894 Type, Line, Text = self._DirectiveStack[-1]\r
895 EdkLogger.error('Parser', FORMAT_INVALID, "No matching '!endif' found",\r
896 ExtraData=Text, File=self.MetaFile, Line=Line)\r
897 self._Done()\r
898\r
899 ## <subsection_header> parser\r
900 def _SubsectionHeaderParser(self):\r
901 self._SubsectionName = self._CurrentLine[1:-1].upper()\r
902 if self._SubsectionName in self.DataType:\r
903 self._SubsectionType = self.DataType[self._SubsectionName]\r
904 else:\r
905 self._SubsectionType = MODEL_UNKNOWN\r
906 EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile,\r
907 Line=self._LineIndex+1, ExtraData=self._CurrentLine)\r
908 self._ValueList[0] = self._SubsectionName\r
909\r
910 ## Directive statement parser\r
911 def _DirectiveParser(self):\r
ccaa7754 912 self._ValueList = ['', '', '']\r
f51461c8
LG
913 TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)\r
914 self._ValueList[0:len(TokenList)] = TokenList\r
915\r
916 # Syntax check\r
917 DirectiveName = self._ValueList[0].upper()\r
918 if DirectiveName not in self.DataType:\r
919 EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName,\r
920 File=self.MetaFile, Line=self._LineIndex+1)\r
921 if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '':\r
922 EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression",\r
923 File=self.MetaFile, Line=self._LineIndex+1,\r
924 ExtraData=self._CurrentLine)\r
925\r
926 ItemType = self.DataType[DirectiveName]\r
927 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:\r
928 # Remove all directives between !if and !endif, including themselves\r
929 while self._DirectiveStack:\r
930 # Remove any !else or !elseif\r
931 DirectiveInfo = self._DirectiveStack.pop()\r
932 if DirectiveInfo[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
933 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
934 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:\r
935 break\r
936 else:\r
937 EdkLogger.error("Parser", FORMAT_INVALID, "Redundant '!endif'",\r
938 File=self.MetaFile, Line=self._LineIndex+1,\r
939 ExtraData=self._CurrentLine)\r
940 elif ItemType != MODEL_META_DATA_INCLUDE:\r
941 # Break if there's a !else is followed by a !elseif\r
942 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF and \\r
943 self._DirectiveStack and \\r
944 self._DirectiveStack[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:\r
945 EdkLogger.error("Parser", FORMAT_INVALID, "'!elseif' after '!else'",\r
946 File=self.MetaFile, Line=self._LineIndex+1,\r
947 ExtraData=self._CurrentLine)\r
948 self._DirectiveStack.append((ItemType, self._LineIndex+1, self._CurrentLine))\r
949 elif self._From > 0:\r
950 EdkLogger.error('Parser', FORMAT_INVALID,\r
951 "No '!include' allowed in included file",\r
f7496d71 952 ExtraData=self._CurrentLine, File=self.MetaFile,\r
f51461c8
LG
953 Line=self._LineIndex+1)\r
954\r
955 #\r
956 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,\r
957 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1\r
958 #\r
959 self._LastItem = self._Store(\r
960 ItemType,\r
961 self._ValueList[0],\r
962 self._ValueList[1],\r
963 self._ValueList[2],\r
964 'COMMON',\r
965 'COMMON',\r
966 self._Owner[-1],\r
967 self.FileID,\r
968 self._From,\r
969 self._LineIndex+1,\r
970 -1,\r
971 self._LineIndex+1,\r
972 -1,\r
973 0\r
974 )\r
975\r
976 ## [defines] section parser\r
977 @ParseMacro\r
978 def _DefineParser(self):\r
979 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
980 self._ValueList[1:len(TokenList)] = TokenList\r
981\r
982 # Syntax check\r
983 if not self._ValueList[1]:\r
984 EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",\r
985 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)\r
986 if not self._ValueList[2]:\r
987 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",\r
988 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)\r
f05c2e9f
HC
989 if (not self._ValueList[1] in self.DefineKeywords and\r
990 (self._InSubsection and self._ValueList[1] not in self.SubSectionDefineKeywords)):\r
f51461c8
LG
991 EdkLogger.error('Parser', FORMAT_INVALID,\r
992 "Unknown keyword found: %s. "\r
993 "If this is a macro you must "\r
994 "add it as a DEFINE in the DSC" % self._ValueList[1],\r
995 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)\r
996 self._Defines[self._ValueList[1]] = self._ValueList[2]\r
997 self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]\r
998\r
999 @ParseMacro\r
1000 def _SkuIdParser(self):\r
1001 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
1002 if len(TokenList) != 2:\r
1003 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Integer>|<UiName>'",\r
1004 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)\r
1005 self._ValueList[0:len(TokenList)] = TokenList\r
1006\r
1007 ## Parse Edk style of library modules\r
1008 def _LibraryInstanceParser(self):\r
1009 self._ValueList[0] = self._CurrentLine\r
1010\r
1011 ## PCD sections parser\r
1012 #\r
1013 # [PcdsFixedAtBuild]\r
1014 # [PcdsPatchableInModule]\r
1015 # [PcdsFeatureFlag]\r
1016 # [PcdsDynamicEx\r
1017 # [PcdsDynamicExDefault]\r
1018 # [PcdsDynamicExVpd]\r
1019 # [PcdsDynamicExHii]\r
1020 # [PcdsDynamic]\r
1021 # [PcdsDynamicDefault]\r
1022 # [PcdsDynamicVpd]\r
1023 # [PcdsDynamicHii]\r
1024 #\r
1025 @ParseMacro\r
1026 def _PcdParser(self):\r
1027 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
1028 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
1029 if len(TokenList) == 2:\r
1030 self._ValueList[2] = TokenList[1]\r
1031 if self._ValueList[0] == '' or self._ValueList[1] == '':\r
1032 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
1033 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",\r
1034 File=self.MetaFile, Line=self._LineIndex+1)\r
1035 if self._ValueList[2] == '':\r
1036 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",\r
1037 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",\r
1038 File=self.MetaFile, Line=self._LineIndex+1)\r
1039 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.\r
1040 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)\r
1041 if DscPcdValueList[0] in ['True', 'true', 'TRUE']:\r
1042 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1);\r
1043 elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:\r
1044 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);\r
1045\r
1046 ## [components] section parser\r
1047 @ParseMacro\r
1048 def _ComponentParser(self):\r
1049 if self._CurrentLine[-1] == '{':\r
1050 self._ValueList[0] = self._CurrentLine[0:-1].strip()\r
1051 self._InSubsection = True\r
1052 else:\r
1053 self._ValueList[0] = self._CurrentLine\r
1054\r
1055 ## [LibraryClasses] section\r
1056 @ParseMacro\r
1057 def _LibraryClassParser(self):\r
1058 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
1059 if len(TokenList) < 2:\r
1060 EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",\r
1061 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
1062 File=self.MetaFile, Line=self._LineIndex+1)\r
1063 if TokenList[0] == '':\r
1064 EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",\r
1065 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
1066 File=self.MetaFile, Line=self._LineIndex+1)\r
1067 if TokenList[1] == '':\r
1068 EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",\r
1069 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
1070 File=self.MetaFile, Line=self._LineIndex+1)\r
1071\r
1072 self._ValueList[0:len(TokenList)] = TokenList\r
1073\r
f51461c8
LG
1074\r
1075 ## [BuildOptions] section parser\r
1076 @ParseMacro\r
1077 def _BuildOptionParser(self):\r
1078 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
1079 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)\r
1080 if len(TokenList2) == 2:\r
1081 self._ValueList[0] = TokenList2[0] # toolchain family\r
1082 self._ValueList[1] = TokenList2[1] # keys\r
1083 else:\r
1084 self._ValueList[1] = TokenList[0]\r
1085 if len(TokenList) == 2: # value\r
1086 self._ValueList[2] = TokenList[1]\r
1087\r
1088 if self._ValueList[1].count('_') != 4:\r
1089 EdkLogger.error(\r
1090 'Parser',\r
1091 FORMAT_INVALID,\r
1092 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],\r
1093 ExtraData=self._CurrentLine,\r
1094 File=self.MetaFile,\r
1095 Line=self._LineIndex+1\r
1096 )\r
1097\r
1098 ## Override parent's method since we'll do all macro replacements in parser\r
1099 def _GetMacros(self):\r
94c04559 1100 Macros = dict( [('ARCH', 'IA32'), ('FAMILY', TAB_COMPILER_MSFT), ('TOOL_CHAIN_TAG', 'VS2008x86'), ('TARGET', 'DEBUG')])\r
f51461c8
LG
1101 Macros.update(self._FileLocalMacros)\r
1102 Macros.update(self._GetApplicableSectionMacro())\r
1103 Macros.update(GlobalData.gEdkGlobal)\r
1104 Macros.update(GlobalData.gPlatformDefines)\r
1105 Macros.update(GlobalData.gCommandLineDefines)\r
1106 # PCD cannot be referenced in macro definition\r
1107 if self._ItemType not in [MODEL_META_DATA_DEFINE, MODEL_META_DATA_GLOBAL_DEFINE]:\r
1108 Macros.update(self._Symbols)\r
1109 return Macros\r
1110\r
1111 def _PostProcess(self):\r
1112 Processer = {\r
1113 MODEL_META_DATA_SECTION_HEADER : self.__ProcessSectionHeader,\r
1114 MODEL_META_DATA_SUBSECTION_HEADER : self.__ProcessSubsectionHeader,\r
1115 MODEL_META_DATA_HEADER : self.__ProcessDefine,\r
1116 MODEL_META_DATA_DEFINE : self.__ProcessDefine,\r
1117 MODEL_META_DATA_GLOBAL_DEFINE : self.__ProcessDefine,\r
1118 MODEL_META_DATA_INCLUDE : self.__ProcessDirective,\r
1119 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF : self.__ProcessDirective,\r
1120 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE : self.__ProcessDirective,\r
1121 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF : self.__ProcessDirective,\r
1122 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF : self.__ProcessDirective,\r
1123 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF : self.__ProcessDirective,\r
1124 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF : self.__ProcessDirective,\r
1125 MODEL_EFI_SKU_ID : self.__ProcessSkuId,\r
1126 MODEL_EFI_LIBRARY_INSTANCE : self.__ProcessLibraryInstance,\r
1127 MODEL_EFI_LIBRARY_CLASS : self.__ProcessLibraryClass,\r
1128 MODEL_PCD_FIXED_AT_BUILD : self.__ProcessPcd,\r
1129 MODEL_PCD_PATCHABLE_IN_MODULE : self.__ProcessPcd,\r
1130 MODEL_PCD_FEATURE_FLAG : self.__ProcessPcd,\r
1131 MODEL_PCD_DYNAMIC_DEFAULT : self.__ProcessPcd,\r
1132 MODEL_PCD_DYNAMIC_HII : self.__ProcessPcd,\r
1133 MODEL_PCD_DYNAMIC_VPD : self.__ProcessPcd,\r
1134 MODEL_PCD_DYNAMIC_EX_DEFAULT : self.__ProcessPcd,\r
1135 MODEL_PCD_DYNAMIC_EX_HII : self.__ProcessPcd,\r
1136 MODEL_PCD_DYNAMIC_EX_VPD : self.__ProcessPcd,\r
1137 MODEL_META_DATA_COMPONENT : self.__ProcessComponent,\r
f51461c8
LG
1138 MODEL_META_DATA_BUILD_OPTION : self.__ProcessBuildOption,\r
1139 MODEL_UNKNOWN : self._Skip,\r
1140 MODEL_META_DATA_USER_EXTENSION : self._Skip,\r
8d62ae35 1141 MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR : self._Skip,\r
f51461c8 1142 }\r
f7496d71 1143\r
f51461c8
LG
1144 self._RawTable = self._Table\r
1145 self._Table = MetaFileStorage(self._RawTable.Cur, self.MetaFile, MODEL_FILE_DSC, True)\r
1146 self._DirectiveStack = []\r
1147 self._DirectiveEvalStack = []\r
1148 self._FileWithError = self.MetaFile\r
1149 self._FileLocalMacros = {}\r
1150 self._SectionsMacroDict = {}\r
1151 GlobalData.gPlatformDefines = {}\r
1152\r
1153 # Get all macro and PCD which has straitforward value\r
1154 self.__RetrievePcdValue()\r
1155 self._Content = self._RawTable.GetAll()\r
1156 self._ContentIndex = 0\r
1157 while self._ContentIndex < len(self._Content) :\r
1158 Id, self._ItemType, V1, V2, V3, S1, S2, Owner, BelongsToFile, self._From, \\r
1159 LineStart, ColStart, LineEnd, ColEnd, Enabled = self._Content[self._ContentIndex]\r
1160\r
1161 if self._From < 0:\r
1162 self._FileWithError = self.MetaFile\r
1163\r
1164 self._ContentIndex += 1\r
1165\r
1166 self._Scope = [[S1, S2]]\r
1167 self._LineIndex = LineStart - 1\r
1168 self._ValueList = [V1, V2, V3]\r
1169\r
1170 try:\r
1171 Processer[self._ItemType]()\r
5b0671c1 1172 except EvaluationException as Excpt:\r
f7496d71 1173 #\r
f51461c8
LG
1174 # Only catch expression evaluation error here. We need to report\r
1175 # the precise number of line on which the error occurred\r
1176 #\r
8d62ae35
HC
1177 pass\r
1178# EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),\r
1179# File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1180# Line=self._LineIndex+1)\r
5b0671c1 1181 except MacroException as Excpt:\r
f51461c8 1182 EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt),\r
f7496d71 1183 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
f51461c8
LG
1184 Line=self._LineIndex+1)\r
1185\r
4231a819 1186 if self._ValueList is None:\r
f7496d71 1187 continue\r
f51461c8
LG
1188\r
1189 NewOwner = self._IdMapping.get(Owner, -1)\r
1190 self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack))\r
1191 self._LastItem = self._Store(\r
1192 self._ItemType,\r
1193 self._ValueList[0],\r
1194 self._ValueList[1],\r
1195 self._ValueList[2],\r
1196 S1,\r
1197 S2,\r
1198 NewOwner,\r
1199 BelongsToFile,\r
1200 self._From,\r
1201 self._LineIndex+1,\r
1202 -1,\r
1203 self._LineIndex+1,\r
1204 -1,\r
1205 self._Enabled\r
1206 )\r
1207 self._IdMapping[Id] = self._LastItem\r
1208\r
1209 RecordList = self._Table.GetAll()\r
f7496d71 1210\r
f51461c8
LG
1211 self._RawTable.Drop()\r
1212 self._Table.Drop()\r
1213 for Record in RecordList:\r
ccaa7754 1214 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
1215 GlobalData.gPlatformDefines.update(self._FileLocalMacros)\r
1216 self._PostProcessed = True\r
1217 self._Content = None\r
1218\r
1219 def __ProcessSectionHeader(self):\r
1220 self._SectionName = self._ValueList[0]\r
1221 if self._SectionName in self.DataType:\r
1222 self._SectionType = self.DataType[self._SectionName]\r
1223 else:\r
1224 self._SectionType = MODEL_UNKNOWN\r
1225\r
1226 def __ProcessSubsectionHeader(self):\r
1227 self._SubsectionName = self._ValueList[0]\r
1228 if self._SubsectionName in self.DataType:\r
1229 self._SubsectionType = self.DataType[self._SubsectionName]\r
1230 else:\r
1231 self._SubsectionType = MODEL_UNKNOWN\r
1232\r
1233 def __RetrievePcdValue(self):\r
1234 Records = self._RawTable.Query(MODEL_PCD_FEATURE_FLAG, BelongsToItem=-1.0)\r
ccaa7754 1235 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, ID, Line in Records:\r
f51461c8
LG
1236 Value, DatumType, MaxDatumSize = AnalyzePcdData(Value)\r
1237 # Only use PCD whose value is straitforward (no macro and PCD)\r
1238 if self.SymbolPattern.findall(Value):\r
1239 continue\r
1240 Name = TokenSpaceGuid + '.' + PcdName\r
1241 # Don't use PCD with different values.\r
1242 if Name in self._Symbols and self._Symbols[Name] != Value:\r
1243 self._Symbols.pop(Name)\r
f7496d71 1244 continue\r
f51461c8
LG
1245 self._Symbols[Name] = Value\r
1246\r
1247 Records = self._RawTable.Query(MODEL_PCD_FIXED_AT_BUILD, BelongsToItem=-1.0)\r
ccaa7754 1248 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, ID, Line in Records:\r
f51461c8
LG
1249 Value, DatumType, MaxDatumSize = AnalyzePcdData(Value)\r
1250 # Only use PCD whose value is straitforward (no macro and PCD)\r
1251 if self.SymbolPattern.findall(Value):\r
f7496d71 1252 continue\r
f51461c8
LG
1253 Name = TokenSpaceGuid+'.'+PcdName\r
1254 # Don't use PCD with different values.\r
1255 if Name in self._Symbols and self._Symbols[Name] != Value:\r
1256 self._Symbols.pop(Name)\r
f7496d71 1257 continue\r
f51461c8
LG
1258 self._Symbols[Name] = Value\r
1259\r
1260 def __ProcessDefine(self):\r
1261 if not self._Enabled:\r
1262 return\r
1263\r
1264 Type, Name, Value = self._ValueList\r
1265 Value = ReplaceMacro(Value, self._Macros, False)\r
1266 if self._ItemType == MODEL_META_DATA_DEFINE:\r
1267 if self._SectionType == MODEL_META_DATA_HEADER:\r
1268 self._FileLocalMacros[Name] = Value\r
1269 else:\r
1270 SectionDictKey = self._SectionType, self._Scope[0][0], self._Scope[0][1]\r
1271 if SectionDictKey not in self._SectionsMacroDict:\r
1272 self._SectionsMacroDict[SectionDictKey] = {}\r
1273 SectionLocalMacros = self._SectionsMacroDict[SectionDictKey]\r
1274 SectionLocalMacros[Name] = Value\r
1275 elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE:\r
1276 GlobalData.gEdkGlobal[Name] = Value\r
f7496d71 1277\r
f51461c8
LG
1278 #\r
1279 # Keyword in [Defines] section can be used as Macros\r
1280 #\r
1281 if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER):\r
1282 self._FileLocalMacros[Name] = Value\r
f7496d71 1283\r
f51461c8
LG
1284 self._ValueList = [Type, Name, Value]\r
1285\r
1286 def __ProcessDirective(self):\r
1287 Result = None\r
1288 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1289 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF]:\r
1290 Macros = self._Macros\r
1291 Macros.update(GlobalData.gGlobalDefines)\r
1292 try:\r
1293 Result = ValueExpression(self._ValueList[1], Macros)()\r
5b0671c1 1294 except SymbolNotFound as Exc:\r
f51461c8
LG
1295 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])\r
1296 Result = False\r
5b0671c1 1297 except WrnExpression as Excpt:\r
f7496d71 1298 #\r
f51461c8
LG
1299 # Catch expression evaluation warning here. We need to report\r
1300 # the precise number of line and return the evaluation result\r
1301 #\r
1302 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),\r
f7496d71 1303 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
f51461c8
LG
1304 Line=self._LineIndex+1)\r
1305 Result = Excpt.result\r
5b0671c1 1306 except BadExpression as Exc:\r
ce2f5940
HC
1307 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])\r
1308 Result = False\r
f51461c8
LG
1309\r
1310 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1311 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
1312 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:\r
1313 self._DirectiveStack.append(self._ItemType)\r
1314 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF:\r
1315 Result = bool(Result)\r
1316 else:\r
1317 Macro = self._ValueList[1]\r
1318 Macro = Macro[2:-1] if (Macro.startswith("$(") and Macro.endswith(")")) else Macro\r
1319 Result = Macro in self._Macros\r
1320 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF:\r
1321 Result = not Result\r
1322 self._DirectiveEvalStack.append(Result)\r
1323 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF:\r
1324 self._DirectiveStack.append(self._ItemType)\r
1325 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]\r
1326 self._DirectiveEvalStack.append(bool(Result))\r
1327 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:\r
1328 self._DirectiveStack[-1] = self._ItemType\r
1329 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]\r
1330 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:\r
1331 # Back to the nearest !if/!ifdef/!ifndef\r
1332 while self._DirectiveStack:\r
1333 self._DirectiveEvalStack.pop()\r
1334 Directive = self._DirectiveStack.pop()\r
1335 if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1336 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
1337 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,\r
1338 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:\r
1339 break\r
1340 elif self._ItemType == MODEL_META_DATA_INCLUDE:\r
1341 # The included file must be relative to workspace or same directory as DSC file\r
1342 __IncludeMacros = {}\r
1343 #\r
1344 # Allow using system environment variables in path after !include\r
1345 #\r
1346 __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE']\r
f7496d71 1347\r
f51461c8 1348 #\r
f7496d71 1349 # Allow using MACROs comes from [Defines] section to keep compatible.\r
f51461c8
LG
1350 #\r
1351 __IncludeMacros.update(self._Macros)\r
f7496d71 1352\r
f51461c8
LG
1353 IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True))\r
1354 #\r
1355 # First search the include file under the same directory as DSC file\r
1356 #\r
1357 IncludedFile1 = PathClass(IncludedFile, self.MetaFile.Dir)\r
1358 ErrorCode, ErrorInfo1 = IncludedFile1.Validate()\r
1359 if ErrorCode != 0:\r
1360 #\r
1361 # Also search file under the WORKSPACE directory\r
1362 #\r
1363 IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)\r
1364 ErrorCode, ErrorInfo2 = IncludedFile1.Validate()\r
1365 if ErrorCode != 0:\r
f7496d71 1366 EdkLogger.error('parser', ErrorCode, File=self._FileWithError,\r
f51461c8
LG
1367 Line=self._LineIndex+1, ExtraData=ErrorInfo1 + "\n"+ ErrorInfo2)\r
1368\r
1369 self._FileWithError = IncludedFile1\r
1370\r
1371 IncludedFileTable = MetaFileStorage(self._Table.Cur, IncludedFile1, MODEL_FILE_DSC, True)\r
1372 Owner = self._Content[self._ContentIndex-1][0]\r
f7496d71 1373 Parser = DscParser(IncludedFile1, self._FileType, IncludedFileTable,\r
f51461c8
LG
1374 Owner=Owner, From=Owner)\r
1375\r
1376 # set the parser status with current status\r
1377 Parser._SectionName = self._SectionName\r
1378 Parser._SectionType = self._SectionType\r
1379 Parser._Scope = self._Scope\r
1380 Parser._Enabled = self._Enabled\r
1381 # Parse the included file\r
1382 Parser.Start()\r
1383\r
1384 # update current status with sub-parser's status\r
1385 self._SectionName = Parser._SectionName\r
1386 self._SectionType = Parser._SectionType\r
1387 self._Scope = Parser._Scope\r
1388 self._Enabled = Parser._Enabled\r
1389\r
1390 # Insert all records in the table for the included file into dsc file table\r
1391 Records = IncludedFileTable.GetAll()\r
1392 if Records:\r
1393 self._Content[self._ContentIndex:self._ContentIndex] = Records\r
1394 self._Content.pop(self._ContentIndex-1)\r
1395 self._ValueList = None\r
1396 self._ContentIndex -= 1\r
f7496d71 1397\r
f51461c8
LG
1398 def __ProcessSkuId(self):\r
1399 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)\r
1400 for Value in self._ValueList]\r
1401\r
1402 def __ProcessLibraryInstance(self):\r
1403 self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]\r
1404\r
1405 def __ProcessLibraryClass(self):\r
1406 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True)\r
1407\r
1408 def __ProcessPcd(self):\r
1409 ValueList = GetSplitValueList(self._ValueList[2])\r
1410 #\r
1411 # PCD value can be an expression\r
1412 #\r
656d2539 1413 if len(ValueList) > 1 and ValueList[1] == TAB_VOID:\r
f7496d71 1414 PcdValue = ValueList[0]\r
f51461c8
LG
1415 try:\r
1416 ValueList[0] = ValueExpression(PcdValue, self._Macros)(True)\r
5b0671c1 1417 except WrnExpression as Value:\r
f7496d71 1418 ValueList[0] = Value.result\r
f51461c8
LG
1419 else:\r
1420 PcdValue = ValueList[-1]\r
1421 try:\r
1422 ValueList[-1] = ValueExpression(PcdValue, self._Macros)(True)\r
5b0671c1 1423 except WrnExpression as Value:\r
f51461c8 1424 ValueList[-1] = Value.result\r
f7496d71 1425\r
f51461c8
LG
1426 if ValueList[-1] == 'True':\r
1427 ValueList[-1] = '1'\r
1428 if ValueList[-1] == 'False':\r
f7496d71 1429 ValueList[-1] = '0'\r
f51461c8
LG
1430\r
1431 self._ValueList[2] = '|'.join(ValueList)\r
1432\r
1433 def __ProcessComponent(self):\r
1434 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)\r
1435\r
f51461c8
LG
1436 def __ProcessBuildOption(self):\r
1437 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False)\r
1438 for Value in self._ValueList]\r
1439\r
1440 _SectionParser = {\r
1441 MODEL_META_DATA_HEADER : _DefineParser,\r
1442 MODEL_EFI_SKU_ID : _SkuIdParser,\r
1443 MODEL_EFI_LIBRARY_INSTANCE : _LibraryInstanceParser,\r
1444 MODEL_EFI_LIBRARY_CLASS : _LibraryClassParser,\r
1445 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,\r
1446 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,\r
1447 MODEL_PCD_FEATURE_FLAG : _PcdParser,\r
1448 MODEL_PCD_DYNAMIC_DEFAULT : _PcdParser,\r
1449 MODEL_PCD_DYNAMIC_HII : _PcdParser,\r
1450 MODEL_PCD_DYNAMIC_VPD : _PcdParser,\r
1451 MODEL_PCD_DYNAMIC_EX_DEFAULT : _PcdParser,\r
1452 MODEL_PCD_DYNAMIC_EX_HII : _PcdParser,\r
1453 MODEL_PCD_DYNAMIC_EX_VPD : _PcdParser,\r
1454 MODEL_META_DATA_COMPONENT : _ComponentParser,\r
f51461c8
LG
1455 MODEL_META_DATA_BUILD_OPTION : _BuildOptionParser,\r
1456 MODEL_UNKNOWN : MetaFileParser._Skip,\r
1457 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip,\r
1458 MODEL_META_DATA_SECTION_HEADER : MetaFileParser._SectionHeaderParser,\r
1459 MODEL_META_DATA_SUBSECTION_HEADER : _SubsectionHeaderParser,\r
1460 }\r
1461\r
1462 _Macros = property(_GetMacros)\r
1463\r
1464## DEC file parser class\r
1465#\r
1466# @param FilePath The path of platform description file\r
1467# @param FileType The raw data of DSC file\r
1468# @param Table Database used to retrieve module/package information\r
1469# @param Macros Macros used for replacement in file\r
1470#\r
1471class DecParser(MetaFileParser):\r
1472 # DEC file supported data types (one type per section)\r
1473 DataType = {\r
1474 TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER,\r
1475 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,\r
1476 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,\r
1477 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,\r
1478 TAB_GUIDS.upper() : MODEL_EFI_GUID,\r
1479 TAB_PPIS.upper() : MODEL_EFI_PPI,\r
1480 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,\r
1481 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,\r
1482 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,\r
1483 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,\r
1484 TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC,\r
1485 TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX,\r
1486 }\r
1487\r
1488 ## Constructor of DecParser\r
1489 #\r
1490 # Initialize object of DecParser\r
1491 #\r
1492 # @param FilePath The path of platform description file\r
1493 # @param FileType The raw data of DSC file\r
1494 # @param Table Database used to retrieve module/package information\r
1495 # @param Macros Macros used for replacement in file\r
1496 #\r
1497 def __init__(self, FilePath, FileType, Table):\r
1498 # prevent re-initialization\r
1499 if hasattr(self, "_Table"):\r
1500 return\r
1501 MetaFileParser.__init__(self, FilePath, FileType, Table)\r
1502 self._Comments = []\r
1503 self._Version = 0x00010005 # Only EDK2 dec file is supported\r
1504 self.TblFile = EccGlobalData.gDb.TblFile\r
1505 self.FileID = -1\r
1506\r
1507 ## Parser starter\r
1508 def Start(self):\r
1509 Content = ''\r
1510 try:\r
1511 Content = open(str(self.MetaFile), 'r').readlines()\r
1512 except:\r
1513 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)\r
1514\r
1515 #\r
1516 # Insert a record for file\r
1517 #\r
1518 Filename = NormPath(self.MetaFile)\r
1519 FileID = self.TblFile.GetFileId(Filename)\r
1520 if FileID:\r
1521 self.FileID = FileID\r
1522 else:\r
1523 self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_DEC)\r
f7496d71 1524\r
f51461c8
LG
1525 for Index in range(0, len(Content)):\r
1526 Line, Comment = CleanString2(Content[Index])\r
1527 self._CurrentLine = Line\r
1528 self._LineIndex = Index\r
1529\r
1530 # save comment for later use\r
1531 if Comment:\r
1532 self._Comments.append((Comment, self._LineIndex+1))\r
1533 # skip empty line\r
1534 if Line == '':\r
1535 continue\r
1536\r
1537 # section header\r
1538 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:\r
1539 self._SectionHeaderParser()\r
1540 self._Comments = []\r
1541 continue\r
1542 elif len(self._SectionType) == 0:\r
1543 self._Comments = []\r
1544 continue\r
1545\r
1546 # section content\r
ccaa7754 1547 self._ValueList = ['', '', '']\r
f51461c8 1548 self._SectionParser[self._SectionType[0]](self)\r
4231a819 1549 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:\r
f51461c8
LG
1550 self._ItemType = -1\r
1551 self._Comments = []\r
1552 continue\r
1553\r
1554 #\r
1555 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,\r
1556 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1\r
1557 #\r
1558 for Arch, ModuleType, Type in self._Scope:\r
1559 self._LastItem = self._Store(\r
1560 Type,\r
1561 self._ValueList[0],\r
1562 self._ValueList[1],\r
1563 self._ValueList[2],\r
1564 Arch,\r
1565 ModuleType,\r
1566 self._Owner[-1],\r
1567 self.FileID,\r
1568 self._LineIndex+1,\r
1569 -1,\r
1570 self._LineIndex+1,\r
1571 -1,\r
1572 0\r
1573 )\r
1574 for Comment, LineNo in self._Comments:\r
1575 self._Store(\r
1576 MODEL_META_DATA_COMMENT,\r
1577 Comment,\r
1578 self._ValueList[0],\r
1579 self._ValueList[1],\r
1580 Arch,\r
1581 ModuleType,\r
1582 self._LastItem,\r
1583 self.FileID,\r
1584 LineNo,\r
1585 -1,\r
1586 LineNo,\r
1587 -1,\r
1588 0\r
1589 )\r
1590 self._Comments = []\r
1591 self._Done()\r
1592\r
1593 def _GetApplicableSectionMacro(self):\r
1594 Macros = {}\r
1595 for S1, S2, SectionType in self._Scope:\r
1596 for Scope1, Scope2 in [("COMMON", "COMMON"), ("COMMON", S2), (S1, "COMMON"), (S1, S2)]:\r
1597 if (SectionType, Scope1, Scope2) in self._SectionsMacroDict:\r
1598 Macros.update(self._SectionsMacroDict[(SectionType, Scope1, Scope2)])\r
1599 return Macros\r
1600\r
1601 ## Section header parser\r
1602 #\r
1603 # The section header is always in following format:\r
1604 #\r
1605 # [section_name.arch<.platform|module_type>]\r
1606 #\r
1607 def _SectionHeaderParser(self):\r
1608 self._Scope = []\r
1609 self._SectionName = ''\r
1610 self._SectionType = []\r
1611 ArchList = set()\r
1612 for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):\r
1613 if Item == '':\r
1614 continue\r
1615 ItemList = GetSplitValueList(Item, TAB_SPLIT)\r
1616\r
1617 # different types of PCD are permissible in one section\r
1618 self._SectionName = ItemList[0].upper()\r
1619 if self._SectionName in self.DataType:\r
1620 if self.DataType[self._SectionName] not in self._SectionType:\r
1621 self._SectionType.append(self.DataType[self._SectionName])\r
1622 else:\r
1623 EdkLogger.warn("Parser", "Unrecognized section", File=self.MetaFile,\r
1624 Line=self._LineIndex+1, ExtraData=self._CurrentLine)\r
1625 continue\r
1626\r
1627 if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:\r
1628 EdkLogger.error(\r
1629 'Parser',\r
1630 FORMAT_INVALID,\r
1631 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,\r
1632 File=self.MetaFile,\r
1633 Line=self._LineIndex+1,\r
1634 ExtraData=self._CurrentLine\r
1635 )\r
1636 # S1 is always Arch\r
1637 if len(ItemList) > 1:\r
1638 S1 = ItemList[1].upper()\r
1639 else:\r
1640 S1 = 'COMMON'\r
1641 ArchList.add(S1)\r
1642 # S2 may be Platform or ModuleType\r
1643 if len(ItemList) > 2:\r
1644 S2 = ItemList[2].upper()\r
1645 else:\r
1646 S2 = 'COMMON'\r
1647 if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:\r
1648 self._Scope.append([S1, S2, self.DataType[self._SectionName]])\r
1649\r
1650 # 'COMMON' must not be used with specific ARCHs at the same section\r
1651 if 'COMMON' in ArchList and len(ArchList) > 1:\r
1652 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",\r
1653 File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine)\r
1654\r
1655 ## [guids], [ppis] and [protocols] section parser\r
1656 @ParseMacro\r
1657 def _GuidParser(self):\r
1658 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
1659 if len(TokenList) < 2:\r
1660 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",\r
1661 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1662 File=self.MetaFile, Line=self._LineIndex+1)\r
1663 if TokenList[0] == '':\r
1664 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",\r
1665 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1666 File=self.MetaFile, Line=self._LineIndex+1)\r
1667 if TokenList[1] == '':\r
1668 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",\r
1669 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1670 File=self.MetaFile, Line=self._LineIndex+1)\r
1671 if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':\r
1672 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",\r
1673 ExtraData=self._CurrentLine + \\r
1674 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",\r
1675 File=self.MetaFile, Line=self._LineIndex+1)\r
1676 self._ValueList[0] = TokenList[0]\r
1677 #Parse the Guid value format\r
1678 GuidValueList = TokenList[1].strip(' {}').split(',')\r
1679 Index = 0\r
1680 HexList = []\r
1681 if len(GuidValueList) == 11:\r
1682 for GuidValue in GuidValueList:\r
1683 GuidValue = GuidValue.strip()\r
1684 if GuidValue.startswith('0x') or GuidValue.startswith('0X'):\r
1685 HexList.append('0x' + str(GuidValue[2:]))\r
1686 Index += 1\r
1687 continue\r
1688 else:\r
1689 if GuidValue.startswith('{'):\r
e84d2b70
HC
1690 GuidValue = GuidValue.lstrip(' {')\r
1691 HexList.append('0x' + str(GuidValue[2:]))\r
f51461c8 1692 Index += 1\r
ccaa7754 1693 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
1694 else:\r
1695 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",\r
1696 ExtraData=self._CurrentLine + \\r
1697 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",\r
1698 File=self.MetaFile, Line=self._LineIndex+1)\r
1699 self._ValueList[0] = ''\r
1700\r
1701 ## PCD sections parser\r
1702 #\r
1703 # [PcdsFixedAtBuild]\r
1704 # [PcdsPatchableInModule]\r
1705 # [PcdsFeatureFlag]\r
1706 # [PcdsDynamicEx\r
1707 # [PcdsDynamic]\r
1708 #\r
1709 @ParseMacro\r
1710 def _PcdParser(self):\r
1711 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
1712 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
1713 # check PCD information\r
1714 if self._ValueList[0] == '' or self._ValueList[1] == '':\r
1715 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
1716 ExtraData=self._CurrentLine + \\r
1717 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1718 File=self.MetaFile, Line=self._LineIndex+1)\r
1719 # check PCD datum information\r
1720 if len(TokenList) < 2 or TokenList[1] == '':\r
1721 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",\r
1722 ExtraData=self._CurrentLine + \\r
1723 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1724 File=self.MetaFile, Line=self._LineIndex+1)\r
1725\r
f7496d71 1726\r
f51461c8
LG
1727 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')\r
1728 PtrValue = ValueRe.findall(TokenList[1])\r
f7496d71
LG
1729\r
1730 # Has VOID* type string, may contain "|" character in the string.\r
f51461c8
LG
1731 if len(PtrValue) != 0:\r
1732 ptrValueList = re.sub(ValueRe, '', TokenList[1])\r
1733 ValueList = GetSplitValueList(ptrValueList)\r
1734 ValueList[0] = PtrValue[0]\r
1735 else:\r
1736 ValueList = GetSplitValueList(TokenList[1])\r
f7496d71
LG
1737\r
1738\r
f51461c8
LG
1739 # check if there's enough datum information given\r
1740 if len(ValueList) != 3:\r
1741 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",\r
1742 ExtraData=self._CurrentLine + \\r
1743 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1744 File=self.MetaFile, Line=self._LineIndex+1)\r
1745 # check default value\r
1746 if ValueList[0] == '':\r
1747 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",\r
1748 ExtraData=self._CurrentLine + \\r
1749 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1750 File=self.MetaFile, Line=self._LineIndex+1)\r
1751 # check datum type\r
1752 if ValueList[1] == '':\r
1753 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",\r
1754 ExtraData=self._CurrentLine + \\r
1755 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1756 File=self.MetaFile, Line=self._LineIndex+1)\r
1757 # check token of the PCD\r
1758 if ValueList[2] == '':\r
1759 EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",\r
1760 ExtraData=self._CurrentLine + \\r
1761 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1762 File=self.MetaFile, Line=self._LineIndex+1)\r
1763 # check format of default value against the datum type\r
1764 IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])\r
1765 if not IsValid:\r
1766 EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,\r
1767 File=self.MetaFile, Line=self._LineIndex+1)\r
f7496d71 1768\r
b66592d8
HC
1769 if EccGlobalData.gConfig.UniCheckPCDInfo == '1' or EccGlobalData.gConfig.UniCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
1770 # check Description, Prompt information\r
1771 PatternDesc = re.compile('##\s*([\x21-\x7E\s]*)', re.S)\r
1772 PatternPrompt = re.compile('#\s+@Prompt\s+([\x21-\x7E\s]*)', re.S)\r
1773 Description = None\r
1774 Prompt = None\r
1775 # check @ValidRange, @ValidList and @Expression format valid\r
1776 ErrorCodeValid = '0x0 <= %s <= 0xFFFFFFFF'\r
1777 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
1778 PatternValidRng = re.compile('^' + '(NOT)?\s*' + PatternValidRangeIn + '$')\r
1779 for Comment in self._Comments:\r
1780 Comm = Comment[0].strip()\r
1781 if not Comm:\r
1782 continue\r
1783 if not Description:\r
1784 Description = PatternDesc.findall(Comm)\r
1785 if not Prompt:\r
1786 Prompt = PatternPrompt.findall(Comm)\r
1787 if Comm[0] == '#':\r
1788 ValidFormt = Comm.lstrip('#')\r
1789 ValidFormt = ValidFormt.lstrip()\r
1790 if ValidFormt[0:11] == '@ValidRange':\r
1791 ValidFormt = ValidFormt[11:]\r
1792 ValidFormt = ValidFormt.lstrip()\r
1793 try:\r
1794 ErrorCode, Expression = ValidFormt.split('|', 1)\r
1795 except ValueError:\r
1796 ErrorCode = '0x0'\r
1797 Expression = ValidFormt\r
1798 ErrorCode, Expression = ErrorCode.strip(), Expression.strip()\r
1799 try:\r
1800 if not eval(ErrorCodeValid % ErrorCode):\r
1801 EdkLogger.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))\r
1802 except:\r
1803 EdkLogger.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))\r
1804 if not PatternValidRng.search(Expression):\r
1805 EdkLogger.warn('Parser', '@ValidRange Expression(%s) of PCD %s is incorrect format.' % (Expression, TokenList[0]))\r
1806 if ValidFormt[0:10] == '@ValidList':\r
1807 ValidFormt = ValidFormt[10:]\r
1808 ValidFormt = ValidFormt.lstrip()\r
1809 try:\r
1810 ErrorCode, Expression = ValidFormt.split('|', 1)\r
1811 except ValueError:\r
1812 ErrorCode = '0x0'\r
1813 Expression = ValidFormt\r
1814 ErrorCode, Expression = ErrorCode.strip(), Expression.strip()\r
1815 try:\r
1816 if not eval(ErrorCodeValid % ErrorCode):\r
1817 EdkLogger.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))\r
1818 except:\r
1819 EdkLogger.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))\r
1820 Values = Expression.split(',')\r
1821 for Value in Values:\r
1822 Value = Value.strip()\r
1823 try:\r
1824 eval(Value)\r
1825 except:\r
1826 EdkLogger.warn('Parser', '@ValidList Expression of PCD %s include a invalid value(%s).' % (TokenList[0], Value))\r
1827 break\r
1828 if ValidFormt[0:11] == '@Expression':\r
1829 ValidFormt = ValidFormt[11:]\r
1830 ValidFormt = ValidFormt.lstrip()\r
1831 try:\r
1832 ErrorCode, Expression = ValidFormt.split('|', 1)\r
1833 except ValueError:\r
1834 ErrorCode = '0x0'\r
1835 Expression = ValidFormt\r
1836 ErrorCode, Expression = ErrorCode.strip(), Expression.strip()\r
1837 try:\r
1838 if not eval(ErrorCodeValid % ErrorCode):\r
1839 EdkLogger.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))\r
1840 except:\r
1841 EdkLogger.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))\r
1842 if not Expression:\r
1843 EdkLogger.warn('Parser', '@Expression Expression of PCD %s is incorrect format.' % TokenList[0])\r
1844 if not Description:\r
1845 EdkLogger.warn('Parser', 'PCD %s Description information is not provided.' % TokenList[0])\r
1846 if not Prompt:\r
1847 EdkLogger.warn('Parser', 'PCD %s Prompt information is not provided.' % TokenList[0])\r
1848 # check Description, Prompt localization information\r
1849 if self._UniObj:\r
1850 self._UniObj.CheckPcdInfo(TokenList[0])\r
f51461c8
LG
1851\r
1852 if ValueList[0] in ['True', 'true', 'TRUE']:\r
1853 ValueList[0] = '1'\r
1854 elif ValueList[0] in ['False', 'false', 'FALSE']:\r
1855 ValueList[0] = '0'\r
1856\r
1857 self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()\r
1858\r
1859 _SectionParser = {\r
1860 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,\r
1861 MODEL_EFI_INCLUDE : MetaFileParser._PathParser,\r
1862 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,\r
1863 MODEL_EFI_GUID : _GuidParser,\r
1864 MODEL_EFI_PPI : _GuidParser,\r
1865 MODEL_EFI_PROTOCOL : _GuidParser,\r
1866 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,\r
1867 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,\r
1868 MODEL_PCD_FEATURE_FLAG : _PcdParser,\r
1869 MODEL_PCD_DYNAMIC : _PcdParser,\r
1870 MODEL_PCD_DYNAMIC_EX : _PcdParser,\r
1871 MODEL_UNKNOWN : MetaFileParser._Skip,\r
1872 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip,\r
1873 }\r
1874\r
1875\r
f51461c8
LG
1876## Fdf\r
1877#\r
1878# This class defined the structure used in Fdf object\r
f7496d71 1879#\r
f51461c8
LG
1880# @param Filename: Input value for Ffilename of Fdf file, default is None\r
1881# @param WorkspaceDir: Input value for current workspace directory, default is None\r
1882#\r
0b560b98 1883class Fdf(object):\r
f51461c8
LG
1884 def __init__(self, Filename = None, IsToDatabase = False, WorkspaceDir = None, Database = None):\r
1885 self.WorkspaceDir = WorkspaceDir\r
1886 self.IsToDatabase = IsToDatabase\r
f7496d71 1887\r
f51461c8
LG
1888 self.Cur = Database.Cur\r
1889 self.TblFile = Database.TblFile\r
1890 self.TblFdf = Database.TblFdf\r
1891 self.FileID = -1\r
1892 self.FileList = {}\r
1893\r
1894 #\r
1895 # Load Fdf file if filename is not None\r
1896 #\r
4231a819 1897 if Filename is not None:\r
8d62ae35
HC
1898 try:\r
1899 self.LoadFdfFile(Filename)\r
1900 except Exception:\r
1901 pass\r
f51461c8
LG
1902\r
1903 #\r
1904 # Insert a FDF file record into database\r
1905 #\r
1906 def InsertFile(self, Filename):\r
1907 FileID = -1\r
1908 Filename = NormPath(Filename)\r
1909 if Filename not in self.FileList:\r
1910 FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_FDF)\r
1911 self.FileList[Filename] = FileID\r
1912\r
1913 return self.FileList[Filename]\r
f7496d71
LG
1914\r
1915\r
f51461c8
LG
1916 ## Load Fdf file\r
1917 #\r
1918 # Load the file if it exists\r
1919 #\r
1920 # @param Filename: Input value for filename of Fdf file\r
1921 #\r
f7496d71 1922 def LoadFdfFile(self, Filename):\r
f51461c8
LG
1923 FileList = []\r
1924 #\r
1925 # Parse Fdf file\r
1926 #\r
1927 Filename = NormPath(Filename)\r
1928 Fdf = FdfParser(Filename)\r
1929 Fdf.ParseFile()\r
1930\r
1931 #\r
1932 # Insert inf file and pcd information\r
1933 #\r
1934 if self.IsToDatabase:\r
1935 (Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled) = \\r
1936 (0, '', '', '', 'COMMON', 'COMMON', -1, -1, -1, -1, -1, -1, 0)\r
1937 for Index in range(0, len(Fdf.Profile.PcdDict)):\r
1938 pass\r
1939 for Key in Fdf.Profile.PcdDict.keys():\r
1940 Model = MODEL_PCD\r
1941 Value1 = Key[1]\r
1942 Value2 = Key[0]\r
1943 FileName = Fdf.Profile.PcdFileLineDict[Key][0]\r
1944 StartLine = Fdf.Profile.PcdFileLineDict[Key][1]\r
1945 BelongsToFile = self.InsertFile(FileName)\r
1946 self.TblFdf.Insert(Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled)\r
1947 for Index in range(0, len(Fdf.Profile.InfList)):\r
1948 Model = MODEL_META_DATA_COMPONENT\r
1949 Value1 = Fdf.Profile.InfList[Index]\r
1950 Value2 = ''\r
1951 FileName = Fdf.Profile.InfFileLineList[Index][0]\r
1952 StartLine = Fdf.Profile.InfFileLineList[Index][1]\r
1953 BelongsToFile = self.InsertFile(FileName)\r
1954 self.TblFdf.Insert(Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled)\r
1955\r
1b2467c5
HC
1956class UniParser(object):\r
1957 # IsExtraUni defined the UNI file is Module UNI or extra Module UNI\r
1958 # IsModuleUni defined the UNI file is Module UNI or Package UNI\r
1959 def __init__(self, FilePath, IsExtraUni=False, IsModuleUni=True):\r
1960 self.FilePath = FilePath\r
1961 self.FileName = os.path.basename(FilePath)\r
1962 self.IsExtraUni = IsExtraUni\r
1963 self.IsModuleUni = IsModuleUni\r
1964 self.FileIn = None\r
1965 self.Missing = []\r
1966 self.__read()\r
f7496d71 1967\r
1b2467c5
HC
1968 def __read(self):\r
1969 try:\r
97588927 1970 self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_8').read()\r
1b2467c5 1971 except UnicodeError:\r
97588927
HC
1972 self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_16').read()\r
1973 except UnicodeError:\r
1974 self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_16_le').read()\r
1b2467c5
HC
1975 except IOError:\r
1976 self.FileIn = ""\r
f7496d71 1977\r
1b2467c5
HC
1978 def Start(self):\r
1979 if self.IsModuleUni:\r
1980 if self.IsExtraUni:\r
1981 ModuleName = self.CheckKeyValid('STR_PROPERTIES_MODULE_NAME')\r
1982 self.PrintLog('STR_PROPERTIES_MODULE_NAME', ModuleName)\r
1983 else:\r
1984 ModuleAbstract = self.CheckKeyValid('STR_MODULE_ABSTRACT')\r
1985 self.PrintLog('STR_MODULE_ABSTRACT', ModuleAbstract)\r
1986 ModuleDescription = self.CheckKeyValid('STR_MODULE_DESCRIPTION')\r
1987 self.PrintLog('STR_MODULE_DESCRIPTION', ModuleDescription)\r
1988 else:\r
1989 if self.IsExtraUni:\r
1990 PackageName = self.CheckKeyValid('STR_PROPERTIES_PACKAGE_NAME')\r
1991 self.PrintLog('STR_PROPERTIES_PACKAGE_NAME', PackageName)\r
1992 else:\r
1993 PackageAbstract = self.CheckKeyValid('STR_PACKAGE_ABSTRACT')\r
1994 self.PrintLog('STR_PACKAGE_ABSTRACT', PackageAbstract)\r
1995 PackageDescription = self.CheckKeyValid('STR_PACKAGE_DESCRIPTION')\r
1996 self.PrintLog('STR_PACKAGE_DESCRIPTION', PackageDescription)\r
f7496d71 1997\r
1b2467c5
HC
1998 def CheckKeyValid(self, Key, Contents=None):\r
1999 if not Contents:\r
2000 Contents = self.FileIn\r
2001 KeyPattern = re.compile('#string\s+%s\s+.*?#language.*?".*?"' % Key, re.S)\r
2002 if KeyPattern.search(Contents):\r
2003 return True\r
2004 return False\r
f7496d71 2005\r
1b2467c5
HC
2006 def CheckPcdInfo(self, PcdCName):\r
2007 PromptKey = 'STR_%s_PROMPT' % PcdCName.replace('.', '_')\r
2008 PcdPrompt = self.CheckKeyValid(PromptKey)\r
2009 self.PrintLog(PromptKey, PcdPrompt)\r
2010 HelpKey = 'STR_%s_HELP' % PcdCName.replace('.', '_')\r
2011 PcdHelp = self.CheckKeyValid(HelpKey)\r
2012 self.PrintLog(HelpKey, PcdHelp)\r
f7496d71 2013\r
1b2467c5
HC
2014 def PrintLog(self, Key, Value):\r
2015 if not Value and Key not in self.Missing:\r
2016 Msg = '%s is missing in the %s file.' % (Key, self.FileName)\r
2017 EdkLogger.warn('Parser', Msg)\r
2018 EccGlobalData.gDb.TblReport.Insert(EccToolError.ERROR_GENERAL_CHECK_UNI_HELP_INFO, OtherMsg=Msg, BelongsToTable='File', BelongsToItem=-2)\r
2019 self.Missing.append(Key)\r
2020\r
f51461c8
LG
2021##\r
2022#\r
2023# This acts like the main() function for the script, unless it is 'import'ed into another\r
2024# script.\r
2025#\r
2026if __name__ == '__main__':\r
2027 pass\r
2028\r