1## @file 2# This file is used to define common parsing related functions used in parsing 3# INF/DEC/DSC process 4# 5# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR> 6# 7# SPDX-License-Identifier: BSD-2-Clause-Patent 8# 9 10''' 11Parsing 12''' 13from __future__ import absolute_import 14 15## 16# Import Modules 17# 18import os.path 19import re 20 21from Library.StringUtils import RaiseParserError 22from Library.StringUtils import GetSplitValueList 23from Library.StringUtils import CheckFileType 24from Library.StringUtils import CheckFileExist 25from Library.StringUtils import CleanString 26from Library.StringUtils import NormPath 27 28from Logger.ToolError import FILE_NOT_FOUND 29from Logger.ToolError import FatalError 30from Logger.ToolError import FORMAT_INVALID 31 32from Library import DataType 33 34from Library.Misc import GuidStructureStringToGuidString 35from Library.Misc import CheckGuidRegFormat 36from Logger import StringTable as ST 37import Logger.Log as Logger 38 39from Parser.DecParser import Dec 40from . import GlobalData 41 42gPKG_INFO_DICT = {} 43 44## GetBuildOption 45# 46# Parse a string with format "[<Family>:]<ToolFlag>=Flag" 47# Return (Family, ToolFlag, Flag) 48# 49# @param String: String with BuildOption statement 50# @param File: The file which defines build option, used in error report 51# 52def GetBuildOption(String, File, LineNo= -1): 53 (Family, ToolChain, Flag) = ('', '', '') 54 if String.find(DataType.TAB_EQUAL_SPLIT) < 0: 55 RaiseParserError(String, 'BuildOptions', File, \ 56 '[<Family>:]<ToolFlag>=Flag', LineNo) 57 else: 58 List = GetSplitValueList(String, DataType.TAB_EQUAL_SPLIT, MaxSplit=1) 59 if List[0].find(':') > -1: 60 Family = List[0][ : List[0].find(':')].strip() 61 ToolChain = List[0][List[0].find(':') + 1 : ].strip() 62 else: 63 ToolChain = List[0].strip() 64 Flag = List[1].strip() 65 return (Family, ToolChain, Flag) 66 67## Get Library Class 68# 69# Get Library of Dsc as <LibraryClassKeyWord>|<LibraryInstance> 70# 71# @param Item: String as <LibraryClassKeyWord>|<LibraryInstance> 72# @param ContainerFile: The file which describes the library class, used for 73# error report 74# 75def GetLibraryClass(Item, ContainerFile, WorkspaceDir, LineNo= -1): 76 List = GetSplitValueList(Item[0]) 77 SupMod = DataType.SUP_MODULE_LIST_STRING 78 if len(List) != 2: 79 RaiseParserError(Item[0], 'LibraryClasses', ContainerFile, \ 80 '<LibraryClassKeyWord>|<LibraryInstance>') 81 else: 82 CheckFileType(List[1], '.Inf', ContainerFile, \ 83 'library class instance', Item[0], LineNo) 84 CheckFileExist(WorkspaceDir, List[1], ContainerFile, \ 85 'LibraryClasses', Item[0], LineNo) 86 if Item[1] != '': 87 SupMod = Item[1] 88 89 return (List[0], List[1], SupMod) 90 91## Get Library Class 92# 93# Get Library of Dsc as <LibraryClassKeyWord>[|<LibraryInstance>] 94# [|<TokenSpaceGuidCName>.<PcdCName>] 95# 96# @param Item: String as <LibraryClassKeyWord>|<LibraryInstance> 97# @param ContainerFile: The file which describes the library class, used for 98# error report 99# 100def GetLibraryClassOfInf(Item, ContainerFile, WorkspaceDir, LineNo= -1): 101 ItemList = GetSplitValueList((Item[0] + DataType.TAB_VALUE_SPLIT * 2)) 102 SupMod = DataType.SUP_MODULE_LIST_STRING 103 104 if len(ItemList) > 5: 105 RaiseParserError\ 106 (Item[0], 'LibraryClasses', ContainerFile, \ 107 '<LibraryClassKeyWord>[|<LibraryInstance>]\ 108 [|<TokenSpaceGuidCName>.<PcdCName>]') 109 else: 110 CheckFileType(ItemList[1], '.Inf', ContainerFile, 'LibraryClasses', \ 111 Item[0], LineNo) 112 CheckFileExist(WorkspaceDir, ItemList[1], ContainerFile, \ 113 'LibraryClasses', Item[0], LineNo) 114 if ItemList[2] != '': 115 CheckPcdTokenInfo(ItemList[2], 'LibraryClasses', \ 116 ContainerFile, LineNo) 117 if Item[1] != '': 118 SupMod = Item[1] 119 120 return (ItemList[0], ItemList[1], ItemList[2], SupMod) 121 122## CheckPcdTokenInfo 123# 124# Check if PcdTokenInfo is following <TokenSpaceGuidCName>.<PcdCName> 125# 126# @param TokenInfoString: String to be checked 127# @param Section: Used for error report 128# @param File: Used for error report 129# 130def CheckPcdTokenInfo(TokenInfoString, Section, File, LineNo= -1): 131 Format = '<TokenSpaceGuidCName>.<PcdCName>' 132 if TokenInfoString != '' and TokenInfoString is not None: 133 TokenInfoList = GetSplitValueList(TokenInfoString, DataType.TAB_SPLIT) 134 if len(TokenInfoList) == 2: 135 return True 136 137 RaiseParserError(TokenInfoString, Section, File, Format, LineNo) 138 139## Get Pcd 140# 141# Get Pcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<Value> 142# [|<Type>|<MaximumDatumSize>] 143# 144# @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>| 145# <Value>[|<Type>|<MaximumDatumSize>] 146# @param ContainerFile: The file which describes the pcd, used for error 147# report 148 149# 150def GetPcd(Item, Type, ContainerFile, LineNo= -1): 151 TokenGuid, TokenName, Value, MaximumDatumSize, Token = '', '', '', '', '' 152 List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2) 153 154 if len(List) < 4 or len(List) > 6: 155 RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \ 156 '<PcdTokenSpaceGuidCName>.<TokenCName>|<Value>\ 157 [|<Type>|<MaximumDatumSize>]', LineNo) 158 else: 159 Value = List[1] 160 MaximumDatumSize = List[2] 161 Token = List[3] 162 163 if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo): 164 (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT) 165 166 return (TokenName, TokenGuid, Value, MaximumDatumSize, Token, Type) 167 168## Get FeatureFlagPcd 169# 170# Get FeatureFlagPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE 171# 172# @param Item: String as <PcdTokenSpaceGuidCName> 173# .<TokenCName>|TRUE/FALSE 174# @param ContainerFile: The file which describes the pcd, used for error 175# report 176# 177def GetFeatureFlagPcd(Item, Type, ContainerFile, LineNo= -1): 178 TokenGuid, TokenName, Value = '', '', '' 179 List = GetSplitValueList(Item) 180 if len(List) != 2: 181 RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \ 182 '<PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE', \ 183 LineNo) 184 else: 185 Value = List[1] 186 if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo): 187 (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT) 188 189 return (TokenName, TokenGuid, Value, Type) 190 191## Get DynamicDefaultPcd 192# 193# Get DynamicDefaultPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName> 194# |<Value>[|<DatumTyp>[|<MaxDatumSize>]] 195# 196# @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>| 197# TRUE/FALSE 198# @param ContainerFile: The file which describes the pcd, used for error 199# report 200# 201def GetDynamicDefaultPcd(Item, Type, ContainerFile, LineNo= -1): 202 TokenGuid, TokenName, Value, DatumTyp, MaxDatumSize = '', '', '', '', '' 203 List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2) 204 if len(List) < 4 or len(List) > 8: 205 RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \ 206 '<PcdTokenSpaceGuidCName>.<TokenCName>|<Value>\ 207 [|<DatumTyp>[|<MaxDatumSize>]]', LineNo) 208 else: 209 Value = List[1] 210 DatumTyp = List[2] 211 MaxDatumSize = List[3] 212 if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo): 213 (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT) 214 215 return (TokenName, TokenGuid, Value, DatumTyp, MaxDatumSize, Type) 216 217## Get DynamicHiiPcd 218# 219# Get DynamicHiiPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<String>| 220# <VariableGuidCName>|<VariableOffset>[|<DefaultValue>[|<MaximumDatumSize>]] 221# 222# @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>| 223# TRUE/FALSE 224# @param ContainerFile: The file which describes the pcd, used for error 225# report 226# 227def GetDynamicHiiPcd(Item, Type, ContainerFile, LineNo= -1): 228 TokenGuid, TokenName, List1, List2, List3, List4, List5 = \ 229 '', '', '', '', '', '', '' 230 List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2) 231 if len(List) < 6 or len(List) > 8: 232 RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \ 233 '<PcdTokenSpaceGuidCName>.<TokenCName>|<String>|\ 234 <VariableGuidCName>|<VariableOffset>[|<DefaultValue>\ 235 [|<MaximumDatumSize>]]', LineNo) 236 else: 237 List1, List2, List3, List4, List5 = \ 238 List[1], List[2], List[3], List[4], List[5] 239 if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo): 240 (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT) 241 242 return (TokenName, TokenGuid, List1, List2, List3, List4, List5, Type) 243 244## Get DynamicVpdPcd 245# 246# Get DynamicVpdPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>| 247# <VpdOffset>[|<MaximumDatumSize>] 248# 249# @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName> 250# |TRUE/FALSE 251# @param ContainerFile: The file which describes the pcd, used for error 252# report 253# 254def GetDynamicVpdPcd(Item, Type, ContainerFile, LineNo= -1): 255 TokenGuid, TokenName, List1, List2 = '', '', '', '' 256 List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT) 257 if len(List) < 3 or len(List) > 4: 258 RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \ 259 '<PcdTokenSpaceGuidCName>.<TokenCName>|<VpdOffset>\ 260 [|<MaximumDatumSize>]', LineNo) 261 else: 262 List1, List2 = List[1], List[2] 263 if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo): 264 (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT) 265 266 return (TokenName, TokenGuid, List1, List2, Type) 267 268## GetComponent 269# 270# Parse block of the components defined in dsc file 271# Set KeyValues as [ ['component name', [lib1, lib2, lib3], 272# [bo1, bo2, bo3], [pcd1, pcd2, pcd3]], ...] 273# 274# @param Lines: The content to be parsed 275# @param KeyValues: To store data after parsing 276# 277def GetComponent(Lines, KeyValues): 278 (FindBlock, FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ 279 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, FindPcdsDynamic, \ 280 FindPcdsDynamicEx) = (False, False, False, False, False, False, False, \ 281 False) 282 ListItem = None 283 LibraryClassItem = [] 284 BuildOption = [] 285 Pcd = [] 286 287 for Line in Lines: 288 Line = Line[0] 289 # 290 # Ignore !include statement 291 # 292 if Line.upper().find(DataType.TAB_INCLUDE.upper() + ' ') > -1 or \ 293 Line.upper().find(DataType.TAB_DEFINE + ' ') > -1: 294 continue 295 296 if FindBlock == False: 297 ListItem = Line 298 # 299 # find '{' at line tail 300 # 301 if Line.endswith('{'): 302 FindBlock = True 303 ListItem = CleanString(Line.rsplit('{', 1)[0], \ 304 DataType.TAB_COMMENT_SPLIT) 305 306 # 307 # Parse a block content 308 # 309 if FindBlock: 310 if Line.find('<LibraryClasses>') != -1: 311 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ 312 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ 313 FindPcdsDynamic, FindPcdsDynamicEx) = \ 314 (True, False, False, False, False, False, False) 315 continue 316 if Line.find('<BuildOptions>') != -1: 317 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ 318 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ 319 FindPcdsDynamic, FindPcdsDynamicEx) = \ 320 (False, True, False, False, False, False, False) 321 continue 322 if Line.find('<PcdsFeatureFlag>') != -1: 323 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ 324 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ 325 FindPcdsDynamic, FindPcdsDynamicEx) = \ 326 (False, False, True, False, False, False, False) 327 continue 328 if Line.find('<PcdsPatchableInModule>') != -1: 329 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ 330 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ 331 FindPcdsDynamic, FindPcdsDynamicEx) = \ 332 (False, False, False, True, False, False, False) 333 continue 334 if Line.find('<PcdsFixedAtBuild>') != -1: 335 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ 336 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ 337 FindPcdsDynamic, FindPcdsDynamicEx) = \ 338 (False, False, False, False, True, False, False) 339 continue 340 if Line.find('<PcdsDynamic>') != -1: 341 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ 342 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ 343 FindPcdsDynamic, FindPcdsDynamicEx) = \ 344 (False, False, False, False, False, True, False) 345 continue 346 if Line.find('<PcdsDynamicEx>') != -1: 347 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ 348 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ 349 FindPcdsDynamic, FindPcdsDynamicEx) = \ 350 (False, False, False, False, False, False, True) 351 continue 352 if Line.endswith('}'): 353 # 354 # find '}' at line tail 355 # 356 KeyValues.append([ListItem, LibraryClassItem, \ 357 BuildOption, Pcd]) 358 (FindBlock, FindLibraryClass, FindBuildOption, \ 359 FindPcdsFeatureFlag, FindPcdsPatchableInModule, \ 360 FindPcdsFixedAtBuild, FindPcdsDynamic, FindPcdsDynamicEx) = \ 361 (False, False, False, False, False, False, False, False) 362 LibraryClassItem, BuildOption, Pcd = [], [], [] 363 continue 364 365 if FindBlock: 366 if FindLibraryClass: 367 LibraryClassItem.append(Line) 368 elif FindBuildOption: 369 BuildOption.append(Line) 370 elif FindPcdsFeatureFlag: 371 Pcd.append((DataType.TAB_PCDS_FEATURE_FLAG_NULL, Line)) 372 elif FindPcdsPatchableInModule: 373 Pcd.append((DataType.TAB_PCDS_PATCHABLE_IN_MODULE_NULL, Line)) 374 elif FindPcdsFixedAtBuild: 375 Pcd.append((DataType.TAB_PCDS_FIXED_AT_BUILD_NULL, Line)) 376 elif FindPcdsDynamic: 377 Pcd.append((DataType.TAB_PCDS_DYNAMIC_DEFAULT_NULL, Line)) 378 elif FindPcdsDynamicEx: 379 Pcd.append((DataType.TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL, Line)) 380 else: 381 KeyValues.append([ListItem, [], [], []]) 382 383 return True 384 385## GetExec 386# 387# Parse a string with format "InfFilename [EXEC = ExecFilename]" 388# Return (InfFilename, ExecFilename) 389# 390# @param String: String with EXEC statement 391# 392def GetExec(String): 393 InfFilename = '' 394 ExecFilename = '' 395 if String.find('EXEC') > -1: 396 InfFilename = String[ : String.find('EXEC')].strip() 397 ExecFilename = String[String.find('EXEC') + len('EXEC') : ].strip() 398 else: 399 InfFilename = String.strip() 400 401 return (InfFilename, ExecFilename) 402 403## GetComponents 404# 405# Parse block of the components defined in dsc file 406# Set KeyValues as [ ['component name', [lib1, lib2, lib3], [bo1, bo2, bo3], 407# [pcd1, pcd2, pcd3]], ...] 408# 409# @param Lines: The content to be parsed 410# @param Key: Reserved 411# @param KeyValues: To store data after parsing 412# @param CommentCharacter: Comment char, used to ignore comment content 413# 414# @retval True Get component successfully 415# 416def GetComponents(Lines, KeyValues, CommentCharacter): 417 if Lines.find(DataType.TAB_SECTION_END) > -1: 418 Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1] 419 (FindBlock, FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ 420 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, FindPcdsDynamic, \ 421 FindPcdsDynamicEx) = \ 422 (False, False, False, False, False, False, False, False) 423 ListItem = None 424 LibraryClassItem = [] 425 BuildOption = [] 426 Pcd = [] 427 428 LineList = Lines.split('\n') 429 for Line in LineList: 430 Line = CleanString(Line, CommentCharacter) 431 if Line is None or Line == '': 432 continue 433 434 if FindBlock == False: 435 ListItem = Line 436 # 437 # find '{' at line tail 438 # 439 if Line.endswith('{'): 440 FindBlock = True 441 ListItem = CleanString(Line.rsplit('{', 1)[0], CommentCharacter) 442 443 # 444 # Parse a block content 445 # 446 if FindBlock: 447 if Line.find('<LibraryClasses>') != -1: 448 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ 449 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ 450 FindPcdsDynamic, FindPcdsDynamicEx) = \ 451 (True, False, False, False, False, False, False) 452 continue 453 if Line.find('<BuildOptions>') != -1: 454 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ 455 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ 456 FindPcdsDynamic, FindPcdsDynamicEx) = \ 457 (False, True, False, False, False, False, False) 458 continue 459 if Line.find('<PcdsFeatureFlag>') != -1: 460 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ 461 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ 462 FindPcdsDynamic, FindPcdsDynamicEx) = \ 463 (False, False, True, False, False, False, False) 464 continue 465 if Line.find('<PcdsPatchableInModule>') != -1: 466 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ 467 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ 468 FindPcdsDynamic, FindPcdsDynamicEx) = \ 469 (False, False, False, True, False, False, False) 470 continue 471 if Line.find('<PcdsFixedAtBuild>') != -1: 472 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ 473 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ 474 FindPcdsDynamic, FindPcdsDynamicEx) = \ 475 (False, False, False, False, True, False, False) 476 continue 477 if Line.find('<PcdsDynamic>') != -1: 478 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ 479 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ 480 FindPcdsDynamic, FindPcdsDynamicEx) = \ 481 (False, False, False, False, False, True, False) 482 continue 483 if Line.find('<PcdsDynamicEx>') != -1: 484 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ 485 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ 486 FindPcdsDynamic, FindPcdsDynamicEx) = \ 487 (False, False, False, False, False, False, True) 488 continue 489 if Line.endswith('}'): 490 # 491 # find '}' at line tail 492 # 493 KeyValues.append([ListItem, LibraryClassItem, BuildOption, \ 494 Pcd]) 495 (FindBlock, FindLibraryClass, FindBuildOption, \ 496 FindPcdsFeatureFlag, FindPcdsPatchableInModule, \ 497 FindPcdsFixedAtBuild, FindPcdsDynamic, FindPcdsDynamicEx) = \ 498 (False, False, False, False, False, False, False, False) 499 LibraryClassItem, BuildOption, Pcd = [], [], [] 500 continue 501 502 if FindBlock: 503 if FindLibraryClass: 504 LibraryClassItem.append(Line) 505 elif FindBuildOption: 506 BuildOption.append(Line) 507 elif FindPcdsFeatureFlag: 508 Pcd.append((DataType.TAB_PCDS_FEATURE_FLAG, Line)) 509 elif FindPcdsPatchableInModule: 510 Pcd.append((DataType.TAB_PCDS_PATCHABLE_IN_MODULE, Line)) 511 elif FindPcdsFixedAtBuild: 512 Pcd.append((DataType.TAB_PCDS_FIXED_AT_BUILD, Line)) 513 elif FindPcdsDynamic: 514 Pcd.append((DataType.TAB_PCDS_DYNAMIC, Line)) 515 elif FindPcdsDynamicEx: 516 Pcd.append((DataType.TAB_PCDS_DYNAMIC_EX, Line)) 517 else: 518 KeyValues.append([ListItem, [], [], []]) 519 520 return True 521 522## Get Source 523# 524# Get Source of Inf as <Filename>[|<Family>[|<TagName>[|<ToolCode> 525# [|<PcdFeatureFlag>]]]] 526# 527# @param Item: String as <Filename>[|<Family>[|<TagName>[|<ToolCode> 528# [|<PcdFeatureFlag>]]]] 529# @param ContainerFile: The file which describes the library class, used 530# for error report 531# 532def GetSource(Item, ContainerFile, FileRelativePath, LineNo= -1): 533 ItemNew = Item + DataType.TAB_VALUE_SPLIT * 4 534 List = GetSplitValueList(ItemNew) 535 if len(List) < 5 or len(List) > 9: 536 RaiseParserError(Item, 'Sources', ContainerFile, \ 537 '<Filename>[|<Family>[|<TagName>[|<ToolCode>\ 538 [|<PcdFeatureFlag>]]]]', LineNo) 539 List[0] = NormPath(List[0]) 540 CheckFileExist(FileRelativePath, List[0], ContainerFile, 'Sources', \ 541 Item, LineNo) 542 if List[4] != '': 543 CheckPcdTokenInfo(List[4], 'Sources', ContainerFile, LineNo) 544 545 return (List[0], List[1], List[2], List[3], List[4]) 546 547## Get Binary 548# 549# Get Binary of Inf as <Filename>[|<Family>[|<TagName>[|<ToolCode> 550# [|<PcdFeatureFlag>]]]] 551# 552# @param Item: String as <Filename>[|<Family>[|<TagName> 553# [|<ToolCode>[|<PcdFeatureFlag>]]]] 554# @param ContainerFile: The file which describes the library class, 555# used for error report 556# 557def GetBinary(Item, ContainerFile, LineNo= -1): 558 ItemNew = Item + DataType.TAB_VALUE_SPLIT 559 List = GetSplitValueList(ItemNew) 560 if len(List) < 3 or len(List) > 5: 561 RaiseParserError(Item, 'Binaries', ContainerFile, \ 562 "<FileType>|<Filename>[|<Target>\ 563 [|<TokenSpaceGuidCName>.<PcdCName>]]", LineNo) 564 565 if len(List) >= 4: 566 if List[3] != '': 567 CheckPcdTokenInfo(List[3], 'Binaries', ContainerFile, LineNo) 568 return (List[0], List[1], List[2], List[3]) 569 elif len(List) == 3: 570 return (List[0], List[1], List[2], '') 571 572## Get Guids/Protocols/Ppis 573# 574# Get Guids/Protocols/Ppis of Inf as <GuidCName>[|<PcdFeatureFlag>] 575# 576# @param Item: String as <GuidCName>[|<PcdFeatureFlag>] 577# @param Type: Type of parsing string 578# @param ContainerFile: The file which describes the library class, 579# used for error report 580# 581def GetGuidsProtocolsPpisOfInf(Item): 582 ItemNew = Item + DataType.TAB_VALUE_SPLIT 583 List = GetSplitValueList(ItemNew) 584 return (List[0], List[1]) 585 586## Get Guids/Protocols/Ppis 587# 588# Get Guids/Protocols/Ppis of Dec as <GuidCName>=<GuidValue> 589# 590# @param Item: String as <GuidCName>=<GuidValue> 591# @param Type: Type of parsing string 592# @param ContainerFile: The file which describes the library class, 593# used for error report 594# 595def GetGuidsProtocolsPpisOfDec(Item, Type, ContainerFile, LineNo= -1): 596 List = GetSplitValueList(Item, DataType.TAB_EQUAL_SPLIT) 597 if len(List) != 2: 598 RaiseParserError(Item, Type, ContainerFile, '<CName>=<GuidValue>', \ 599 LineNo) 600 # 601 #convert C-Format Guid to Register Format 602 # 603 if List[1][0] == '{' and List[1][-1] == '}': 604 RegisterFormatGuid = GuidStructureStringToGuidString(List[1]) 605 if RegisterFormatGuid == '': 606 RaiseParserError(Item, Type, ContainerFile, \ 607 'CFormat or RegisterFormat', LineNo) 608 else: 609 if CheckGuidRegFormat(List[1]): 610 RegisterFormatGuid = List[1] 611 else: 612 RaiseParserError(Item, Type, ContainerFile, \ 613 'CFormat or RegisterFormat', LineNo) 614 615 return (List[0], RegisterFormatGuid) 616 617## GetPackage 618# 619# Get Package of Inf as <PackagePath>[|<PcdFeatureFlag>] 620# 621# @param Item: String as <PackagePath>[|<PcdFeatureFlag>] 622# @param Type: Type of parsing string 623# @param ContainerFile: The file which describes the library class, 624# used for error report 625# 626def GetPackage(Item, ContainerFile, FileRelativePath, LineNo= -1): 627 ItemNew = Item + DataType.TAB_VALUE_SPLIT 628 List = GetSplitValueList(ItemNew) 629 CheckFileType(List[0], '.Dec', ContainerFile, 'package', List[0], LineNo) 630 CheckFileExist(FileRelativePath, List[0], ContainerFile, 'Packages', \ 631 List[0], LineNo) 632 if List[1] != '': 633 CheckPcdTokenInfo(List[1], 'Packages', ContainerFile, LineNo) 634 635 return (List[0], List[1]) 636 637## Get Pcd Values of Inf 638# 639# Get Pcd of Inf as <TokenSpaceGuidCName>.<PcdCName>[|<Value>] 640# 641# @param Item: The string describes pcd 642# @param Type: The type of Pcd 643# @param File: The file which describes the pcd, used for error report 644# 645def GetPcdOfInf(Item, Type, File, LineNo): 646 Format = '<TokenSpaceGuidCName>.<PcdCName>[|<Value>]' 647 TokenGuid, TokenName, Value, InfType = '', '', '', '' 648 649 if Type == DataType.TAB_PCDS_FIXED_AT_BUILD: 650 InfType = DataType.TAB_INF_FIXED_PCD 651 elif Type == DataType.TAB_PCDS_PATCHABLE_IN_MODULE: 652 InfType = DataType.TAB_INF_PATCH_PCD 653 elif Type == DataType.TAB_PCDS_FEATURE_FLAG: 654 InfType = DataType.TAB_INF_FEATURE_PCD 655 elif Type == DataType.TAB_PCDS_DYNAMIC_EX: 656 InfType = DataType.TAB_INF_PCD_EX 657 elif Type == DataType.TAB_PCDS_DYNAMIC: 658 InfType = DataType.TAB_INF_PCD 659 List = GetSplitValueList(Item, DataType.TAB_VALUE_SPLIT, 1) 660 TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT) 661 if len(TokenInfo) != 2: 662 RaiseParserError(Item, InfType, File, Format, LineNo) 663 else: 664 TokenGuid = TokenInfo[0] 665 TokenName = TokenInfo[1] 666 667 if len(List) > 1: 668 Value = List[1] 669 else: 670 Value = None 671 return (TokenGuid, TokenName, Value, InfType) 672 673 674## Get Pcd Values of Dec 675# 676# Get Pcd of Dec as <TokenSpcCName>.<TokenCName>|<Value>|<DatumType>|<Token> 677# @param Item: Pcd item 678# @param Type: Pcd type 679# @param File: Dec file 680# @param LineNo: Line number 681# 682def GetPcdOfDec(Item, Type, File, LineNo= -1): 683 Format = '<TokenSpaceGuidCName>.<PcdCName>|<Value>|<DatumType>|<Token>' 684 TokenGuid, TokenName, Value, DatumType, Token = '', '', '', '', '' 685 List = GetSplitValueList(Item) 686 if len(List) != 4: 687 RaiseParserError(Item, 'Pcds' + Type, File, Format, LineNo) 688 else: 689 Value = List[1] 690 DatumType = List[2] 691 Token = List[3] 692 TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT) 693 if len(TokenInfo) != 2: 694 RaiseParserError(Item, 'Pcds' + Type, File, Format, LineNo) 695 else: 696 TokenGuid = TokenInfo[0] 697 TokenName = TokenInfo[1] 698 699 return (TokenGuid, TokenName, Value, DatumType, Token, Type) 700 701## Parse DEFINE statement 702# 703# Get DEFINE macros 704# 705# @param LineValue: A DEFINE line value 706# @param StartLine: A DEFINE start line 707# @param Table: A table 708# @param FileID: File ID 709# @param Filename: File name 710# @param SectionName: DEFINE section name 711# @param SectionModel: DEFINE section model 712# @param Arch: DEFINE arch 713# 714def ParseDefine(LineValue, StartLine, Table, FileID, SectionName, \ 715 SectionModel, Arch): 716 Logger.Debug(Logger.DEBUG_2, ST.MSG_DEFINE_STATEMENT_FOUND % (LineValue, \ 717 SectionName)) 718 Define = \ 719 GetSplitValueList(CleanString\ 720 (LineValue[LineValue.upper().\ 721 find(DataType.TAB_DEFINE.upper() + ' ') + \ 722 len(DataType.TAB_DEFINE + ' ') : ]), \ 723 DataType.TAB_EQUAL_SPLIT, 1) 724 Table.Insert(DataType.MODEL_META_DATA_DEFINE, Define[0], Define[1], '', \ 725 '', '', Arch, SectionModel, FileID, StartLine, -1, \ 726 StartLine, -1, 0) 727 728## InsertSectionItems 729# 730# Insert item data of a section to a dict 731# 732# @param Model: A model 733# @param CurrentSection: Current section 734# @param SectionItemList: Section item list 735# @param ArchList: Arch list 736# @param ThirdList: Third list 737# @param RecordSet: Record set 738# 739def InsertSectionItems(Model, SectionItemList, ArchList, \ 740 ThirdList, RecordSet): 741 # 742 # Insert each item data of a section 743 # 744 for Index in range(0, len(ArchList)): 745 Arch = ArchList[Index] 746 Third = ThirdList[Index] 747 if Arch == '': 748 Arch = DataType.TAB_ARCH_COMMON 749 750 Records = RecordSet[Model] 751 for SectionItem in SectionItemList: 752 LineValue, StartLine, Comment = SectionItem[0], \ 753 SectionItem[1], SectionItem[2] 754 755 Logger.Debug(4, ST.MSG_PARSING % LineValue) 756 # 757 # And then parse DEFINE statement 758 # 759 if LineValue.upper().find(DataType.TAB_DEFINE.upper() + ' ') > -1: 760 continue 761 # 762 # At last parse other sections 763 # 764 IdNum = -1 765 Records.append([LineValue, Arch, StartLine, IdNum, Third, Comment]) 766 767 if RecordSet != {}: 768 RecordSet[Model] = Records 769 770## GenMetaDatSectionItem 771# 772# @param Key: A key 773# @param Value: A value 774# @param List: A list 775# 776def GenMetaDatSectionItem(Key, Value, List): 777 if Key not in List: 778 List[Key] = [Value] 779 else: 780 List[Key].append(Value) 781 782## GetPkgInfoFromDec 783# 784# get package name, guid, version info from dec files 785# 786# @param Path: File path 787# 788def GetPkgInfoFromDec(Path): 789 PkgName = None 790 PkgGuid = None 791 PkgVersion = None 792 793 Path = Path.replace('\\', '/') 794 795 if not os.path.exists(Path): 796 Logger.Error("\nUPT", FILE_NOT_FOUND, File=Path) 797 798 if Path in gPKG_INFO_DICT: 799 return gPKG_INFO_DICT[Path] 800 801 try: 802 DecParser = None 803 if Path not in GlobalData.gPackageDict: 804 DecParser = Dec(Path) 805 GlobalData.gPackageDict[Path] = DecParser 806 else: 807 DecParser = GlobalData.gPackageDict[Path] 808 809 PkgName = DecParser.GetPackageName() 810 PkgGuid = DecParser.GetPackageGuid() 811 PkgVersion = DecParser.GetPackageVersion() 812 gPKG_INFO_DICT[Path] = (PkgName, PkgGuid, PkgVersion) 813 return PkgName, PkgGuid, PkgVersion 814 except FatalError: 815 return None, None, None 816 817 818## GetWorkspacePackage 819# 820# Get a list of workspace package information. 821# 822def GetWorkspacePackage(): 823 DecFileList = [] 824 WorkspaceDir = GlobalData.gWORKSPACE 825 PackageDir = GlobalData.gPACKAGE_PATH 826 for PkgRoot in [WorkspaceDir] + PackageDir: 827 for Root, Dirs, Files in os.walk(PkgRoot): 828 if 'CVS' in Dirs: 829 Dirs.remove('CVS') 830 if '.svn' in Dirs: 831 Dirs.remove('.svn') 832 for Dir in Dirs: 833 if Dir.startswith('.'): 834 Dirs.remove(Dir) 835 for FileSp in Files: 836 if FileSp.startswith('.'): 837 continue 838 Ext = os.path.splitext(FileSp)[1] 839 if Ext.lower() in ['.dec']: 840 DecFileList.append\ 841 (os.path.normpath(os.path.join(Root, FileSp))) 842 # 843 # abstract package guid, version info from DecFile List 844 # 845 PkgList = [] 846 for DecFile in DecFileList: 847 (PkgName, PkgGuid, PkgVersion) = GetPkgInfoFromDec(DecFile) 848 if PkgName and PkgGuid and PkgVersion: 849 PkgList.append((PkgName, PkgGuid, PkgVersion, DecFile)) 850 851 return PkgList 852 853## GetWorkspaceModule 854# 855# Get a list of workspace modules. 856# 857def GetWorkspaceModule(): 858 InfFileList = [] 859 WorkspaceDir = GlobalData.gWORKSPACE 860 for Root, Dirs, Files in os.walk(WorkspaceDir): 861 if 'CVS' in Dirs: 862 Dirs.remove('CVS') 863 if '.svn' in Dirs: 864 Dirs.remove('.svn') 865 if 'Build' in Dirs: 866 Dirs.remove('Build') 867 for Dir in Dirs: 868 if Dir.startswith('.'): 869 Dirs.remove(Dir) 870 for FileSp in Files: 871 if FileSp.startswith('.'): 872 continue 873 Ext = os.path.splitext(FileSp)[1] 874 if Ext.lower() in ['.inf']: 875 InfFileList.append\ 876 (os.path.normpath(os.path.join(Root, FileSp))) 877 878 return InfFileList 879 880## MacroParser used to parse macro definition 881# 882# @param Line: The content contain linestring and line number 883# @param FileName: The meta-file file name 884# @param SectionType: Section for the Line belong to 885# @param FileLocalMacros: A list contain Macro defined in [Defines] section. 886# 887def MacroParser(Line, FileName, SectionType, FileLocalMacros): 888 MacroDefPattern = re.compile("^(DEFINE)[ \t]+") 889 LineContent = Line[0] 890 LineNo = Line[1] 891 Match = MacroDefPattern.match(LineContent) 892 if not Match: 893 # 894 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method 895 # 896 return None, None 897 898 TokenList = GetSplitValueList(LineContent[Match.end(1):], \ 899 DataType.TAB_EQUAL_SPLIT, 1) 900 # 901 # Syntax check 902 # 903 if not TokenList[0]: 904 Logger.Error('Parser', FORMAT_INVALID, ST.ERR_MACRONAME_NOGIVEN, 905 ExtraData=LineContent, File=FileName, Line=LineNo) 906 if len(TokenList) < 2: 907 Logger.Error('Parser', FORMAT_INVALID, ST.ERR_MACROVALUE_NOGIVEN, 908 ExtraData=LineContent, File=FileName, Line=LineNo) 909 910 Name, Value = TokenList 911 912 # 913 # DEFINE defined macros 914 # 915 if SectionType == DataType.MODEL_META_DATA_HEADER: 916 FileLocalMacros[Name] = Value 917 918 ReIsValidMacroName = re.compile(r"^[A-Z][A-Z0-9_]*$", re.DOTALL) 919 if ReIsValidMacroName.match(Name) is None: 920 Logger.Error('Parser', 921 FORMAT_INVALID, 922 ST.ERR_MACRONAME_INVALID % (Name), 923 ExtraData=LineContent, 924 File=FileName, 925 Line=LineNo) 926 927 # Validate MACRO Value 928 # 929 # <MacroDefinition> ::= [<Comments>]{0,} 930 # "DEFINE" <MACRO> "=" [{<PATH>} {<VALUE>}] <EOL> 931 # <Value> ::= {<NumVal>} {<Boolean>} {<AsciiString>} {<GUID>} 932 # {<CString>} {<UnicodeString>} {<CArray>} 933 # 934 # The definition of <NumVal>, <PATH>, <Boolean>, <GUID>, <CString>, 935 # <UnicodeString>, <CArray> are subset of <AsciiString>. 936 # 937 ReIsValidMacroValue = re.compile(r"^[\x20-\x7e]*$", re.DOTALL) 938 if ReIsValidMacroValue.match(Value) is None: 939 Logger.Error('Parser', 940 FORMAT_INVALID, 941 ST.ERR_MACROVALUE_INVALID % (Value), 942 ExtraData=LineContent, 943 File=FileName, 944 Line=LineNo) 945 946 return Name, Value 947 948## GenSection 949# 950# generate section contents 951# 952# @param SectionName: indicate the name of the section, details refer to 953# INF, DEC specs 954# @param SectionDict: section statement dict, key is SectionAttrs(arch, 955# moduletype or platform may exist as needed) list 956# separated by space, 957# value is statement 958# 959def GenSection(SectionName, SectionDict, SplitArch=True, NeedBlankLine=False): 960 Content = '' 961 for SectionAttrs in SectionDict: 962 StatementList = SectionDict[SectionAttrs] 963 if SectionAttrs and SectionName != 'Defines' and SectionAttrs.strip().upper() != DataType.TAB_ARCH_COMMON: 964 if SplitArch: 965 ArchList = GetSplitValueList(SectionAttrs, DataType.TAB_SPACE_SPLIT) 966 else: 967 if SectionName != 'UserExtensions': 968 ArchList = GetSplitValueList(SectionAttrs, DataType.TAB_COMMENT_SPLIT) 969 else: 970 ArchList = [SectionAttrs] 971 for Index in range(0, len(ArchList)): 972 ArchList[Index] = ConvertArchForInstall(ArchList[Index]) 973 Section = '[' + SectionName + '.' + (', ' + SectionName + '.').join(ArchList) + ']' 974 else: 975 Section = '[' + SectionName + ']' 976 Content += '\n' + Section + '\n' 977 if StatementList is not None: 978 for Statement in StatementList: 979 LineList = Statement.split('\n') 980 NewStatement = "" 981 for Line in LineList: 982 # ignore blank comment 983 if not Line.replace("#", '').strip() and SectionName not in ('Defines', 'Hob', 'Event', 'BootMode'): 984 continue 985 # add two space before non-comments line except the comments in Defines section 986 if Line.strip().startswith('#') and SectionName == 'Defines': 987 NewStatement += "%s\n" % Line 988 continue 989 NewStatement += " %s\n" % Line 990 if NeedBlankLine: 991 Content += NewStatement + '\n' 992 else: 993 Content += NewStatement 994 995 if NeedBlankLine: 996 Content = Content[:-1] 997 if not Content.replace('\\n', '').strip(): 998 return '' 999 return Content 1000 1001## ConvertArchForInstall 1002# if Arch.upper() is in "IA32", "X64", "IPF", and "EBC", it must be upper case. "common" must be lower case. 1003# Anything else, the case must be preserved 1004# 1005# @param Arch: the arch string that need to be converted, it should be stripped before pass in 1006# @return: the arch string that get converted 1007# 1008def ConvertArchForInstall(Arch): 1009 if Arch.upper() in [DataType.TAB_ARCH_IA32, DataType.TAB_ARCH_X64, 1010 DataType.TAB_ARCH_IPF, DataType.TAB_ARCH_EBC]: 1011 Arch = Arch.upper() 1012 elif Arch.upper() == DataType.TAB_ARCH_COMMON: 1013 Arch = Arch.lower() 1014 1015 return Arch 1016