Home | History | Annotate | Download | only in Parser
      1 ## @file

      2 # This file contained the parser for sections in INF file 

      3 #

      4 # Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>

      5 #

      6 # This program and the accompanying materials are licensed and made available 

      7 # under the terms and conditions of the BSD License which accompanies this 

      8 # distribution. The full text of the license may be found at 

      9 # http://opensource.org/licenses/bsd-license.php

     10 #

     11 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

     12 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

     13 #

     14 
     15 '''
     16 InfSectionParser
     17 '''
     18 ##

     19 # Import Modules

     20 #

     21 from copy import deepcopy
     22 import re
     23 
     24 from Library.String import GetSplitValueList
     25 from Library.CommentParsing import ParseHeaderCommentSection
     26 from Library.CommentParsing import ParseComment
     27 
     28 from Library import DataType as DT
     29 
     30 import Logger.Log as Logger
     31 from Logger import StringTable as ST
     32 from Logger.ToolError import FORMAT_INVALID
     33 
     34 from Object.Parser.InfDefineObject import InfDefObject
     35 from Object.Parser.InfBuildOptionObject import InfBuildOptionsObject
     36 from Object.Parser.InfLibraryClassesObject import InfLibraryClassObject
     37 from Object.Parser.InfPackagesObject import InfPackageObject
     38 from Object.Parser.InfPcdObject import InfPcdObject
     39 from Object.Parser.InfSoucesObject import InfSourcesObject
     40 from Object.Parser.InfUserExtensionObject import InfUserExtensionObject
     41 from Object.Parser.InfProtocolObject import InfProtocolObject
     42 from Object.Parser.InfPpiObject import InfPpiObject
     43 from Object.Parser.InfGuidObject import InfGuidObject
     44 from Object.Parser.InfDepexObject import InfDepexObject
     45 from Object.Parser.InfBinaryObject import InfBinariesObject
     46 from Object.Parser.InfHeaderObject import InfHeaderObject
     47 from Object.Parser.InfMisc import InfSpecialCommentObject
     48 from Object.Parser.InfMisc import InfHobObject
     49 from Object.Parser.InfMisc import InfBootModeObject
     50 from Object.Parser.InfMisc import InfEventObject
     51 from Parser.InfParserMisc import gINF_SECTION_DEF
     52 from Parser.InfDefineSectionParser import InfDefinSectionParser
     53 from Parser.InfBuildOptionSectionParser import InfBuildOptionSectionParser
     54 from Parser.InfSourceSectionParser import InfSourceSectionParser
     55 from Parser.InfLibrarySectionParser import InfLibrarySectionParser
     56 from Parser.InfPackageSectionParser import InfPackageSectionParser
     57 from Parser.InfGuidPpiProtocolSectionParser import InfGuidPpiProtocolSectionParser
     58 from Parser.InfBinarySectionParser import InfBinarySectionParser
     59 from Parser.InfPcdSectionParser import InfPcdSectionParser
     60 from Parser.InfDepexSectionParser import InfDepexSectionParser
     61 
     62 ## GetSpecialStr2

     63 #

     64 # GetSpecialStr2

     65 #

     66 def GetSpecialStr2(ItemList, FileName, LineNo, SectionString):
     67     Str2 = ''
     68     #

     69     # S2 may be Platform or ModuleType

     70     #

     71     if len(ItemList) == 3:
     72         #

     73         # Except [LibraryClass], [Depex]

     74         # section can has more than 2 items in section header string,

     75         # others should report error.

     76         #

     77         if not (ItemList[0].upper() == DT.TAB_LIBRARY_CLASSES.upper() or \
     78                 ItemList[0].upper() == DT.TAB_DEPEX.upper() or \
     79                 ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper()):
     80             if ItemList[2] != '':
     81                 Logger.Error('Parser',
     82                              FORMAT_INVALID,
     83                              ST.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID % (SectionString),
     84                              File=FileName,
     85                              Line=LineNo,
     86                              ExtraData=SectionString)
     87         Str2 = ItemList[2]
     88     elif len(ItemList) == 4:
     89         #

     90         # Except [UserExtension]

     91         # section can has 4 items in section header string,

     92         # others should report error.

     93         #

     94         if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper() or ItemList[0].upper() == DT.TAB_DEPEX.upper():
     95             if ItemList[3] != '':
     96                 Logger.Error('Parser', FORMAT_INVALID, ST.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID \
     97                              % (SectionString), File=FileName, Line=LineNo, ExtraData=SectionString)
     98         
     99         if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper():
    100             Str2 = ItemList[2] + ' | ' + ItemList[3]
    101         else:
    102             Str2 = ItemList[2]
    103 
    104     elif len(ItemList) > 4:
    105         Logger.Error('Parser', FORMAT_INVALID, ST.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID \
    106                      % (SectionString), File=FileName, Line=LineNo, ExtraData=SectionString)
    107 
    108     return Str2
    109 
    110 ## ProcessUseExtHeader

    111 # 

    112 #

    113 def ProcessUseExtHeader(ItemList):
    114     NewItemList = []
    115     AppendContent = ''
    116     CompleteFlag = False
    117     for Item in ItemList:
    118         if Item.startswith('\"') and not Item.endswith('\"'):
    119             AppendContent = Item
    120             CompleteFlag = True
    121         elif Item.endswith('\"') and not Item.startswith('\"'):
    122             #

    123             # Should not have an userId or IdString not starts with " before but ends with ".

    124             #

    125             if not CompleteFlag:
    126                 return False, []
    127             AppendContent = AppendContent + "." + Item
    128             NewItemList.append(AppendContent)
    129             CompleteFlag = False
    130             AppendContent = ''
    131         elif Item.endswith('\"') and Item.startswith('\"'):
    132             #

    133             # Common item, not need to combine the information

    134             #

    135             NewItemList.append(Item)
    136         else:
    137             if not CompleteFlag:
    138                 NewItemList.append(Item)
    139             else:
    140                 AppendContent = AppendContent + "." + Item
    141     
    142     if len(NewItemList) > 4:
    143         return False, []
    144     
    145     return True, NewItemList
    146   
    147 ## GetArch

    148 #

    149 # GetArch

    150 #

    151 def GetArch(ItemList, ArchList, FileName, LineNo, SectionString):
    152     #

    153     # S1 is always Arch

    154     #

    155     if len(ItemList) > 1:
    156         Arch = ItemList[1]
    157     else:
    158         Arch = 'COMMON'
    159     ArchList.add(Arch)
    160 
    161     #

    162     # 'COMMON' must not be used with specific ARCHs at the same section

    163     #

    164     if 'COMMON' in ArchList and len(ArchList) > 1:
    165         Logger.Error('Parser',
    166                      FORMAT_INVALID,
    167                      ST.ERR_INF_PARSER_SECTION_ARCH_CONFLICT,
    168                      File=FileName,
    169                      Line=LineNo,
    170                      ExtraData=SectionString)
    171 
    172     return Arch, ArchList
    173 
    174 ## InfSectionParser

    175 #

    176 # Inherit from object

    177 #

    178 class InfSectionParser(InfDefinSectionParser,
    179                        InfBuildOptionSectionParser,
    180                        InfSourceSectionParser,
    181                        InfLibrarySectionParser,
    182                        InfPackageSectionParser,
    183                        InfGuidPpiProtocolSectionParser,
    184                        InfBinarySectionParser,
    185                        InfPcdSectionParser,
    186                        InfDepexSectionParser):
    187     #

    188     # Parser objects used to implement singleton

    189     #

    190     MetaFiles = {}
    191 
    192     ## Factory method

    193     #

    194     # One file, one parser object. This factory method makes sure that there's

    195     # only one object constructed for one meta file.

    196     #

    197     #   @param  Class           class object of real AutoGen class

    198     #                           (InfParser, DecParser or DscParser)

    199     #   @param  FilePath        The path of meta file

    200     #

    201     def __new__(cls, FilePath, *args, **kwargs):
    202         if args:
    203             pass
    204         if kwargs:
    205             pass
    206         if FilePath in cls.MetaFiles:
    207             return cls.MetaFiles[FilePath]
    208         else:
    209             ParserObject = super(InfSectionParser, cls).__new__(cls)
    210             cls.MetaFiles[FilePath] = ParserObject
    211             return ParserObject
    212 
    213     def __init__(self):
    214         InfDefinSectionParser.__init__(self)
    215         InfBuildOptionSectionParser.__init__(self)
    216         InfSourceSectionParser.__init__(self)
    217         InfLibrarySectionParser.__init__(self)
    218         InfPackageSectionParser.__init__(self)
    219         InfGuidPpiProtocolSectionParser.__init__(self)
    220         InfBinarySectionParser.__init__(self)
    221         InfPcdSectionParser.__init__(self)
    222         InfDepexSectionParser.__init__(self)
    223         #

    224         # Initialize all objects that an INF file will generated.

    225         #

    226         self.InfDefSection = InfDefObject()
    227         self.InfBuildOptionSection = InfBuildOptionsObject()
    228         self.InfLibraryClassSection = InfLibraryClassObject()
    229         self.InfPackageSection = InfPackageObject()
    230         self.InfPcdSection = InfPcdObject(self.MetaFiles.keys()[0])
    231         self.InfSourcesSection = InfSourcesObject()
    232         self.InfUserExtensionSection = InfUserExtensionObject()
    233         self.InfProtocolSection = InfProtocolObject()
    234         self.InfPpiSection = InfPpiObject()
    235         self.InfGuidSection = InfGuidObject()
    236         self.InfDepexSection = InfDepexObject()
    237         self.InfPeiDepexSection = InfDepexObject()
    238         self.InfDxeDepexSection = InfDepexObject()
    239         self.InfSmmDepexSection = InfDepexObject()
    240         self.InfBinariesSection = InfBinariesObject()
    241         self.InfHeader = InfHeaderObject()
    242         self.InfBinaryHeader = InfHeaderObject()
    243         self.InfSpecialCommentSection = InfSpecialCommentObject()
    244 
    245         #

    246         # A List for store define section content.

    247         #    

    248         self._PcdNameList = []
    249         self._SectionName = ''
    250         self._SectionType = 0
    251         self.RelaPath = ''
    252         self.FileName = ''
    253 
    254     #

    255     # File Header content parser

    256     #    

    257     def InfHeaderParser(self, Content, InfHeaderObject2, FileName, IsBinaryHeader = False):
    258         if IsBinaryHeader:
    259             (Abstract, Description, Copyright, License) = ParseHeaderCommentSection(Content, FileName, True)
    260             if not Abstract or not Description or not Copyright or not License:
    261                 Logger.Error('Parser',
    262                              FORMAT_INVALID,
    263                              ST.ERR_INVALID_BINARYHEADER_FORMAT,
    264                              File=FileName)
    265         else:
    266             (Abstract, Description, Copyright, License) = ParseHeaderCommentSection(Content, FileName)
    267         #

    268         # Not process file name now, for later usage.

    269         #

    270         if self.FileName:
    271             pass
    272 
    273         #

    274         # Insert Abstract, Description, CopyRight, License into header object

    275         #                                

    276         InfHeaderObject2.SetAbstract(Abstract)
    277         InfHeaderObject2.SetDescription(Description)
    278         InfHeaderObject2.SetCopyright(Copyright)
    279         InfHeaderObject2.SetLicense(License)
    280 
    281 
    282 
    283 
    284     ## Section header parser

    285     #

    286     #   The section header is always in following format:

    287     #

    288     #       [section_name.arch<.platform|module_type>]

    289     #

    290     # @param String    A string contained the content need to be parsed. 

    291     #

    292     def SectionHeaderParser(self, SectionString, FileName, LineNo):
    293         _Scope = []
    294         _SectionName = ''
    295         ArchList = set()
    296         _ValueList = []
    297         _PcdNameList = [DT.TAB_INF_FIXED_PCD.upper(),
    298                              DT.TAB_INF_FEATURE_PCD.upper(),
    299                              DT.TAB_INF_PATCH_PCD.upper(),
    300                              DT.TAB_INF_PCD.upper(),
    301                              DT.TAB_INF_PCD_EX.upper()
    302                              ]
    303         SectionString = SectionString.strip()
    304         for Item in GetSplitValueList(SectionString[1:-1], DT.TAB_COMMA_SPLIT):
    305             if Item == '':
    306                 Logger.Error('Parser',
    307                              FORMAT_INVALID,
    308                              ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (""),
    309                              File=FileName,
    310                              Line=LineNo,
    311                              ExtraData=SectionString)
    312             ItemList = GetSplitValueList(Item, DT.TAB_SPLIT)
    313             #

    314             # different section should not mix in one section

    315             # Allow different PCD type sections mixed together

    316             # 

    317             if _SectionName.upper() not in _PcdNameList:
    318                 if _SectionName != '' and _SectionName.upper() != ItemList[0].upper():
    319                     Logger.Error('Parser',
    320                                  FORMAT_INVALID,
    321                                  ST.ERR_INF_PARSER_SECTION_NAME_DUPLICATE,
    322                                  File=FileName,
    323                                  Line=LineNo,
    324                                  ExtraData=SectionString)
    325             elif _PcdNameList[1] in [_SectionName.upper(), ItemList[0].upper()] and \
    326                 (_SectionName.upper()!= ItemList[0].upper()):
    327                 Logger.Error('Parser',
    328                              FORMAT_INVALID,
    329                              ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (""),
    330                              File=FileName,
    331                              Line=LineNo,
    332                              ExtraData=SectionString)
    333 
    334             _SectionName = ItemList[0]
    335             if _SectionName.upper() in gINF_SECTION_DEF:
    336                 self._SectionType = gINF_SECTION_DEF[_SectionName.upper()]
    337             else:
    338                 self._SectionType = DT.MODEL_UNKNOWN
    339                 Logger.Error("Parser",
    340                              FORMAT_INVALID,
    341                              ST.ERR_INF_PARSER_UNKNOWN_SECTION,
    342                              File=FileName,
    343                              Line=LineNo,
    344                              ExtraData=SectionString)
    345 
    346             #

    347             # Get Arch

    348             #

    349             Str1, ArchList = GetArch(ItemList, ArchList, FileName, LineNo, SectionString)
    350 
    351             #

    352             # For [Defines] section, do special check.

    353             # 

    354             if ItemList[0].upper() == DT.TAB_COMMON_DEFINES.upper():
    355                 if len(ItemList) != 1:
    356                     Logger.Error('Parser',
    357                                  FORMAT_INVALID,
    358                                  ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (SectionString),
    359                                  File=FileName, Line=LineNo, ExtraData=SectionString)
    360 
    361             #

    362             # For [UserExtension] section, do special check.

    363             # 

    364             if ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper():
    365             
    366                 RetValue = ProcessUseExtHeader(ItemList)
    367                 
    368                 if not RetValue[0]:
    369                     Logger.Error('Parser',
    370                                  FORMAT_INVALID,
    371                                  ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (SectionString),
    372                                  File=FileName, Line=LineNo, ExtraData=SectionString)
    373                 else:
    374                     ItemList = RetValue[1]              
    375                 
    376                 if len(ItemList) == 3:
    377                     ItemList.append('COMMON')
    378                 
    379                 Str1 = ItemList[1]
    380 
    381             #

    382             # For Library classes, need to check module type.       

    383             #

    384             if ItemList[0].upper() == DT.TAB_LIBRARY_CLASSES.upper() and len(ItemList) == 3:
    385                 if ItemList[2] != '':
    386                     ModuleTypeList = GetSplitValueList(ItemList[2], DT.TAB_VALUE_SPLIT)
    387                     for Item in ModuleTypeList:
    388                         if Item.strip() not in DT.MODULE_LIST:
    389                             Logger.Error('Parser',
    390                                          FORMAT_INVALID,
    391                                          ST.ERR_INF_PARSER_DEFINE_MODULETYPE_INVALID % (Item),
    392                                          File=FileName,
    393                                          Line=LineNo,
    394                                          ExtraData=SectionString)
    395             #

    396             # GetSpecialStr2

    397             #

    398             Str2 = GetSpecialStr2(ItemList, FileName, LineNo, SectionString)
    399 
    400             _Scope.append([Str1, Str2])
    401 
    402             _NewValueList = []
    403             _AppendFlag = True
    404             if _SectionName.upper() in _PcdNameList:
    405                 for ValueItem in _ValueList:
    406                     if _SectionName.upper() == ValueItem[0].upper() and Str1.upper() not in ValueItem[1].split():
    407                         ValueItem[1] = ValueItem[1] + " " + Str1
    408                         _AppendFlag = False
    409                     elif _SectionName.upper() == ValueItem[0].upper() and Str1.upper() in ValueItem[1].split():
    410                         _AppendFlag = False
    411 
    412                     _NewValueList.append(ValueItem)
    413 
    414                 _ValueList = _NewValueList
    415 
    416             if _AppendFlag:
    417                 if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper():
    418                     _ValueList.append([_SectionName, Str1, Str2, LineNo])
    419                 else:
    420                     if len(ItemList) == 4:
    421                         _ValueList.append([_SectionName, Str1, Str2, ItemList[3], LineNo])
    422 
    423         self.SectionHeaderContent = deepcopy(_ValueList)
    424 
    425     ## GenSpecialSectionList

    426     #

    427     #  @param SpecialSectionList: a list of list, of which item's format 

    428     #                             (Comment, LineNum)

    429     #  @param ContainerFile:      Input value for filename of Inf file

    430     # 

    431     def InfSpecialCommentParser (self, SpecialSectionList, InfSectionObject, ContainerFile, SectionType):
    432         ReFindSpecialCommentRe = re.compile(r"""#(?:\s*)\[(.*?)\](?:.*)""", re.DOTALL)
    433         ReFindHobArchRe = re.compile(r"""[Hh][Oo][Bb]\.([^,]*)""", re.DOTALL)
    434         if self.FileName:
    435             pass
    436         SpecialObjectList = []
    437         ArchList = []
    438         if SectionType == DT.TYPE_EVENT_SECTION:
    439             TokenDict = DT.EVENT_TOKENS
    440         elif SectionType == DT.TYPE_HOB_SECTION:
    441             TokenDict = DT.HOB_TOKENS
    442         else:
    443             TokenDict = DT.BOOTMODE_TOKENS
    444 
    445         for List in SpecialSectionList:
    446             #

    447             # Hob has Arch attribute, need to be handled specially here

    448             #

    449             if SectionType == DT.TYPE_HOB_SECTION:
    450 
    451                 MatchObject = ReFindSpecialCommentRe.search(List[0][0])
    452                 HobSectionStr = MatchObject.group(1)
    453                 ArchList = []
    454                 for Match in ReFindHobArchRe.finditer(HobSectionStr):
    455                     Arch = Match.groups(1)[0].upper()
    456                     ArchList.append(Arch)
    457             CommentSoFar = ''
    458             for Index in xrange(1, len(List)):
    459                 Result = ParseComment(List[Index], DT.ALL_USAGE_TOKENS, TokenDict, [], False)
    460                 Usage = Result[0]
    461                 Type = Result[1]
    462                 HelpText = Result[3]
    463 
    464                 if Usage == DT.ITEM_UNDEFINED and Type == DT.ITEM_UNDEFINED:
    465                     if HelpText is None:
    466                         HelpText = ''
    467                     if not HelpText.endswith('\n'):
    468                         HelpText += '\n'
    469                     CommentSoFar += HelpText
    470                 else:
    471                     if HelpText:
    472                         CommentSoFar += HelpText
    473                     if SectionType == DT.TYPE_EVENT_SECTION:
    474                         SpecialObject = InfEventObject()
    475                         SpecialObject.SetEventType(Type)
    476                         SpecialObject.SetUsage(Usage)
    477                         SpecialObject.SetHelpString(CommentSoFar)
    478                     elif SectionType == DT.TYPE_HOB_SECTION:
    479                         SpecialObject = InfHobObject()
    480                         SpecialObject.SetHobType(Type)
    481                         SpecialObject.SetUsage(Usage)
    482                         SpecialObject.SetHelpString(CommentSoFar)
    483                         if len(ArchList) >= 1:
    484                             SpecialObject.SetSupArchList(ArchList)
    485                     else:
    486                         SpecialObject = InfBootModeObject()
    487                         SpecialObject.SetSupportedBootModes(Type)
    488                         SpecialObject.SetUsage(Usage)
    489                         SpecialObject.SetHelpString(CommentSoFar)
    490 
    491                     SpecialObjectList.append(SpecialObject)
    492                     CommentSoFar = ''
    493         if not InfSectionObject.SetSpecialComments(SpecialObjectList,
    494                                                    SectionType):
    495             Logger.Error('InfParser',
    496                          FORMAT_INVALID,
    497                          ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (SectionType),
    498                          ContainerFile
    499                          )
    500