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