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