## @file
# This file contained the parser for [Libraries] sections in INF file 
#
# Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available 
# under the terms and conditions of the BSD License which accompanies this 
# distribution. The full text of the license may be found at 
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
'''
InfLibrarySectionParser
'''
##
# Import Modules
#

import Logger.Log as Logger
from Logger import StringTable as ST
from Logger.ToolError import FORMAT_INVALID
from Parser.InfParserMisc import InfExpandMacro
from Library import DataType as DT
from Library.Parsing import MacroParser
from Library.Misc import GetSplitValueList
from Object.Parser.InfCommonObject import InfLineCommentObject
from Library import GlobalData
from Parser.InfParserMisc import IsLibInstanceInfo
from Parser.InfAsBuiltProcess import GetLibInstanceInfo
from Parser.InfParserMisc import InfParserSectionRoot

class InfLibrarySectionParser(InfParserSectionRoot):
    ## InfLibraryParser
    #
    #                 
    def InfLibraryParser(self, SectionString, InfSectionObject, FileName):
        #
        # For Common INF file
        #
        if not GlobalData.gIS_BINARY_INF:
            #
            # Macro defined in this section 
            #
            SectionMacros = {}
            ValueList = []
            LibraryList = []
            LibStillCommentFalg = False
            LibHeaderComments = []
            LibLineComment = None
            #
            # Parse section content
            #
            for Line in SectionString:
                LibLineContent = Line[0]
                LibLineNo = Line[1]

                if LibLineContent.strip() == '':
                    continue

                #
                # Found Header Comments 
                #
                if LibLineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
                    #
                    # Last line is comments, and this line go on.
                    #
                    if LibStillCommentFalg:
                        LibHeaderComments.append(Line)
                        continue
                    #
                    # First time encounter comment 
                    #
                    else:
                        #
                        # Clear original data
                        #
                        LibHeaderComments = []
                        LibHeaderComments.append(Line)
                        LibStillCommentFalg = True
                        continue
                else:
                    LibStillCommentFalg = False

                if len(LibHeaderComments) >= 1:
                    LibLineComment = InfLineCommentObject()
                    LineCommentContent = ''
                    for Item in LibHeaderComments:
                        LineCommentContent += Item[0] + DT.END_OF_LINE
                    LibLineComment.SetHeaderComments(LineCommentContent)

                #
                # Find Tail comment.
                #
                if LibLineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
                    LibTailComments = LibLineContent[LibLineContent.find(DT.TAB_COMMENT_SPLIT):]
                    LibLineContent = LibLineContent[:LibLineContent.find(DT.TAB_COMMENT_SPLIT)]
                    if LibLineComment is None:
                        LibLineComment = InfLineCommentObject()
                    LibLineComment.SetTailComments(LibTailComments)

                #
                # Find Macro
                #
                Name, Value = MacroParser((LibLineContent, LibLineNo),
                                          FileName,
                                          DT.MODEL_EFI_LIBRARY_CLASS,
                                          self.FileLocalMacros)
                if Name is not None:
                    SectionMacros[Name] = Value
                    LibLineComment = None
                    LibHeaderComments = []
                    continue

                TokenList = GetSplitValueList(LibLineContent, DT.TAB_VALUE_SPLIT, 1)
                ValueList[0:len(TokenList)] = TokenList

                #
                # Replace with Local section Macro and [Defines] section Macro.
                #            
                ValueList = [InfExpandMacro(Value, (FileName, LibLineContent, LibLineNo),
                                            self.FileLocalMacros, SectionMacros, True)
                                            for Value in ValueList]

                LibraryList.append((ValueList, LibLineComment,
                                    (LibLineContent, LibLineNo, FileName)))
                ValueList = []
                LibLineComment = None
                LibTailComments = ''
                LibHeaderComments = []

                continue

            #
            # Current section archs
            #    
            KeyList = []
            for Item in self.LastSectionHeaderContent:
                if (Item[1], Item[2]) not in KeyList:
                    KeyList.append((Item[1], Item[2]))

            if not InfSectionObject.SetLibraryClasses(LibraryList, KeyList=KeyList):
                Logger.Error('InfParser',
                             FORMAT_INVALID,
                             ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Library]"),
                             File=FileName,
                             Line=Item[3])
        #
        # For Binary INF
        #
        else:
            self.InfAsBuiltLibraryParser(SectionString, InfSectionObject, FileName)

    def InfAsBuiltLibraryParser(self, SectionString, InfSectionObject, FileName):
        LibraryList = []
        LibInsFlag = False
        for Line in SectionString:
            LineContent = Line[0]
            LineNo = Line[1]

            if LineContent.strip() == '':
                LibInsFlag = False
                continue

            if not LineContent.strip().startswith("#"):
                Logger.Error('InfParser',
                            FORMAT_INVALID,
                            ST.ERR_LIB_CONTATIN_ASBUILD_AND_COMMON,
                            File=FileName,
                            Line=LineNo,
                            ExtraData=LineContent)

            if IsLibInstanceInfo(LineContent):
                LibInsFlag = True
                continue

            if LibInsFlag:
                LibGuid, LibVer = GetLibInstanceInfo(LineContent, GlobalData.gWORKSPACE, LineNo, FileName)
                #
                # If the VERSION_STRING is missing from the INF file, tool should default to "0".
                #
                if LibVer == '':
                    LibVer = '0'
                if LibGuid != '':
                    if (LibGuid, LibVer) not in LibraryList:
                        LibraryList.append((LibGuid, LibVer))

        #
        # Current section archs
        #    
        KeyList = []
        Item = ['', '', '']
        for Item in self.LastSectionHeaderContent:
            if (Item[1], Item[2]) not in KeyList:
                KeyList.append((Item[1], Item[2]))

        if not InfSectionObject.SetLibraryClasses(LibraryList, KeyList=KeyList):
            Logger.Error('InfParser',
                         FORMAT_INVALID,
                         ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Library]"),
                         File=FileName,
                         Line=Item[3])
