# Recipe creation tool - kernel module support plugin
#
# Copyright (C) 2016 Intel Corporation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

import re
import logging
from recipetool.create import RecipeHandler, read_pkgconfig_provides, validate_pv

logger = logging.getLogger('recipetool')

tinfoil = None

def tinfoil_init(instance):
    global tinfoil
    tinfoil = instance


class KernelModuleRecipeHandler(RecipeHandler):
    def process(self, srctree, classes, lines_before, lines_after, handled, extravalues):
        import bb.process
        if 'buildsystem' in handled:
            return False

        module_inc_re = re.compile(r'^#include\s+<linux/module.h>$')
        makefiles = []
        is_module = False

        makefiles = []

        files = RecipeHandler.checkfiles(srctree, ['*.c', '*.h'], recursive=True, excludedirs=['contrib', 'test', 'examples'])
        if files:
            for cfile in files:
                # Look in same dir or parent for Makefile
                for makefile in [os.path.join(os.path.dirname(cfile), 'Makefile'), os.path.join(os.path.dirname(os.path.dirname(cfile)), 'Makefile')]:
                    if makefile in makefiles:
                        break
                    else:
                        if os.path.exists(makefile):
                            makefiles.append(makefile)
                            break
                else:
                    continue
                with open(cfile, 'r', errors='surrogateescape') as f:
                    for line in f:
                        if module_inc_re.match(line.strip()):
                            is_module = True
                            break
                if is_module:
                    break

        if is_module:
            classes.append('module')
            handled.append('buildsystem')
            # module.bbclass and the classes it inherits do most of the hard
            # work, but we need to tweak it slightly depending on what the
            # Makefile does (and there is a range of those)
            # Check the makefile for the appropriate install target
            install_lines = []
            compile_lines = []
            in_install = False
            in_compile = False
            install_target = None
            with open(makefile, 'r', errors='surrogateescape') as f:
                for line in f:
                    if line.startswith('install:'):
                        if not install_lines:
                            in_install = True
                            install_target = 'install'
                    elif line.startswith('modules_install:'):
                        install_lines = []
                        in_install = True
                        install_target = 'modules_install'
                    elif line.startswith('modules:'):
                        compile_lines = []
                        in_compile = True
                    elif line.startswith(('all:', 'default:')):
                        if not compile_lines:
                            in_compile = True
                    elif line:
                        if line[0] == '\t':
                            if in_install:
                                install_lines.append(line)
                            elif in_compile:
                                compile_lines.append(line)
                        elif ':' in line:
                            in_install = False
                            in_compile = False

            def check_target(lines, install):
                kdirpath = ''
                manual_install = False
                for line in lines:
                    splitline = line.split()
                    if splitline[0] in ['make', 'gmake', '$(MAKE)']:
                        if '-C' in splitline:
                            idx = splitline.index('-C') + 1
                            if idx < len(splitline):
                                kdirpath = splitline[idx]
                                break
                    elif install and splitline[0] == 'install':
                        if '.ko' in line:
                            manual_install = True
                return kdirpath, manual_install

            kdirpath = None
            manual_install = False
            if install_lines:
                kdirpath, manual_install = check_target(install_lines, install=True)
            if compile_lines and not kdirpath:
                kdirpath, _ = check_target(compile_lines, install=False)

            if manual_install or not install_lines:
                lines_after.append('EXTRA_OEMAKE_append_task-install = " -C ${STAGING_KERNEL_DIR} M=${S}"')
            elif install_target and install_target != 'modules_install':
                lines_after.append('MODULES_INSTALL_TARGET = "install"')

            warnmsg = None
            kdirvar = None
            if kdirpath:
                res = re.match(r'\$\(([^$)]+)\)', kdirpath)
                if res:
                    kdirvar = res.group(1)
                    if kdirvar != 'KERNEL_SRC':
                        lines_after.append('EXTRA_OEMAKE += "%s=${STAGING_KERNEL_DIR}"' % kdirvar)
                elif kdirpath.startswith('/lib/'):
                    warnmsg = 'Kernel path in install makefile is hardcoded - you will need to patch the makefile'
            if not kdirvar and not warnmsg:
                warnmsg = 'Unable to find means of passing kernel path into install makefile - if kernel path is hardcoded you will need to patch the makefile'
            if warnmsg:
                warnmsg += '. Note that the variable KERNEL_SRC will be passed in as the kernel source path.'
                logger.warning(warnmsg)
                lines_after.append('# %s' % warnmsg)

            return True

        return False

def register_recipe_handlers(handlers):
    handlers.append((KernelModuleRecipeHandler(), 15))
