## @file
# This file is used to define each component of tools_def.txt file
#
# Copyright (c) 2007 - 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.
#

##
# Import Modules
#
import Common.LongFilePathOs as os
import re
import EdkLogger

from BuildToolError import *
from TargetTxtClassObject import *
from Common.LongFilePathSupport import OpenLongFilePath as open
from Common.Misc import PathClass
from Common.StringUtils import NormPath
import Common.GlobalData as GlobalData
from Common import GlobalData
from Common.MultipleWorkspace import MultipleWorkspace as mws
from DataType import TAB_TOD_DEFINES_TARGET, TAB_TOD_DEFINES_TOOL_CHAIN_TAG,\
                     TAB_TOD_DEFINES_TARGET_ARCH, TAB_TOD_DEFINES_COMMAND_TYPE\
                     , TAB_TOD_DEFINES_FAMILY, TAB_TOD_DEFINES_BUILDRULEFAMILY


##
# Static variables used for pattern
#
gMacroRefPattern = re.compile('(DEF\([^\(\)]+\))')
gEnvRefPattern = re.compile('(ENV\([^\(\)]+\))')
gMacroDefPattern = re.compile("DEFINE\s+([^\s]+)")
gDefaultToolsDefFile = "tools_def.txt"

## ToolDefClassObject
#
# This class defined content used in file tools_def.txt
#
# @param object:               Inherited from object class
# @param Filename:             Input value for full path of tools_def.txt
#
# @var ToolsDefTxtDictionary:  To store keys and values defined in target.txt
# @var MacroDictionary:        To store keys and values defined in DEFINE statement
#
class ToolDefClassObject(object):
    def __init__(self, FileName=None):
        self.ToolsDefTxtDictionary = {}
        self.MacroDictionary = {}
        for Env in os.environ:
            self.MacroDictionary["ENV(%s)" % Env] = os.environ[Env]

        if FileName is not None:
            self.LoadToolDefFile(FileName)

    ## LoadToolDefFile
    #
    # Load target.txt file and parse it
    #
    # @param Filename:  Input value for full path of tools_def.txt
    #
    def LoadToolDefFile(self, FileName):
        # set multiple workspace
        PackagesPath = os.getenv("PACKAGES_PATH")
        mws.setWs(GlobalData.gWorkspace, PackagesPath)

        self.ToolsDefTxtDatabase = {
            TAB_TOD_DEFINES_TARGET          :   [],
            TAB_TOD_DEFINES_TOOL_CHAIN_TAG  :   [],
            TAB_TOD_DEFINES_TARGET_ARCH     :   [],
            TAB_TOD_DEFINES_COMMAND_TYPE    :   []
        }

        self.IncludeToolDefFile(FileName)

        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET]))
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG]))
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH]))

        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE]))

        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET].sort()
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG].sort()
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH].sort()
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE].sort()

        KeyList = [TAB_TOD_DEFINES_TARGET, TAB_TOD_DEFINES_TOOL_CHAIN_TAG, TAB_TOD_DEFINES_TARGET_ARCH, TAB_TOD_DEFINES_COMMAND_TYPE]
        for Index in range(3, -1, -1):
            # make a copy of the keys to enumerate over to prevent issues when
            # adding/removing items from the original dict.
            for Key in list(self.ToolsDefTxtDictionary.keys()):
                List = Key.split('_')
                if List[Index] == '*':
                    for String in self.ToolsDefTxtDatabase[KeyList[Index]]:
                        List[Index] = String
                        NewKey = '%s_%s_%s_%s_%s' % tuple(List)
                        if NewKey not in self.ToolsDefTxtDictionary:
                            self.ToolsDefTxtDictionary[NewKey] = self.ToolsDefTxtDictionary[Key]
                    del self.ToolsDefTxtDictionary[Key]
                elif List[Index] not in self.ToolsDefTxtDatabase[KeyList[Index]]:
                    del self.ToolsDefTxtDictionary[Key]


    ## IncludeToolDefFile
    #
    # Load target.txt file and parse it as if it's contents were inside the main file
    #
    # @param Filename:  Input value for full path of tools_def.txt
    #
    def IncludeToolDefFile(self, FileName):
        FileContent = []
        if os.path.isfile(FileName):
            try:
                F = open(FileName, 'r')
                FileContent = F.readlines()
            except:
                EdkLogger.error("tools_def.txt parser", FILE_OPEN_FAILURE, ExtraData=FileName)
        else:
            EdkLogger.error("tools_def.txt parser", FILE_NOT_FOUND, ExtraData=FileName)

        for Index in range(len(FileContent)):
            Line = FileContent[Index].strip()
            if Line == "" or Line[0] == '#':
                continue

            if Line.startswith("!include"):
                IncFile = Line[8:].strip()
                Done, IncFile = self.ExpandMacros(IncFile)
                if not Done:
                    EdkLogger.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE,
                                    "Macro or Environment has not been defined",
                                ExtraData=IncFile[4:-1], File=FileName, Line=Index+1)
                IncFile = NormPath(IncFile)

                if not os.path.isabs(IncFile):
                    #
                    # try WORKSPACE
                    #
                    IncFileTmp = PathClass(IncFile, GlobalData.gWorkspace)
                    ErrorCode = IncFileTmp.Validate()[0]
                    if ErrorCode != 0:
                        #
                        # try PACKAGES_PATH
                        #
                        IncFileTmp = mws.join(GlobalData.gWorkspace, IncFile)
                        if not os.path.exists(IncFileTmp):
                            #
                            # try directory of current file
                            #
                            IncFileTmp = PathClass(IncFile, os.path.dirname(FileName))
                            ErrorCode = IncFileTmp.Validate()[0]
                            if ErrorCode != 0:
                                EdkLogger.error("tools_def.txt parser", FILE_NOT_FOUND, ExtraData=IncFile)

                    if isinstance(IncFileTmp, PathClass):
                        IncFile = IncFileTmp.Path
                    else:
                        IncFile = IncFileTmp

                self.IncludeToolDefFile(IncFile)
                continue

            NameValuePair = Line.split("=", 1)
            if len(NameValuePair) != 2:
                EdkLogger.warn("tools_def.txt parser", "Line %d: not correct assignment statement, skipped" % (Index + 1))
                continue

            Name = NameValuePair[0].strip()
            Value = NameValuePair[1].strip()

            if Name == "IDENTIFIER":
                EdkLogger.debug(EdkLogger.DEBUG_8, "Line %d: Found identifier statement, skipped: %s" % ((Index + 1), Value))
                continue

            MacroDefinition = gMacroDefPattern.findall(Name)
            if MacroDefinition != []:
                Done, Value = self.ExpandMacros(Value)
                if not Done:
                    EdkLogger.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE,
                                    "Macro or Environment has not been defined",
                                ExtraData=Value[4:-1], File=FileName, Line=Index+1)

                MacroName = MacroDefinition[0].strip()
                self.MacroDictionary["DEF(%s)" % MacroName] = Value
                EdkLogger.debug(EdkLogger.DEBUG_8, "Line %d: Found macro: %s = %s" % ((Index + 1), MacroName, Value))
                continue

            Done, Value = self.ExpandMacros(Value)
            if not Done:
                EdkLogger.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE,
                                "Macro or Environment has not been defined",
                                ExtraData=Value[4:-1], File=FileName, Line=Index+1)

            List = Name.split('_')
            if len(List) != 5:
                EdkLogger.verbose("Line %d: Not a valid name of definition: %s" % ((Index + 1), Name))
                continue
            elif List[4] == '*':
                EdkLogger.verbose("Line %d: '*' is not allowed in last field: %s" % ((Index + 1), Name))
                continue
            else:
                self.ToolsDefTxtDictionary[Name] = Value
                if List[0] != '*':
                    self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET] += [List[0]]
                if List[1] != '*':
                    self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG] += [List[1]]
                if List[2] != '*':
                    self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH] += [List[2]]
                if List[3] != '*':
                    self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE] += [List[3]]
                if List[4] == TAB_TOD_DEFINES_FAMILY and List[2] == '*' and List[3] == '*':
                    if TAB_TOD_DEFINES_FAMILY not in self.ToolsDefTxtDatabase:
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY] = {}
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] = Value
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY] = {}
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value
                    elif List[1] not in self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY]:
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] = Value
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value
                    elif self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] != Value:
                        EdkLogger.verbose("Line %d: No override allowed for the family of a tool chain: %s" % ((Index + 1), Name))
                if List[4] == TAB_TOD_DEFINES_BUILDRULEFAMILY and List[2] == '*' and List[3] == '*':
                    if TAB_TOD_DEFINES_BUILDRULEFAMILY not in self.ToolsDefTxtDatabase \
                       or List[1] not in self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY]:
                        EdkLogger.verbose("Line %d: The family is not specified, but BuildRuleFamily is specified for the tool chain: %s" % ((Index + 1), Name))
                    self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value

    ## ExpandMacros
    #
    # Replace defined macros with real value
    #
    # @param Value:   The string with unreplaced macros
    #
    # @retval Value:  The string which has been replaced with real value
    #
    def ExpandMacros(self, Value):
        # os.environ contains all environment variables uppercase on Windows which cause the key in the self.MacroDictionary is uppercase, but Ref may not
        EnvReference = gEnvRefPattern.findall(Value)
        for Ref in EnvReference:
            if Ref not in self.MacroDictionary and Ref.upper() not in self.MacroDictionary:
                Value = Value.replace(Ref, "")
            else:
                if Ref in self.MacroDictionary:
                    Value = Value.replace(Ref, self.MacroDictionary[Ref])
                else:
                    Value = Value.replace(Ref, self.MacroDictionary[Ref.upper()])
        MacroReference = gMacroRefPattern.findall(Value)
        for Ref in MacroReference:
            if Ref not in self.MacroDictionary:
                return False, Ref
            Value = Value.replace(Ref, self.MacroDictionary[Ref])

        return True, Value

## ToolDefDict
#
# Load tools_def.txt in input Conf dir
#
# @param ConfDir:  Conf dir
#
# @retval ToolDef An instance of ToolDefClassObject() with loaded tools_def.txt
#
def ToolDefDict(ConfDir):
    Target = TargetTxtDict(ConfDir)
    ToolDef = ToolDefClassObject()
    if DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF in Target.TargetTxtDictionary:
        ToolsDefFile = Target.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
        if ToolsDefFile:
            ToolDef.LoadToolDefFile(os.path.normpath(ToolsDefFile))
        else:
            ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(ConfDir, gDefaultToolsDefFile)))
    else:
        ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(ConfDir, gDefaultToolsDefFile)))
    return ToolDef

##
#
# This acts like the main() function for the script, unless it is 'import'ed into another
# script.
#
if __name__ == '__main__':
    ToolDef = ToolDefDict(os.getenv("WORKSPACE"))
    pass
