from __future__ import print_function
import sys, os, time
from binding import namespaces
import codegen


extension_entry = '''

extern "C" {

#if (PY_MAJOR_VERSION >= 3)

PyMODINIT_FUNC
PyInit_%(module)s(void)
{
PyObject *module = create_python_module("%(module)s", meth_%(ns)s);
if (module) {
if (populate_submodules(module, submodule_%(ns)s))
return module;
}
return NULL;
}

#else

PyMODINIT_FUNC
init%(module)s(void)
{
PyObject *module = create_python_module("%(module)s", meth_%(ns)s);
if (module) {
populate_submodules(module, submodule_%(ns)s);
}
}
#endif

} // end extern C

'''


def populate_headers(println):
    includes = [
        'cstring',
        'Python.h',
        'python3adapt.h',
        'capsulethunk.h',
        'llvm_binding/conversion.h',
        'llvm_binding/binding.h',
        'llvm_binding/capsule_context.h',
        'llvm_binding/extra.h', # extra submodule to add
    ]
    for inc in includes:
        println('#include "%s"' % inc)
    println()


def main():
    outputfilename = sys.argv[1]
    entry_modname = sys.argv[2]
    sys.path += [os.path.dirname(os.curdir)]
    entry_module = __import__(entry_modname)
    rootns = namespaces['']

    # Check if files are modified

    outputfilepath = '%s.cpp' % outputfilename
    try:
        mtime = os.path.getmtime(outputfilepath)
    except OSError:
        mtime = 0

    if entry_module.last_mtime <= mtime:
        print("up to date")
        return

    # Generate C++ source
    with open(outputfilepath, 'w') as cppfile:
        println = codegen.wrap_println_from_file(cppfile)
        populate_headers(println)                  # extra headers
        # print all includes
        for inc in rootns.aggregate_includes():
            println('#include "%s"' % inc)
        println()
        # print all downcast
        downcast_fns = rootns.aggregate_downcast()
        for ((fromty, toty), fn) in downcast_fns:
            name = fn.name
            fmt = '''
static
%(toty)s* %(name)s(%(fromty)s* arg)
{
    return typecast< %(toty)s >::from(arg);
}
'''
            println(fmt % locals())

            fn.generate_cpp(println)

        println('static')
        println('PyMethodDef downcast_methodtable[] = {')
        fmt = '{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },'
        for _, fn in downcast_fns:
            name = fn.name
            func = fn.c_name
            println(fmt % locals())
        println('{ NULL }')
        println('};')
        println()
        # generate submodule
        rootns.generate_cpp(println, extras=[('extra', 'extra_methodtable'),
                                             ('downcast',
                                              'downcast_methodtable')])
        println(extension_entry % {'module': '_api',
                                   'ns': ''})

    # Generate Python source
    rootns.generate_py(rootdir='.', name='api')


if __name__ == '__main__':
    main()

@@ -983,19 +983,158 @@
 )%0A%0A%0A
-def main():
+FILE_HEADER = %22%22%22// This file is generated automatically%0A// Python: 0x%25x%0A%22%22%22 %25 (sys.hexversion,)%0A%0A%0Adef main():%0A    print(%22Running LLVM API generator%22)
 %0A   
@@ -1534,16 +1534,215 @@
  mtime:%0A
+%0A        # Check if file header matches%0A        with open(outputfilepath) as checkfile:%0A            n = len(FILE_HEADER)%0A            header = checkfile.read(n)%0A%0A        if header == FILE_HEADER:%0A    
         
@@ -1769,22 +1769,95 @@
         
+    
 return
+%0A        else:%0A            print(%22file is outdated%22)%0A            pass
 %0A%0A    # 
@@ -1981,16 +1981,45 @@
 ppfile)%0A
+        println(FILE_HEADER)%0A
         

Fix api.cpp not regenerated when switching python version