## @file
# This file contained the parser for define sections in INF file 
#
# Copyright (c) 2011, 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.
#

'''
InfDefineSectionParser
'''
##
# Import Modules
#
import re

from Library import DataType as DT
from Library import GlobalData
from Library.Parsing import MacroParser
from Library.Misc import GetSplitValueList
from Library.ParserValidate import IsValidArch
from Object.Parser.InfCommonObject import InfLineCommentObject
from Object.Parser.InfDefineObject import InfDefMember
from Parser.InfParserMisc import InfExpandMacro
from Object.Parser.InfMisc import ErrorInInf
from Logger import StringTable as ST
from Parser.InfParserMisc import InfParserSectionRoot

## __GetValidateArchList
#        
#
def GetValidateArchList(LineContent):
    
    TempArch = ''
    ArchList = []
    ValidateAcrhPatten = re.compile(r"^\s*#\s*VALID_ARCHITECTURES\s*=\s*.*$", re.DOTALL)
    
    if ValidateAcrhPatten.match(LineContent):
        TempArch = GetSplitValueList(LineContent, DT.TAB_EQUAL_SPLIT, 1)[1]
                                
        TempArch = GetSplitValueList(TempArch, '(', 1)[0]
                                
        ArchList = re.split('\s+', TempArch)
        NewArchList = []
        for Arch in ArchList:
            if IsValidArch(Arch):
                NewArchList.append(Arch)
        
        ArchList = NewArchList
        
    return ArchList   

class InfDefinSectionParser(InfParserSectionRoot):
    def InfDefineParser(self, SectionString, InfSectionObject, FileName, SectionComment):
        
        if SectionComment:
            pass
        #
        # Parser Defines section content and fill self._ContentList dict.
        #
        StillCommentFalg  = False
        HeaderComments = []
        SectionContent = ''
        ArchList       = []
        _ContentList   = []
        _ValueList     = []
        #
        # Add WORKSPACE to global Marco dict.
        #
        self.FileLocalMacros['WORKSPACE'] = GlobalData.gWORKSPACE
        
        for Line in SectionString:
            LineContent = Line[0]
            LineNo      = Line[1]
            TailComments   = ''
            LineComment    = None
            
            LineInfo       = ['', -1, '']
            LineInfo[0]    = FileName
            LineInfo[1]    = LineNo
            LineInfo[2]    = LineContent
            
            if LineContent.strip() == '':
                continue
            #
            # The first time encountered VALIDATE_ARCHITECHERS will be considered as support arch list.
            #
            if not ArchList:
                ArchList = GetValidateArchList(LineContent)

            #
            # Parser Comment
            #
            if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
                #
                # Last line is comments, and this line go on.
                #
                if StillCommentFalg:
                    HeaderComments.append(Line)
                    SectionContent += LineContent + DT.END_OF_LINE
                    continue
                #
                # First time encounter comment 
                #
                else:
                    #
                    # Clear original data
                    #
                    HeaderComments = []
                    HeaderComments.append(Line)
                    StillCommentFalg = True
                    SectionContent += LineContent + DT.END_OF_LINE
                    continue
            else:
                StillCommentFalg = False
                          
            if len(HeaderComments) >= 1:
                LineComment = InfLineCommentObject()
                LineCommentContent = ''
                for Item in HeaderComments:
                    LineCommentContent += Item[0] + DT.END_OF_LINE
                LineComment.SetHeaderComments(LineCommentContent)
            
            #
            # Find Tail comment.
            #
            if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
                TailComments = LineContent[LineContent.find(DT.TAB_COMMENT_SPLIT):]
                LineContent = LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)]
                if LineComment is None:
                    LineComment = InfLineCommentObject()
                LineComment.SetTailComments(TailComments)
                              
            #
            # Find Macro
            #
            Name, Value = MacroParser((LineContent, LineNo), 
                                      FileName, 
                                      DT.MODEL_META_DATA_HEADER, 
                                      self.FileLocalMacros)
            if Name is not None:
                self.FileLocalMacros[Name] = Value
                continue            

            #
            # Replace with [Defines] section Macro
            #
            LineContent = InfExpandMacro(LineContent, 
                                         (FileName, LineContent, LineNo), 
                                         self.FileLocalMacros, 
                                         None, True)
                       
            SectionContent += LineContent + DT.END_OF_LINE
            
            TokenList = GetSplitValueList(LineContent, DT.TAB_EQUAL_SPLIT, 1)
            if len(TokenList) < 2:
                ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_NO_VALUE,
                           LineInfo=LineInfo)                
            _ValueList[0:len(TokenList)] = TokenList
            if not _ValueList[0]:
                ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_NO_NAME,
                           LineInfo=LineInfo)
            if not _ValueList[1]:
                ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_NO_VALUE,
                           LineInfo=LineInfo)   
   
            Name, Value = _ValueList[0], _ValueList[1]            
            
            InfDefMemberObj = InfDefMember(Name, Value)
            if (LineComment is not None):
                InfDefMemberObj.Comments.SetHeaderComments(LineComment.GetHeaderComments())
                InfDefMemberObj.Comments.SetTailComments(LineComment.GetTailComments())
                
            InfDefMemberObj.CurrentLine.SetFileName(self.FullPath)
            InfDefMemberObj.CurrentLine.SetLineString(LineContent)
            InfDefMemberObj.CurrentLine.SetLineNo(LineNo)
                       
            _ContentList.append(InfDefMemberObj)
            HeaderComments = []
            TailComments = ''
        
        #
        # Current Define section archs
        #
        if not ArchList:
            ArchList = ['COMMON']
        
        InfSectionObject.SetAllContent(SectionContent)                
        
        InfSectionObject.SetDefines(_ContentList, Arch=ArchList)
        