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