1## @file 2# This file contained the parser for INF file 3# 4# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR> 5# 6# SPDX-License-Identifier: BSD-2-Clause-Patent 7# 8 9''' 10InfParser 11''' 12 13## 14# Import Modules 15# 16import re 17import os 18from copy import deepcopy 19 20from Library.StringUtils import GetSplitValueList 21from Library.StringUtils import ConvertSpecialChar 22from Library.Misc import ProcessLineExtender 23from Library.Misc import ProcessEdkComment 24from Library.Parsing import NormPath 25from Library.ParserValidate import IsValidInfMoudleTypeList 26from Library.ParserValidate import IsValidArch 27from Library import DataType as DT 28from Library import GlobalData 29 30import Logger.Log as Logger 31from Logger import StringTable as ST 32from Logger.ToolError import FORMAT_INVALID 33from Logger.ToolError import FILE_READ_FAILURE 34from Logger.ToolError import PARSER_ERROR 35 36from Object.Parser.InfCommonObject import InfSectionCommonDef 37from Parser.InfSectionParser import InfSectionParser 38from Parser.InfParserMisc import gINF_SECTION_DEF 39from Parser.InfParserMisc import IsBinaryInf 40 41## OpenInfFile 42# 43# 44def OpenInfFile(Filename): 45 FileLinesList = [] 46 47 try: 48 FInputfile = open(Filename, "r") 49 try: 50 FileLinesList = FInputfile.readlines() 51 except BaseException: 52 Logger.Error("InfParser", 53 FILE_READ_FAILURE, 54 ST.ERR_FILE_OPEN_FAILURE, 55 File=Filename) 56 finally: 57 FInputfile.close() 58 except BaseException: 59 Logger.Error("InfParser", 60 FILE_READ_FAILURE, 61 ST.ERR_FILE_OPEN_FAILURE, 62 File=Filename) 63 64 return FileLinesList 65 66## InfParser 67# 68# This class defined the structure used in InfParser object 69# 70# @param InfObject: Inherited from InfSectionParser class 71# @param Filename: Input value for Filename of INF file, default is 72# None 73# @param WorkspaceDir: Input value for current workspace directory, 74# default is None 75# 76class InfParser(InfSectionParser): 77 78 def __init__(self, Filename = None, WorkspaceDir = None): 79 80 # 81 # Call parent class construct function 82 # 83 InfSectionParser.__init__() 84 85 self.WorkspaceDir = WorkspaceDir 86 self.SupArchList = DT.ARCH_LIST 87 self.EventList = [] 88 self.HobList = [] 89 self.BootModeList = [] 90 91 # 92 # Load Inf file if filename is not None 93 # 94 if Filename is not None: 95 self.ParseInfFile(Filename) 96 97 ## Parse INF file 98 # 99 # Parse the file if it exists 100 # 101 # @param Filename: Input value for filename of INF file 102 # 103 def ParseInfFile(self, Filename): 104 105 Filename = NormPath(Filename) 106 (Path, Name) = os.path.split(Filename) 107 self.FullPath = Filename 108 self.RelaPath = Path 109 self.FileName = Name 110 GlobalData.gINF_MODULE_DIR = Path 111 GlobalData.gINF_MODULE_NAME = self.FullPath 112 GlobalData.gIS_BINARY_INF = False 113 # 114 # Initialize common data 115 # 116 LineNo = 0 117 CurrentSection = DT.MODEL_UNKNOWN 118 SectionLines = [] 119 120 # 121 # Flags 122 # 123 HeaderCommentStart = False 124 HeaderCommentEnd = False 125 HeaderStarLineNo = -1 126 BinaryHeaderCommentStart = False 127 BinaryHeaderCommentEnd = False 128 BinaryHeaderStarLineNo = -1 129 130 # 131 # While Section ends. parse whole section contents. 132 # 133 NewSectionStartFlag = False 134 FirstSectionStartFlag = False 135 136 # 137 # Parse file content 138 # 139 CommentBlock = [] 140 141 # 142 # Variables for Event/Hob/BootMode 143 # 144 self.EventList = [] 145 self.HobList = [] 146 self.BootModeList = [] 147 SectionType = '' 148 149 FileLinesList = OpenInfFile (Filename) 150 151 # 152 # One INF file can only has one [Defines] section. 153 # 154 DefineSectionParsedFlag = False 155 156 # 157 # Convert special characters in lines to space character. 158 # 159 FileLinesList = ConvertSpecialChar(FileLinesList) 160 161 # 162 # Process Line Extender 163 # 164 FileLinesList = ProcessLineExtender(FileLinesList) 165 166 # 167 # Process EdkI INF style comment if found 168 # 169 OrigLines = [Line for Line in FileLinesList] 170 FileLinesList, EdkCommentStartPos = ProcessEdkComment(FileLinesList) 171 172 # 173 # Judge whether the INF file is Binary INF or not 174 # 175 if IsBinaryInf(FileLinesList): 176 GlobalData.gIS_BINARY_INF = True 177 178 InfSectionCommonDefObj = None 179 180 for Line in FileLinesList: 181 LineNo = LineNo + 1 182 Line = Line.strip() 183 if (LineNo < len(FileLinesList) - 1): 184 NextLine = FileLinesList[LineNo].strip() 185 186 # 187 # blank line 188 # 189 if (Line == '' or not Line) and LineNo == len(FileLinesList): 190 LastSectionFalg = True 191 192 # 193 # check whether file header comment section started 194 # 195 if Line.startswith(DT.TAB_SPECIAL_COMMENT) and \ 196 (Line.find(DT.TAB_HEADER_COMMENT) > -1) and \ 197 not HeaderCommentStart and not HeaderCommentEnd: 198 199 CurrentSection = DT.MODEL_META_DATA_FILE_HEADER 200 # 201 # Append the first line to section lines. 202 # 203 HeaderStarLineNo = LineNo 204 SectionLines.append((Line, LineNo)) 205 HeaderCommentStart = True 206 continue 207 208 # 209 # Collect Header content. 210 # 211 if (Line.startswith(DT.TAB_COMMENT_SPLIT) and CurrentSection == DT.MODEL_META_DATA_FILE_HEADER) and\ 212 HeaderCommentStart and not Line.startswith(DT.TAB_SPECIAL_COMMENT) and not\ 213 HeaderCommentEnd and NextLine != '': 214 SectionLines.append((Line, LineNo)) 215 continue 216 # 217 # Header content end 218 # 219 if (Line.startswith(DT.TAB_SPECIAL_COMMENT) or not Line.strip().startswith("#")) and HeaderCommentStart \ 220 and not HeaderCommentEnd: 221 HeaderCommentEnd = True 222 BinaryHeaderCommentStart = False 223 BinaryHeaderCommentEnd = False 224 HeaderCommentStart = False 225 if Line.find(DT.TAB_BINARY_HEADER_COMMENT) > -1: 226 self.InfHeaderParser(SectionLines, self.InfHeader, self.FileName) 227 SectionLines = [] 228 else: 229 SectionLines.append((Line, LineNo)) 230 # 231 # Call Header comment parser. 232 # 233 self.InfHeaderParser(SectionLines, self.InfHeader, self.FileName) 234 SectionLines = [] 235 continue 236 237 # 238 # check whether binary header comment section started 239 # 240 if Line.startswith(DT.TAB_SPECIAL_COMMENT) and \ 241 (Line.find(DT.TAB_BINARY_HEADER_COMMENT) > -1) and \ 242 not BinaryHeaderCommentStart: 243 SectionLines = [] 244 CurrentSection = DT.MODEL_META_DATA_FILE_HEADER 245 # 246 # Append the first line to section lines. 247 # 248 BinaryHeaderStarLineNo = LineNo 249 SectionLines.append((Line, LineNo)) 250 BinaryHeaderCommentStart = True 251 HeaderCommentEnd = True 252 continue 253 254 # 255 # check whether there are more than one binary header exist 256 # 257 if Line.startswith(DT.TAB_SPECIAL_COMMENT) and BinaryHeaderCommentStart and \ 258 not BinaryHeaderCommentEnd and (Line.find(DT.TAB_BINARY_HEADER_COMMENT) > -1): 259 Logger.Error('Parser', 260 FORMAT_INVALID, 261 ST.ERR_MULTIPLE_BINARYHEADER_EXIST, 262 File=Filename) 263 264 # 265 # Collect Binary Header content. 266 # 267 if (Line.startswith(DT.TAB_COMMENT_SPLIT) and CurrentSection == DT.MODEL_META_DATA_FILE_HEADER) and\ 268 BinaryHeaderCommentStart and not Line.startswith(DT.TAB_SPECIAL_COMMENT) and not\ 269 BinaryHeaderCommentEnd and NextLine != '': 270 SectionLines.append((Line, LineNo)) 271 continue 272 # 273 # Binary Header content end 274 # 275 if (Line.startswith(DT.TAB_SPECIAL_COMMENT) or not Line.strip().startswith(DT.TAB_COMMENT_SPLIT)) and \ 276 BinaryHeaderCommentStart and not BinaryHeaderCommentEnd: 277 SectionLines.append((Line, LineNo)) 278 BinaryHeaderCommentStart = False 279 # 280 # Call Binary Header comment parser. 281 # 282 self.InfHeaderParser(SectionLines, self.InfBinaryHeader, self.FileName, True) 283 SectionLines = [] 284 BinaryHeaderCommentEnd = True 285 continue 286 # 287 # Find a new section tab 288 # Or at the last line of INF file, 289 # need to process the last section. 290 # 291 LastSectionFalg = False 292 if LineNo == len(FileLinesList): 293 LastSectionFalg = True 294 295 if Line.startswith(DT.TAB_COMMENT_SPLIT) and not Line.startswith(DT.TAB_SPECIAL_COMMENT): 296 SectionLines.append((Line, LineNo)) 297 if not LastSectionFalg: 298 continue 299 300 # 301 # Encountered a section. start with '[' and end with ']' 302 # 303 if (Line.startswith(DT.TAB_SECTION_START) and \ 304 Line.find(DT.TAB_SECTION_END) > -1) or LastSectionFalg: 305 306 HeaderCommentEnd = True 307 BinaryHeaderCommentEnd = True 308 309 if not LastSectionFalg: 310 # 311 # check to prevent '#' inside section header 312 # 313 HeaderContent = Line[1:Line.find(DT.TAB_SECTION_END)] 314 if HeaderContent.find(DT.TAB_COMMENT_SPLIT) != -1: 315 Logger.Error("InfParser", 316 FORMAT_INVALID, 317 ST.ERR_INF_PARSER_DEFINE_SECTION_HEADER_INVALID, 318 File=self.FullPath, 319 Line=LineNo, 320 ExtraData=Line) 321 322 # 323 # Keep last time section header content for section parser 324 # usage. 325 # 326 self.LastSectionHeaderContent = deepcopy(self.SectionHeaderContent) 327 328 # 329 # TailComments in section define. 330 # 331 TailComments = '' 332 CommentIndex = Line.find(DT.TAB_COMMENT_SPLIT) 333 if CommentIndex > -1: 334 TailComments = Line[CommentIndex:] 335 Line = Line[:CommentIndex] 336 337 InfSectionCommonDefObj = InfSectionCommonDef() 338 if TailComments != '': 339 InfSectionCommonDefObj.SetTailComments(TailComments) 340 if CommentBlock != '': 341 InfSectionCommonDefObj.SetHeaderComments(CommentBlock) 342 CommentBlock = [] 343 # 344 # Call section parser before section header parer to avoid encounter EDKI INF file 345 # 346 if CurrentSection == DT.MODEL_META_DATA_DEFINE: 347 DefineSectionParsedFlag = self._CallSectionParsers(CurrentSection, 348 DefineSectionParsedFlag, SectionLines, 349 InfSectionCommonDefObj, LineNo) 350 # 351 # Compare the new section name with current 352 # 353 self.SectionHeaderParser(Line, self.FileName, LineNo) 354 355 self._CheckSectionHeaders(Line, LineNo) 356 357 SectionType = _ConvertSecNameToType(self.SectionHeaderContent[0][0]) 358 359 if not FirstSectionStartFlag: 360 CurrentSection = SectionType 361 FirstSectionStartFlag = True 362 else: 363 NewSectionStartFlag = True 364 else: 365 SectionLines.append((Line, LineNo)) 366 continue 367 368 if LastSectionFalg: 369 SectionLines, CurrentSection = self._ProcessLastSection(SectionLines, Line, LineNo, CurrentSection) 370 371 # 372 # End of section content collect. 373 # Parser the section content collected previously. 374 # 375 if NewSectionStartFlag or LastSectionFalg: 376 if CurrentSection != DT.MODEL_META_DATA_DEFINE or \ 377 (LastSectionFalg and CurrentSection == DT.MODEL_META_DATA_DEFINE): 378 DefineSectionParsedFlag = self._CallSectionParsers(CurrentSection, 379 DefineSectionParsedFlag, SectionLines, 380 InfSectionCommonDefObj, LineNo) 381 382 CurrentSection = SectionType 383 # 384 # Clear section lines 385 # 386 SectionLines = [] 387 388 if HeaderStarLineNo == -1: 389 Logger.Error("InfParser", 390 FORMAT_INVALID, 391 ST.ERR_NO_SOURCE_HEADER, 392 File=self.FullPath) 393 if BinaryHeaderStarLineNo > -1 and HeaderStarLineNo > -1 and HeaderStarLineNo > BinaryHeaderStarLineNo: 394 Logger.Error("InfParser", 395 FORMAT_INVALID, 396 ST.ERR_BINARY_HEADER_ORDER, 397 File=self.FullPath) 398 # 399 # EDKII INF should not have EDKI style comment 400 # 401 if EdkCommentStartPos != -1: 402 Logger.Error("InfParser", 403 FORMAT_INVALID, 404 ST.ERR_INF_PARSER_EDKI_COMMENT_IN_EDKII, 405 File=self.FullPath, 406 Line=EdkCommentStartPos + 1, 407 ExtraData=OrigLines[EdkCommentStartPos]) 408 409 # 410 # extract [Event] [Hob] [BootMode] sections 411 # 412 self._ExtractEventHobBootMod(FileLinesList) 413 414 ## _CheckSectionHeaders 415 # 416 # 417 def _CheckSectionHeaders(self, Line, LineNo): 418 if len(self.SectionHeaderContent) == 0: 419 Logger.Error("InfParser", 420 FORMAT_INVALID, 421 ST.ERR_INF_PARSER_DEFINE_SECTION_HEADER_INVALID, 422 File=self.FullPath, 423 Line=LineNo, ExtraData=Line) 424 else: 425 for SectionItem in self.SectionHeaderContent: 426 ArchList = [] 427 # 428 # Not cover Depex/UserExtension section header 429 # check. 430 # 431 if SectionItem[0].strip().upper() == DT.TAB_INF_FIXED_PCD.upper() or \ 432 SectionItem[0].strip().upper() == DT.TAB_INF_PATCH_PCD.upper() or \ 433 SectionItem[0].strip().upper() == DT.TAB_INF_PCD_EX.upper() or \ 434 SectionItem[0].strip().upper() == DT.TAB_INF_PCD.upper() or \ 435 SectionItem[0].strip().upper() == DT.TAB_INF_FEATURE_PCD.upper(): 436 ArchList = GetSplitValueList(SectionItem[1].strip(), ' ') 437 else: 438 ArchList = [SectionItem[1].strip()] 439 440 for Arch in ArchList: 441 if (not IsValidArch(Arch)) and \ 442 (SectionItem[0].strip().upper() != DT.TAB_DEPEX.upper()) and \ 443 (SectionItem[0].strip().upper() != DT.TAB_USER_EXTENSIONS.upper()) and \ 444 (SectionItem[0].strip().upper() != DT.TAB_COMMON_DEFINES.upper()): 445 Logger.Error("InfParser", 446 FORMAT_INVALID, 447 ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(SectionItem[1]), 448 File=self.FullPath, 449 Line=LineNo, ExtraData=Line) 450 # 451 # Check if the ModuleType is valid 452 # 453 ChkModSectionList = ['LIBRARYCLASSES'] 454 if (self.SectionHeaderContent[0][0].upper() in ChkModSectionList): 455 if SectionItem[2].strip().upper(): 456 MoudleTypeList = GetSplitValueList( 457 SectionItem[2].strip().upper()) 458 if (not IsValidInfMoudleTypeList(MoudleTypeList)): 459 Logger.Error("InfParser", 460 FORMAT_INVALID, 461 ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(SectionItem[2]), 462 File=self.FullPath, Line=LineNo, 463 ExtraData=Line) 464 465 ## _CallSectionParsers 466 # 467 # 468 def _CallSectionParsers(self, CurrentSection, DefineSectionParsedFlag, 469 SectionLines, InfSectionCommonDefObj, LineNo): 470 if CurrentSection == DT.MODEL_META_DATA_DEFINE: 471 if not DefineSectionParsedFlag: 472 self.InfDefineParser(SectionLines, 473 self.InfDefSection, 474 self.FullPath, 475 InfSectionCommonDefObj) 476 DefineSectionParsedFlag = True 477 else: 478 Logger.Error("Parser", 479 PARSER_ERROR, 480 ST.ERR_INF_PARSER_MULTI_DEFINE_SECTION, 481 File=self.FullPath, 482 RaiseError = Logger.IS_RAISE_ERROR) 483 484 elif CurrentSection == DT.MODEL_META_DATA_BUILD_OPTION: 485 self.InfBuildOptionParser(SectionLines, 486 self.InfBuildOptionSection, 487 self.FullPath) 488 489 elif CurrentSection == DT.MODEL_EFI_LIBRARY_CLASS: 490 self.InfLibraryParser(SectionLines, 491 self.InfLibraryClassSection, 492 self.FullPath) 493 494 elif CurrentSection == DT.MODEL_META_DATA_PACKAGE: 495 self.InfPackageParser(SectionLines, 496 self.InfPackageSection, 497 self.FullPath) 498 # 499 # [Pcd] Sections, put it together 500 # 501 elif CurrentSection == DT.MODEL_PCD_FIXED_AT_BUILD or \ 502 CurrentSection == DT.MODEL_PCD_PATCHABLE_IN_MODULE or \ 503 CurrentSection == DT.MODEL_PCD_FEATURE_FLAG or \ 504 CurrentSection == DT.MODEL_PCD_DYNAMIC_EX or \ 505 CurrentSection == DT.MODEL_PCD_DYNAMIC: 506 self.InfPcdParser(SectionLines, 507 self.InfPcdSection, 508 self.FullPath) 509 510 elif CurrentSection == DT.MODEL_EFI_SOURCE_FILE: 511 self.InfSourceParser(SectionLines, 512 self.InfSourcesSection, 513 self.FullPath) 514 515 elif CurrentSection == DT.MODEL_META_DATA_USER_EXTENSION: 516 self.InfUserExtensionParser(SectionLines, 517 self.InfUserExtensionSection, 518 self.FullPath) 519 520 elif CurrentSection == DT.MODEL_EFI_PROTOCOL: 521 self.InfProtocolParser(SectionLines, 522 self.InfProtocolSection, 523 self.FullPath) 524 525 elif CurrentSection == DT.MODEL_EFI_PPI: 526 self.InfPpiParser(SectionLines, 527 self.InfPpiSection, 528 self.FullPath) 529 530 elif CurrentSection == DT.MODEL_EFI_GUID: 531 self.InfGuidParser(SectionLines, 532 self.InfGuidSection, 533 self.FullPath) 534 535 elif CurrentSection == DT.MODEL_EFI_DEPEX: 536 self.InfDepexParser(SectionLines, 537 self.InfDepexSection, 538 self.FullPath) 539 540 elif CurrentSection == DT.MODEL_EFI_BINARY_FILE: 541 self.InfBinaryParser(SectionLines, 542 self.InfBinariesSection, 543 self.FullPath) 544 # 545 # Unknown section type found, raise error. 546 # 547 else: 548 if len(self.SectionHeaderContent) >= 1: 549 Logger.Error("Parser", 550 PARSER_ERROR, 551 ST.ERR_INF_PARSER_UNKNOWN_SECTION, 552 File=self.FullPath, Line=LineNo, 553 RaiseError = Logger.IS_RAISE_ERROR) 554 else: 555 Logger.Error("Parser", 556 PARSER_ERROR, 557 ST.ERR_INF_PARSER_NO_SECTION_ERROR, 558 File=self.FullPath, Line=LineNo, 559 RaiseError = Logger.IS_RAISE_ERROR) 560 561 return DefineSectionParsedFlag 562 563 def _ExtractEventHobBootMod(self, FileLinesList): 564 SpecialSectionStart = False 565 CheckLocation = False 566 GFindSpecialCommentRe = \ 567 re.compile(r"""#(?:\s*)\[(.*?)\](?:.*)""", re.DOTALL) 568 GFindNewSectionRe2 = \ 569 re.compile(r"""#?(\s*)\[(.*?)\](.*)""", re.DOTALL) 570 LineNum = 0 571 Element = [] 572 for Line in FileLinesList: 573 Line = Line.strip() 574 LineNum += 1 575 MatchObject = GFindSpecialCommentRe.search(Line) 576 if MatchObject: 577 SpecialSectionStart = True 578 Element = [] 579 if MatchObject.group(1).upper().startswith("EVENT"): 580 List = self.EventList 581 elif MatchObject.group(1).upper().startswith("HOB"): 582 List = self.HobList 583 elif MatchObject.group(1).upper().startswith("BOOTMODE"): 584 List = self.BootModeList 585 else: 586 SpecialSectionStart = False 587 CheckLocation = False 588 if SpecialSectionStart: 589 Element.append([Line, LineNum]) 590 List.append(Element) 591 else: 592 # 593 # if currently in special section, try to detect end of current section 594 # 595 MatchObject = GFindNewSectionRe2.search(Line) 596 if SpecialSectionStart: 597 if MatchObject: 598 SpecialSectionStart = False 599 CheckLocation = False 600 Element = [] 601 elif not Line: 602 SpecialSectionStart = False 603 CheckLocation = True 604 Element = [] 605 else: 606 if not Line.startswith(DT.TAB_COMMENT_SPLIT): 607 Logger.Warn("Parser", 608 ST.WARN_SPECIAL_SECTION_LOCATION_WRONG, 609 File=self.FullPath, Line=LineNum) 610 SpecialSectionStart = False 611 CheckLocation = False 612 Element = [] 613 else: 614 Element.append([Line, LineNum]) 615 else: 616 if CheckLocation: 617 if MatchObject: 618 CheckLocation = False 619 elif Line: 620 Logger.Warn("Parser", 621 ST.WARN_SPECIAL_SECTION_LOCATION_WRONG, 622 File=self.FullPath, Line=LineNum) 623 CheckLocation = False 624 625 if len(self.BootModeList) >= 1: 626 self.InfSpecialCommentParser(self.BootModeList, 627 self.InfSpecialCommentSection, 628 self.FileName, 629 DT.TYPE_BOOTMODE_SECTION) 630 631 if len(self.EventList) >= 1: 632 self.InfSpecialCommentParser(self.EventList, 633 self.InfSpecialCommentSection, 634 self.FileName, 635 DT.TYPE_EVENT_SECTION) 636 637 if len(self.HobList) >= 1: 638 self.InfSpecialCommentParser(self.HobList, 639 self.InfSpecialCommentSection, 640 self.FileName, 641 DT.TYPE_HOB_SECTION) 642 ## _ProcessLastSection 643 # 644 # 645 def _ProcessLastSection(self, SectionLines, Line, LineNo, CurrentSection): 646 # 647 # The last line is a section header. will discard it. 648 # 649 if not (Line.startswith(DT.TAB_SECTION_START) and Line.find(DT.TAB_SECTION_END) > -1): 650 SectionLines.append((Line, LineNo)) 651 652 if len(self.SectionHeaderContent) >= 1: 653 TemSectionName = self.SectionHeaderContent[0][0].upper() 654 if TemSectionName.upper() not in gINF_SECTION_DEF.keys(): 655 Logger.Error("InfParser", 656 FORMAT_INVALID, 657 ST.ERR_INF_PARSER_UNKNOWN_SECTION, 658 File=self.FullPath, 659 Line=LineNo, 660 ExtraData=Line, 661 RaiseError = Logger.IS_RAISE_ERROR 662 ) 663 else: 664 CurrentSection = gINF_SECTION_DEF[TemSectionName] 665 self.LastSectionHeaderContent = self.SectionHeaderContent 666 667 return SectionLines, CurrentSection 668 669## _ConvertSecNameToType 670# 671# 672def _ConvertSecNameToType(SectionName): 673 SectionType = '' 674 if SectionName.upper() not in gINF_SECTION_DEF.keys(): 675 SectionType = DT.MODEL_UNKNOWN 676 else: 677 SectionType = gINF_SECTION_DEF[SectionName.upper()] 678 679 return SectionType 680 681