Blame bin/cython_freeze

Packit Service 99d393
#!/usr/bin/env python
Packit Service 99d393
"""
Packit Service 99d393
Create a C file for embedding one or more Cython source files.
Packit Service 99d393
Requires Cython 0.11.2 (or perhaps newer).
Packit Service 99d393
Packit Service 99d393
See Demos/freeze/README.rst for more details.
Packit Service 99d393
"""
Packit Service 99d393
from __future__ import print_function
Packit Service 99d393
Packit Service 99d393
import optparse
Packit Service 99d393
from os.path import splitext, basename
Packit Service 99d393
Packit Service 99d393
usage= '%prog [-o outfile] [-p] module [module ...]'
Packit Service 99d393
description = 'Create a C file for embedding Cython modules.'
Packit Service 99d393
p = optparse.OptionParser(usage=usage, description=description)
Packit Service 99d393
p.add_option('-o', '--output', metavar='FILE',
Packit Service 99d393
        help='write output to FILE instead of standard output')
Packit Service 99d393
p.add_option('-p', '--pymain', action='store_true', default=False,
Packit Service 99d393
        help='do not automatically run the first module as __main__')
Packit Service 99d393
Packit Service 99d393
options, args = p.parse_args()
Packit Service 99d393
Packit Service 99d393
if len(args) < 1:
Packit Service 99d393
    p.print_help()
Packit Service 99d393
    p.exit(1)
Packit Service 99d393
Packit Service 99d393
if options.output:
Packit Service 99d393
    import sys
Packit Service 99d393
    old_stdout = sys.stdout
Packit Service 99d393
    sys.stdout = open(options.output, 'w')
Packit Service 99d393
Packit Service 99d393
modules = [basename(splitext(x)[0]).replace('.', '_') for x in args]
Packit Service 99d393
Packit Service 99d393
print("""\
Packit Service 99d393
#include <Python.h>
Packit Service 99d393
#include <locale.h>
Packit Service 99d393
#include <stdio.h>
Packit Service 99d393
#include <stdlib.h>
Packit Service 99d393
Packit Service 99d393
#ifdef __FreeBSD__
Packit Service 99d393
#include <floatingpoint.h>
Packit Service 99d393
#endif
Packit Service 99d393
Packit Service 99d393
#if PY_MAJOR_VERSION < 3
Packit Service 99d393
# define MODINIT(name)  init ## name
Packit Service 99d393
#else
Packit Service 99d393
# define MODINIT(name)  PyInit_ ## name
Packit Service 99d393
#endif
Packit Service 99d393
""")
Packit Service 99d393
Packit Service 99d393
for name in modules:
Packit Service 99d393
    print("PyMODINIT_FUNC MODINIT(%s) (void);" % name)
Packit Service 99d393
Packit Service 99d393
print("""
Packit Service 99d393
static struct _inittab inittab[] = {""")
Packit Service 99d393
Packit Service 99d393
for name in modules:
Packit Service 99d393
    print('    {"%(name)s", MODINIT(%(name)s)},' % {'name' : name})
Packit Service 99d393
Packit Service 99d393
print("""    {NULL, NULL}
Packit Service 99d393
};
Packit Service 99d393
""", end=' ')
Packit Service 99d393
Packit Service 99d393
if not options.pymain:
Packit Service 99d393
    print("\nextern int __pyx_module_is_main_%s;" % modules[0])
Packit Service 99d393
Packit Service 99d393
print("""
Packit Service 99d393
#if PY_MAJOR_VERSION < 3
Packit Service 99d393
int main(int argc, char** argv) {
Packit Service 99d393
#elif defined(WIN32) || defined(MS_WINDOWS)
Packit Service 99d393
int wmain(int argc, wchar_t **argv) {
Packit Service 99d393
#else
Packit Service 99d393
static int python_main(int argc, wchar_t **argv) {
Packit Service 99d393
#endif
Packit Service 99d393
""", end=' ')
Packit Service 99d393
if not options.pymain:
Packit Service 99d393
    print("""\
Packit Service 99d393
    PyObject *m = NULL;
Packit Service 99d393
    int r = 0;
Packit Service 99d393
""", end=' ')
Packit Service 99d393
print("""\
Packit Service 99d393
    /* 754 requires that FP exceptions run in "no stop" mode by default,
Packit Service 99d393
     * and until C vendors implement C99's ways to control FP exceptions,
Packit Service 99d393
     * Python requires non-stop mode.  Alas, some platforms enable FP
Packit Service 99d393
     * exceptions by default.  Here we disable them.
Packit Service 99d393
     */
Packit Service 99d393
#ifdef __FreeBSD__
Packit Service 99d393
    fp_except_t m;
Packit Service 99d393
Packit Service 99d393
    m = fpgetmask();
Packit Service 99d393
    fpsetmask(m & ~FP_X_OFL);
Packit Service 99d393
#endif
Packit Service 99d393
    if (PyImport_ExtendInittab(inittab)) {
Packit Service 99d393
        fprintf(stderr, "No memory\\n");
Packit Service 99d393
        exit(1);
Packit Service 99d393
    }
Packit Service 99d393
""", end=' ')
Packit Service 99d393
if options.pymain:
Packit Service 99d393
    print("""\
Packit Service 99d393
    return Py_Main(argc, argv);
Packit Service 99d393
}
Packit Service 99d393
""")
Packit Service 99d393
else:
Packit Service 99d393
    print("""\
Packit Service 99d393
    Py_SetProgramName(argv[0]);
Packit Service 99d393
    Py_Initialize();
Packit Service 99d393
    PySys_SetArgv(argc, argv);
Packit Service 99d393
    __pyx_module_is_main_%(main)s = 1;
Packit Service 99d393
    m = PyImport_ImportModule(inittab[0].name);
Packit Service 99d393
    if (!m) {
Packit Service 99d393
        r = 1;
Packit Service 99d393
        PyErr_Print(); /* This exits with the right code if SystemExit. */
Packit Service 99d393
#if PY_MAJOR_VERSION < 3
Packit Service 99d393
        if (Py_FlushLine())
Packit Service 99d393
            PyErr_Clear();
Packit Service 99d393
#endif
Packit Service 99d393
    }
Packit Service 99d393
    Py_XDECREF(m);
Packit Service 99d393
    Py_Finalize();
Packit Service 99d393
    return r;
Packit Service 99d393
}
Packit Service 99d393
""" % {'main' : modules[0]}, end=' ')
Packit Service 99d393
Packit Service 99d393
print(r"""
Packit Service 99d393
#if PY_MAJOR_VERSION >= 3 && !defined(WIN32) && !defined(MS_WINDOWS)
Packit Service 99d393
static wchar_t*
Packit Service 99d393
char2wchar(char* arg)
Packit Service 99d393
{
Packit Service 99d393
        wchar_t *res;
Packit Service 99d393
#ifdef HAVE_BROKEN_MBSTOWCS
Packit Service 99d393
        /* Some platforms have a broken implementation of
Packit Service 99d393
         * mbstowcs which does not count the characters that
Packit Service 99d393
         * would result from conversion.  Use an upper bound.
Packit Service 99d393
         */
Packit Service 99d393
        size_t argsize = strlen(arg);
Packit Service 99d393
#else
Packit Service 99d393
        size_t argsize = mbstowcs(NULL, arg, 0);
Packit Service 99d393
#endif
Packit Service 99d393
        size_t count;
Packit Service 99d393
        unsigned char *in;
Packit Service 99d393
        wchar_t *out;
Packit Service 99d393
#ifdef HAVE_MBRTOWC
Packit Service 99d393
        mbstate_t mbs;
Packit Service 99d393
#endif
Packit Service 99d393
        if (argsize != (size_t)-1) {
Packit Service 99d393
                res = (wchar_t *)malloc((argsize+1)*sizeof(wchar_t));
Packit Service 99d393
                if (!res)
Packit Service 99d393
                        goto oom;
Packit Service 99d393
                count = mbstowcs(res, arg, argsize+1);
Packit Service 99d393
                if (count != (size_t)-1) {
Packit Service 99d393
                        wchar_t *tmp;
Packit Service 99d393
                        /* Only use the result if it contains no
Packit Service 99d393
                           surrogate characters. */
Packit Service 99d393
                        for (tmp = res; *tmp != 0 &&
Packit Service 99d393
                                     (*tmp < 0xd800 || *tmp > 0xdfff); tmp++)
Packit Service 99d393
                                ;
Packit Service 99d393
                        if (*tmp == 0)
Packit Service 99d393
                                return res;
Packit Service 99d393
                }
Packit Service 99d393
                free(res);
Packit Service 99d393
        }
Packit Service 99d393
        /* Conversion failed. Fall back to escaping with surrogateescape. */
Packit Service 99d393
#ifdef HAVE_MBRTOWC
Packit Service 99d393
        /* Try conversion with mbrtwoc (C99), and escape non-decodable bytes. */
Packit Service 99d393
Packit Service 99d393
        /* Overallocate; as multi-byte characters are in the argument, the
Packit Service 99d393
           actual output could use less memory. */
Packit Service 99d393
        argsize = strlen(arg) + 1;
Packit Service 99d393
        res = malloc(argsize*sizeof(wchar_t));
Packit Service 99d393
        if (!res) goto oom;
Packit Service 99d393
        in = (unsigned char*)arg;
Packit Service 99d393
        out = res;
Packit Service 99d393
        memset(&mbs, 0, sizeof mbs);
Packit Service 99d393
        while (argsize) {
Packit Service 99d393
                size_t converted = mbrtowc(out, (char*)in, argsize, &mbs);
Packit Service 99d393
                if (converted == 0)
Packit Service 99d393
                        /* Reached end of string; null char stored. */
Packit Service 99d393
                        break;
Packit Service 99d393
                if (converted == (size_t)-2) {
Packit Service 99d393
                        /* Incomplete character. This should never happen,
Packit Service 99d393
                           since we provide everything that we have -
Packit Service 99d393
                           unless there is a bug in the C library, or I
Packit Service 99d393
                           misunderstood how mbrtowc works. */
Packit Service 99d393
                        fprintf(stderr, "unexpected mbrtowc result -2\n");
Packit Service 99d393
                        return NULL;
Packit Service 99d393
                }
Packit Service 99d393
                if (converted == (size_t)-1) {
Packit Service 99d393
                        /* Conversion error. Escape as UTF-8b, and start over
Packit Service 99d393
                           in the initial shift state. */
Packit Service 99d393
                        *out++ = 0xdc00 + *in++;
Packit Service 99d393
                        argsize--;
Packit Service 99d393
                        memset(&mbs, 0, sizeof mbs);
Packit Service 99d393
                        continue;
Packit Service 99d393
                }
Packit Service 99d393
                if (*out >= 0xd800 && *out <= 0xdfff) {
Packit Service 99d393
                        /* Surrogate character.  Escape the original
Packit Service 99d393
                           byte sequence with surrogateescape. */
Packit Service 99d393
                        argsize -= converted;
Packit Service 99d393
                        while (converted--)
Packit Service 99d393
                                *out++ = 0xdc00 + *in++;
Packit Service 99d393
                        continue;
Packit Service 99d393
                }
Packit Service 99d393
                /* successfully converted some bytes */
Packit Service 99d393
                in += converted;
Packit Service 99d393
                argsize -= converted;
Packit Service 99d393
                out++;
Packit Service 99d393
        }
Packit Service 99d393
#else
Packit Service 99d393
        /* Cannot use C locale for escaping; manually escape as if charset
Packit Service 99d393
           is ASCII (i.e. escape all bytes > 128. This will still roundtrip
Packit Service 99d393
           correctly in the locale's charset, which must be an ASCII superset. */
Packit Service 99d393
        res = malloc((strlen(arg)+1)*sizeof(wchar_t));
Packit Service 99d393
        if (!res) goto oom;
Packit Service 99d393
        in = (unsigned char*)arg;
Packit Service 99d393
        out = res;
Packit Service 99d393
        while(*in)
Packit Service 99d393
                if(*in < 128)
Packit Service 99d393
                        *out++ = *in++;
Packit Service 99d393
                else
Packit Service 99d393
                        *out++ = 0xdc00 + *in++;
Packit Service 99d393
        *out = 0;
Packit Service 99d393
#endif
Packit Service 99d393
        return res;
Packit Service 99d393
oom:
Packit Service 99d393
        fprintf(stderr, "out of memory\n");
Packit Service 99d393
        return NULL;
Packit Service 99d393
}
Packit Service 99d393
Packit Service 99d393
int
Packit Service 99d393
main(int argc, char **argv)
Packit Service 99d393
{
Packit Service 99d393
        wchar_t **argv_copy = (wchar_t **)malloc(sizeof(wchar_t*)*argc);
Packit Service 99d393
        /* We need a second copies, as Python might modify the first one. */
Packit Service 99d393
        wchar_t **argv_copy2 = (wchar_t **)malloc(sizeof(wchar_t*)*argc);
Packit Service 99d393
        int i, res;
Packit Service 99d393
        char *oldloc;
Packit Service 99d393
        if (!argv_copy || !argv_copy2) {
Packit Service 99d393
                fprintf(stderr, "out of memory\n");
Packit Service 99d393
                return 1;
Packit Service 99d393
        }
Packit Service 99d393
        oldloc = strdup(setlocale(LC_ALL, NULL));
Packit Service 99d393
        setlocale(LC_ALL, "");
Packit Service 99d393
        for (i = 0; i < argc; i++) {
Packit Service 99d393
                argv_copy2[i] = argv_copy[i] = char2wchar(argv[i]);
Packit Service 99d393
                if (!argv_copy[i])
Packit Service 99d393
                        return 1;
Packit Service 99d393
        }
Packit Service 99d393
        setlocale(LC_ALL, oldloc);
Packit Service 99d393
        free(oldloc);
Packit Service 99d393
        res = python_main(argc, argv_copy);
Packit Service 99d393
        for (i = 0; i < argc; i++) {
Packit Service 99d393
                free(argv_copy2[i]);
Packit Service 99d393
        }
Packit Service 99d393
        free(argv_copy);
Packit Service 99d393
        free(argv_copy2);
Packit Service 99d393
        return res;
Packit Service 99d393
}
Packit Service 99d393
#endif""")