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 SymbolPattern = ValueExpression.SymbolPattern 787 788 ## Constructor of DscParser 789 # 790 # Initialize object of DscParser 791 # 792 # @param FilePath The path of platform description file 793 # @param FileType The raw data of DSC file 794 # @param Table Database used to retrieve module/package information 795 # @param Macros Macros used for replacement in file 796 # @param Owner Owner ID (for sub-section parsing) 797 # @param From ID from which the data comes (for !INCLUDE directive) 798 # 799 def __init__(self, FilePath, FileType, Table, Owner=-1, From=-1): 800 # prevent re-initialization 801 if hasattr(self, "_Table"): 802 return 803 MetaFileParser.__init__(self, FilePath, FileType, Table, Owner, From) 804 self._Version = 0x00010005 # Only EDK2 dsc file is supported 805 # to store conditional directive evaluation result 806 self._DirectiveStack = [] 807 self._DirectiveEvalStack = [] 808 self._Enabled = 1 809 810 # Final valid replacable symbols 811 self._Symbols = {} 812 # 813 # Map the ID between the original table and new table to track 814 # the owner item 815 # 816 self._IdMapping = {-1:-1} 817 818 self.TblFile = EccGlobalData.gDb.TblFile 819 self.FileID = -1 820 821 ## Parser starter 822 def Start(self): 823 Content = '' 824 try: 825 Content = open(str(self.MetaFile.Path), 'r').readlines() 826 except: 827 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile) 828 # 829 # Insert a record for file 830 # 831 Filename = NormPath(self.MetaFile.Path) 832 FileID = self.TblFile.GetFileId(Filename) 833 if FileID: 834 self.FileID = FileID 835 else: 836 self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_DSC) 837 838 839 for Index in range(0, len(Content)): 840 Line = CleanString(Content[Index]) 841 # skip empty line 842 if Line == '': 843 continue 844 845 self._CurrentLine = Line 846 self._LineIndex = Index 847 if self._InSubsection and self._Owner[-1] == -1: 848 self._Owner.append(self._LastItem) 849 850 # section header 851 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END: 852 self._SectionType = MODEL_META_DATA_SECTION_HEADER 853 # subsection ending 854 elif Line[0] == '}' and self._InSubsection: 855 self._InSubsection = False 856 self._SubsectionType = MODEL_UNKNOWN 857 self._SubsectionName = '' 858 self._Owner[-1] = -1 859 continue 860 # subsection header 861 elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END: 862 self._SubsectionType = MODEL_META_DATA_SUBSECTION_HEADER 863 # directive line 864 elif Line[0] == '!': 865 self._DirectiveParser() 866 continue 867 868 if self._InSubsection: 869 SectionType = self._SubsectionType 870 else: 871 SectionType = self._SectionType 872 self._ItemType = SectionType 873 874 self._ValueList = ['', '', ''] 875 self._SectionParser[SectionType](self) 876 if self._ValueList == None: 877 continue 878 # 879 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1, 880 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1 881 # 882 for Arch, ModuleType in self._Scope: 883 self._LastItem = self._Store( 884 self._ItemType, 885 self._ValueList[0], 886 self._ValueList[1], 887 self._ValueList[2], 888 Arch, 889 ModuleType, 890 self._Owner[-1], 891 self.FileID, 892 self._From, 893 self._LineIndex+1, 894 -1, 895 self._LineIndex+1, 896 -1, 897 self._Enabled 898 ) 899 900 if self._DirectiveStack: 901 Type, Line, Text = self._DirectiveStack[-1] 902 EdkLogger.error('Parser', FORMAT_INVALID, "No matching '!endif' found", 903 ExtraData=Text, File=self.MetaFile, Line=Line) 904 self._Done() 905 906 ## <subsection_header> parser 907 def _SubsectionHeaderParser(self): 908 self._SubsectionName = self._CurrentLine[1:-1].upper() 909 if self._SubsectionName in self.DataType: 910 self._SubsectionType = self.DataType[self._SubsectionName] 911 else: 912 self._SubsectionType = MODEL_UNKNOWN 913 EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile, 914 Line=self._LineIndex+1, ExtraData=self._CurrentLine) 915 self._ValueList[0] = self._SubsectionName 916 917 ## Directive statement parser 918 def _DirectiveParser(self): 919 self._ValueList = ['','',''] 920 TokenList = GetSplitValueList(self._CurrentLine, ' ', 1) 921 self._ValueList[0:len(TokenList)] = TokenList 922 923 # Syntax check 924 DirectiveName = self._ValueList[0].upper() 925 if DirectiveName not in self.DataType: 926 EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName, 927 File=self.MetaFile, Line=self._LineIndex+1) 928 if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '': 929 EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression", 930 File=self.MetaFile, Line=self._LineIndex+1, 931 ExtraData=self._CurrentLine) 932 933 ItemType = self.DataType[DirectiveName] 934 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF: 935 # Remove all directives between !if and !endif, including themselves 936 while self._DirectiveStack: 937 # Remove any !else or !elseif 938 DirectiveInfo = self._DirectiveStack.pop() 939 if DirectiveInfo[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF, 940 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF, 941 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]: 942 break 943 else: 944 EdkLogger.error("Parser", FORMAT_INVALID, "Redundant '!endif'", 945 File=self.MetaFile, Line=self._LineIndex+1, 946 ExtraData=self._CurrentLine) 947 elif ItemType != MODEL_META_DATA_INCLUDE: 948 # Break if there's a !else is followed by a !elseif 949 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF and \ 950 self._DirectiveStack and \ 951 self._DirectiveStack[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE: 952 EdkLogger.error("Parser", FORMAT_INVALID, "'!elseif' after '!else'", 953 File=self.MetaFile, Line=self._LineIndex+1, 954 ExtraData=self._CurrentLine) 955 self._DirectiveStack.append((ItemType, self._LineIndex+1, self._CurrentLine)) 956 elif self._From > 0: 957 EdkLogger.error('Parser', FORMAT_INVALID, 958 "No '!include' allowed in included file", 959 ExtraData=self._CurrentLine, File=self.MetaFile, 960 Line=self._LineIndex+1) 961 962 # 963 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1, 964 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1 965 # 966 self._LastItem = self._Store( 967 ItemType, 968 self._ValueList[0], 969 self._ValueList[1], 970 self._ValueList[2], 971 'COMMON', 972 'COMMON', 973 self._Owner[-1], 974 self.FileID, 975 self._From, 976 self._LineIndex+1, 977 -1, 978 self._LineIndex+1, 979 -1, 980 0 981 ) 982 983 ## [defines] section parser 984 @ParseMacro 985 def _DefineParser(self): 986 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1) 987 self._ValueList[1:len(TokenList)] = TokenList 988 989 # Syntax check 990 if not self._ValueList[1]: 991 EdkLogger.error('Parser', FORMAT_INVALID, "No name specified", 992 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1) 993 if not self._ValueList[2]: 994 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified", 995 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1) 996 if not self._ValueList[1] in self.DefineKeywords: 997 EdkLogger.error('Parser', FORMAT_INVALID, 998 "Unknown keyword found: %s. " 999 "If this is a macro you must " 1000 "add it as a DEFINE in the DSC" % self._ValueList[1], 1001 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1) 1002 self._Defines[self._ValueList[1]] = self._ValueList[2] 1003 self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()] 1004 1005 @ParseMacro 1006 def _SkuIdParser(self): 1007 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT) 1008 if len(TokenList) != 2: 1009 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Integer>|<UiName>'", 1010 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1) 1011 self._ValueList[0:len(TokenList)] = TokenList 1012 1013 ## Parse Edk style of library modules 1014 def _LibraryInstanceParser(self): 1015 self._ValueList[0] = self._CurrentLine 1016 1017 ## PCD sections parser 1018 # 1019 # [PcdsFixedAtBuild] 1020 # [PcdsPatchableInModule] 1021 # [PcdsFeatureFlag] 1022 # [PcdsDynamicEx 1023 # [PcdsDynamicExDefault] 1024 # [PcdsDynamicExVpd] 1025 # [PcdsDynamicExHii] 1026 # [PcdsDynamic] 1027 # [PcdsDynamicDefault] 1028 # [PcdsDynamicVpd] 1029 # [PcdsDynamicHii] 1030 # 1031 @ParseMacro 1032 def _PcdParser(self): 1033 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1) 1034 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT) 1035 if len(TokenList) == 2: 1036 self._ValueList[2] = TokenList[1] 1037 if self._ValueList[0] == '' or self._ValueList[1] == '': 1038 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified", 1039 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)", 1040 File=self.MetaFile, Line=self._LineIndex+1) 1041 if self._ValueList[2] == '': 1042 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given", 1043 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)", 1044 File=self.MetaFile, Line=self._LineIndex+1) 1045 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0. 1046 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1) 1047 if DscPcdValueList[0] in ['True', 'true', 'TRUE']: 1048 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1); 1049 elif DscPcdValueList[0] in ['False', 'false', 'FALSE']: 1050 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1); 1051 1052 ## [components] section parser 1053 @ParseMacro 1054 def _ComponentParser(self): 1055 if self._CurrentLine[-1] == '{': 1056 self._ValueList[0] = self._CurrentLine[0:-1].strip() 1057 self._InSubsection = True 1058 else: 1059 self._ValueList[0] = self._CurrentLine 1060 1061 ## [LibraryClasses] section 1062 @ParseMacro 1063 def _LibraryClassParser(self): 1064 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT) 1065 if len(TokenList) < 2: 1066 EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified", 1067 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)", 1068 File=self.MetaFile, Line=self._LineIndex+1) 1069 if TokenList[0] == '': 1070 EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified", 1071 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)", 1072 File=self.MetaFile, Line=self._LineIndex+1) 1073 if TokenList[1] == '': 1074 EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified", 1075 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)", 1076 File=self.MetaFile, Line=self._LineIndex+1) 1077 1078 self._ValueList[0:len(TokenList)] = TokenList 1079 1080 def _CompponentSourceOverridePathParser(self): 1081 self._ValueList[0] = self._CurrentLine 1082 1083 ## [BuildOptions] section parser 1084 @ParseMacro 1085 def _BuildOptionParser(self): 1086 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1) 1087 TokenList2 = GetSplitValueList(TokenList[0], ':', 1) 1088 if len(TokenList2) == 2: 1089 self._ValueList[0] = TokenList2[0] # toolchain family 1090 self._ValueList[1] = TokenList2[1] # keys 1091 else: 1092 self._ValueList[1] = TokenList[0] 1093 if len(TokenList) == 2: # value 1094 self._ValueList[2] = TokenList[1] 1095 1096 if self._ValueList[1].count('_') != 4: 1097 EdkLogger.error( 1098 'Parser', 1099 FORMAT_INVALID, 1100 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1], 1101 ExtraData=self._CurrentLine, 1102 File=self.MetaFile, 1103 Line=self._LineIndex+1 1104 ) 1105 1106 ## Override parent's method since we'll do all macro replacements in parser 1107 def _GetMacros(self): 1108 Macros = dict( [('ARCH','IA32'), ('FAMILY','MSFT'),('TOOL_CHAIN_TAG','VS2008x86'),('TARGET','DEBUG')]) 1109 Macros.update(self._FileLocalMacros) 1110 Macros.update(self._GetApplicableSectionMacro()) 1111 Macros.update(GlobalData.gEdkGlobal) 1112 Macros.update(GlobalData.gPlatformDefines) 1113 Macros.update(GlobalData.gCommandLineDefines) 1114 # PCD cannot be referenced in macro definition 1115 if self._ItemType not in [MODEL_META_DATA_DEFINE, MODEL_META_DATA_GLOBAL_DEFINE]: 1116 Macros.update(self._Symbols) 1117 return Macros 1118 1119 def _PostProcess(self): 1120 Processer = { 1121 MODEL_META_DATA_SECTION_HEADER : self.__ProcessSectionHeader, 1122 MODEL_META_DATA_SUBSECTION_HEADER : self.__ProcessSubsectionHeader, 1123 MODEL_META_DATA_HEADER : self.__ProcessDefine, 1124 MODEL_META_DATA_DEFINE : self.__ProcessDefine, 1125 MODEL_META_DATA_GLOBAL_DEFINE : self.__ProcessDefine, 1126 MODEL_META_DATA_INCLUDE : self.__ProcessDirective, 1127 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF : self.__ProcessDirective, 1128 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE : self.__ProcessDirective, 1129 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF : self.__ProcessDirective, 1130 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF : self.__ProcessDirective, 1131 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF : self.__ProcessDirective, 1132 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF : self.__ProcessDirective, 1133 MODEL_EFI_SKU_ID : self.__ProcessSkuId, 1134 MODEL_EFI_LIBRARY_INSTANCE : self.__ProcessLibraryInstance, 1135 MODEL_EFI_LIBRARY_CLASS : self.__ProcessLibraryClass, 1136 MODEL_PCD_FIXED_AT_BUILD : self.__ProcessPcd, 1137 MODEL_PCD_PATCHABLE_IN_MODULE : self.__ProcessPcd, 1138 MODEL_PCD_FEATURE_FLAG : self.__ProcessPcd, 1139 MODEL_PCD_DYNAMIC_DEFAULT : self.__ProcessPcd, 1140 MODEL_PCD_DYNAMIC_HII : self.__ProcessPcd, 1141 MODEL_PCD_DYNAMIC_VPD : self.__ProcessPcd, 1142 MODEL_PCD_DYNAMIC_EX_DEFAULT : self.__ProcessPcd, 1143 MODEL_PCD_DYNAMIC_EX_HII : self.__ProcessPcd, 1144 MODEL_PCD_DYNAMIC_EX_VPD : self.__ProcessPcd, 1145 MODEL_META_DATA_COMPONENT : self.__ProcessComponent, 1146 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : self.__ProcessSourceOverridePath, 1147 MODEL_META_DATA_BUILD_OPTION : self.__ProcessBuildOption, 1148 MODEL_UNKNOWN : self._Skip, 1149 MODEL_META_DATA_USER_EXTENSION : self._Skip, 1150 MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR : self._Skip, 1151 } 1152 1153 self._RawTable = self._Table 1154 self._Table = MetaFileStorage(self._RawTable.Cur, self.MetaFile, MODEL_FILE_DSC, True) 1155 self._DirectiveStack = [] 1156 self._DirectiveEvalStack = [] 1157 self._FileWithError = self.MetaFile 1158 self._FileLocalMacros = {} 1159 self._SectionsMacroDict = {} 1160 GlobalData.gPlatformDefines = {} 1161 1162 # Get all macro and PCD which has straitforward value 1163 self.__RetrievePcdValue() 1164 self._Content = self._RawTable.GetAll() 1165 self._ContentIndex = 0 1166 while self._ContentIndex < len(self._Content) : 1167 Id, self._ItemType, V1, V2, V3, S1, S2, Owner, BelongsToFile, self._From, \ 1168 LineStart, ColStart, LineEnd, ColEnd, Enabled = self._Content[self._ContentIndex] 1169 1170 if self._From < 0: 1171 self._FileWithError = self.MetaFile 1172 1173 self._ContentIndex += 1 1174 1175 self._Scope = [[S1, S2]] 1176 self._LineIndex = LineStart - 1 1177 self._ValueList = [V1, V2, V3] 1178 1179 try: 1180 Processer[self._ItemType]() 1181 except EvaluationException, Excpt: 1182 # 1183 # Only catch expression evaluation error here. We need to report 1184 # the precise number of line on which the error occurred 1185 # 1186 pass 1187# EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt), 1188# File=self._FileWithError, ExtraData=' '.join(self._ValueList), 1189# Line=self._LineIndex+1) 1190 except MacroException, Excpt: 1191 EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt), 1192 File=self._FileWithError, ExtraData=' '.join(self._ValueList), 1193 Line=self._LineIndex+1) 1194 1195 if self._ValueList == None: 1196 continue 1197 1198 NewOwner = self._IdMapping.get(Owner, -1) 1199 self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack)) 1200 self._LastItem = self._Store( 1201 self._ItemType, 1202 self._ValueList[0], 1203 self._ValueList[1], 1204 self._ValueList[2], 1205 S1, 1206 S2, 1207 NewOwner, 1208 BelongsToFile, 1209 self._From, 1210 self._LineIndex+1, 1211 -1, 1212 self._LineIndex+1, 1213 -1, 1214 self._Enabled 1215 ) 1216 self._IdMapping[Id] = self._LastItem 1217 1218 RecordList = self._Table.GetAll() 1219 1220 self._RawTable.Drop() 1221 self._Table.Drop() 1222 for Record in RecordList: 1223 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]) 1224 GlobalData.gPlatformDefines.update(self._FileLocalMacros) 1225 self._PostProcessed = True 1226 self._Content = None 1227 1228 def __ProcessSectionHeader(self): 1229 self._SectionName = self._ValueList[0] 1230 if self._SectionName in self.DataType: 1231 self._SectionType = self.DataType[self._SectionName] 1232 else: 1233 self._SectionType = MODEL_UNKNOWN 1234 1235 def __ProcessSubsectionHeader(self): 1236 self._SubsectionName = self._ValueList[0] 1237 if self._SubsectionName in self.DataType: 1238 self._SubsectionType = self.DataType[self._SubsectionName] 1239 else: 1240 self._SubsectionType = MODEL_UNKNOWN 1241 1242 def __RetrievePcdValue(self): 1243 Records = self._RawTable.Query(MODEL_PCD_FEATURE_FLAG, BelongsToItem=-1.0) 1244 for TokenSpaceGuid,PcdName,Value,Dummy2,Dummy3,ID,Line in Records: 1245 Value, DatumType, MaxDatumSize = AnalyzePcdData(Value) 1246 # Only use PCD whose value is straitforward (no macro and PCD) 1247 if self.SymbolPattern.findall(Value): 1248 continue 1249 Name = TokenSpaceGuid + '.' + PcdName 1250 # Don't use PCD with different values. 1251 if Name in self._Symbols and self._Symbols[Name] != Value: 1252 self._Symbols.pop(Name) 1253 continue 1254 self._Symbols[Name] = Value 1255 1256 Records = self._RawTable.Query(MODEL_PCD_FIXED_AT_BUILD, BelongsToItem=-1.0) 1257 for TokenSpaceGuid,PcdName,Value,Dummy2,Dummy3,ID,Line in Records: 1258 Value, DatumType, MaxDatumSize = AnalyzePcdData(Value) 1259 # Only use PCD whose value is straitforward (no macro and PCD) 1260 if self.SymbolPattern.findall(Value): 1261 continue 1262 Name = TokenSpaceGuid+'.'+PcdName 1263 # Don't use PCD with different values. 1264 if Name in self._Symbols and self._Symbols[Name] != Value: 1265 self._Symbols.pop(Name) 1266 continue 1267 self._Symbols[Name] = Value 1268 1269 def __ProcessDefine(self): 1270 if not self._Enabled: 1271 return 1272 1273 Type, Name, Value = self._ValueList 1274 Value = ReplaceMacro(Value, self._Macros, False) 1275 if self._ItemType == MODEL_META_DATA_DEFINE: 1276 if self._SectionType == MODEL_META_DATA_HEADER: 1277 self._FileLocalMacros[Name] = Value 1278 else: 1279 SectionDictKey = self._SectionType, self._Scope[0][0], self._Scope[0][1] 1280 if SectionDictKey not in self._SectionsMacroDict: 1281 self._SectionsMacroDict[SectionDictKey] = {} 1282 SectionLocalMacros = self._SectionsMacroDict[SectionDictKey] 1283 SectionLocalMacros[Name] = Value 1284 elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE: 1285 GlobalData.gEdkGlobal[Name] = Value 1286 1287 # 1288 # Keyword in [Defines] section can be used as Macros 1289 # 1290 if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER): 1291 self._FileLocalMacros[Name] = Value 1292 1293 self._ValueList = [Type, Name, Value] 1294 1295 def __ProcessDirective(self): 1296 Result = None 1297 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF, 1298 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF]: 1299 Macros = self._Macros 1300 Macros.update(GlobalData.gGlobalDefines) 1301 try: 1302 Result = ValueExpression(self._ValueList[1], Macros)() 1303 except SymbolNotFound, Exc: 1304 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1]) 1305 Result = False 1306 except WrnExpression, Excpt: 1307 # 1308 # Catch expression evaluation warning here. We need to report 1309 # the precise number of line and return the evaluation result 1310 # 1311 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt), 1312 File=self._FileWithError, ExtraData=' '.join(self._ValueList), 1313 Line=self._LineIndex+1) 1314 Result = Excpt.result 1315 except BadExpression, Exc: 1316 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1]) 1317 Result = False 1318 1319 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF, 1320 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF, 1321 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]: 1322 self._DirectiveStack.append(self._ItemType) 1323 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF: 1324 Result = bool(Result) 1325 else: 1326 Macro = self._ValueList[1] 1327 Macro = Macro[2:-1] if (Macro.startswith("$(") and Macro.endswith(")")) else Macro 1328 Result = Macro in self._Macros 1329 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF: 1330 Result = not Result 1331 self._DirectiveEvalStack.append(Result) 1332 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF: 1333 self._DirectiveStack.append(self._ItemType) 1334 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1] 1335 self._DirectiveEvalStack.append(bool(Result)) 1336 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE: 1337 self._DirectiveStack[-1] = self._ItemType 1338 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1] 1339 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF: 1340 # Back to the nearest !if/!ifdef/!ifndef 1341 while self._DirectiveStack: 1342 self._DirectiveEvalStack.pop() 1343 Directive = self._DirectiveStack.pop() 1344 if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF, 1345 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF, 1346 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE, 1347 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]: 1348 break 1349 elif self._ItemType == MODEL_META_DATA_INCLUDE: 1350 # The included file must be relative to workspace or same directory as DSC file 1351 __IncludeMacros = {} 1352 # 1353 # Allow using system environment variables in path after !include 1354 # 1355 __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE'] 1356 if "ECP_SOURCE" in GlobalData.gGlobalDefines.keys(): 1357 __IncludeMacros['ECP_SOURCE'] = GlobalData.gGlobalDefines['ECP_SOURCE'] 1358 # 1359 # During GenFds phase call DSC parser, will go into this branch. 1360 # 1361 elif "ECP_SOURCE" in GlobalData.gCommandLineDefines.keys(): 1362 __IncludeMacros['ECP_SOURCE'] = GlobalData.gCommandLineDefines['ECP_SOURCE'] 1363 1364 __IncludeMacros['EFI_SOURCE'] = GlobalData.gGlobalDefines['EFI_SOURCE'] 1365 __IncludeMacros['EDK_SOURCE'] = GlobalData.gGlobalDefines['EDK_SOURCE'] 1366 # 1367 # Allow using MACROs comes from [Defines] section to keep compatible. 1368 # 1369 __IncludeMacros.update(self._Macros) 1370 1371 IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True)) 1372 # 1373 # First search the include file under the same directory as DSC file 1374 # 1375 IncludedFile1 = PathClass(IncludedFile, self.MetaFile.Dir) 1376 ErrorCode, ErrorInfo1 = IncludedFile1.Validate() 1377 if ErrorCode != 0: 1378 # 1379 # Also search file under the WORKSPACE directory 1380 # 1381 IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace) 1382 ErrorCode, ErrorInfo2 = IncludedFile1.Validate() 1383 if ErrorCode != 0: 1384 EdkLogger.error('parser', ErrorCode, File=self._FileWithError, 1385 Line=self._LineIndex+1, ExtraData=ErrorInfo1 + "\n"+ ErrorInfo2) 1386 1387 self._FileWithError = IncludedFile1 1388 1389 IncludedFileTable = MetaFileStorage(self._Table.Cur, IncludedFile1, MODEL_FILE_DSC, True) 1390 Owner = self._Content[self._ContentIndex-1][0] 1391 Parser = DscParser(IncludedFile1, self._FileType, IncludedFileTable, 1392 Owner=Owner, From=Owner) 1393 1394 # set the parser status with current status 1395 Parser._SectionName = self._SectionName 1396 Parser._SectionType = self._SectionType 1397 Parser._Scope = self._Scope 1398 Parser._Enabled = self._Enabled 1399 # Parse the included file 1400 Parser.Start() 1401 1402 # update current status with sub-parser's status 1403 self._SectionName = Parser._SectionName 1404 self._SectionType = Parser._SectionType 1405 self._Scope = Parser._Scope 1406 self._Enabled = Parser._Enabled 1407 1408 # Insert all records in the table for the included file into dsc file table 1409 Records = IncludedFileTable.GetAll() 1410 if Records: 1411 self._Content[self._ContentIndex:self._ContentIndex] = Records 1412 self._Content.pop(self._ContentIndex-1) 1413 self._ValueList = None 1414 self._ContentIndex -= 1 1415 1416 def __ProcessSkuId(self): 1417 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True) 1418 for Value in self._ValueList] 1419 1420 def __ProcessLibraryInstance(self): 1421 self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList] 1422 1423 def __ProcessLibraryClass(self): 1424 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True) 1425 1426 def __ProcessPcd(self): 1427 ValueList = GetSplitValueList(self._ValueList[2]) 1428 # 1429 # PCD value can be an expression 1430 # 1431 if len(ValueList) > 1 and ValueList[1] == 'VOID*': 1432 PcdValue = ValueList[0] 1433 try: 1434 ValueList[0] = ValueExpression(PcdValue, self._Macros)(True) 1435 except WrnExpression, Value: 1436 ValueList[0] = Value.result 1437 else: 1438 PcdValue = ValueList[-1] 1439 try: 1440 ValueList[-1] = ValueExpression(PcdValue, self._Macros)(True) 1441 except WrnExpression, Value: 1442 ValueList[-1] = Value.result 1443 1444 if ValueList[-1] == 'True': 1445 ValueList[-1] = '1' 1446 if ValueList[-1] == 'False': 1447 ValueList[-1] = '0' 1448 1449 self._ValueList[2] = '|'.join(ValueList) 1450 1451 def __ProcessComponent(self): 1452 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros) 1453 1454 def __ProcessSourceOverridePath(self): 1455 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros) 1456 1457 def __ProcessBuildOption(self): 1458 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False) 1459 for Value in self._ValueList] 1460 1461 _SectionParser = { 1462 MODEL_META_DATA_HEADER : _DefineParser, 1463 MODEL_EFI_SKU_ID : _SkuIdParser, 1464 MODEL_EFI_LIBRARY_INSTANCE : _LibraryInstanceParser, 1465 MODEL_EFI_LIBRARY_CLASS : _LibraryClassParser, 1466 MODEL_PCD_FIXED_AT_BUILD : _PcdParser, 1467 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser, 1468 MODEL_PCD_FEATURE_FLAG : _PcdParser, 1469 MODEL_PCD_DYNAMIC_DEFAULT : _PcdParser, 1470 MODEL_PCD_DYNAMIC_HII : _PcdParser, 1471 MODEL_PCD_DYNAMIC_VPD : _PcdParser, 1472 MODEL_PCD_DYNAMIC_EX_DEFAULT : _PcdParser, 1473 MODEL_PCD_DYNAMIC_EX_HII : _PcdParser, 1474 MODEL_PCD_DYNAMIC_EX_VPD : _PcdParser, 1475 MODEL_META_DATA_COMPONENT : _ComponentParser, 1476 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : _CompponentSourceOverridePathParser, 1477 MODEL_META_DATA_BUILD_OPTION : _BuildOptionParser, 1478 MODEL_UNKNOWN : MetaFileParser._Skip, 1479 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip, 1480 MODEL_META_DATA_SECTION_HEADER : MetaFileParser._SectionHeaderParser, 1481 MODEL_META_DATA_SUBSECTION_HEADER : _SubsectionHeaderParser, 1482 } 1483 1484 _Macros = property(_GetMacros) 1485 1486## DEC file parser class 1487# 1488# @param FilePath The path of platform description file 1489# @param FileType The raw data of DSC file 1490# @param Table Database used to retrieve module/package information 1491# @param Macros Macros used for replacement in file 1492# 1493class DecParser(MetaFileParser): 1494 # DEC file supported data types (one type per section) 1495 DataType = { 1496 TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER, 1497 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE, 1498 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE, 1499 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS, 1500 TAB_GUIDS.upper() : MODEL_EFI_GUID, 1501 TAB_PPIS.upper() : MODEL_EFI_PPI, 1502 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL, 1503 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD, 1504 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE, 1505 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG, 1506 TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC, 1507 TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX, 1508 } 1509 1510 ## Constructor of DecParser 1511 # 1512 # Initialize object of DecParser 1513 # 1514 # @param FilePath The path of platform description file 1515 # @param FileType The raw data of DSC file 1516 # @param Table Database used to retrieve module/package information 1517 # @param Macros Macros used for replacement in file 1518 # 1519 def __init__(self, FilePath, FileType, Table): 1520 # prevent re-initialization 1521 if hasattr(self, "_Table"): 1522 return 1523 MetaFileParser.__init__(self, FilePath, FileType, Table) 1524 self._Comments = [] 1525 self._Version = 0x00010005 # Only EDK2 dec file is supported 1526 self.TblFile = EccGlobalData.gDb.TblFile 1527 self.FileID = -1 1528 1529 ## Parser starter 1530 def Start(self): 1531 Content = '' 1532 try: 1533 Content = open(str(self.MetaFile), 'r').readlines() 1534 except: 1535 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile) 1536 1537 # 1538 # Insert a record for file 1539 # 1540 Filename = NormPath(self.MetaFile) 1541 FileID = self.TblFile.GetFileId(Filename) 1542 if FileID: 1543 self.FileID = FileID 1544 else: 1545 self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_DEC) 1546 1547 for Index in range(0, len(Content)): 1548 Line, Comment = CleanString2(Content[Index]) 1549 self._CurrentLine = Line 1550 self._LineIndex = Index 1551 1552 # save comment for later use 1553 if Comment: 1554 self._Comments.append((Comment, self._LineIndex+1)) 1555 # skip empty line 1556 if Line == '': 1557 continue 1558 1559 # section header 1560 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END: 1561 self._SectionHeaderParser() 1562 self._Comments = [] 1563 continue 1564 elif len(self._SectionType) == 0: 1565 self._Comments = [] 1566 continue 1567 1568 # section content 1569 self._ValueList = ['','',''] 1570 self._SectionParser[self._SectionType[0]](self) 1571 if self._ValueList == None or self._ItemType == MODEL_META_DATA_DEFINE: 1572 self._ItemType = -1 1573 self._Comments = [] 1574 continue 1575 1576 # 1577 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1, 1578 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1 1579 # 1580 for Arch, ModuleType, Type in self._Scope: 1581 self._LastItem = self._Store( 1582 Type, 1583 self._ValueList[0], 1584 self._ValueList[1], 1585 self._ValueList[2], 1586 Arch, 1587 ModuleType, 1588 self._Owner[-1], 1589 self.FileID, 1590 self._LineIndex+1, 1591 -1, 1592 self._LineIndex+1, 1593 -1, 1594 0 1595 ) 1596 for Comment, LineNo in self._Comments: 1597 self._Store( 1598 MODEL_META_DATA_COMMENT, 1599 Comment, 1600 self._ValueList[0], 1601 self._ValueList[1], 1602 Arch, 1603 ModuleType, 1604 self._LastItem, 1605 self.FileID, 1606 LineNo, 1607 -1, 1608 LineNo, 1609 -1, 1610 0 1611 ) 1612 self._Comments = [] 1613 self._Done() 1614 1615 def _GetApplicableSectionMacro(self): 1616 Macros = {} 1617 for S1, S2, SectionType in self._Scope: 1618 for Scope1, Scope2 in [("COMMON", "COMMON"), ("COMMON", S2), (S1, "COMMON"), (S1, S2)]: 1619 if (SectionType, Scope1, Scope2) in self._SectionsMacroDict: 1620 Macros.update(self._SectionsMacroDict[(SectionType, Scope1, Scope2)]) 1621 return Macros 1622 1623 ## Section header parser 1624 # 1625 # The section header is always in following format: 1626 # 1627 # [section_name.arch<.platform|module_type>] 1628 # 1629 def _SectionHeaderParser(self): 1630 self._Scope = [] 1631 self._SectionName = '' 1632 self._SectionType = [] 1633 ArchList = set() 1634 for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT): 1635 if Item == '': 1636 continue 1637 ItemList = GetSplitValueList(Item, TAB_SPLIT) 1638 1639 # different types of PCD are permissible in one section 1640 self._SectionName = ItemList[0].upper() 1641 if self._SectionName in self.DataType: 1642 if self.DataType[self._SectionName] not in self._SectionType: 1643 self._SectionType.append(self.DataType[self._SectionName]) 1644 else: 1645 EdkLogger.warn("Parser", "Unrecognized section", File=self.MetaFile, 1646 Line=self._LineIndex+1, ExtraData=self._CurrentLine) 1647 continue 1648 1649 if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1: 1650 EdkLogger.error( 1651 'Parser', 1652 FORMAT_INVALID, 1653 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL, 1654 File=self.MetaFile, 1655 Line=self._LineIndex+1, 1656 ExtraData=self._CurrentLine 1657 ) 1658 # S1 is always Arch 1659 if len(ItemList) > 1: 1660 S1 = ItemList[1].upper() 1661 else: 1662 S1 = 'COMMON' 1663 ArchList.add(S1) 1664 # S2 may be Platform or ModuleType 1665 if len(ItemList) > 2: 1666 S2 = ItemList[2].upper() 1667 else: 1668 S2 = 'COMMON' 1669 if [S1, S2, self.DataType[self._SectionName]] not in self._Scope: 1670 self._Scope.append([S1, S2, self.DataType[self._SectionName]]) 1671 1672 # 'COMMON' must not be used with specific ARCHs at the same section 1673 if 'COMMON' in ArchList and len(ArchList) > 1: 1674 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs", 1675 File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine) 1676 1677 ## [guids], [ppis] and [protocols] section parser 1678 @ParseMacro 1679 def _GuidParser(self): 1680 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1) 1681 if len(TokenList) < 2: 1682 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified", 1683 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)", 1684 File=self.MetaFile, Line=self._LineIndex+1) 1685 if TokenList[0] == '': 1686 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified", 1687 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)", 1688 File=self.MetaFile, Line=self._LineIndex+1) 1689 if TokenList[1] == '': 1690 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified", 1691 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)", 1692 File=self.MetaFile, Line=self._LineIndex+1) 1693 if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '': 1694 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format", 1695 ExtraData=self._CurrentLine + \ 1696 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)", 1697 File=self.MetaFile, Line=self._LineIndex+1) 1698 self._ValueList[0] = TokenList[0] 1699 #Parse the Guid value format 1700 GuidValueList = TokenList[1].strip(' {}').split(',') 1701 Index = 0 1702 HexList = [] 1703 if len(GuidValueList) == 11: 1704 for GuidValue in GuidValueList: 1705 GuidValue = GuidValue.strip() 1706 if GuidValue.startswith('0x') or GuidValue.startswith('0X'): 1707 HexList.append('0x' + str(GuidValue[2:])) 1708 Index += 1 1709 continue 1710 else: 1711 if GuidValue.startswith('{'): 1712 GuidValue = GuidValue.lstrip(' {') 1713 HexList.append('0x' + str(GuidValue[2:])) 1714 Index += 1 1715 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]) 1716 else: 1717 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format", 1718 ExtraData=self._CurrentLine + \ 1719 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)", 1720 File=self.MetaFile, Line=self._LineIndex+1) 1721 self._ValueList[0] = '' 1722 1723 ## PCD sections parser 1724 # 1725 # [PcdsFixedAtBuild] 1726 # [PcdsPatchableInModule] 1727 # [PcdsFeatureFlag] 1728 # [PcdsDynamicEx 1729 # [PcdsDynamic] 1730 # 1731 @ParseMacro 1732 def _PcdParser(self): 1733 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1) 1734 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT) 1735 # check PCD information 1736 if self._ValueList[0] == '' or self._ValueList[1] == '': 1737 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified", 1738 ExtraData=self._CurrentLine + \ 1739 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)", 1740 File=self.MetaFile, Line=self._LineIndex+1) 1741 # check PCD datum information 1742 if len(TokenList) < 2 or TokenList[1] == '': 1743 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given", 1744 ExtraData=self._CurrentLine + \ 1745 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)", 1746 File=self.MetaFile, Line=self._LineIndex+1) 1747 1748 1749 ValueRe = re.compile(r'^\s*L?\".*\|.*\"') 1750 PtrValue = ValueRe.findall(TokenList[1]) 1751 1752 # Has VOID* type string, may contain "|" character in the string. 1753 if len(PtrValue) != 0: 1754 ptrValueList = re.sub(ValueRe, '', TokenList[1]) 1755 ValueList = GetSplitValueList(ptrValueList) 1756 ValueList[0] = PtrValue[0] 1757 else: 1758 ValueList = GetSplitValueList(TokenList[1]) 1759 1760 1761 # check if there's enough datum information given 1762 if len(ValueList) != 3: 1763 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given", 1764 ExtraData=self._CurrentLine + \ 1765 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)", 1766 File=self.MetaFile, Line=self._LineIndex+1) 1767 # check default value 1768 if ValueList[0] == '': 1769 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information", 1770 ExtraData=self._CurrentLine + \ 1771 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)", 1772 File=self.MetaFile, Line=self._LineIndex+1) 1773 # check datum type 1774 if ValueList[1] == '': 1775 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information", 1776 ExtraData=self._CurrentLine + \ 1777 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)", 1778 File=self.MetaFile, Line=self._LineIndex+1) 1779 # check token of the PCD 1780 if ValueList[2] == '': 1781 EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information", 1782 ExtraData=self._CurrentLine + \ 1783 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)", 1784 File=self.MetaFile, Line=self._LineIndex+1) 1785 # check format of default value against the datum type 1786 IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0]) 1787 if not IsValid: 1788 EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine, 1789 File=self.MetaFile, Line=self._LineIndex+1) 1790 1791 if EccGlobalData.gConfig.UniCheckPCDInfo == '1' or EccGlobalData.gConfig.UniCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1': 1792 # check Description, Prompt information 1793 PatternDesc = re.compile('##\s*([\x21-\x7E\s]*)', re.S) 1794 PatternPrompt = re.compile('#\s+@Prompt\s+([\x21-\x7E\s]*)', re.S) 1795 Description = None 1796 Prompt = None 1797 # check @ValidRange, @ValidList and @Expression format valid 1798 ErrorCodeValid = '0x0 <= %s <= 0xFFFFFFFF' 1799 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]+)' 1800 PatternValidRng = re.compile('^' + '(NOT)?\s*' + PatternValidRangeIn + '$') 1801 for Comment in self._Comments: 1802 Comm = Comment[0].strip() 1803 if not Comm: 1804 continue 1805 if not Description: 1806 Description = PatternDesc.findall(Comm) 1807 if not Prompt: 1808 Prompt = PatternPrompt.findall(Comm) 1809 if Comm[0] == '#': 1810 ValidFormt = Comm.lstrip('#') 1811 ValidFormt = ValidFormt.lstrip() 1812 if ValidFormt[0:11] == '@ValidRange': 1813 ValidFormt = ValidFormt[11:] 1814 ValidFormt = ValidFormt.lstrip() 1815 try: 1816 ErrorCode, Expression = ValidFormt.split('|', 1) 1817 except ValueError: 1818 ErrorCode = '0x0' 1819 Expression = ValidFormt 1820 ErrorCode, Expression = ErrorCode.strip(), Expression.strip() 1821 try: 1822 if not eval(ErrorCodeValid % ErrorCode): 1823 EdkLogger.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0])) 1824 except: 1825 EdkLogger.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0])) 1826 if not PatternValidRng.search(Expression): 1827 EdkLogger.warn('Parser', '@ValidRange Expression(%s) of PCD %s is incorrect format.' % (Expression, TokenList[0])) 1828 if ValidFormt[0:10] == '@ValidList': 1829 ValidFormt = ValidFormt[10:] 1830 ValidFormt = ValidFormt.lstrip() 1831 try: 1832 ErrorCode, Expression = ValidFormt.split('|', 1) 1833 except ValueError: 1834 ErrorCode = '0x0' 1835 Expression = ValidFormt 1836 ErrorCode, Expression = ErrorCode.strip(), Expression.strip() 1837 try: 1838 if not eval(ErrorCodeValid % ErrorCode): 1839 EdkLogger.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0])) 1840 except: 1841 EdkLogger.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0])) 1842 Values = Expression.split(',') 1843 for Value in Values: 1844 Value = Value.strip() 1845 try: 1846 eval(Value) 1847 except: 1848 EdkLogger.warn('Parser', '@ValidList Expression of PCD %s include a invalid value(%s).' % (TokenList[0], Value)) 1849 break 1850 if ValidFormt[0:11] == '@Expression': 1851 ValidFormt = ValidFormt[11:] 1852 ValidFormt = ValidFormt.lstrip() 1853 try: 1854 ErrorCode, Expression = ValidFormt.split('|', 1) 1855 except ValueError: 1856 ErrorCode = '0x0' 1857 Expression = ValidFormt 1858 ErrorCode, Expression = ErrorCode.strip(), Expression.strip() 1859 try: 1860 if not eval(ErrorCodeValid % ErrorCode): 1861 EdkLogger.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0])) 1862 except: 1863 EdkLogger.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0])) 1864 if not Expression: 1865 EdkLogger.warn('Parser', '@Expression Expression of PCD %s is incorrect format.' % TokenList[0]) 1866 if not Description: 1867 EdkLogger.warn('Parser', 'PCD %s Description information is not provided.' % TokenList[0]) 1868 if not Prompt: 1869 EdkLogger.warn('Parser', 'PCD %s Prompt information is not provided.' % TokenList[0]) 1870 # check Description, Prompt localization information 1871 if self._UniObj: 1872 self._UniObj.CheckPcdInfo(TokenList[0]) 1873 1874 if ValueList[0] in ['True', 'true', 'TRUE']: 1875 ValueList[0] = '1' 1876 elif ValueList[0] in ['False', 'false', 'FALSE']: 1877 ValueList[0] = '0' 1878 1879 self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip() 1880 1881 _SectionParser = { 1882 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser, 1883 MODEL_EFI_INCLUDE : MetaFileParser._PathParser, 1884 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser, 1885 MODEL_EFI_GUID : _GuidParser, 1886 MODEL_EFI_PPI : _GuidParser, 1887 MODEL_EFI_PROTOCOL : _GuidParser, 1888 MODEL_PCD_FIXED_AT_BUILD : _PcdParser, 1889 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser, 1890 MODEL_PCD_FEATURE_FLAG : _PcdParser, 1891 MODEL_PCD_DYNAMIC : _PcdParser, 1892 MODEL_PCD_DYNAMIC_EX : _PcdParser, 1893 MODEL_UNKNOWN : MetaFileParser._Skip, 1894 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip, 1895 } 1896 1897 1898## FdfObject 1899# 1900# This class defined basic Fdf object which is used by inheriting 1901# 1902# @param object: Inherited from object class 1903# 1904class FdfObject(object): 1905 def __init__(self): 1906 object.__init__() 1907 1908## Fdf 1909# 1910# This class defined the structure used in Fdf object 1911# 1912# @param FdfObject: Inherited from FdfObject class 1913# @param Filename: Input value for Ffilename of Fdf file, default is None 1914# @param WorkspaceDir: Input value for current workspace directory, default is None 1915# 1916class Fdf(FdfObject): 1917 def __init__(self, Filename = None, IsToDatabase = False, WorkspaceDir = None, Database = None): 1918 self.WorkspaceDir = WorkspaceDir 1919 self.IsToDatabase = IsToDatabase 1920 1921 self.Cur = Database.Cur 1922 self.TblFile = Database.TblFile 1923 self.TblFdf = Database.TblFdf 1924 self.FileID = -1 1925 self.FileList = {} 1926 1927 # 1928 # Load Fdf file if filename is not None 1929 # 1930 if Filename != None: 1931 try: 1932 self.LoadFdfFile(Filename) 1933 except Exception: 1934 pass 1935 1936 # 1937 # Insert a FDF file record into database 1938 # 1939 def InsertFile(self, Filename): 1940 FileID = -1 1941 Filename = NormPath(Filename) 1942 if Filename not in self.FileList: 1943 FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_FDF) 1944 self.FileList[Filename] = FileID 1945 1946 return self.FileList[Filename] 1947 1948 1949 ## Load Fdf file 1950 # 1951 # Load the file if it exists 1952 # 1953 # @param Filename: Input value for filename of Fdf file 1954 # 1955 def LoadFdfFile(self, Filename): 1956 FileList = [] 1957 # 1958 # Parse Fdf file 1959 # 1960 Filename = NormPath(Filename) 1961 Fdf = FdfParser(Filename) 1962 Fdf.ParseFile() 1963 1964 # 1965 # Insert inf file and pcd information 1966 # 1967 if self.IsToDatabase: 1968 (Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled) = \ 1969 (0, '', '', '', 'COMMON', 'COMMON', -1, -1, -1, -1, -1, -1, 0) 1970 for Index in range(0, len(Fdf.Profile.PcdDict)): 1971 pass 1972 for Key in Fdf.Profile.PcdDict.keys(): 1973 Model = MODEL_PCD 1974 Value1 = Key[1] 1975 Value2 = Key[0] 1976 FileName = Fdf.Profile.PcdFileLineDict[Key][0] 1977 StartLine = Fdf.Profile.PcdFileLineDict[Key][1] 1978 BelongsToFile = self.InsertFile(FileName) 1979 self.TblFdf.Insert(Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled) 1980 for Index in range(0, len(Fdf.Profile.InfList)): 1981 Model = MODEL_META_DATA_COMPONENT 1982 Value1 = Fdf.Profile.InfList[Index] 1983 Value2 = '' 1984 FileName = Fdf.Profile.InfFileLineList[Index][0] 1985 StartLine = Fdf.Profile.InfFileLineList[Index][1] 1986 BelongsToFile = self.InsertFile(FileName) 1987 self.TblFdf.Insert(Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled) 1988 1989class UniParser(object): 1990 # IsExtraUni defined the UNI file is Module UNI or extra Module UNI 1991 # IsModuleUni defined the UNI file is Module UNI or Package UNI 1992 def __init__(self, FilePath, IsExtraUni=False, IsModuleUni=True): 1993 self.FilePath = FilePath 1994 self.FileName = os.path.basename(FilePath) 1995 self.IsExtraUni = IsExtraUni 1996 self.IsModuleUni = IsModuleUni 1997 self.FileIn = None 1998 self.Missing = [] 1999 self.__read() 2000 2001 def __read(self): 2002 try: 2003 self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_8').read() 2004 except UnicodeError: 2005 self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_16').read() 2006 except UnicodeError: 2007 self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_16_le').read() 2008 except IOError: 2009 self.FileIn = "" 2010 2011 def Start(self): 2012 if self.IsModuleUni: 2013 if self.IsExtraUni: 2014 ModuleName = self.CheckKeyValid('STR_PROPERTIES_MODULE_NAME') 2015 self.PrintLog('STR_PROPERTIES_MODULE_NAME', ModuleName) 2016 else: 2017 ModuleAbstract = self.CheckKeyValid('STR_MODULE_ABSTRACT') 2018 self.PrintLog('STR_MODULE_ABSTRACT', ModuleAbstract) 2019 ModuleDescription = self.CheckKeyValid('STR_MODULE_DESCRIPTION') 2020 self.PrintLog('STR_MODULE_DESCRIPTION', ModuleDescription) 2021 else: 2022 if self.IsExtraUni: 2023 PackageName = self.CheckKeyValid('STR_PROPERTIES_PACKAGE_NAME') 2024 self.PrintLog('STR_PROPERTIES_PACKAGE_NAME', PackageName) 2025 else: 2026 PackageAbstract = self.CheckKeyValid('STR_PACKAGE_ABSTRACT') 2027 self.PrintLog('STR_PACKAGE_ABSTRACT', PackageAbstract) 2028 PackageDescription = self.CheckKeyValid('STR_PACKAGE_DESCRIPTION') 2029 self.PrintLog('STR_PACKAGE_DESCRIPTION', PackageDescription) 2030 2031 def CheckKeyValid(self, Key, Contents=None): 2032 if not Contents: 2033 Contents = self.FileIn 2034 KeyPattern = re.compile('#string\s+%s\s+.*?#language.*?".*?"' % Key, re.S) 2035 if KeyPattern.search(Contents): 2036 return True 2037 return False 2038 2039 def CheckPcdInfo(self, PcdCName): 2040 PromptKey = 'STR_%s_PROMPT' % PcdCName.replace('.', '_') 2041 PcdPrompt = self.CheckKeyValid(PromptKey) 2042 self.PrintLog(PromptKey, PcdPrompt) 2043 HelpKey = 'STR_%s_HELP' % PcdCName.replace('.', '_') 2044 PcdHelp = self.CheckKeyValid(HelpKey) 2045 self.PrintLog(HelpKey, PcdHelp) 2046 2047 def PrintLog(self, Key, Value): 2048 if not Value and Key not in self.Missing: 2049 Msg = '%s is missing in the %s file.' % (Key, self.FileName) 2050 EdkLogger.warn('Parser', Msg) 2051 EccGlobalData.gDb.TblReport.Insert(EccToolError.ERROR_GENERAL_CHECK_UNI_HELP_INFO, OtherMsg=Msg, BelongsToTable='File', BelongsToItem=-2) 2052 self.Missing.append(Key) 2053 2054## 2055# 2056# This acts like the main() function for the script, unless it is 'import'ed into another 2057# script. 2058# 2059if __name__ == '__main__': 2060 pass 2061 2062