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