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