#!/usr/bin/python

import os
import sys
import optparse
import inspect

def die(msg, parser):
    sys.stderr.write("Error: "+msg+"\n")
    parser.print_help()
    sys.exit(1)

def parse(config):
    """parse a kernel config file into a dict"""
    fd = open(config)
    tmp = {}
    for i in fd:
        i = i.strip()
        if i.startswith('#'):
            if i.endswith(' is not set'):
                i = i[2:]
                (key, non) = i.split(' ', 1)
                tmp[key] = None
        elif len(i) == 0:
            pass
        else:
            (key, value) = i.split('=', 1)
            tmp[key] = value
    fd.close()
    return tmp

def print_value(k, v):
    """print config entry"""
    if v == None:
        print "# %s is not set" % k
    else:
        print "%s=%s" % (k, v)

def print_values(keys, values):
    for i in keys:
        print_value(i, values[i])


# COMMON ALGOS
def diff(a, b):
    return filter(lambda i: i not in b, a)

def base(a, b):
    return filter(lambda i: i in b, a)

def udiff(a, b):
    d1 = diff(a, b)
    d2 = diff(b, a)
    d1.extend(d2)
    d1.sort()
    return d1

def common_multi(fun, args):
    (f1, f2) = map(parse, args)
    c = fun(f1, f2)
    c.sort()
    print_values(c, f1)


# ACTIONS
def action_base(args):
    '''base - prints everything in 1 AND 2'''
    common_multi(base, args)

def action_diff(args):
    '''diff - prints everything in 1 AND NOT in 2'''
    common_multi(diff, args)

def action_udiff(args):
    '''udiff - prints everyting thats missing in either 1 or 2'''
    (f1, f2) = map(parse, args)
    d = udiff(f1, f2)
    f2.update(f1)
    print_values(d, f2)


# MAIN
if __name__ == "__main__":
    # actionname -> fun()
    actions = {}
    for k,v in globals().copy().iteritems():
        prefix = 'action_'
        if k.startswith(prefix):
            if callable(v):
                actions[k[len(prefix):]] = v
    docstrings = [ '\t'+inspect.getdoc(i) for i in actions.itervalues() ]
    docstrings.sort()
    usage = "usage: %prog [options] <action> <config1> <config2>\n\n" +\
            "%prog is a program which helps in kernel config handling\n\n" +\
            "ACTIONS:\n" + '\n'.join(docstrings)
    parser = optparse.OptionParser(usage)
    (opts, args) = parser.parse_args()
    if len(args) <1:
        die("no argument given", parser)
    cmd = args[0]
    if cmd == "help":
        parser.print_help()
        sys.exit(0)
    if len(args) <3:
        die("wrong number of arguments", parser)
    args = args[1:]
    if cmd in actions:
        actions[cmd](args)
    else:
        parser.error("no such action: " + cmd)

