From 8c10c8526c17f4931736afb8e13ef2d3176711af Mon Sep 17 00:00:00 2001 From: Mark Lodato Date: Sat, 24 Oct 2009 16:17:23 -0400 Subject: [PATCH] --embed mode: fix Py3, floating point on FreeBSD Incorporate the changes of cython_freeze: * fix when compiling on Python 3 (Issue #434) * fix floating point issues on FreeBSD --- Cython/Compiler/ModuleNode.py | 163 +++++++++++++++++++++++++++++++++- 1 file changed, 160 insertions(+), 3 deletions(-) diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index bb93e7b0..84efa23e 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -2510,13 +2510,30 @@ refnanny_utility_code = UtilityCode(proto=""" main_method = UtilityCode( impl = """ -#if PY_MAJOR_VERSION < 3 || (!defined(WIN32) && !defined(MS_WINDOWS)) +#ifdef __FreeBSD__ +#include +#endif + +#if PY_MAJOR_VERSION < 3 int main(int argc, char** argv) { -#else +#elif defined(WIN32) || defined(MS_WINDOWS) int wmain(int argc, wchar_t **argv) { +#else +static int __Pyx_main(int argc, wchar_t **argv) { #endif int r = 0; PyObject* m = NULL; + /* 754 requires that FP exceptions run in "no stop" mode by default, + * and until C vendors implement C99's ways to control FP exceptions, + * Python requires non-stop mode. Alas, some platforms enable FP + * exceptions by default. Here we disable them. + */ +#ifdef __FreeBSD__ + fp_except_t m; + + m = fpgetmask(); + fpsetmask(m & ~FP_X_OFL); +#endif Py_SetProgramName(argv[0]); Py_Initialize(); PySys_SetArgv(argc, argv); @@ -2524,17 +2541,157 @@ int wmain(int argc, wchar_t **argv) { #if PY_MAJOR_VERSION < 3 init%(module_name)s(); #else - m = PyInit_%(module_name)s(name); + m = PyInit_%(module_name)s(); #endif if (PyErr_Occurred() != NULL) { r = 1; PyErr_Print(); /* This exits with the right code if SystemExit. */ +#if PY_MAJOR_VERSION < 3 if (Py_FlushLine()) PyErr_Clear(); +#endif } Py_XDECREF(m); Py_Finalize(); return r; } + + +#if PY_MAJOR_VERSION >= 3 && !defined(WIN32) && !defined(MS_WINDOWS) +#include + +static wchar_t* +__Pyx_char2wchar(char* arg) +{ + wchar_t *res; +#ifdef HAVE_BROKEN_MBSTOWCS + /* Some platforms have a broken implementation of + * mbstowcs which does not count the characters that + * would result from conversion. Use an upper bound. + */ + size_t argsize = strlen(arg); +#else + size_t argsize = mbstowcs(NULL, arg, 0); +#endif + size_t count; + unsigned char *in; + wchar_t *out; +#ifdef HAVE_MBRTOWC + mbstate_t mbs; +#endif + if (argsize != (size_t)-1) { + res = (wchar_t *)PyMem_Malloc((argsize+1)*sizeof(wchar_t)); + if (!res) + goto oom; + count = mbstowcs(res, arg, argsize+1); + if (count != (size_t)-1) { + wchar_t *tmp; + /* Only use the result if it contains no + surrogate characters. */ + for (tmp = res; *tmp != 0 && + (*tmp < 0xd800 || *tmp > 0xdfff); tmp++) + ; + if (*tmp == 0) + return res; + } + PyMem_Free(res); + } + /* Conversion failed. Fall back to escaping with surrogateescape. */ +#ifdef HAVE_MBRTOWC + /* Try conversion with mbrtwoc (C99), and escape non-decodable bytes. */ + + /* Overallocate; as multi-byte characters are in the argument, the + actual output could use less memory. */ + argsize = strlen(arg) + 1; + res = PyMem_Malloc(argsize*sizeof(wchar_t)); + if (!res) goto oom; + in = (unsigned char*)arg; + out = res; + memset(&mbs, 0, sizeof mbs); + while (argsize) { + size_t converted = mbrtowc(out, (char*)in, argsize, &mbs); + if (converted == 0) + /* Reached end of string; null char stored. */ + break; + if (converted == (size_t)-2) { + /* Incomplete character. This should never happen, + since we provide everything that we have - + unless there is a bug in the C library, or I + misunderstood how mbrtowc works. */ + fprintf(stderr, "unexpected mbrtowc result -2\\n"); + return NULL; + } + if (converted == (size_t)-1) { + /* Conversion error. Escape as UTF-8b, and start over + in the initial shift state. */ + *out++ = 0xdc00 + *in++; + argsize--; + memset(&mbs, 0, sizeof mbs); + continue; + } + if (*out >= 0xd800 && *out <= 0xdfff) { + /* Surrogate character. Escape the original + byte sequence with surrogateescape. */ + argsize -= converted; + while (converted--) + *out++ = 0xdc00 + *in++; + continue; + } + /* successfully converted some bytes */ + in += converted; + argsize -= converted; + out++; + } +#else + /* Cannot use C locale for escaping; manually escape as if charset + is ASCII (i.e. escape all bytes > 128. This will still roundtrip + correctly in the locale's charset, which must be an ASCII superset. */ + res = PyMem_Malloc((strlen(arg)+1)*sizeof(wchar_t)); + if (!res) goto oom; + in = (unsigned char*)arg; + out = res; + while(*in) + if(*in < 128) + *out++ = *in++; + else + *out++ = 0xdc00 + *in++; + *out = 0; +#endif + return res; +oom: + fprintf(stderr, "out of memory\\n"); + return NULL; +} + +int +main(int argc, char **argv) +{ + wchar_t **argv_copy = (wchar_t **)PyMem_Malloc(sizeof(wchar_t*)*argc); + /* We need a second copies, as Python might modify the first one. */ + wchar_t **argv_copy2 = (wchar_t **)PyMem_Malloc(sizeof(wchar_t*)*argc); + int i, res; + char *oldloc; + if (!argv_copy || !argv_copy2) { + fprintf(stderr, "out of memory\\n"); + return 1; + } + oldloc = strdup(setlocale(LC_ALL, NULL)); + setlocale(LC_ALL, ""); + for (i = 0; i < argc; i++) { + argv_copy2[i] = argv_copy[i] = __Pyx_char2wchar(argv[i]); + if (!argv_copy[i]) + return 1; + } + setlocale(LC_ALL, oldloc); + free(oldloc); + res = __Pyx_main(argc, argv_copy); + for (i = 0; i < argc; i++) { + PyMem_Free(argv_copy2[i]); + } + PyMem_Free(argv_copy); + PyMem_Free(argv_copy2); + return res; +} +#endif """) packed_struct_utility_code = UtilityCode(proto=""" -- 2.26.2