#!/usr/bin/env python3
#
import sys, cpp, kernel, glob, os, re, getopt, clean_header, shutil
from defaults import *
from utils import *

def Usage():
    print("""\
  usage: %(progname)s [kernel-original-path] [kernel-modified-path]

    this program is used to update all the auto-generated clean headers
    used by the Bionic C library. it assumes the following:

      - a set of source kernel headers is located in
        'external/kernel-headers/original', relative to the current
        android tree

      - a set of manually modified kernel header files located in
        'external/kernel-headers/modified', relative to the current
        android tree

      - the clean headers will be placed in 'bionic/libc/kernel/arch-<arch>/asm',
        'bionic/libc/kernel/android', etc..
""" % { "progname" : os.path.basename(sys.argv[0]) })
    sys.exit(0)

def ProcessFiles(updater, original_dir, modified_dir, src_rel_dir, update_rel_dir):
    # Delete the old headers before updating to the new headers.
    update_dir = os.path.join(get_kernel_dir(), update_rel_dir)
    for root, dirs, files in os.walk(update_dir, topdown=True):
        for entry in files:
            # BUILD is a special file that needs to be preserved.
            if entry == "BUILD":
                continue
            os.remove(os.path.join(root, entry))
        for entry in dirs:
            shutil.rmtree(os.path.join(root, entry))

    src_dir = os.path.normpath(os.path.join(original_dir, src_rel_dir))
    src_dir_len = len(src_dir) + 1
    mod_src_dir = os.path.join(modified_dir, src_rel_dir)
    update_dir = os.path.join(get_kernel_dir(), update_rel_dir)

    kernel_dir = get_kernel_dir()
    for root, _, files in os.walk(src_dir):
        for file in sorted(files):
            _, ext = os.path.splitext(file)
            if ext != ".h":
                continue
            src_file = os.path.normpath(os.path.join(root, file))
            rel_path = src_file[src_dir_len:]
            # Check to see if there is a modified header to use instead.
            if os.path.exists(os.path.join(mod_src_dir, rel_path)):
                src_file = os.path.join(mod_src_dir, rel_path)
                src_str = os.path.join("<modified>", src_rel_dir, rel_path)
            else:
                src_str = os.path.join("<original>", src_rel_dir, rel_path)
            dst_file = os.path.join(update_dir, rel_path)
            new_data = clean_header.cleanupFile(dst_file, src_file, rel_path)
            if not new_data:
                continue
            updater.readFile(dst_file)
            ret_val = updater.editFile(dst_file, new_data)
            if ret_val == 0:
                state = "unchanged"
            elif ret_val == 1:
                state = "edited"
            else:
                state = "added"
            update_path = os.path.join(update_rel_dir, rel_path)
            print("cleaning %s -> %s (%s)" % (src_str, update_path, state))


# This lets us support regular system calls like __NR_write and also weird
# ones like __ARM_NR_cacheflush, where the NR doesn't come at the start.
def make__NR_name(name):
    if name.startswith('__ARM_NR_'):
        return name
    else:
        return '__NR_%s' % (name)


# Scan Linux kernel asm/unistd.h files containing __NR_* constants
# and write out equivalent SYS_* constants for glibc source compatibility.
def GenerateGlibcSyscallsHeader(updater):
    libc_root = '%s/bionic/libc/' % os.environ['ANDROID_BUILD_TOP']

    # Collect the set of all syscalls for all architectures.
    syscalls = set()
    pattern = re.compile(r'^\s*#\s*define\s*__NR_([a-z_]\S+)')
    for unistd_h in ['kernel/uapi/asm-generic/unistd.h',
                     'kernel/uapi/asm-arm/asm/unistd.h',
                     'kernel/uapi/asm-arm/asm/unistd-eabi.h',
                     'kernel/uapi/asm-arm/asm/unistd-oabi.h',
                     'kernel/uapi/asm-x86/asm/unistd_32.h',
                     'kernel/uapi/asm-x86/asm/unistd_64.h',
                     'kernel/uapi/asm-x86/asm/unistd_x32.h']:
        for line in open(os.path.join(libc_root, unistd_h)):
            m = re.search(pattern, line)
            if m:
                nr_name = m.group(1)
                if 'reserved' not in nr_name and 'unused' not in nr_name:
                    syscalls.add(nr_name)

    # Create a single file listing them all.
    # Note that the input files include #if trickery, so even for a single
    # architecture we don't know exactly which ones are available.
    # https://b.corp.google.com/issues/37110151
    content = '/* Generated file. Do not edit. */\n'
    content += '#pragma once\n'

    for syscall in sorted(syscalls):
        nr_name = make__NR_name(syscall)
        content += '#if defined(%s)\n' % nr_name
        content += '  #define SYS_%s %s\n' % (syscall, nr_name)
        content += '#endif\n'

    syscall_file = os.path.join(libc_root, 'include/bits/glibc-syscalls.h')
    updater.readFile(syscall_file)
    updater.editFile(syscall_file, content)


try:
    optlist, args = getopt.getopt(sys.argv[1:], '')
except:
    # Unrecognized option
    sys.stderr.write("error: unrecognized option\n")
    Usage()

if len(optlist) > 0 or len(args) > 2:
    Usage()

if len(args) > 0:
    original_dir = args[0]
else:
    original_dir = get_kernel_headers_original_dir()

if len(args) > 1:
    modified_dir = args[1]
else:
    modified_dir = get_kernel_headers_modified_dir()

if not os.path.isdir(original_dir):
    panic("The kernel directory %s is not a directory\n" % original_dir)

if not os.path.isdir(modified_dir):
    panic("The kernel modified directory %s is not a directory\n" % modified_dir)

updater = BatchFileUpdater()

# Process the original uapi headers first.
ProcessFiles(updater, original_dir, modified_dir, "uapi", "uapi"),

# Now process the special files.
ProcessFiles(updater, original_dir, modified_dir, "scsi", os.path.join("android", "scsi", "scsi"))

# Copy all of the files.
updater.updateFiles()

# Now re-generate the <bits/glibc-syscalls.h> from the new uapi headers.
updater = BatchFileUpdater()
GenerateGlibcSyscallsHeader(updater)
updater.updateFiles()
