# this file contains definitions related to the Linux kernel itself
#

# list here the macros that you know are always defined/undefined when including
# the kernel headers
#
import sys, cpp, re, os.path, time
from defaults import *

verboseSearch = 0
verboseFind   = 0

########################################################################
########################################################################
#####                                                              #####
#####           H E A D E R   S C A N N E R                        #####
#####                                                              #####
########################################################################
########################################################################


class HeaderScanner:
    """a class used to non-recursively detect which Linux kernel headers are
       used by a given set of input source files"""

    # to use the HeaderScanner, do the following:
    #
    #    scanner = HeaderScanner()
    #    for path in <your list of files>:
    #        scanner.parseFile(path)
    #
    #    # get the set of Linux headers included by your files
    #    headers = scanner.getHeaders()
    #
    #    # get the set of of input files that do include Linux headers
    #    files   = scanner.getFiles()
    #
    #    note that the result of getHeaders() is a set of strings, each one
    #    corresponding to a non-bracketed path name, e.g.:
    #
    #        set("linux/types","asm/types.h")
    #

    # the default algorithm is pretty smart and will analyze the input
    # files with a custom C pre-processor in order to optimize out macros,
    # get rid of comments, empty lines, etc..
    #
    # this avoids many annoying false positives... !!
    #

    # this regular expression is used to detect include paths that relate to
    # the kernel, by default, it selects one of:
    #    <linux/*>
    #    <asm/*>
    #    <asm-generic/*>
    #    <mtd/*>
    #
    re_combined_str=\
       r"^.*<((%s)/[\d\w_\+\.\-/]*)>.*$" % "|".join(kernel_dirs)

    re_combined = re.compile(re_combined_str)

    # some kernel files choose to include files with relative paths (x86 32/64
    # dispatch for instance)
    re_rel_dir = re.compile(r'^.*"([\d\w_\+\.\-/]+)".*$')

    def __init__(self,config={}):
        """initialize a HeaderScanner"""
        self.reset()
        self.config = config

    def reset(self,config={}):
        self.files    = set()  # set of files being parsed for headers
        self.headers  = {}     # maps headers to set of users
        self.config   = config

    def checkInclude(self, line, from_file, kernel_root=None):
        relative = False
        m = HeaderScanner.re_combined.match(line)
        if kernel_root and not m:
            m = HeaderScanner.re_rel_dir.match(line)
            relative = True
        if not m: return

        header = m.group(1)
        if from_file:
            self.files.add(from_file)
            if kernel_root and relative:
                hdr_dir = os.path.realpath(os.path.dirname(from_file))
                hdr_dir = hdr_dir.replace("%s/" % os.path.realpath(kernel_root),
                                          "")
                if hdr_dir:
                    _prefix = "%s/" % hdr_dir
                else:
                    _prefix = ""
                header = "%s%s" % (_prefix, header)

        if not header in self.headers:
            self.headers[header] = set()

        if from_file:
            if verboseFind:
                print("=== %s uses %s" % (from_file, header))
            self.headers[header].add(from_file)

    def parseFile(self, path, arch=None, kernel_root=None):
        """parse a given file for Linux headers"""
        if not os.path.exists(path):
            return

        # since tokenizing the file is very slow, we first try a quick grep
        # to see if this returns any meaningful results. only if this is true
        # do we do the tokenization"""
        try:
            f = open(path, "rt")
        except:
            print("!!! can't read '%s'" % path)
            return

        hasIncludes = False
        for line in f:
            if (HeaderScanner.re_combined.match(line) or
                (kernel_root and HeaderScanner.re_rel_dir.match(line))):
                hasIncludes = True
                break

        if not hasIncludes:
            if verboseSearch: print("::: " + path)
            return

        if verboseSearch: print("*** " + path)

        list = cpp.BlockParser().parseFile(path)
        if list:
            macros = kernel_known_macros.copy()
            if kernel_root:
                macros.update(self.config)
                if arch and arch in kernel_default_arch_macros:
                    macros.update(kernel_default_arch_macros[arch])
            list.optimizeMacros(macros)
            list.optimizeIf01()
            includes = list.findIncludes()
            for inc in includes:
                self.checkInclude(inc, path, kernel_root)

    def getHeaders(self):
        """return the set of all needed kernel headers"""
        return set(self.headers.keys())

    def getHeaderUsers(self,header):
        """return the set of all users for a given header"""
        return set(self.headers.get(header))

    def getAllUsers(self):
        """return a dictionary mapping heaaders to their user set"""
        return self.headers.copy()

    def getFiles(self):
        """returns the set of files that do include kernel headers"""
        return self.files.copy()


##########################################################################
##########################################################################
#####                                                                #####
#####           H E A D E R   F I N D E R                            #####
#####                                                                #####
##########################################################################
##########################################################################


class KernelHeaderFinder:
    """a class used to scan the kernel headers themselves."""

    # this is different
    #  from a HeaderScanner because we need to translate the path returned by
    #  HeaderScanner.getHeaders() into possibly architecture-specific ones.
    #
    # for example, <asm/XXXX.h> needs to be translated in <asm-ARCH/XXXX.h>
    # where ARCH is appropriately chosen

    # here's how to use this:
    #
    #    scanner = HeaderScanner()
    #    for path in <your list of user sources>:
    #        scanner.parseFile(path)
    #
    #    used_headers = scanner.getHeaders()
    #    finder       = KernelHeaderFinder(used_headers, [ "arm", "x86" ],
    #                                      "<kernel_include_path>")
    #    all_headers  = finder.scanForAllArchs()
    #
    #   not that the result of scanForAllArchs() is a list of relative
    #   header paths that are not bracketed
    #

    def __init__(self,headers,archs,kernel_root,kernel_config):
        """init a KernelHeaderScanner,

            'headers' is a list or set of headers,
            'archs' is a list of architectures
            'kernel_root' is the path to the 'include' directory
             of your original kernel sources
        """

        if len(kernel_root) > 0 and kernel_root[-1] != "/":
            kernel_root += "/"
        self.archs         = archs
        self.searched      = set(headers)
        self.kernel_root   = kernel_root
        self.kernel_config = kernel_config
        self.needed        = {}
        self.setArch(arch=None)

    def setArch(self,arch=None):
        self.curr_arch = arch
        self.arch_headers = set()
        if arch:
            self.prefix = "asm-%s/" % arch
        else:
            self.prefix = None

    def pathFromHeader(self,header):
        path = header
        if self.prefix and path.startswith("asm/"):
            path = "%s%s" % (self.prefix, path[4:])
        return path

    def pathToHeader(self,path):
        if self.prefix and path.startswith(self.prefix):
            path = "asm/%s" % path[len(self.prefix):]
        return "%s" % path

    def setSearchedHeaders(self,headers):
        self.searched = set(headers)

    def scanForArch(self):
        fparser   = HeaderScanner(config=self.kernel_config)
        workqueue = []
        needed    = {}
        for h in self.searched:
            path = self.pathFromHeader(h)
            if not path in needed:
                needed[path] = set()
            workqueue.append(path)

        i = 0
        while i < len(workqueue):
            path = workqueue[i]
            i   += 1
            fparser.parseFile(self.kernel_root + path,
                              arch=self.curr_arch, kernel_root=self.kernel_root)
            for used in fparser.getHeaders():
                path  = self.pathFromHeader(used)
                if not path in needed:
                    needed[path] = set()
                    workqueue.append(path)
                for user in fparser.getHeaderUsers(used):
                    needed[path].add(user)

        # now copy the arch-specific headers into the global list
        for header in needed.keys():
            users = needed[header]
            if not header in self.needed:
                self.needed[header] = set()

            for user in users:
                self.needed[header].add(user)

    def scanForAllArchs(self):
        """scan for all architectures and return the set of all needed kernel headers"""
        for arch in self.archs:
            self.setArch(arch)
            self.scanForArch()

        return set(self.needed.keys())

    def getHeaderUsers(self,header):
        """return the set of all users for a given header"""
        return set(self.needed[header])

    def getArchHeaders(self,arch):
        """return the set of all <asm/...> headers required by a given architecture"""
        return set()  # XXX: TODO

#####################################################################################
#####################################################################################
#####                                                                           #####
#####           C O N F I G   P A R S E R                                       #####
#####                                                                           #####
#####################################################################################
#####################################################################################

class ConfigParser:
    """a class used to parse the Linux kernel .config file"""
    re_CONFIG_ = re.compile(r"^(CONFIG_\w+)=(.*)$")

    def __init__(self):
        self.items = {}
        self.duplicates = False

    def parseLine(self, line):
        line = line.strip()

        # skip empty and comment lines
        if len(line) == 0 or line[0] == "#":
            return

        m = ConfigParser.re_CONFIG_.match(line)
        if not m: return

        name  = m.group(1)
        value = m.group(2)

        if name in self.items:  # aarg, duplicate value
            self.duplicates = True

        self.items[name] = value

    def parseFile(self,path):
        f = file(path, "r")
        for line in f:
            if len(line) > 0:
                if line[-1] == "\n":
                    line = line[:-1]
                    if len(line) > 0 and line[-1] == "\r":
                        line = line[:-1]
                self.parseLine(line)
        f.close()

    def getDefinitions(self):
        """retrieve a dictionary containing definitions for CONFIG_XXX"""
        return self.items.copy()

    def __repr__(self):
        return repr(self.items)

    def __str__(self):
        return str(self.items)
