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