BaseTools: cleanup class heirarchy
[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
4231a819 231 if self._RawTable and (len(DataInfo) == 1 or DataInfo[1] is None):\r
f51461c8
LG
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
4231a819 567 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:\r
f51461c8
LG
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
f05c2e9f
HC
786 SubSectionDefineKeywords = [\r
787 "FILE_GUID"\r
788 ]\r
789\r
f51461c8
LG
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
4231a819 880 if self._ValueList is None:\r
f51461c8
LG
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
f05c2e9f
HC
1000 if (not self._ValueList[1] in self.DefineKeywords and\r
1001 (self._InSubsection and self._ValueList[1] not in self.SubSectionDefineKeywords)):\r
f51461c8
LG
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
e4ac870f 1113 Macros = dict( [('ARCH','IA32'), ('FAMILY','MSFT'),('TOOL_CHAIN_TAG','VS2008x86'),('TARGET','DEBUG')])\r
f51461c8
LG
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
8d62ae35 1155 MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR : self._Skip,\r
f51461c8
LG
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
8d62ae35
HC
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
f51461c8
LG
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
4231a819 1200 if self._ValueList is None:\r
f51461c8
LG
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
ce2f5940
HC
1320 except BadExpression, Exc:\r
1321 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])\r
1322 Result = False\r
f51461c8
LG
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
4231a819 1576 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:\r
f51461c8
LG
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
e84d2b70
HC
1717 GuidValue = GuidValue.lstrip(' {')\r
1718 HexList.append('0x' + str(GuidValue[2:]))\r
f51461c8
LG
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
b66592d8
HC
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
f51461c8
LG
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
f51461c8
LG
1903## Fdf\r
1904#\r
1905# This class defined the structure used in Fdf object\r
1906# \r
f51461c8
LG
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
0b560b98 1910class Fdf(object):\r
f51461c8
LG
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
4231a819 1924 if Filename is not None:\r
8d62ae35
HC
1925 try:\r
1926 self.LoadFdfFile(Filename)\r
1927 except Exception:\r
1928 pass\r
f51461c8
LG
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
1b2467c5
HC
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
97588927 1997 self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_8').read()\r
1b2467c5 1998 except UnicodeError:\r
97588927
HC
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
1b2467c5
HC
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
f51461c8
LG
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