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