]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/Ecc/MetaFileWorkspace/MetaFileParser.py
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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
82af1cbf 4# Copyright (c) 2008 - 2020, Intel Corporation. All rights reserved.<BR>\r
2e351cbe 5# SPDX-License-Identifier: BSD-2-Clause-Patent\r
f51461c8
LG
6#\r
7\r
8##\r
9# Import Modules\r
10#\r
b6f6b636 11from __future__ import absolute_import\r
1be2ed90 12import Common.LongFilePathOs as os\r
f51461c8
LG
13import re\r
14import time\r
15import copy\r
82af1cbf 16from hashlib import md5\r
f51461c8
LG
17import Common.EdkLogger as EdkLogger\r
18import Common.GlobalData as GlobalData\r
855698fb 19import Ecc.EccGlobalData as EccGlobalData\r
20import Ecc.EccToolError as EccToolError\r
f51461c8
LG
21\r
22from CommonDataClass.DataClass import *\r
23from Common.DataType import *\r
5a57246e 24from Common.StringUtils import *\r
f51461c8
LG
25from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData\r
26from Common.Expression import *\r
27from CommonDataClass.Exceptions import *\r
28\r
855698fb 29from Ecc.MetaFileWorkspace.MetaFileTable import MetaFileStorage\r
1be2ed90
HC
30from GenFds.FdfParser import FdfParser\r
31from Common.LongFilePathSupport import OpenLongFilePath as open\r
1b2467c5 32from Common.LongFilePathSupport import CodecOpenLongFilePath\r
f51461c8 33\r
ec30a4a0 34## RegEx for finding file versions\r
35hexVersionPattern = re.compile(r'0[xX][\da-f-A-F]{5,8}')\r
36decVersionPattern = re.compile(r'\d+\.\d+')\r
37\r
f51461c8
LG
38## A decorator used to parse macro definition\r
39def ParseMacro(Parser):\r
40 def MacroParser(self):\r
938cf4c3 41 Match = GlobalData.gMacroDefPattern.match(self._CurrentLine)\r
f51461c8
LG
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
938cf4c3 62 if not GlobalData.gMacroNamePattern.match(Name):\r
f51461c8
LG
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
0d1f5b2b 70 if isinstance(self, DecParser):\r
f51461c8
LG
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
0d1f5b2b 85 elif not isinstance(self, DscParser):\r
f51461c8
LG
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
f7496d71 94\r
f51461c8
LG
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
0d1f5b2b 217 if not isinstance(DataInfo, type(())):\r
f51461c8
LG
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
4231a819 230 if self._RawTable and (len(DataInfo) == 1 or DataInfo[1] is None):\r
f51461c8
LG
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
0d1f5b2b 259 if not isinstance(self, DscParser):\r
f51461c8
LG
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
f7496d71 336 # Sometimes, we need to make differences between EDK and EDK2 modules\r
f51461c8 337 if Name == 'INF_VERSION':\r
ec30a4a0 338 if hexVersionPattern.match(Value):\r
f51461c8 339 self._Version = int(Value, 0)\r
ec30a4a0 340 elif decVersionPattern.match(Value):\r
341 ValueList = Value.split('.')\r
342 Major = int(ValueList[0], 0)\r
343 Minor = int(ValueList[1], 0)\r
344 if Major > 0xffff or Minor > 0xffff:\r
345 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",\r
346 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
347 self._Version = int('0x{0:04x}{1:04x}'.format(Major, Minor), 0)\r
348 else:\r
f51461c8 349 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",\r
ec30a4a0 350 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
1b2467c5
HC
351 elif Name == 'MODULE_UNI_FILE':\r
352 UniFile = os.path.join(os.path.dirname(self.MetaFile), Value)\r
353 if os.path.exists(UniFile):\r
354 self._UniObj = UniParser(UniFile, IsExtraUni=False, IsModuleUni=True)\r
355 self._UniObj.Start()\r
356 else:\r
357 EdkLogger.error('Parser', FILE_NOT_FOUND, "Module UNI file %s is missing." % Value,\r
358 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1,\r
359 RaiseError=False)\r
360 elif Name == 'PACKAGE_UNI_FILE':\r
361 UniFile = os.path.join(os.path.dirname(self.MetaFile), Value)\r
362 if os.path.exists(UniFile):\r
363 self._UniObj = UniParser(UniFile, IsExtraUni=False, IsModuleUni=False)\r
f7496d71 364\r
0d1f5b2b 365 if isinstance(self, InfParser) and self._Version < 0x00010005:\r
f51461c8
LG
366 # EDK module allows using defines as macros\r
367 self._FileLocalMacros[Name] = Value\r
368 self._Defines[Name] = Value\r
369\r
370 ## [BuildOptions] section parser\r
371 @ParseMacro\r
372 def _BuildOptionParser(self):\r
373 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
374 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)\r
375 if len(TokenList2) == 2:\r
376 self._ValueList[0] = TokenList2[0] # toolchain family\r
377 self._ValueList[1] = TokenList2[1] # keys\r
378 else:\r
379 self._ValueList[1] = TokenList[0]\r
0d1f5b2b 380 if len(TokenList) == 2 and not isinstance(self, DscParser): # value\r
f51461c8
LG
381 self._ValueList[2] = ReplaceMacro(TokenList[1], self._Macros)\r
382\r
383 if self._ValueList[1].count('_') != 4:\r
384 EdkLogger.error(\r
385 'Parser',\r
386 FORMAT_INVALID,\r
387 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],\r
388 ExtraData=self._CurrentLine,\r
389 File=self.MetaFile,\r
390 Line=self._LineIndex+1\r
391 )\r
392\r
393 def _GetMacros(self):\r
394 Macros = {}\r
395 Macros.update(self._FileLocalMacros)\r
396 Macros.update(self._GetApplicableSectionMacro())\r
397 return Macros\r
398\r
399\r
f7496d71 400 ## Get section Macros that are applicable to current line, which may come from other sections\r
f51461c8
LG
401 ## that share the same name while scope is wider\r
402 def _GetApplicableSectionMacro(self):\r
403 Macros = {}\r
404 for Scope1, Scope2 in [("COMMON", "COMMON"), ("COMMON", self._Scope[0][1]),\r
405 (self._Scope[0][0], "COMMON"), (self._Scope[0][0], self._Scope[0][1])]:\r
406 if (self._SectionType, Scope1, Scope2) in self._SectionsMacroDict:\r
407 Macros.update(self._SectionsMacroDict[(self._SectionType, Scope1, Scope2)])\r
408 return Macros\r
409\r
410 _SectionParser = {}\r
411 Finished = property(_GetFinished, _SetFinished)\r
412 _Macros = property(_GetMacros)\r
413\r
414\r
415## INF file parser class\r
416#\r
417# @param FilePath The path of platform description file\r
418# @param FileType The raw data of DSC file\r
419# @param Table Database used to retrieve module/package information\r
420# @param Macros Macros used for replacement in file\r
421#\r
422class InfParser(MetaFileParser):\r
423 # INF file supported data types (one type per section)\r
424 DataType = {\r
425 TAB_UNKNOWN.upper() : MODEL_UNKNOWN,\r
426 TAB_INF_DEFINES.upper() : MODEL_META_DATA_HEADER,\r
427 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,\r
428 TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,\r
429 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,\r
430 TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,\r
431 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,\r
432 TAB_PACKAGES.upper() : MODEL_META_DATA_PACKAGE,\r
433 TAB_NMAKE.upper() : MODEL_META_DATA_NMAKE,\r
434 TAB_INF_FIXED_PCD.upper() : MODEL_PCD_FIXED_AT_BUILD,\r
435 TAB_INF_PATCH_PCD.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,\r
436 TAB_INF_FEATURE_PCD.upper() : MODEL_PCD_FEATURE_FLAG,\r
437 TAB_INF_PCD_EX.upper() : MODEL_PCD_DYNAMIC_EX,\r
438 TAB_INF_PCD.upper() : MODEL_PCD_DYNAMIC,\r
439 TAB_SOURCES.upper() : MODEL_EFI_SOURCE_FILE,\r
440 TAB_GUIDS.upper() : MODEL_EFI_GUID,\r
441 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,\r
442 TAB_PPIS.upper() : MODEL_EFI_PPI,\r
443 TAB_DEPEX.upper() : MODEL_EFI_DEPEX,\r
444 TAB_BINARIES.upper() : MODEL_EFI_BINARY_FILE,\r
445 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION\r
446 }\r
447\r
448 ## Constructor of InfParser\r
449 #\r
450 # Initialize object of InfParser\r
451 #\r
452 # @param FilePath The path of module description file\r
453 # @param FileType The raw data of DSC file\r
454 # @param Table Database used to retrieve module/package information\r
455 # @param Macros Macros used for replacement in file\r
456 #\r
457 def __init__(self, FilePath, FileType, Table):\r
458 # prevent re-initialization\r
459 if hasattr(self, "_Table"):\r
460 return\r
461 MetaFileParser.__init__(self, FilePath, FileType, Table)\r
462 self.TblFile = EccGlobalData.gDb.TblFile\r
463 self.FileID = -1\r
464\r
465 ## Parser starter\r
466 def Start(self):\r
467 NmakeLine = ''\r
468 Content = ''\r
b3d07ff8 469 Usage = ''\r
f51461c8
LG
470 try:\r
471 Content = open(str(self.MetaFile), 'r').readlines()\r
472 except:\r
473 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)\r
474 #\r
475 # Insert a record for file\r
476 #\r
477 Filename = NormPath(self.MetaFile)\r
478 FileID = self.TblFile.GetFileId(Filename)\r
479 if FileID:\r
480 self.FileID = FileID\r
481 else:\r
482 self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_INF)\r
f7496d71 483\r
f51461c8
LG
484 # parse the file line by line\r
485 IsFindBlockComment = False\r
486\r
487 for Index in range(0, len(Content)):\r
b3d07ff8
HC
488 if self._SectionType in [MODEL_EFI_GUID,\r
489 MODEL_EFI_PROTOCOL,\r
490 MODEL_EFI_PPI,\r
491 MODEL_PCD_FIXED_AT_BUILD,\r
492 MODEL_PCD_PATCHABLE_IN_MODULE,\r
493 MODEL_PCD_FEATURE_FLAG,\r
494 MODEL_PCD_DYNAMIC_EX,\r
495 MODEL_PCD_DYNAMIC]:\r
496 Line = Content[Index].strip()\r
8d62ae35
HC
497 if Line.startswith(TAB_SPECIAL_COMMENT):\r
498 Usage += ' ' + Line[Line.find(TAB_SPECIAL_COMMENT):]\r
499 continue\r
500 elif Line.startswith(TAB_COMMENT_SPLIT):\r
b3d07ff8
HC
501 continue\r
502 elif Line.find(TAB_COMMENT_SPLIT) > 0:\r
8d62ae35 503 Usage += ' ' + Line[Line.find(TAB_COMMENT_SPLIT):]\r
b3d07ff8 504 Line = Line[:Line.find(TAB_COMMENT_SPLIT)]\r
b3d07ff8 505 else:\r
f51461c8 506 # skip empty, commented, block commented lines\r
b3d07ff8
HC
507 Line = CleanString(Content[Index], AllowCppStyleComment=True)\r
508 Usage = ''\r
f51461c8
LG
509 NextLine = ''\r
510 if Index + 1 < len(Content):\r
511 NextLine = CleanString(Content[Index + 1])\r
512 if Line == '':\r
513 continue\r
514 if Line.find(DataType.TAB_COMMENT_EDK_START) > -1:\r
515 IsFindBlockComment = True\r
516 continue\r
517 if Line.find(DataType.TAB_COMMENT_EDK_END) > -1:\r
518 IsFindBlockComment = False\r
519 continue\r
520 if IsFindBlockComment:\r
521 continue\r
522\r
523 self._LineIndex = Index\r
524 self._CurrentLine = Line\r
525\r
526 # section header\r
527 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:\r
528 self._SectionHeaderParser()\r
529 # Check invalid sections\r
530 if self._Version < 0x00010005:\r
531 if self._SectionType in [MODEL_META_DATA_BUILD_OPTION,\r
532 MODEL_EFI_LIBRARY_CLASS,\r
533 MODEL_META_DATA_PACKAGE,\r
534 MODEL_PCD_FIXED_AT_BUILD,\r
535 MODEL_PCD_PATCHABLE_IN_MODULE,\r
536 MODEL_PCD_FEATURE_FLAG,\r
537 MODEL_PCD_DYNAMIC_EX,\r
538 MODEL_PCD_DYNAMIC,\r
539 MODEL_EFI_GUID,\r
540 MODEL_EFI_PROTOCOL,\r
541 MODEL_EFI_PPI,\r
542 MODEL_META_DATA_USER_EXTENSION]:\r
543 EdkLogger.error('Parser', FORMAT_INVALID,\r
544 "Section [%s] is not allowed in inf file without version" % (self._SectionName),\r
545 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)\r
546 elif self._SectionType in [MODEL_EFI_INCLUDE,\r
547 MODEL_EFI_LIBRARY_INSTANCE,\r
548 MODEL_META_DATA_NMAKE]:\r
549 EdkLogger.error('Parser', FORMAT_INVALID,\r
550 "Section [%s] is not allowed in inf file with version 0x%08x" % (self._SectionName, self._Version),\r
551 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)\r
552 continue\r
553 # merge two lines specified by '\' in section NMAKE\r
554 elif self._SectionType == MODEL_META_DATA_NMAKE:\r
555 if Line[-1] == '\\':\r
556 if NextLine == '':\r
557 self._CurrentLine = NmakeLine + Line[0:-1]\r
558 NmakeLine = ''\r
559 else:\r
560 if NextLine[0] == TAB_SECTION_START and NextLine[-1] == TAB_SECTION_END:\r
561 self._CurrentLine = NmakeLine + Line[0:-1]\r
562 NmakeLine = ''\r
563 else:\r
564 NmakeLine = NmakeLine + ' ' + Line[0:-1]\r
565 continue\r
566 else:\r
567 self._CurrentLine = NmakeLine + Line\r
568 NmakeLine = ''\r
569\r
570 # section content\r
ccaa7754 571 self._ValueList = ['', '', '']\r
f51461c8
LG
572 # parse current line, result will be put in self._ValueList\r
573 self._SectionParser[self._SectionType](self)\r
4231a819 574 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:\r
f51461c8
LG
575 self._ItemType = -1\r
576 continue\r
577 #\r
578 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,\r
579 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1\r
580 #\r
581 self._ValueList[0] = self._ValueList[0].replace('/', '\\')\r
8d62ae35 582 Usage = Usage.strip()\r
f51461c8
LG
583 for Arch, Platform in self._Scope:\r
584 self._Store(self._SectionType,\r
585 self._ValueList[0],\r
586 self._ValueList[1],\r
587 self._ValueList[2],\r
588 Arch,\r
589 Platform,\r
590 self._Owner[-1],\r
591 self.FileID,\r
592 self._LineIndex+1,\r
593 -1,\r
594 self._LineIndex+1,\r
595 -1,\r
b3d07ff8
HC
596 0,\r
597 Usage\r
f51461c8 598 )\r
8d62ae35 599 Usage = ''\r
f51461c8 600 if IsFindBlockComment:\r
f7496d71 601 EdkLogger.error("Parser", FORMAT_INVALID, "Open block comments (starting with /*) are expected to end with */",\r
f51461c8
LG
602 File=self.MetaFile)\r
603 self._Done()\r
604\r
605 ## Data parser for the format in which there's path\r
606 #\r
607 # Only path can have macro used. So we need to replace them before use.\r
608 #\r
609 def _IncludeParser(self):\r
610 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
611 self._ValueList[0:len(TokenList)] = TokenList\r
612 Macros = self._Macros\r
613 if Macros:\r
614 for Index in range(0, len(self._ValueList)):\r
615 Value = self._ValueList[Index]\r
616 if not Value:\r
617 continue\r
618\r
f51461c8
LG
619 self._ValueList[Index] = ReplaceMacro(Value, Macros)\r
620\r
621 ## Parse [Sources] section\r
622 #\r
623 # Only path can have macro used. So we need to replace them before use.\r
624 #\r
625 @ParseMacro\r
626 def _SourceFileParser(self):\r
627 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
628 self._ValueList[0:len(TokenList)] = TokenList\r
629 Macros = self._Macros\r
630 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'\r
631 if 'COMPONENT_TYPE' in Macros:\r
632 if self._Defines['COMPONENT_TYPE'].upper() == 'ACPITABLE':\r
633 self._ValueList[0] = GetSplitValueList(self._ValueList[0], ' ', 1)[0]\r
634 if self._Defines['BASE_NAME'] == 'Microcode':\r
635 pass\r
636 self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]\r
637\r
638 ## Parse [Binaries] section\r
639 #\r
640 # Only path can have macro used. So we need to replace them before use.\r
641 #\r
642 @ParseMacro\r
643 def _BinaryFileParser(self):\r
644 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 2)\r
645 if len(TokenList) < 2:\r
646 EdkLogger.error('Parser', FORMAT_INVALID, "No file type or path specified",\r
647 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",\r
648 File=self.MetaFile, Line=self._LineIndex+1)\r
649 if not TokenList[0]:\r
650 EdkLogger.error('Parser', FORMAT_INVALID, "No file type specified",\r
651 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",\r
652 File=self.MetaFile, Line=self._LineIndex+1)\r
653 if not TokenList[1]:\r
654 EdkLogger.error('Parser', FORMAT_INVALID, "No file path specified",\r
655 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",\r
656 File=self.MetaFile, Line=self._LineIndex+1)\r
657 self._ValueList[0:len(TokenList)] = TokenList\r
658 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)\r
659\r
660 ## [nmake] section parser (Edk.x style only)\r
661 def _NmakeParser(self):\r
662 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
663 self._ValueList[0:len(TokenList)] = TokenList\r
664 # remove macros\r
665 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)\r
666 # remove self-reference in macro setting\r
667 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})\r
668\r
669 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser\r
670 @ParseMacro\r
671 def _PcdParser(self):\r
672 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
673 ValueList = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
674 if len(ValueList) != 2:\r
675 EdkLogger.error('Parser', FORMAT_INVALID, "Illegal token space GUID and PCD name format",\r
676 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",\r
677 File=self.MetaFile, Line=self._LineIndex+1)\r
678 self._ValueList[0:1] = ValueList\r
679 if len(TokenList) > 1:\r
680 self._ValueList[2] = TokenList[1]\r
681 if self._ValueList[0] == '' or self._ValueList[1] == '':\r
682 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
683 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",\r
684 File=self.MetaFile, Line=self._LineIndex+1)\r
685\r
686 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.\r
687 if self._ValueList[2] != '':\r
688 InfPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)\r
689 if InfPcdValueList[0] in ['True', 'true', 'TRUE']:\r
690 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '1', 1);\r
691 elif InfPcdValueList[0] in ['False', 'false', 'FALSE']:\r
692 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '0', 1);\r
693\r
694 ## [depex] section parser\r
695 @ParseMacro\r
696 def _DepexParser(self):\r
697 self._ValueList[0:1] = [self._CurrentLine]\r
698\r
699 _SectionParser = {\r
700 MODEL_UNKNOWN : MetaFileParser._Skip,\r
701 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,\r
702 MODEL_META_DATA_BUILD_OPTION : MetaFileParser._BuildOptionParser,\r
703 MODEL_EFI_INCLUDE : _IncludeParser, # for Edk.x modules\r
704 MODEL_EFI_LIBRARY_INSTANCE : MetaFileParser._CommonParser, # for Edk.x modules\r
705 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,\r
706 MODEL_META_DATA_PACKAGE : MetaFileParser._PathParser,\r
707 MODEL_META_DATA_NMAKE : _NmakeParser, # for Edk.x modules\r
708 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,\r
709 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,\r
710 MODEL_PCD_FEATURE_FLAG : _PcdParser,\r
711 MODEL_PCD_DYNAMIC_EX : _PcdParser,\r
712 MODEL_PCD_DYNAMIC : _PcdParser,\r
713 MODEL_EFI_SOURCE_FILE : _SourceFileParser,\r
714 MODEL_EFI_GUID : MetaFileParser._CommonParser,\r
715 MODEL_EFI_PROTOCOL : MetaFileParser._CommonParser,\r
716 MODEL_EFI_PPI : MetaFileParser._CommonParser,\r
717 MODEL_EFI_DEPEX : _DepexParser,\r
718 MODEL_EFI_BINARY_FILE : _BinaryFileParser,\r
719 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip,\r
720 }\r
721\r
722## DSC file parser class\r
723#\r
724# @param FilePath The path of platform description file\r
725# @param FileType The raw data of DSC file\r
726# @param Table Database used to retrieve module/package information\r
727# @param Macros Macros used for replacement in file\r
728# @param Owner Owner ID (for sub-section parsing)\r
729# @param From ID from which the data comes (for !INCLUDE directive)\r
730#\r
731class DscParser(MetaFileParser):\r
732 # DSC file supported data types (one type per section)\r
733 DataType = {\r
734 TAB_SKUIDS.upper() : MODEL_EFI_SKU_ID,\r
735 TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,\r
736 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,\r
737 TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,\r
738 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,\r
739 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,\r
740 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,\r
741 TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_DEFAULT,\r
742 TAB_PCDS_DYNAMIC_HII_NULL.upper() : MODEL_PCD_DYNAMIC_HII,\r
743 TAB_PCDS_DYNAMIC_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_VPD,\r
744 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT,\r
745 TAB_PCDS_DYNAMIC_EX_HII_NULL.upper() : MODEL_PCD_DYNAMIC_EX_HII,\r
746 TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_EX_VPD,\r
747 TAB_COMPONENTS.upper() : MODEL_META_DATA_COMPONENT,\r
f51461c8
LG
748 TAB_DSC_DEFINES.upper() : MODEL_META_DATA_HEADER,\r
749 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,\r
750 TAB_DSC_DEFINES_EDKGLOBAL : MODEL_META_DATA_GLOBAL_DEFINE,\r
751 TAB_INCLUDE.upper() : MODEL_META_DATA_INCLUDE,\r
752 TAB_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
753 TAB_IF_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
754 TAB_IF_N_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF,\r
755 TAB_ELSE_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF,\r
756 TAB_ELSE.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,\r
757 TAB_END_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF,\r
8d62ae35 758 TAB_ERROR.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR,\r
f51461c8
LG
759 }\r
760\r
761 # Valid names in define section\r
762 DefineKeywords = [\r
763 "DSC_SPECIFICATION",\r
764 "PLATFORM_NAME",\r
765 "PLATFORM_GUID",\r
766 "PLATFORM_VERSION",\r
767 "SKUID_IDENTIFIER",\r
768 "PCD_INFO_GENERATION",\r
769 "SUPPORTED_ARCHITECTURES",\r
770 "BUILD_TARGETS",\r
771 "OUTPUT_DIRECTORY",\r
772 "FLASH_DEFINITION",\r
773 "BUILD_NUMBER",\r
774 "RFC_LANGUAGES",\r
775 "ISO_LANGUAGES",\r
776 "TIME_STAMP_FILE",\r
777 "VPD_TOOL_GUID",\r
778 "FIX_LOAD_TOP_MEMORY_ADDRESS"\r
779 ]\r
780\r
f05c2e9f
HC
781 SubSectionDefineKeywords = [\r
782 "FILE_GUID"\r
783 ]\r
784\r
f51461c8
LG
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
f7496d71 816\r
f51461c8
LG
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
f7496d71
LG
836\r
837\r
f51461c8
LG
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
f7496d71 848\r
f51461c8
LG
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
4231a819 875 if self._ValueList is None:\r
f51461c8
LG
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
ccaa7754 918 self._ValueList = ['', '', '']\r
f51461c8
LG
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
f7496d71 958 ExtraData=self._CurrentLine, File=self.MetaFile,\r
f51461c8
LG
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
f05c2e9f
HC
995 if (not self._ValueList[1] in self.DefineKeywords and\r
996 (self._InSubsection and self._ValueList[1] not in self.SubSectionDefineKeywords)):\r
f51461c8
LG
997 EdkLogger.error('Parser', FORMAT_INVALID,\r
998 "Unknown keyword found: %s. "\r
999 "If this is a macro you must "\r
1000 "add it as a DEFINE in the DSC" % self._ValueList[1],\r
1001 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)\r
1002 self._Defines[self._ValueList[1]] = self._ValueList[2]\r
1003 self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]\r
1004\r
1005 @ParseMacro\r
1006 def _SkuIdParser(self):\r
1007 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
1008 if len(TokenList) != 2:\r
1009 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Integer>|<UiName>'",\r
1010 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)\r
1011 self._ValueList[0:len(TokenList)] = TokenList\r
1012\r
1013 ## Parse Edk style of library modules\r
1014 def _LibraryInstanceParser(self):\r
1015 self._ValueList[0] = self._CurrentLine\r
1016\r
1017 ## PCD sections parser\r
1018 #\r
1019 # [PcdsFixedAtBuild]\r
1020 # [PcdsPatchableInModule]\r
1021 # [PcdsFeatureFlag]\r
1022 # [PcdsDynamicEx\r
1023 # [PcdsDynamicExDefault]\r
1024 # [PcdsDynamicExVpd]\r
1025 # [PcdsDynamicExHii]\r
1026 # [PcdsDynamic]\r
1027 # [PcdsDynamicDefault]\r
1028 # [PcdsDynamicVpd]\r
1029 # [PcdsDynamicHii]\r
1030 #\r
1031 @ParseMacro\r
1032 def _PcdParser(self):\r
1033 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
1034 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
1035 if len(TokenList) == 2:\r
1036 self._ValueList[2] = TokenList[1]\r
1037 if self._ValueList[0] == '' or self._ValueList[1] == '':\r
1038 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
1039 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",\r
1040 File=self.MetaFile, Line=self._LineIndex+1)\r
1041 if self._ValueList[2] == '':\r
1042 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",\r
1043 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",\r
1044 File=self.MetaFile, Line=self._LineIndex+1)\r
1045 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.\r
1046 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)\r
1047 if DscPcdValueList[0] in ['True', 'true', 'TRUE']:\r
1048 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1);\r
1049 elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:\r
1050 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);\r
1051\r
1052 ## [components] section parser\r
1053 @ParseMacro\r
1054 def _ComponentParser(self):\r
1055 if self._CurrentLine[-1] == '{':\r
1056 self._ValueList[0] = self._CurrentLine[0:-1].strip()\r
1057 self._InSubsection = True\r
1058 else:\r
1059 self._ValueList[0] = self._CurrentLine\r
1060\r
1061 ## [LibraryClasses] section\r
1062 @ParseMacro\r
1063 def _LibraryClassParser(self):\r
1064 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
1065 if len(TokenList) < 2:\r
1066 EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",\r
1067 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
1068 File=self.MetaFile, Line=self._LineIndex+1)\r
1069 if TokenList[0] == '':\r
1070 EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",\r
1071 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
1072 File=self.MetaFile, Line=self._LineIndex+1)\r
1073 if TokenList[1] == '':\r
1074 EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",\r
1075 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",\r
1076 File=self.MetaFile, Line=self._LineIndex+1)\r
1077\r
1078 self._ValueList[0:len(TokenList)] = TokenList\r
1079\r
f51461c8
LG
1080\r
1081 ## [BuildOptions] section parser\r
1082 @ParseMacro\r
1083 def _BuildOptionParser(self):\r
1084 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
1085 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)\r
1086 if len(TokenList2) == 2:\r
1087 self._ValueList[0] = TokenList2[0] # toolchain family\r
1088 self._ValueList[1] = TokenList2[1] # keys\r
1089 else:\r
1090 self._ValueList[1] = TokenList[0]\r
1091 if len(TokenList) == 2: # value\r
1092 self._ValueList[2] = TokenList[1]\r
1093\r
1094 if self._ValueList[1].count('_') != 4:\r
1095 EdkLogger.error(\r
1096 'Parser',\r
1097 FORMAT_INVALID,\r
1098 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],\r
1099 ExtraData=self._CurrentLine,\r
1100 File=self.MetaFile,\r
1101 Line=self._LineIndex+1\r
1102 )\r
1103\r
1104 ## Override parent's method since we'll do all macro replacements in parser\r
1105 def _GetMacros(self):\r
94c04559 1106 Macros = dict( [('ARCH', 'IA32'), ('FAMILY', TAB_COMPILER_MSFT), ('TOOL_CHAIN_TAG', 'VS2008x86'), ('TARGET', 'DEBUG')])\r
f51461c8
LG
1107 Macros.update(self._FileLocalMacros)\r
1108 Macros.update(self._GetApplicableSectionMacro())\r
1109 Macros.update(GlobalData.gEdkGlobal)\r
1110 Macros.update(GlobalData.gPlatformDefines)\r
1111 Macros.update(GlobalData.gCommandLineDefines)\r
1112 # PCD cannot be referenced in macro definition\r
1113 if self._ItemType not in [MODEL_META_DATA_DEFINE, MODEL_META_DATA_GLOBAL_DEFINE]:\r
1114 Macros.update(self._Symbols)\r
1115 return Macros\r
1116\r
1117 def _PostProcess(self):\r
1118 Processer = {\r
1119 MODEL_META_DATA_SECTION_HEADER : self.__ProcessSectionHeader,\r
1120 MODEL_META_DATA_SUBSECTION_HEADER : self.__ProcessSubsectionHeader,\r
1121 MODEL_META_DATA_HEADER : self.__ProcessDefine,\r
1122 MODEL_META_DATA_DEFINE : self.__ProcessDefine,\r
1123 MODEL_META_DATA_GLOBAL_DEFINE : self.__ProcessDefine,\r
1124 MODEL_META_DATA_INCLUDE : self.__ProcessDirective,\r
1125 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF : self.__ProcessDirective,\r
1126 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE : self.__ProcessDirective,\r
1127 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF : self.__ProcessDirective,\r
1128 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF : self.__ProcessDirective,\r
1129 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF : self.__ProcessDirective,\r
1130 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF : self.__ProcessDirective,\r
1131 MODEL_EFI_SKU_ID : self.__ProcessSkuId,\r
1132 MODEL_EFI_LIBRARY_INSTANCE : self.__ProcessLibraryInstance,\r
1133 MODEL_EFI_LIBRARY_CLASS : self.__ProcessLibraryClass,\r
1134 MODEL_PCD_FIXED_AT_BUILD : self.__ProcessPcd,\r
1135 MODEL_PCD_PATCHABLE_IN_MODULE : self.__ProcessPcd,\r
1136 MODEL_PCD_FEATURE_FLAG : self.__ProcessPcd,\r
1137 MODEL_PCD_DYNAMIC_DEFAULT : self.__ProcessPcd,\r
1138 MODEL_PCD_DYNAMIC_HII : self.__ProcessPcd,\r
1139 MODEL_PCD_DYNAMIC_VPD : self.__ProcessPcd,\r
1140 MODEL_PCD_DYNAMIC_EX_DEFAULT : self.__ProcessPcd,\r
1141 MODEL_PCD_DYNAMIC_EX_HII : self.__ProcessPcd,\r
1142 MODEL_PCD_DYNAMIC_EX_VPD : self.__ProcessPcd,\r
1143 MODEL_META_DATA_COMPONENT : self.__ProcessComponent,\r
f51461c8
LG
1144 MODEL_META_DATA_BUILD_OPTION : self.__ProcessBuildOption,\r
1145 MODEL_UNKNOWN : self._Skip,\r
1146 MODEL_META_DATA_USER_EXTENSION : self._Skip,\r
8d62ae35 1147 MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR : self._Skip,\r
f51461c8 1148 }\r
f7496d71 1149\r
f51461c8
LG
1150 self._RawTable = self._Table\r
1151 self._Table = MetaFileStorage(self._RawTable.Cur, self.MetaFile, MODEL_FILE_DSC, True)\r
1152 self._DirectiveStack = []\r
1153 self._DirectiveEvalStack = []\r
1154 self._FileWithError = self.MetaFile\r
1155 self._FileLocalMacros = {}\r
1156 self._SectionsMacroDict = {}\r
1157 GlobalData.gPlatformDefines = {}\r
1158\r
1159 # Get all macro and PCD which has straitforward value\r
1160 self.__RetrievePcdValue()\r
1161 self._Content = self._RawTable.GetAll()\r
1162 self._ContentIndex = 0\r
1163 while self._ContentIndex < len(self._Content) :\r
1164 Id, self._ItemType, V1, V2, V3, S1, S2, Owner, BelongsToFile, self._From, \\r
1165 LineStart, ColStart, LineEnd, ColEnd, Enabled = self._Content[self._ContentIndex]\r
1166\r
1167 if self._From < 0:\r
1168 self._FileWithError = self.MetaFile\r
1169\r
1170 self._ContentIndex += 1\r
1171\r
1172 self._Scope = [[S1, S2]]\r
1173 self._LineIndex = LineStart - 1\r
1174 self._ValueList = [V1, V2, V3]\r
1175\r
1176 try:\r
1177 Processer[self._ItemType]()\r
5b0671c1 1178 except EvaluationException as Excpt:\r
f7496d71 1179 #\r
f51461c8
LG
1180 # Only catch expression evaluation error here. We need to report\r
1181 # the precise number of line on which the error occurred\r
1182 #\r
8d62ae35
HC
1183 pass\r
1184# EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),\r
1185# File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
1186# Line=self._LineIndex+1)\r
5b0671c1 1187 except MacroException as Excpt:\r
f51461c8 1188 EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt),\r
f7496d71 1189 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
f51461c8
LG
1190 Line=self._LineIndex+1)\r
1191\r
4231a819 1192 if self._ValueList is None:\r
f7496d71 1193 continue\r
f51461c8
LG
1194\r
1195 NewOwner = self._IdMapping.get(Owner, -1)\r
1196 self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack))\r
1197 self._LastItem = self._Store(\r
1198 self._ItemType,\r
1199 self._ValueList[0],\r
1200 self._ValueList[1],\r
1201 self._ValueList[2],\r
1202 S1,\r
1203 S2,\r
1204 NewOwner,\r
1205 BelongsToFile,\r
1206 self._From,\r
1207 self._LineIndex+1,\r
1208 -1,\r
1209 self._LineIndex+1,\r
1210 -1,\r
1211 self._Enabled\r
1212 )\r
1213 self._IdMapping[Id] = self._LastItem\r
1214\r
1215 RecordList = self._Table.GetAll()\r
f7496d71 1216\r
f51461c8
LG
1217 self._RawTable.Drop()\r
1218 self._Table.Drop()\r
1219 for Record in RecordList:\r
ccaa7754 1220 EccGlobalData.gDb.TblDsc.Insert(Record[1], Record[2], Record[3], Record[4], Record[5], Record[6], Record[7], Record[8], Record[9], Record[10], Record[11], Record[12], Record[13], Record[14])\r
f51461c8
LG
1221 GlobalData.gPlatformDefines.update(self._FileLocalMacros)\r
1222 self._PostProcessed = True\r
1223 self._Content = None\r
1224\r
1225 def __ProcessSectionHeader(self):\r
1226 self._SectionName = self._ValueList[0]\r
1227 if self._SectionName in self.DataType:\r
1228 self._SectionType = self.DataType[self._SectionName]\r
1229 else:\r
1230 self._SectionType = MODEL_UNKNOWN\r
1231\r
1232 def __ProcessSubsectionHeader(self):\r
1233 self._SubsectionName = self._ValueList[0]\r
1234 if self._SubsectionName in self.DataType:\r
1235 self._SubsectionType = self.DataType[self._SubsectionName]\r
1236 else:\r
1237 self._SubsectionType = MODEL_UNKNOWN\r
1238\r
1239 def __RetrievePcdValue(self):\r
1240 Records = self._RawTable.Query(MODEL_PCD_FEATURE_FLAG, BelongsToItem=-1.0)\r
ccaa7754 1241 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, ID, Line in Records:\r
f51461c8
LG
1242 Value, DatumType, MaxDatumSize = AnalyzePcdData(Value)\r
1243 # Only use PCD whose value is straitforward (no macro and PCD)\r
1244 if self.SymbolPattern.findall(Value):\r
1245 continue\r
1246 Name = TokenSpaceGuid + '.' + PcdName\r
1247 # Don't use PCD with different values.\r
1248 if Name in self._Symbols and self._Symbols[Name] != Value:\r
1249 self._Symbols.pop(Name)\r
f7496d71 1250 continue\r
f51461c8
LG
1251 self._Symbols[Name] = Value\r
1252\r
1253 Records = self._RawTable.Query(MODEL_PCD_FIXED_AT_BUILD, BelongsToItem=-1.0)\r
ccaa7754 1254 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, ID, Line in Records:\r
f51461c8
LG
1255 Value, DatumType, MaxDatumSize = AnalyzePcdData(Value)\r
1256 # Only use PCD whose value is straitforward (no macro and PCD)\r
1257 if self.SymbolPattern.findall(Value):\r
f7496d71 1258 continue\r
f51461c8
LG
1259 Name = TokenSpaceGuid+'.'+PcdName\r
1260 # Don't use PCD with different values.\r
1261 if Name in self._Symbols and self._Symbols[Name] != Value:\r
1262 self._Symbols.pop(Name)\r
f7496d71 1263 continue\r
f51461c8
LG
1264 self._Symbols[Name] = Value\r
1265\r
1266 def __ProcessDefine(self):\r
1267 if not self._Enabled:\r
1268 return\r
1269\r
1270 Type, Name, Value = self._ValueList\r
1271 Value = ReplaceMacro(Value, self._Macros, False)\r
1272 if self._ItemType == MODEL_META_DATA_DEFINE:\r
1273 if self._SectionType == MODEL_META_DATA_HEADER:\r
1274 self._FileLocalMacros[Name] = Value\r
1275 else:\r
1276 SectionDictKey = self._SectionType, self._Scope[0][0], self._Scope[0][1]\r
1277 if SectionDictKey not in self._SectionsMacroDict:\r
1278 self._SectionsMacroDict[SectionDictKey] = {}\r
1279 SectionLocalMacros = self._SectionsMacroDict[SectionDictKey]\r
1280 SectionLocalMacros[Name] = Value\r
1281 elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE:\r
1282 GlobalData.gEdkGlobal[Name] = Value\r
f7496d71 1283\r
f51461c8
LG
1284 #\r
1285 # Keyword in [Defines] section can be used as Macros\r
1286 #\r
1287 if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER):\r
1288 self._FileLocalMacros[Name] = Value\r
f7496d71 1289\r
f51461c8
LG
1290 self._ValueList = [Type, Name, Value]\r
1291\r
1292 def __ProcessDirective(self):\r
1293 Result = None\r
1294 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1295 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF]:\r
1296 Macros = self._Macros\r
1297 Macros.update(GlobalData.gGlobalDefines)\r
1298 try:\r
1299 Result = ValueExpression(self._ValueList[1], Macros)()\r
5b0671c1 1300 except SymbolNotFound as Exc:\r
f51461c8
LG
1301 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])\r
1302 Result = False\r
5b0671c1 1303 except WrnExpression as Excpt:\r
f7496d71 1304 #\r
f51461c8
LG
1305 # Catch expression evaluation warning here. We need to report\r
1306 # the precise number of line and return the evaluation result\r
1307 #\r
1308 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),\r
f7496d71 1309 File=self._FileWithError, ExtraData=' '.join(self._ValueList),\r
f51461c8
LG
1310 Line=self._LineIndex+1)\r
1311 Result = Excpt.result\r
5b0671c1 1312 except BadExpression as Exc:\r
ce2f5940
HC
1313 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])\r
1314 Result = False\r
f51461c8
LG
1315\r
1316 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1317 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
1318 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:\r
1319 self._DirectiveStack.append(self._ItemType)\r
1320 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF:\r
1321 Result = bool(Result)\r
1322 else:\r
1323 Macro = self._ValueList[1]\r
1324 Macro = Macro[2:-1] if (Macro.startswith("$(") and Macro.endswith(")")) else Macro\r
1325 Result = Macro in self._Macros\r
1326 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF:\r
1327 Result = not Result\r
1328 self._DirectiveEvalStack.append(Result)\r
1329 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF:\r
1330 self._DirectiveStack.append(self._ItemType)\r
1331 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]\r
1332 self._DirectiveEvalStack.append(bool(Result))\r
1333 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:\r
1334 self._DirectiveStack[-1] = self._ItemType\r
1335 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]\r
1336 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:\r
1337 # Back to the nearest !if/!ifdef/!ifndef\r
1338 while self._DirectiveStack:\r
1339 self._DirectiveEvalStack.pop()\r
1340 Directive = self._DirectiveStack.pop()\r
1341 if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
1342 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
1343 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,\r
1344 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:\r
1345 break\r
1346 elif self._ItemType == MODEL_META_DATA_INCLUDE:\r
1347 # The included file must be relative to workspace or same directory as DSC file\r
1348 __IncludeMacros = {}\r
1349 #\r
1350 # Allow using system environment variables in path after !include\r
1351 #\r
1352 __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE']\r
f7496d71 1353\r
f51461c8 1354 #\r
f7496d71 1355 # Allow using MACROs comes from [Defines] section to keep compatible.\r
f51461c8
LG
1356 #\r
1357 __IncludeMacros.update(self._Macros)\r
f7496d71 1358\r
f51461c8
LG
1359 IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True))\r
1360 #\r
1361 # First search the include file under the same directory as DSC file\r
1362 #\r
1363 IncludedFile1 = PathClass(IncludedFile, self.MetaFile.Dir)\r
1364 ErrorCode, ErrorInfo1 = IncludedFile1.Validate()\r
1365 if ErrorCode != 0:\r
1366 #\r
1367 # Also search file under the WORKSPACE directory\r
1368 #\r
1369 IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)\r
1370 ErrorCode, ErrorInfo2 = IncludedFile1.Validate()\r
1371 if ErrorCode != 0:\r
f7496d71 1372 EdkLogger.error('parser', ErrorCode, File=self._FileWithError,\r
f51461c8
LG
1373 Line=self._LineIndex+1, ExtraData=ErrorInfo1 + "\n"+ ErrorInfo2)\r
1374\r
1375 self._FileWithError = IncludedFile1\r
1376\r
1377 IncludedFileTable = MetaFileStorage(self._Table.Cur, IncludedFile1, MODEL_FILE_DSC, True)\r
1378 Owner = self._Content[self._ContentIndex-1][0]\r
f7496d71 1379 Parser = DscParser(IncludedFile1, self._FileType, IncludedFileTable,\r
f51461c8
LG
1380 Owner=Owner, From=Owner)\r
1381\r
1382 # set the parser status with current status\r
1383 Parser._SectionName = self._SectionName\r
1384 Parser._SectionType = self._SectionType\r
1385 Parser._Scope = self._Scope\r
1386 Parser._Enabled = self._Enabled\r
1387 # Parse the included file\r
1388 Parser.Start()\r
1389\r
1390 # update current status with sub-parser's status\r
1391 self._SectionName = Parser._SectionName\r
1392 self._SectionType = Parser._SectionType\r
1393 self._Scope = Parser._Scope\r
1394 self._Enabled = Parser._Enabled\r
1395\r
1396 # Insert all records in the table for the included file into dsc file table\r
1397 Records = IncludedFileTable.GetAll()\r
1398 if Records:\r
1399 self._Content[self._ContentIndex:self._ContentIndex] = Records\r
1400 self._Content.pop(self._ContentIndex-1)\r
1401 self._ValueList = None\r
1402 self._ContentIndex -= 1\r
f7496d71 1403\r
f51461c8
LG
1404 def __ProcessSkuId(self):\r
1405 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)\r
1406 for Value in self._ValueList]\r
1407\r
1408 def __ProcessLibraryInstance(self):\r
1409 self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]\r
1410\r
1411 def __ProcessLibraryClass(self):\r
1412 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True)\r
1413\r
1414 def __ProcessPcd(self):\r
1415 ValueList = GetSplitValueList(self._ValueList[2])\r
1416 #\r
1417 # PCD value can be an expression\r
1418 #\r
656d2539 1419 if len(ValueList) > 1 and ValueList[1] == TAB_VOID:\r
f7496d71 1420 PcdValue = ValueList[0]\r
f51461c8
LG
1421 try:\r
1422 ValueList[0] = ValueExpression(PcdValue, self._Macros)(True)\r
5b0671c1 1423 except WrnExpression as Value:\r
f7496d71 1424 ValueList[0] = Value.result\r
f51461c8
LG
1425 else:\r
1426 PcdValue = ValueList[-1]\r
1427 try:\r
1428 ValueList[-1] = ValueExpression(PcdValue, self._Macros)(True)\r
5b0671c1 1429 except WrnExpression as Value:\r
f51461c8 1430 ValueList[-1] = Value.result\r
f7496d71 1431\r
f51461c8
LG
1432 if ValueList[-1] == 'True':\r
1433 ValueList[-1] = '1'\r
1434 if ValueList[-1] == 'False':\r
f7496d71 1435 ValueList[-1] = '0'\r
f51461c8
LG
1436\r
1437 self._ValueList[2] = '|'.join(ValueList)\r
1438\r
1439 def __ProcessComponent(self):\r
1440 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)\r
1441\r
f51461c8
LG
1442 def __ProcessBuildOption(self):\r
1443 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False)\r
1444 for Value in self._ValueList]\r
1445\r
1446 _SectionParser = {\r
1447 MODEL_META_DATA_HEADER : _DefineParser,\r
1448 MODEL_EFI_SKU_ID : _SkuIdParser,\r
1449 MODEL_EFI_LIBRARY_INSTANCE : _LibraryInstanceParser,\r
1450 MODEL_EFI_LIBRARY_CLASS : _LibraryClassParser,\r
1451 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,\r
1452 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,\r
1453 MODEL_PCD_FEATURE_FLAG : _PcdParser,\r
1454 MODEL_PCD_DYNAMIC_DEFAULT : _PcdParser,\r
1455 MODEL_PCD_DYNAMIC_HII : _PcdParser,\r
1456 MODEL_PCD_DYNAMIC_VPD : _PcdParser,\r
1457 MODEL_PCD_DYNAMIC_EX_DEFAULT : _PcdParser,\r
1458 MODEL_PCD_DYNAMIC_EX_HII : _PcdParser,\r
1459 MODEL_PCD_DYNAMIC_EX_VPD : _PcdParser,\r
1460 MODEL_META_DATA_COMPONENT : _ComponentParser,\r
f51461c8
LG
1461 MODEL_META_DATA_BUILD_OPTION : _BuildOptionParser,\r
1462 MODEL_UNKNOWN : MetaFileParser._Skip,\r
1463 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip,\r
1464 MODEL_META_DATA_SECTION_HEADER : MetaFileParser._SectionHeaderParser,\r
1465 MODEL_META_DATA_SUBSECTION_HEADER : _SubsectionHeaderParser,\r
1466 }\r
1467\r
1468 _Macros = property(_GetMacros)\r
1469\r
1470## DEC file parser class\r
1471#\r
1472# @param FilePath The path of platform description file\r
1473# @param FileType The raw data of DSC file\r
1474# @param Table Database used to retrieve module/package information\r
1475# @param Macros Macros used for replacement in file\r
1476#\r
1477class DecParser(MetaFileParser):\r
1478 # DEC file supported data types (one type per section)\r
1479 DataType = {\r
1480 TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER,\r
1481 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,\r
1482 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,\r
1483 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,\r
1484 TAB_GUIDS.upper() : MODEL_EFI_GUID,\r
1485 TAB_PPIS.upper() : MODEL_EFI_PPI,\r
1486 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,\r
1487 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,\r
1488 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,\r
1489 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,\r
1490 TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC,\r
1491 TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX,\r
1492 }\r
1493\r
1494 ## Constructor of DecParser\r
1495 #\r
1496 # Initialize object of DecParser\r
1497 #\r
1498 # @param FilePath The path of platform description file\r
1499 # @param FileType The raw data of DSC file\r
1500 # @param Table Database used to retrieve module/package information\r
1501 # @param Macros Macros used for replacement in file\r
1502 #\r
1503 def __init__(self, FilePath, FileType, Table):\r
1504 # prevent re-initialization\r
1505 if hasattr(self, "_Table"):\r
1506 return\r
1507 MetaFileParser.__init__(self, FilePath, FileType, Table)\r
1508 self._Comments = []\r
1509 self._Version = 0x00010005 # Only EDK2 dec file is supported\r
1510 self.TblFile = EccGlobalData.gDb.TblFile\r
1511 self.FileID = -1\r
1512\r
82af1cbf
FZ
1513 self._CurrentStructurePcdName = ""\r
1514 self._include_flag = False\r
1515 self._package_flag = False\r
1516\r
f51461c8
LG
1517 ## Parser starter\r
1518 def Start(self):\r
1519 Content = ''\r
1520 try:\r
1521 Content = open(str(self.MetaFile), 'r').readlines()\r
1522 except:\r
1523 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)\r
1524\r
1525 #\r
1526 # Insert a record for file\r
1527 #\r
1528 Filename = NormPath(self.MetaFile)\r
1529 FileID = self.TblFile.GetFileId(Filename)\r
1530 if FileID:\r
1531 self.FileID = FileID\r
1532 else:\r
1533 self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_DEC)\r
f7496d71 1534\r
f51461c8
LG
1535 for Index in range(0, len(Content)):\r
1536 Line, Comment = CleanString2(Content[Index])\r
1537 self._CurrentLine = Line\r
1538 self._LineIndex = Index\r
1539\r
1540 # save comment for later use\r
1541 if Comment:\r
1542 self._Comments.append((Comment, self._LineIndex+1))\r
1543 # skip empty line\r
1544 if Line == '':\r
1545 continue\r
1546\r
1547 # section header\r
1548 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:\r
1549 self._SectionHeaderParser()\r
1550 self._Comments = []\r
1551 continue\r
1552 elif len(self._SectionType) == 0:\r
1553 self._Comments = []\r
1554 continue\r
1555\r
1556 # section content\r
ccaa7754 1557 self._ValueList = ['', '', '']\r
f51461c8 1558 self._SectionParser[self._SectionType[0]](self)\r
4231a819 1559 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:\r
f51461c8
LG
1560 self._ItemType = -1\r
1561 self._Comments = []\r
1562 continue\r
1563\r
1564 #\r
1565 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,\r
1566 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1\r
1567 #\r
1568 for Arch, ModuleType, Type in self._Scope:\r
1569 self._LastItem = self._Store(\r
1570 Type,\r
1571 self._ValueList[0],\r
1572 self._ValueList[1],\r
1573 self._ValueList[2],\r
1574 Arch,\r
1575 ModuleType,\r
1576 self._Owner[-1],\r
1577 self.FileID,\r
1578 self._LineIndex+1,\r
1579 -1,\r
1580 self._LineIndex+1,\r
1581 -1,\r
1582 0\r
1583 )\r
1584 for Comment, LineNo in self._Comments:\r
1585 self._Store(\r
1586 MODEL_META_DATA_COMMENT,\r
1587 Comment,\r
1588 self._ValueList[0],\r
1589 self._ValueList[1],\r
1590 Arch,\r
1591 ModuleType,\r
1592 self._LastItem,\r
1593 self.FileID,\r
1594 LineNo,\r
1595 -1,\r
1596 LineNo,\r
1597 -1,\r
1598 0\r
1599 )\r
1600 self._Comments = []\r
1601 self._Done()\r
1602\r
1603 def _GetApplicableSectionMacro(self):\r
1604 Macros = {}\r
1605 for S1, S2, SectionType in self._Scope:\r
1606 for Scope1, Scope2 in [("COMMON", "COMMON"), ("COMMON", S2), (S1, "COMMON"), (S1, S2)]:\r
1607 if (SectionType, Scope1, Scope2) in self._SectionsMacroDict:\r
1608 Macros.update(self._SectionsMacroDict[(SectionType, Scope1, Scope2)])\r
1609 return Macros\r
1610\r
1611 ## Section header parser\r
1612 #\r
1613 # The section header is always in following format:\r
1614 #\r
1615 # [section_name.arch<.platform|module_type>]\r
1616 #\r
1617 def _SectionHeaderParser(self):\r
1618 self._Scope = []\r
1619 self._SectionName = ''\r
1620 self._SectionType = []\r
1621 ArchList = set()\r
1622 for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):\r
1623 if Item == '':\r
1624 continue\r
1625 ItemList = GetSplitValueList(Item, TAB_SPLIT)\r
1626\r
1627 # different types of PCD are permissible in one section\r
1628 self._SectionName = ItemList[0].upper()\r
1629 if self._SectionName in self.DataType:\r
1630 if self.DataType[self._SectionName] not in self._SectionType:\r
1631 self._SectionType.append(self.DataType[self._SectionName])\r
1632 else:\r
1633 EdkLogger.warn("Parser", "Unrecognized section", File=self.MetaFile,\r
1634 Line=self._LineIndex+1, ExtraData=self._CurrentLine)\r
1635 continue\r
1636\r
1637 if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:\r
1638 EdkLogger.error(\r
1639 'Parser',\r
1640 FORMAT_INVALID,\r
1641 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,\r
1642 File=self.MetaFile,\r
1643 Line=self._LineIndex+1,\r
1644 ExtraData=self._CurrentLine\r
1645 )\r
1646 # S1 is always Arch\r
1647 if len(ItemList) > 1:\r
1648 S1 = ItemList[1].upper()\r
1649 else:\r
1650 S1 = 'COMMON'\r
1651 ArchList.add(S1)\r
1652 # S2 may be Platform or ModuleType\r
1653 if len(ItemList) > 2:\r
1654 S2 = ItemList[2].upper()\r
1655 else:\r
1656 S2 = 'COMMON'\r
1657 if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:\r
1658 self._Scope.append([S1, S2, self.DataType[self._SectionName]])\r
1659\r
1660 # 'COMMON' must not be used with specific ARCHs at the same section\r
1661 if 'COMMON' in ArchList and len(ArchList) > 1:\r
1662 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",\r
1663 File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine)\r
1664\r
1665 ## [guids], [ppis] and [protocols] section parser\r
1666 @ParseMacro\r
1667 def _GuidParser(self):\r
1668 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
1669 if len(TokenList) < 2:\r
1670 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",\r
1671 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1672 File=self.MetaFile, Line=self._LineIndex+1)\r
1673 if TokenList[0] == '':\r
1674 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",\r
1675 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1676 File=self.MetaFile, Line=self._LineIndex+1)\r
1677 if TokenList[1] == '':\r
1678 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",\r
1679 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",\r
1680 File=self.MetaFile, Line=self._LineIndex+1)\r
1681 if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':\r
1682 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",\r
1683 ExtraData=self._CurrentLine + \\r
1684 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",\r
1685 File=self.MetaFile, Line=self._LineIndex+1)\r
1686 self._ValueList[0] = TokenList[0]\r
1687 #Parse the Guid value format\r
1688 GuidValueList = TokenList[1].strip(' {}').split(',')\r
1689 Index = 0\r
1690 HexList = []\r
1691 if len(GuidValueList) == 11:\r
1692 for GuidValue in GuidValueList:\r
1693 GuidValue = GuidValue.strip()\r
1694 if GuidValue.startswith('0x') or GuidValue.startswith('0X'):\r
1695 HexList.append('0x' + str(GuidValue[2:]))\r
1696 Index += 1\r
1697 continue\r
1698 else:\r
1699 if GuidValue.startswith('{'):\r
e84d2b70
HC
1700 GuidValue = GuidValue.lstrip(' {')\r
1701 HexList.append('0x' + str(GuidValue[2:]))\r
f51461c8 1702 Index += 1\r
ccaa7754 1703 self._ValueList[1] = "{ %s, %s, %s, { %s, %s, %s, %s, %s, %s, %s, %s }}" % (HexList[0], HexList[1], HexList[2], HexList[3], HexList[4], HexList[5], HexList[6], HexList[7], HexList[8], HexList[9], HexList[10])\r
f51461c8
LG
1704 else:\r
1705 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",\r
1706 ExtraData=self._CurrentLine + \\r
1707 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",\r
1708 File=self.MetaFile, Line=self._LineIndex+1)\r
1709 self._ValueList[0] = ''\r
1710\r
82af1cbf
FZ
1711 def ParsePcdName(self,namelist):\r
1712 if "[" in namelist[1]:\r
1713 pcdname = namelist[1][:namelist[1].index("[")]\r
1714 arrayindex = namelist[1][namelist[1].index("["):]\r
1715 namelist[1] = pcdname\r
1716 if len(namelist) == 2:\r
1717 namelist.append(arrayindex)\r
1718 else:\r
1719 namelist[2] = ".".join((arrayindex,namelist[2]))\r
1720 return namelist\r
1721\r
1722 def StructPcdParser(self):\r
1723 self._ValueList[0] = self._CurrentStructurePcdName\r
1724\r
1725 if "|" not in self._CurrentLine:\r
1726 if "<HeaderFiles>" == self._CurrentLine:\r
1727 self._include_flag = True\r
1728 self._package_flag = False\r
1729 self._ValueList = None\r
1730 return\r
1731 if "<Packages>" == self._CurrentLine:\r
1732 self._package_flag = True\r
1733 self._ValueList = None\r
1734 self._include_flag = False\r
1735 return\r
1736\r
1737 if self._include_flag:\r
1738 self._ValueList[1] = "<HeaderFiles>_" + md5(self._CurrentLine.encode('utf-8')).hexdigest()\r
1739 self._ValueList[2] = self._CurrentLine\r
1740 if self._package_flag and "}" != self._CurrentLine:\r
1741 self._ValueList[1] = "<Packages>_" + md5(self._CurrentLine.encode('utf-8')).hexdigest()\r
1742 self._ValueList[2] = self._CurrentLine\r
1743 if self._CurrentLine == "}":\r
1744 self._package_flag = False\r
1745 self._include_flag = False\r
1746 self._ValueList = None\r
1747 else:\r
1748 PcdTockens = self._CurrentLine.split(TAB_VALUE_SPLIT)\r
1749 PcdNames = self.ParsePcdName(PcdTockens[0].split(TAB_SPLIT))\r
1750 if len(PcdNames) == 2:\r
1751 if PcdNames[1].strip().endswith("]"):\r
1752 PcdName = PcdNames[1][:PcdNames[1].index('[')]\r
1753 Index = PcdNames[1][PcdNames[1].index('['):]\r
1754 self._ValueList[0] = TAB_SPLIT.join((PcdNames[0], PcdName))\r
1755 self._ValueList[1] = Index\r
1756 self._ValueList[2] = PcdTockens[1]\r
1757 else:\r
1758 self._CurrentStructurePcdName = ""\r
1759 else:\r
1760 if self._CurrentStructurePcdName != TAB_SPLIT.join(PcdNames[:2]):\r
1761 EdkLogger.error('Parser', FORMAT_INVALID, "Pcd Name does not match: %s and %s " % (\r
1762 self._CurrentStructurePcdName, TAB_SPLIT.join(PcdNames[:2])),\r
1763 File=self.MetaFile, Line=self._LineIndex + 1)\r
1764 self._ValueList[1] = TAB_SPLIT.join(PcdNames[2:])\r
1765 self._ValueList[2] = PcdTockens[1]\r
1766\r
f51461c8
LG
1767 ## PCD sections parser\r
1768 #\r
1769 # [PcdsFixedAtBuild]\r
1770 # [PcdsPatchableInModule]\r
1771 # [PcdsFeatureFlag]\r
1772 # [PcdsDynamicEx\r
1773 # [PcdsDynamic]\r
1774 #\r
1775 @ParseMacro\r
1776 def _PcdParser(self):\r
82af1cbf
FZ
1777 if self._CurrentStructurePcdName:\r
1778 self.StructPcdParser()\r
1779 return\r
f51461c8
LG
1780 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
1781 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
1782 # check PCD information\r
1783 if self._ValueList[0] == '' or self._ValueList[1] == '':\r
1784 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
1785 ExtraData=self._CurrentLine + \\r
1786 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1787 File=self.MetaFile, Line=self._LineIndex+1)\r
1788 # check PCD datum information\r
1789 if len(TokenList) < 2 or TokenList[1] == '':\r
1790 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",\r
1791 ExtraData=self._CurrentLine + \\r
1792 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1793 File=self.MetaFile, Line=self._LineIndex+1)\r
1794\r
f7496d71 1795\r
f51461c8
LG
1796 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')\r
1797 PtrValue = ValueRe.findall(TokenList[1])\r
f7496d71
LG
1798\r
1799 # Has VOID* type string, may contain "|" character in the string.\r
f51461c8
LG
1800 if len(PtrValue) != 0:\r
1801 ptrValueList = re.sub(ValueRe, '', TokenList[1])\r
1802 ValueList = GetSplitValueList(ptrValueList)\r
1803 ValueList[0] = PtrValue[0]\r
1804 else:\r
1805 ValueList = GetSplitValueList(TokenList[1])\r
f7496d71
LG
1806\r
1807\r
f51461c8
LG
1808 # check if there's enough datum information given\r
1809 if len(ValueList) != 3:\r
1810 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",\r
1811 ExtraData=self._CurrentLine + \\r
1812 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1813 File=self.MetaFile, Line=self._LineIndex+1)\r
1814 # check default value\r
1815 if ValueList[0] == '':\r
1816 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",\r
1817 ExtraData=self._CurrentLine + \\r
1818 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1819 File=self.MetaFile, Line=self._LineIndex+1)\r
1820 # check datum type\r
1821 if ValueList[1] == '':\r
1822 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",\r
1823 ExtraData=self._CurrentLine + \\r
1824 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1825 File=self.MetaFile, Line=self._LineIndex+1)\r
1826 # check token of the PCD\r
1827 if ValueList[2] == '':\r
1828 EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",\r
1829 ExtraData=self._CurrentLine + \\r
1830 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",\r
1831 File=self.MetaFile, Line=self._LineIndex+1)\r
1832 # check format of default value against the datum type\r
1833 IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])\r
1834 if not IsValid:\r
1835 EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,\r
1836 File=self.MetaFile, Line=self._LineIndex+1)\r
82af1cbf
FZ
1837 if Cause == "StructurePcd":\r
1838 self._CurrentStructurePcdName = TAB_SPLIT.join(self._ValueList[0:2])\r
1839 self._ValueList[0] = self._CurrentStructurePcdName\r
1840 self._ValueList[1] = ValueList[1].strip()\r
f7496d71 1841\r
b66592d8
HC
1842 if EccGlobalData.gConfig.UniCheckPCDInfo == '1' or EccGlobalData.gConfig.UniCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
1843 # check Description, Prompt information\r
1844 PatternDesc = re.compile('##\s*([\x21-\x7E\s]*)', re.S)\r
1845 PatternPrompt = re.compile('#\s+@Prompt\s+([\x21-\x7E\s]*)', re.S)\r
1846 Description = None\r
1847 Prompt = None\r
1848 # check @ValidRange, @ValidList and @Expression format valid\r
1849 ErrorCodeValid = '0x0 <= %s <= 0xFFFFFFFF'\r
1850 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
1851 PatternValidRng = re.compile('^' + '(NOT)?\s*' + PatternValidRangeIn + '$')\r
1852 for Comment in self._Comments:\r
1853 Comm = Comment[0].strip()\r
1854 if not Comm:\r
1855 continue\r
1856 if not Description:\r
1857 Description = PatternDesc.findall(Comm)\r
1858 if not Prompt:\r
1859 Prompt = PatternPrompt.findall(Comm)\r
1860 if Comm[0] == '#':\r
1861 ValidFormt = Comm.lstrip('#')\r
1862 ValidFormt = ValidFormt.lstrip()\r
1863 if ValidFormt[0:11] == '@ValidRange':\r
1864 ValidFormt = ValidFormt[11:]\r
1865 ValidFormt = ValidFormt.lstrip()\r
1866 try:\r
1867 ErrorCode, Expression = ValidFormt.split('|', 1)\r
1868 except ValueError:\r
1869 ErrorCode = '0x0'\r
1870 Expression = ValidFormt\r
1871 ErrorCode, Expression = ErrorCode.strip(), Expression.strip()\r
1872 try:\r
1873 if not eval(ErrorCodeValid % ErrorCode):\r
1874 EdkLogger.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))\r
1875 except:\r
1876 EdkLogger.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))\r
1877 if not PatternValidRng.search(Expression):\r
1878 EdkLogger.warn('Parser', '@ValidRange Expression(%s) of PCD %s is incorrect format.' % (Expression, TokenList[0]))\r
1879 if ValidFormt[0:10] == '@ValidList':\r
1880 ValidFormt = ValidFormt[10:]\r
1881 ValidFormt = ValidFormt.lstrip()\r
1882 try:\r
1883 ErrorCode, Expression = ValidFormt.split('|', 1)\r
1884 except ValueError:\r
1885 ErrorCode = '0x0'\r
1886 Expression = ValidFormt\r
1887 ErrorCode, Expression = ErrorCode.strip(), Expression.strip()\r
1888 try:\r
1889 if not eval(ErrorCodeValid % ErrorCode):\r
1890 EdkLogger.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))\r
1891 except:\r
1892 EdkLogger.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))\r
1893 Values = Expression.split(',')\r
1894 for Value in Values:\r
1895 Value = Value.strip()\r
1896 try:\r
1897 eval(Value)\r
1898 except:\r
1899 EdkLogger.warn('Parser', '@ValidList Expression of PCD %s include a invalid value(%s).' % (TokenList[0], Value))\r
1900 break\r
1901 if ValidFormt[0:11] == '@Expression':\r
1902 ValidFormt = ValidFormt[11:]\r
1903 ValidFormt = ValidFormt.lstrip()\r
1904 try:\r
1905 ErrorCode, Expression = ValidFormt.split('|', 1)\r
1906 except ValueError:\r
1907 ErrorCode = '0x0'\r
1908 Expression = ValidFormt\r
1909 ErrorCode, Expression = ErrorCode.strip(), Expression.strip()\r
1910 try:\r
1911 if not eval(ErrorCodeValid % ErrorCode):\r
1912 EdkLogger.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))\r
1913 except:\r
1914 EdkLogger.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))\r
1915 if not Expression:\r
1916 EdkLogger.warn('Parser', '@Expression Expression of PCD %s is incorrect format.' % TokenList[0])\r
1917 if not Description:\r
1918 EdkLogger.warn('Parser', 'PCD %s Description information is not provided.' % TokenList[0])\r
1919 if not Prompt:\r
1920 EdkLogger.warn('Parser', 'PCD %s Prompt information is not provided.' % TokenList[0])\r
1921 # check Description, Prompt localization information\r
1922 if self._UniObj:\r
1923 self._UniObj.CheckPcdInfo(TokenList[0])\r
f51461c8
LG
1924\r
1925 if ValueList[0] in ['True', 'true', 'TRUE']:\r
1926 ValueList[0] = '1'\r
1927 elif ValueList[0] in ['False', 'false', 'FALSE']:\r
1928 ValueList[0] = '0'\r
1929\r
1930 self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()\r
1931\r
1932 _SectionParser = {\r
1933 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,\r
1934 MODEL_EFI_INCLUDE : MetaFileParser._PathParser,\r
1935 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,\r
1936 MODEL_EFI_GUID : _GuidParser,\r
1937 MODEL_EFI_PPI : _GuidParser,\r
1938 MODEL_EFI_PROTOCOL : _GuidParser,\r
1939 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,\r
1940 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,\r
1941 MODEL_PCD_FEATURE_FLAG : _PcdParser,\r
1942 MODEL_PCD_DYNAMIC : _PcdParser,\r
1943 MODEL_PCD_DYNAMIC_EX : _PcdParser,\r
1944 MODEL_UNKNOWN : MetaFileParser._Skip,\r
1945 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip,\r
1946 }\r
1947\r
1948\r
f51461c8
LG
1949## Fdf\r
1950#\r
1951# This class defined the structure used in Fdf object\r
f7496d71 1952#\r
f51461c8
LG
1953# @param Filename: Input value for Ffilename of Fdf file, default is None\r
1954# @param WorkspaceDir: Input value for current workspace directory, default is None\r
1955#\r
0b560b98 1956class Fdf(object):\r
f51461c8
LG
1957 def __init__(self, Filename = None, IsToDatabase = False, WorkspaceDir = None, Database = None):\r
1958 self.WorkspaceDir = WorkspaceDir\r
1959 self.IsToDatabase = IsToDatabase\r
f7496d71 1960\r
f51461c8
LG
1961 self.Cur = Database.Cur\r
1962 self.TblFile = Database.TblFile\r
1963 self.TblFdf = Database.TblFdf\r
1964 self.FileID = -1\r
1965 self.FileList = {}\r
1966\r
1967 #\r
1968 # Load Fdf file if filename is not None\r
1969 #\r
4231a819 1970 if Filename is not None:\r
8d62ae35
HC
1971 try:\r
1972 self.LoadFdfFile(Filename)\r
1973 except Exception:\r
1974 pass\r
f51461c8
LG
1975\r
1976 #\r
1977 # Insert a FDF file record into database\r
1978 #\r
1979 def InsertFile(self, Filename):\r
1980 FileID = -1\r
1981 Filename = NormPath(Filename)\r
1982 if Filename not in self.FileList:\r
1983 FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_FDF)\r
1984 self.FileList[Filename] = FileID\r
1985\r
1986 return self.FileList[Filename]\r
f7496d71
LG
1987\r
1988\r
f51461c8
LG
1989 ## Load Fdf file\r
1990 #\r
1991 # Load the file if it exists\r
1992 #\r
1993 # @param Filename: Input value for filename of Fdf file\r
1994 #\r
f7496d71 1995 def LoadFdfFile(self, Filename):\r
f51461c8
LG
1996 FileList = []\r
1997 #\r
1998 # Parse Fdf file\r
1999 #\r
2000 Filename = NormPath(Filename)\r
2001 Fdf = FdfParser(Filename)\r
2002 Fdf.ParseFile()\r
2003\r
2004 #\r
2005 # Insert inf file and pcd information\r
2006 #\r
2007 if self.IsToDatabase:\r
2008 (Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled) = \\r
2009 (0, '', '', '', 'COMMON', 'COMMON', -1, -1, -1, -1, -1, -1, 0)\r
2010 for Index in range(0, len(Fdf.Profile.PcdDict)):\r
2011 pass\r
2012 for Key in Fdf.Profile.PcdDict.keys():\r
2013 Model = MODEL_PCD\r
2014 Value1 = Key[1]\r
2015 Value2 = Key[0]\r
2016 FileName = Fdf.Profile.PcdFileLineDict[Key][0]\r
2017 StartLine = Fdf.Profile.PcdFileLineDict[Key][1]\r
2018 BelongsToFile = self.InsertFile(FileName)\r
2019 self.TblFdf.Insert(Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled)\r
2020 for Index in range(0, len(Fdf.Profile.InfList)):\r
2021 Model = MODEL_META_DATA_COMPONENT\r
2022 Value1 = Fdf.Profile.InfList[Index]\r
2023 Value2 = ''\r
2024 FileName = Fdf.Profile.InfFileLineList[Index][0]\r
2025 StartLine = Fdf.Profile.InfFileLineList[Index][1]\r
2026 BelongsToFile = self.InsertFile(FileName)\r
2027 self.TblFdf.Insert(Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled)\r
2028\r
1b2467c5
HC
2029class UniParser(object):\r
2030 # IsExtraUni defined the UNI file is Module UNI or extra Module UNI\r
2031 # IsModuleUni defined the UNI file is Module UNI or Package UNI\r
2032 def __init__(self, FilePath, IsExtraUni=False, IsModuleUni=True):\r
2033 self.FilePath = FilePath\r
2034 self.FileName = os.path.basename(FilePath)\r
2035 self.IsExtraUni = IsExtraUni\r
2036 self.IsModuleUni = IsModuleUni\r
2037 self.FileIn = None\r
2038 self.Missing = []\r
2039 self.__read()\r
f7496d71 2040\r
1b2467c5
HC
2041 def __read(self):\r
2042 try:\r
97588927 2043 self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_8').read()\r
1b2467c5 2044 except UnicodeError:\r
97588927
HC
2045 self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_16').read()\r
2046 except UnicodeError:\r
2047 self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_16_le').read()\r
1b2467c5
HC
2048 except IOError:\r
2049 self.FileIn = ""\r
f7496d71 2050\r
1b2467c5
HC
2051 def Start(self):\r
2052 if self.IsModuleUni:\r
2053 if self.IsExtraUni:\r
2054 ModuleName = self.CheckKeyValid('STR_PROPERTIES_MODULE_NAME')\r
2055 self.PrintLog('STR_PROPERTIES_MODULE_NAME', ModuleName)\r
2056 else:\r
2057 ModuleAbstract = self.CheckKeyValid('STR_MODULE_ABSTRACT')\r
2058 self.PrintLog('STR_MODULE_ABSTRACT', ModuleAbstract)\r
2059 ModuleDescription = self.CheckKeyValid('STR_MODULE_DESCRIPTION')\r
2060 self.PrintLog('STR_MODULE_DESCRIPTION', ModuleDescription)\r
2061 else:\r
2062 if self.IsExtraUni:\r
2063 PackageName = self.CheckKeyValid('STR_PROPERTIES_PACKAGE_NAME')\r
2064 self.PrintLog('STR_PROPERTIES_PACKAGE_NAME', PackageName)\r
2065 else:\r
2066 PackageAbstract = self.CheckKeyValid('STR_PACKAGE_ABSTRACT')\r
2067 self.PrintLog('STR_PACKAGE_ABSTRACT', PackageAbstract)\r
2068 PackageDescription = self.CheckKeyValid('STR_PACKAGE_DESCRIPTION')\r
2069 self.PrintLog('STR_PACKAGE_DESCRIPTION', PackageDescription)\r
f7496d71 2070\r
1b2467c5
HC
2071 def CheckKeyValid(self, Key, Contents=None):\r
2072 if not Contents:\r
2073 Contents = self.FileIn\r
2074 KeyPattern = re.compile('#string\s+%s\s+.*?#language.*?".*?"' % Key, re.S)\r
2075 if KeyPattern.search(Contents):\r
2076 return True\r
2077 return False\r
f7496d71 2078\r
1b2467c5
HC
2079 def CheckPcdInfo(self, PcdCName):\r
2080 PromptKey = 'STR_%s_PROMPT' % PcdCName.replace('.', '_')\r
2081 PcdPrompt = self.CheckKeyValid(PromptKey)\r
2082 self.PrintLog(PromptKey, PcdPrompt)\r
2083 HelpKey = 'STR_%s_HELP' % PcdCName.replace('.', '_')\r
2084 PcdHelp = self.CheckKeyValid(HelpKey)\r
2085 self.PrintLog(HelpKey, PcdHelp)\r
f7496d71 2086\r
1b2467c5
HC
2087 def PrintLog(self, Key, Value):\r
2088 if not Value and Key not in self.Missing:\r
2089 Msg = '%s is missing in the %s file.' % (Key, self.FileName)\r
2090 EdkLogger.warn('Parser', Msg)\r
2091 EccGlobalData.gDb.TblReport.Insert(EccToolError.ERROR_GENERAL_CHECK_UNI_HELP_INFO, OtherMsg=Msg, BelongsToTable='File', BelongsToItem=-2)\r
2092 self.Missing.append(Key)\r
2093\r
f51461c8
LG
2094##\r
2095#\r
2096# This acts like the main() function for the script, unless it is 'import'ed into another\r
2097# script.\r
2098#\r
2099if __name__ == '__main__':\r
2100 pass\r
2101\r