"""Extension management for Windows.

Under Windows it is unlikely the .obj files are of use, as special compiler options
are needed (primarily to toggle the behavior of "public" symbols.

I dont consider it worth parsing the MSVC makefiles for compiler options.  Even if
we get it just right, a specific freeze application may have specific compiler
options anyway (eg, to enable or disable specific functionality)

So my basic stragtegy is:

* Have some Windows INI files which "describe" one or more extension modules.
  (Freeze comes with a default one for all known modules - but you can specify
  your own).
* This description can include:
  - The MSVC .dsp file for the extension.  The .c source file names
    are extraced from there.
  - Specific compiler/linker options
  - Flag to indicate if Unicode compilation is expected.

At the moment the name and location of this INI file is hardcoded,
but an obvious enhancement would be to provide command line options.
"""

import os, sys
try:
    import win32api
except ImportError:
    win32api = None # User has already been warned

class CExtension:
    """An abstraction of an extension implemented in C/C++
    """
    def __init__(self, name, sourceFiles):
        self.name = name
        # A list of strings defining additional compiler options.
        self.sourceFiles = sourceFiles
        # A list of special compiler options to be applied to
        # all source modules in this extension.
        self.compilerOptions = []
        # A list of .lib files the final .EXE will need.
        self.linkerLibs = []

    def GetSourceFiles(self):
        return self.sourceFiles

    def AddCompilerOption(self, option):
        self.compilerOptions.append(option)
    def GetCompilerOptions(self):
        return self.compilerOptions

    def AddLinkerLib(self, lib):
        self.linkerLibs.append(lib)
    def GetLinkerLibs(self):
        return self.linkerLibs

def checkextensions(unknown, extra_inis, prefix):
    # Create a table of frozen extensions

    defaultMapName = os.path.join( os.path.split(sys.argv[0])[0], "extensions_win32.ini")
    if not os.path.isfile(defaultMapName):
        sys.stderr.write("WARNING: %s can not be found - standard extensions may not be found\n" % defaultMapName)
    else:
        # must go on end, so other inis can override.
        extra_inis.append(defaultMapName)

    ret = []
    for mod in unknown:
        for ini in extra_inis:
#                       print "Looking for", mod, "in", win32api.GetFullPathName(ini),"...",
            defn = get_extension_defn( mod, ini, prefix )
            if defn is not None:
#                               print "Yay - found it!"
                ret.append( defn )
                break
#                       print "Nope!"
        else: # For not broken!
            sys.stderr.write("No definition of module %s in any specified map file.\n" % (mod))

    return ret

def get_extension_defn(moduleName, mapFileName, prefix):
    if win32api is None: return None
    os.environ['PYTHONPREFIX'] = prefix
    dsp = win32api.GetProfileVal(moduleName, "dsp", "", mapFileName)
    if dsp=="":
        return None

    # We allow environment variables in the file name
    dsp = win32api.ExpandEnvironmentStrings(dsp)
    # If the path to the .DSP file is not absolute, assume it is relative
    # to the description file.
    if not os.path.isabs(dsp):
        dsp = os.path.join( os.path.split(mapFileName)[0], dsp)
    # Parse it to extract the source files.
    sourceFiles = parse_dsp(dsp)
    if sourceFiles is None:
        return None

    module = CExtension(moduleName, sourceFiles)
    # Put the path to the DSP into the environment so entries can reference it.
    os.environ['dsp_path'] = os.path.split(dsp)[0]
    os.environ['ini_path'] = os.path.split(mapFileName)[0]

    cl_options = win32api.GetProfileVal(moduleName, "cl", "", mapFileName)
    if cl_options:
        module.AddCompilerOption(win32api.ExpandEnvironmentStrings(cl_options))

    exclude = win32api.GetProfileVal(moduleName, "exclude", "", mapFileName)
    exclude = exclude.split()

    if win32api.GetProfileVal(moduleName, "Unicode", 0, mapFileName):
        module.AddCompilerOption('/D UNICODE /D _UNICODE')

    libs = win32api.GetProfileVal(moduleName, "libs", "", mapFileName).split()
    for lib in libs:
        module.AddLinkerLib(win32api.ExpandEnvironmentStrings(lib))

    for exc in exclude:
        if exc in module.sourceFiles:
            modules.sourceFiles.remove(exc)

    return module

# Given an MSVC DSP file, locate C source files it uses
# returns a list of source files.
def parse_dsp(dsp):
#       print "Processing", dsp
    # For now, only support
    ret = []
    dsp_path, dsp_name = os.path.split(dsp)
    try:
        lines = open(dsp, "r").readlines()
    except IOError, msg:
        sys.stderr.write("%s: %s\n" % (dsp, msg))
        return None
    for line in lines:
        fields = line.strip().split("=", 2)
        if fields[0]=="SOURCE":
            if os.path.splitext(fields[1])[1].lower() in ['.cpp', '.c']:
                ret.append( win32api.GetFullPathName(os.path.join(dsp_path, fields[1] ) ) )
    return ret

def write_extension_table(fname, modules):
    fp = open(fname, "w")
    try:
        fp.write (ext_src_header)
        # Write fn protos
        for module in modules:
            # bit of a hack for .pyd's as part of packages.
            name = module.name.split('.')[-1]
            fp.write('extern void init%s(void);\n' % (name) )
        # Write the table
        fp.write (ext_tab_header)
        for module in modules:
            name = module.name.split('.')[-1]
            fp.write('\t{"%s", init%s},\n' % (name, name) )

        fp.write (ext_tab_footer)
        fp.write(ext_src_footer)
    finally:
        fp.close()


ext_src_header = """\
#include "Python.h"
"""

ext_tab_header = """\

static struct _inittab extensions[] = {
"""

ext_tab_footer = """\
        /* Sentinel */
        {0, 0}
};
"""

ext_src_footer = """\
extern DL_IMPORT(int) PyImport_ExtendInittab(struct _inittab *newtab);

int PyInitFrozenExtensions()
{
        return PyImport_ExtendInittab(extensions);
}

"""
