#!/usr/bin/env python3
# Copyright 2015-2017 Obsidian Research Corp.
# Licensed under BSD (MIT variant) or GPLv2. See COPYING.
import argparse
import subprocess
import os
import collections
import re
import itertools

headers = {
    "bits/sysmacros.h",
    "endian.h",
    "netinet/in.h",
    "pthread.h",
    "stdatomic.h",
    "stdlib.h",
    "sys/socket.h",
    };

def norm_header(fn):
    for I in headers:
        flat = I.replace("/","-");
        if fn.endswith(flat):
            return I;
        if fn.endswith(flat + ".diff"):
            return I;
    return None;

def find_system_header(args,hdr):
    """/usr/include is not always where the include files are, particularly if we
    are running full multi-arch as the azure_pipeline container does. Get gcc
    to tell us where /usr/include is"""
    if "incpath" not in args:
        cpp = subprocess.check_output([args.cc, "-print-prog-name=cpp"],universal_newlines=True).strip()
        data = subprocess.check_output([cpp, "-v"],universal_newlines=True,stdin=subprocess.DEVNULL,
                                       stderr=subprocess.STDOUT)
        args.incpath = [];
        for incdir in re.finditer(r"^ (/\S+)$", data, re.MULTILINE):
            incdir = incdir.group(1)
            if "fixed" in incdir:
                continue;
            args.incpath.append(incdir)

    for incdir in args.incpath:
        fn = os.path.join(incdir,hdr)
        if os.path.exists(fn):
            return fn
    return None;

def get_buildlib_patches(dfn):
    """Within the buildlib directory we store patches for the glibc headers. Each
    patch is in a numbered sub directory that indicates the order to try, the
    number should match the glibc version used to make the diff."""
    ver_hdrs = [];
    all_hdrs = []
    for d,_,files in os.walk(dfn):
        for I in files:
            if d != dfn:
                bn = int(os.path.basename(d));
            else:
                bn = 0;

            if bn == 0:
                all_hdrs.append(os.path.join(d,I));
            else:
                ver_hdrs.append((bn,os.path.join(d,I)));
    ver_hdrs.sort(reverse=True);

    def add_to_dict(d,lst):
        for I in lst:
            nh = norm_header(I)
            if nh is None:
                continue;
            assert nh not in d
            d[nh] = (I, find_system_header(args,nh))

    ret = []
    for k,g in itertools.groupby(ver_hdrs,key=lambda x:x[0]):
        dd = {}
        ret.append(dd)
        add_to_dict(dd,(I for _,I in g))
        add_to_dict(dd,all_hdrs)
    return ret;

def is_patch(fn):
    with open(fn) as F:
        return F.read(10).startswith("-- /");

def apply_patch(src,patch,dest):
    """Patch a single system header. The output goes into our include search path
    and takes precedence over the system version."""
    if src is None:
        return False

    dfn = os.path.dirname(dest);
    if not os.path.isdir(dfn):
        os.makedirs(dfn);

    if not patch.endswith(".diff"):
        if not os.path.exists(dest):
            os.symlink(patch,dest);
        return True;

    try:
        if os.path.exists(dest + ".rej"):
            os.unlink(dest + ".rej");

        subprocess.check_output(["patch","-f","--follow-symlinks","-V","never","-i",patch,"-o",dest,src]);

        if os.path.exists(dest + ".rej"):
            print("Patch from %r failed"%(patch));
            return False;
    except subprocess.CalledProcessError:
        print("Patch from %r failed"%(patch));
        return False;
    return True;

def replace_headers(suite):
    # Local system does not have the reference system header, this suite is
    # not supported
    for fn,pfn in suite.items():
        if pfn[1] is None:
            return False;

    for fn,pfn in suite.items():
        if not apply_patch(pfn[1],pfn[0],os.path.join(args.INCLUDE,fn)):
            break;
    else:
        return True;

    for fn,_ in suite.items():
        try:
            os.unlink(os.path.join(args.INCLUDE,fn))
        except OSError:
            continue;
    return False;

def save(fn,outdir):
    """Diff the header file in our include directory against the system header and
    store the diff into buildlib. This makes it fairly easy to maintain the
    replacement headers."""
    if os.path.islink(os.path.join(args.INCLUDE,fn)):
        return;

    flatfn = fn.replace("/","-") + ".diff";
    flatfn = os.path.join(outdir,flatfn);

    includefn = os.path.join(args.INCLUDE,fn)
    if not os.path.exists(includefn):
        return

    cwd = os.getcwd()
    with open(flatfn,"wt") as F:
        os.chdir(os.path.join(args.INCLUDE,".."))
        try:
            subprocess.check_call(["diff","-u",
                                   find_system_header(args,fn),
                                   os.path.join("include",fn)],
                                  stdout=F);
        except subprocess.CalledProcessError as ex:
            if ex.returncode == 1:
                return;
            raise;
        finally:
            os.chdir(cwd)

parser = argparse.ArgumentParser(description='Produce sparse shim header files')
parser.add_argument("--out",dest="INCLUDE",required=True,
                    help="Directory to write header files to");
parser.add_argument("--src",dest="SRC",required=True,
                    help="Top of the source tree");
parser.add_argument("--cc",default="gcc",
                    help="System compiler to use to locate the default system headers");
parser.add_argument("--save",action="store_true",default=False,
                    help="Save mode will write the current content of the headers to buildlib as a diff.");
args = parser.parse_args();

if args.save:
    # Get the glibc version string
    ver = subprocess.check_output(["ldd","--version"]).decode()
    ver = ver.splitlines()[0].split(' ')[-1];
    ver = ver.partition(".")[-1];
    outdir = os.path.join(args.SRC,"buildlib","sparse-include",ver);
    if not os.path.isdir(outdir):
        os.makedirs(outdir);

    for I in headers:
        save(I,outdir);
else:
    failed = False;
    suites = get_buildlib_patches(os.path.join(args.SRC,"buildlib","sparse-include"));
    for I in suites:
        if replace_headers(I):
            break;
    else:
        raise ValueError("Patch applications failed");
