## @file
# This file contained the parser for [Pcds] sections in INF file 
#
# Copyright (c) 2011 - 2018, 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.
#
'''
InfPcdSectionParser
'''
##
# 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 Library import GlobalData
from Library.StringUtils import SplitPcdEntry
from Parser.InfParserMisc import InfParserSectionRoot

class InfPcdSectionParser(InfParserSectionRoot):
    ## Section PCD related parser
    # 
    # For 5 types of PCD list below, all use this function.
    # 'FixedPcd', 'FeaturePcd', 'PatchPcd', 'Pcd', 'PcdEx'
    #
    # This is a INF independent parser, the validation in this parser only 
    # cover
    # INF spec scope, will not cross DEC/DSC to check pcd value
    #
    def InfPcdParser(self, SectionString, InfSectionObject, FileName):
        KeysList = []
        PcdList   = []
        CommentsList = []          
        ValueList = [] 
        #
        # Current section archs
        #          
        LineIndex = -1
        for Item in self.LastSectionHeaderContent:
            if (Item[0], Item[1], Item[3]) not in KeysList:
                KeysList.append((Item[0], Item[1], Item[3]))
                LineIndex = Item[3]
            
            if (Item[0].upper() == DT.TAB_INF_FIXED_PCD.upper() or \
                Item[0].upper() == DT.TAB_INF_FEATURE_PCD.upper() or \
                Item[0].upper() == DT.TAB_INF_PCD.upper()) and GlobalData.gIS_BINARY_INF:
                Logger.Error('InfParser', FORMAT_INVALID, ST.ERR_ASBUILD_PCD_SECTION_TYPE%("\"" + Item[0] + "\""),
                             File=FileName, Line=LineIndex)                    
                            
        #
        # For Common INF file
        #
        if not GlobalData.gIS_BINARY_INF:   
            #
            # Macro defined in this section 
            #
            SectionMacros = {}        
            for Line in SectionString:
                PcdLineContent = Line[0]
                PcdLineNo      = Line[1]
                if PcdLineContent.strip() == '':
                    CommentsList = []
                    continue                   
                    
                if PcdLineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
                    CommentsList.append(Line)
                    continue
                else:
                    #
                    # Encounter a PCD entry
                    #
                    if PcdLineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
                        CommentsList.append((
                                PcdLineContent[PcdLineContent.find(DT.TAB_COMMENT_SPLIT):], 
                                PcdLineNo))
                        PcdLineContent = PcdLineContent[:PcdLineContent.find(DT.TAB_COMMENT_SPLIT)] 
                
                if PcdLineContent != '':
                    #
                    # Find Macro
                    #
                    Name, Value = MacroParser((PcdLineContent, PcdLineNo),
                                              FileName,
                                              DT.MODEL_EFI_PCD,
                                              self.FileLocalMacros)
                    if Name is not None:
                        SectionMacros[Name] = Value
                        ValueList = []
                        CommentsList = []
                        continue
                    
                    PcdEntryReturn = SplitPcdEntry(PcdLineContent)
                    
                    if not PcdEntryReturn[1]:
                        TokenList = ['']               
                    else:
                        TokenList = PcdEntryReturn[0]
                          
                    ValueList[0:len(TokenList)] = TokenList
                    
                    #
                    # Replace with Local section Macro and [Defines] section Macro.
                    #            
                    ValueList = [InfExpandMacro(Value, (FileName, PcdLineContent, PcdLineNo), 
                                                self.FileLocalMacros, SectionMacros, True)
                                for Value in ValueList]
                                   
                if len(ValueList) >= 1:
                    PcdList.append((ValueList, CommentsList, (PcdLineContent, PcdLineNo, FileName)))
                    ValueList = []
                    CommentsList = []
                continue
        #
        # For Binary INF file
        #
        else:
            for Line in SectionString:
                LineContent = Line[0].strip()
                LineNo      = Line[1]
                
                if LineContent == '':
                    CommentsList = []
                    continue
                
                if LineContent.startswith(DT.TAB_COMMENT_SPLIT):
                    CommentsList.append(LineContent)
                    continue
                #
                # Have comments at tail.
                #
                CommentIndex = LineContent.find(DT.TAB_COMMENT_SPLIT)
                if  CommentIndex > -1:
                    CommentsList.append(LineContent[CommentIndex+1:])
                    LineContent = LineContent[:CommentIndex]
                
                TokenList = GetSplitValueList(LineContent, DT.TAB_VALUE_SPLIT)
                #
                # PatchablePcd
                # TokenSpace.CName | Value | Offset
                #
                if KeysList[0][0].upper() == DT.TAB_INF_PATCH_PCD.upper():
                    if len(TokenList) != 3:
                        Logger.Error('InfParser', 
                                     FORMAT_INVALID, 
                                     ST.ERR_ASBUILD_PATCHPCD_FORMAT_INVALID,
                                     File=FileName,
                                     Line=LineNo,
                                     ExtraData=LineContent)
                #                    
                elif KeysList[0][0].upper() == DT.TAB_INF_PCD_EX.upper():
                    if len(TokenList) != 1:
                        Logger.Error('InfParser', 
                                     FORMAT_INVALID, 
                                     ST.ERR_ASBUILD_PCDEX_FORMAT_INVALID,
                                     File=FileName,
                                     Line=LineNo,
                                     ExtraData=LineContent)
                ValueList[0:len(TokenList)] = TokenList
                if len(ValueList) >= 1:                
                    PcdList.append((ValueList, CommentsList, (LineContent, LineNo, FileName)))                  
                    ValueList = []
                    CommentsList = []
                continue          
                    
        if not InfSectionObject.SetPcds(PcdList, KeysList = KeysList, 
                                        PackageInfo = self.InfPackageSection.GetPackages()):
            Logger.Error('InfParser', 
                         FORMAT_INVALID, 
                         ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR%("[PCD]"),
                         File=FileName,
                         Line=LineIndex)            
    