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