guard against incorrect values for PYLONG_BITS_IN_DIGIT that do not match CPython's
authorStefan Behnel <stefan_ml@behnel.de>
Sat, 9 Mar 2013 19:27:36 +0000 (20:27 +0100)
committerStefan Behnel <stefan_ml@behnel.de>
Sat, 9 Mar 2013 19:27:36 +0000 (20:27 +0100)
Cython/Compiler/ModuleNode.py
Cython/Compiler/PyrexTypes.py

index 5021754..cc29143 100644 (file)
@@ -506,6 +506,27 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code.putln("/* Generated by Cython %s */" % Version.watermark)
         code.putln("")
         code.putln("#define PY_SSIZE_T_CLEAN")
+
+        # sizeof(PyLongObject.ob_digit[0]) may have been determined dynamically
+        # at compile time in CPython, in which case we can't know the correct
+        # storage size for an installed system.  We can rely on it only if
+        # pyconfig.h defines it statically, i.e. if it was set by "configure".
+        # Once we include "Python.h", it will come up with its own idea about
+        # a suitable value, which may or may not match the real one.
+        code.putln("#ifndef CYTHON_USE_PYLONG_INTERNALS")
+        code.putln("#ifdef PYLONG_BITS_IN_DIGIT")
+        # assume it's an incorrect left-over
+        code.putln("#define CYTHON_USE_PYLONG_INTERNALS 0")
+        code.putln("#else")
+        code.putln('#include "pyconfig.h"')
+        code.putln("#ifdef PYLONG_BITS_IN_DIGIT")
+        code.putln("#define CYTHON_USE_PYLONG_INTERNALS 1")
+        code.putln("#else")
+        code.putln("#define CYTHON_USE_PYLONG_INTERNALS 0")
+        code.putln("#endif")
+        code.putln("#endif")
+        code.putln("#endif")
+
         for filename in env.python_include_files:
             code.putln('#include "%s"' % filename)
         code.putln("#ifndef Py_PYTHON_H")
index ab6e3a9..10cfaf4 100755 (executable)
@@ -1386,8 +1386,10 @@ static CYTHON_INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject *)
 """,
 impl="""
 #if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
 #include "longintrepr.h"
 #endif
+#endif
 static CYTHON_INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject* x) {
     const %(type)s neg_one = (%(type)s)-1, const_zero = 0;
     const int is_unsigned = neg_one > const_zero;
@@ -1405,6 +1407,7 @@ static CYTHON_INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject* x
     if (likely(PyLong_Check(x))) {
         if (is_unsigned) {
 #if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
             if (sizeof(digit) <= sizeof(%(type)s)) {
                 switch (Py_SIZE(x)) {
                     case  0: return 0;
@@ -1412,6 +1415,7 @@ static CYTHON_INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject* x
                 }
             }
 #endif
+#endif
             if (unlikely(Py_SIZE(x) < 0)) {
                 PyErr_SetString(PyExc_OverflowError,
                                 "can't convert negative value to %(type)s");
@@ -1420,6 +1424,7 @@ static CYTHON_INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject* x
             return (%(type)s)PyLong_AsUnsigned%(TypeName)s(x);
         } else {
 #if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
             if (sizeof(digit) <= sizeof(%(type)s)) {
                 switch (Py_SIZE(x)) {
                     case  0: return 0;
@@ -1428,6 +1433,7 @@ static CYTHON_INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject* x
                 }
             }
 #endif
+#endif
             return (%(type)s)PyLong_As%(TypeName)s(x);
         }
     } else {