applied fix by haoyu for bug #543
[cython.git] / Cython / Compiler / ModuleNode.py
index 85b0b1789089c4a1e798d9d627ecb9f89d884a29..143ccbfbbc02c6e913fbf5ad5187881a84893e17 100644 (file)
@@ -227,7 +227,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         h_code.putln("%s DL_IMPORT(PyTypeObject) %s;" % (
             Naming.extern_c_macro,
             type.typeobj_cname))
-        #self.generate_obj_struct_definition(type, h_code)
     
     def generate_cclass_include_code(self, type, i_code):
         i_code.putln("cdef extern class %s.%s:" % (
@@ -393,9 +392,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                     elif type.is_enum:
                         self.generate_enum_definition(entry, code)
                     elif type.is_extension_type and entry not in vtabslot_entries:
-                        self.generate_obj_struct_definition(type, code)
+                        self.generate_objstruct_definition(type, code)
         for entry in vtabslot_list:
-            self.generate_obj_struct_definition(entry.type, code)
+            self.generate_objstruct_definition(entry.type, code)
         for entry in vtab_list:
             self.generate_typeobject_predeclaration(entry, code)
             self.generate_exttype_vtable_struct(entry, code)
@@ -412,7 +411,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         for module in modules:
             defined_here = module is env
             modulecode.putln("/* Module declarations from %s */" %
-                       module.qualified_name.encode("ASCII", "ignore"))
+                             module.qualified_name)
             self.generate_global_declarations(module, modulecode, defined_here)
             self.generate_cfunction_predeclarations(module, modulecode, defined_here)
 
@@ -429,12 +428,34 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code.globalstate["end"].putln("#endif /* Py_PYTHON_H */")
         
         code.put("""
-#ifndef PY_LONG_LONG
-  #define PY_LONG_LONG LONG_LONG
+#include <stddef.h> /* For offsetof */
+#ifndef offsetof
+#define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
+#endif
+
+#if !defined(WIN32) && !defined(MS_WINDOWS)
+  #ifndef __stdcall
+    #define __stdcall
+  #endif
+  #ifndef __cdecl
+    #define __cdecl
+  #endif
+  #ifndef __fastcall
+    #define __fastcall
+  #endif
+#endif
+
+#ifndef DL_IMPORT
+  #define DL_IMPORT(t) t
 #endif
 #ifndef DL_EXPORT
   #define DL_EXPORT(t) t
 #endif
+
+#ifndef PY_LONG_LONG
+  #define PY_LONG_LONG LONG_LONG
+#endif
+
 #if PY_VERSION_HEX < 0x02040000
   #define METH_COEXIST 0
   #define PyDict_CheckExact(op) (Py_TYPE(op) == &PyDict_Type)
@@ -504,11 +525,29 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
 
 #if PY_MAJOR_VERSION >= 3
   #define PyBaseString_Type            PyUnicode_Type
+  #define PyStringObject               PyUnicodeObject
   #define PyString_Type                PyUnicode_Type
+  #define PyString_Check               PyUnicode_Check
   #define PyString_CheckExact          PyUnicode_CheckExact
-#else
+#endif
+
+#if PY_VERSION_HEX < 0x02060000
+  #define PyBytesObject                PyStringObject
   #define PyBytes_Type                 PyString_Type
+  #define PyBytes_Check                PyString_Check
   #define PyBytes_CheckExact           PyString_CheckExact
+  #define PyBytes_FromString           PyString_FromString
+  #define PyBytes_FromStringAndSize    PyString_FromStringAndSize
+  #define PyBytes_FromFormat           PyString_FromFormat
+  #define PyBytes_DecodeEscape         PyString_DecodeEscape
+  #define PyBytes_AsString             PyString_AsString
+  #define PyBytes_AsStringAndSize      PyString_AsStringAndSize
+  #define PyBytes_Size                 PyString_Size
+  #define PyBytes_AS_STRING            PyString_AS_STRING
+  #define PyBytes_GET_SIZE             PyString_GET_SIZE
+  #define PyBytes_Repr                 PyString_Repr
+  #define PyBytes_Concat               PyString_Concat
+  #define PyBytes_ConcatAndDel         PyString_ConcatAndDel
 #endif
 
 #if PY_MAJOR_VERSION >= 3
@@ -525,6 +564,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
   #define PyInt_AsSsize_t              PyLong_AsSsize_t
   #define PyInt_AsUnsignedLongMask     PyLong_AsUnsignedLongMask
   #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask
+#endif
+""")
+
+        code.put("""
+#if PY_MAJOR_VERSION >= 3
   #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
   #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
 #else
@@ -535,25 +579,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         else:
             code.putln("  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_Divide(x,y)")
             code.putln("  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceDivide(x,y)")
-        code.put("""
-#endif
+        code.putln("#endif")
 
+        code.put("""
 #if PY_MAJOR_VERSION >= 3
-  #define PyMethod_New(func, self, klass) PyInstanceMethod_New(func)
-#endif
-
-#if !defined(WIN32) && !defined(MS_WINDOWS)
-  #ifndef __stdcall
-    #define __stdcall
-  #endif
-  #ifndef __cdecl
-    #define __cdecl
-  #endif
-  #ifndef __fastcall
-    #define __fastcall
-  #endif
-#else
-  #define _USE_MATH_DEFINES
+  #define PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : PyInstanceMethod_New(func))
 #endif
 
 #if PY_VERSION_HEX < 0x02050000
@@ -575,7 +605,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
 #endif
 """)
 
+        code.putln("")
         self.generate_extern_c_macro_definition(code)
+        code.putln("")
+        code.putln("#if defined(WIN32) || defined(MS_WINDOWS)")
+        code.putln("#define _USE_MATH_DEFINES")
+        code.putln("#endif")
         code.putln("#include <math.h>")
         code.putln("#define %s" % Naming.api_guard_prefix + self.api_name(env))
         self.generate_includes(env, cimported_modules, code)
@@ -617,11 +652,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
     def generate_includes(self, env, cimported_modules, code):
         includes = []
         for filename in env.include_files:
-            # fake decoding of filenames to their original byte sequence
-            if filename[0] == '<' and filename[-1] == '>':
-                code.putln('#include %s' % filename)
+            byte_decoded_filenname = str(filename)
+            if byte_decoded_filenname[0] == '<' and byte_decoded_filenname[-1] == '>':
+                code.putln('#include %s' % byte_decoded_filenname)
             else:
-                code.putln('#include "%s"' % filename)
+                code.putln('#include "%s"' % byte_decoded_filenname)
     
     def generate_filename_table(self, code):
         code.putln("")
@@ -654,7 +689,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 elif type.is_enum:
                     self.generate_enum_definition(entry, code)
                 elif type.is_extension_type:
-                    self.generate_obj_struct_definition(type, code)
+                    self.generate_objstruct_definition(type, code)
         
     def generate_gcc33_hack(self, env, code):
         # Workaround for spurious warning generation in gcc 3.3
@@ -800,7 +835,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 type.vtabstruct_cname,
                 type.vtabptr_cname))
     
-    def generate_obj_struct_definition(self, type, code):
+    def generate_objstruct_definition(self, type, code):
         code.mark_pos(type.pos)
         # Generate object struct definition for an
         # extension type.
@@ -904,7 +939,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                         self.generate_descr_set_function(scope, code)
                     self.generate_property_accessors(scope, code)
                     self.generate_method_table(scope, code)
-                    self.generate_member_table(scope, code)
                     self.generate_getset_table(scope, code)
                     self.generate_typeobj_definition(full_module_name, entry, code)
     
@@ -1507,7 +1541,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         if type.typedef_flag:
             objstruct = type.objstruct_cname
         else:
-            #objstruct = "struct %s" % scope.parent_type.objstruct_cname
             objstruct = "struct %s" % type.objstruct_cname
         code.putln(
             "sizeof(%s), /*tp_basicsize*/" %
@@ -1522,7 +1555,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
     def generate_method_table(self, env, code):
         code.putln("")
         code.putln(
-            "static struct PyMethodDef %s[] = {" % 
+            "static PyMethodDef %s[] = {" % 
                 env.method_table_cname)
         for entry in env.pyfunc_entries:
             code.put_pymethoddef(entry, ",")
@@ -1531,34 +1564,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code.putln(
             "};")
     
-    def generate_member_table(self, env, code):
-        #print "ModuleNode.generate_member_table: scope =", env ###
-        if env.public_attr_entries:
-            code.putln("")
-            code.putln(
-                "static struct PyMemberDef %s[] = {" %
-                    env.member_table_cname)
-            type = env.parent_type
-            if type.typedef_flag:
-                objstruct = type.objstruct_cname
-            else:
-                objstruct = "struct %s" % type.objstruct_cname
-            for entry in env.public_attr_entries:
-                type_code = entry.type.pymemberdef_typecode
-                if entry.visibility == 'readonly':
-                    flags = "READONLY"
-                else:
-                    flags = "0"
-                code.putln('{(char *)"%s", %s, %s, %s, 0},' % (
-                    entry.name,
-                    type_code,
-                    "offsetof(%s, %s)" % (objstruct, entry.cname),
-                    flags))
-            code.putln(
-                    "{0, 0, 0, 0, 0}")
-            code.putln(
-                "};")
-    
     def generate_getset_table(self, env, code):
         if env.property_entries:
             code.putln("")
@@ -1672,12 +1677,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code.putln("#endif")
 
         code.putln("%s = PyTuple_New(0); %s" % (Naming.empty_tuple, code.error_goto_if_null(Naming.empty_tuple, self.pos)));
-        code.putln("#if PY_MAJOR_VERSION < 3");
-        code.putln("%s = PyString_FromStringAndSize(\"\", 0); %s" % (Naming.empty_bytes, code.error_goto_if_null(Naming.empty_bytes, self.pos)));
-        code.putln("#else");
         code.putln("%s = PyBytes_FromStringAndSize(\"\", 0); %s" % (Naming.empty_bytes, code.error_goto_if_null(Naming.empty_bytes, self.pos)));
-        code.putln("#endif");
-        
+
         code.putln("#ifdef %s_USED" % Naming.binding_cfunc)
         code.putln("if (%s_init() < 0) %s" % (Naming.binding_cfunc, code.error_goto(self.pos)))
         code.putln("#endif")
@@ -1770,7 +1771,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         if not Options.generate_cleanup_code:
             return
         code.globalstate.use_utility_code(register_cleanup_utility_code)
-        code.putln('static PyObject* %s(PyObject *self, PyObject *unused) {' % Naming.cleanup_cname)
+        code.putln('static PyObject *%s(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED PyObject *unused) {' % 
+                   Naming.cleanup_cname)
         if Options.generate_cleanup_code >= 2:
             code.putln("/*--- Global cleanup code ---*/")
             rev_entries = list(env.var_entries)
@@ -2194,7 +2196,11 @@ static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class
         PyOS_snprintf(warning, sizeof(warning), 
             "%s.%s size changed, may indicate binary incompatibility",
             module_name, class_name);
+        #if PY_VERSION_HEX < 0x02050000
+        PyErr_Warn(NULL, warning);
+        #else
         PyErr_WarnEx(NULL, warning, 0);
+        #endif
     }
     else if (((PyTypeObject *)result)->tp_basicsize != size) {
         PyErr_Format(PyExc_ValueError, 
@@ -2237,10 +2243,10 @@ static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *s
             goto bad;
     }
     tmp.fp = f;
-#if PY_VERSION_HEX < 0x03010000
-    cobj = PyCObject_FromVoidPtrAndDesc(tmp.p, (void *)sig, 0);
-#else
+#if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION==3&&PY_MINOR_VERSION==0)
     cobj = PyCapsule_New(tmp.p, sig, 0);
+#else
+    cobj = PyCObject_FromVoidPtrAndDesc(tmp.p, (void *)sig, 0);
 #endif
     if (!cobj)
         goto bad;
@@ -2271,9 +2277,6 @@ static int __Pyx_ImportFunction(PyObject *module, const char *funcname, void (**
         void (*fp)(void);
         void *p;
     } tmp;
-#if PY_VERSION_HEX < 0x03010000
-    const char *desc, *s1, *s2;
-#endif
 
     d = PyObject_GetAttrString(module, (char *)"%(API)s");
     if (!d)
@@ -2285,7 +2288,16 @@ static int __Pyx_ImportFunction(PyObject *module, const char *funcname, void (**
                 PyModule_GetName(module), funcname);
         goto bad;
     }
-#if PY_VERSION_HEX < 0x03010000
+#if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION==3&&PY_MINOR_VERSION==0)
+    if (!PyCapsule_IsValid(cobj, sig)) {
+        PyErr_Format(PyExc_TypeError,
+            "C function %%s.%%s has wrong signature (expected %%s, got %%s)",
+             PyModule_GetName(module), funcname, sig, PyCapsule_GetName(cobj));
+        goto bad;
+    }
+    tmp.p = PyCapsule_GetPointer(cobj, sig);
+#else
+    {const char *desc, *s1, *s2;
     desc = (const char *)PyCObject_GetDesc(cobj);
     if (!desc)
         goto bad;
@@ -2297,15 +2309,7 @@ static int __Pyx_ImportFunction(PyObject *module, const char *funcname, void (**
              PyModule_GetName(module), funcname, sig, desc);
         goto bad;
     }
-    tmp.p = PyCObject_AsVoidPtr(cobj);
-#else
-    if (!PyCapsule_IsValid(cobj, sig)) {
-        PyErr_Format(PyExc_TypeError,
-            "C function %%s.%%s has wrong signature (expected %%s, got %%s)",
-             PyModule_GetName(module), funcname, sig, PyCapsule_GetName(cobj));
-        goto bad;
-    }
-    tmp.p = PyCapsule_GetPointer(cobj, sig);
+    tmp.p = PyCObject_AsVoidPtr(cobj);}
 #endif
     *f = tmp.fp;
     if (!(*f))
@@ -2325,9 +2329,9 @@ bad:
 register_cleanup_utility_code = UtilityCode(
 proto = """
 static int __Pyx_RegisterCleanup(void); /*proto*/
-static PyObject* __pyx_module_cleanup(PyObject *self, PyObject *unused); /*proto*/
-static PyMethodDef cleanup_def = {__Pyx_NAMESTR("__cleanup"), (PyCFunction)&__pyx_module_cleanup, METH_NOARGS, 0};
-""",
+static PyObject* %(module_cleanup)s(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyMethodDef cleanup_def = {__Pyx_NAMESTR("__cleanup"), (PyCFunction)&%(module_cleanup)s, METH_NOARGS, 0};
+""" % {'module_cleanup': Naming.cleanup_cname},
 impl = """
 static int __Pyx_RegisterCleanup(void) {
     /* Don't use Py_AtExit because that has a 32-call limit 
@@ -2444,6 +2448,9 @@ static int %(IMPORT_STAR)s(PyObject* m) {
     char* s;
     PyObject *locals = 0;
     PyObject *list = 0;
+#if PY_MAJOR_VERSION >= 3
+    PyObject *utf8_name = 0;
+#endif
     PyObject *name;
     PyObject *item;
     
@@ -2454,19 +2461,26 @@ static int %(IMPORT_STAR)s(PyObject* m) {
     for(i=0; i<PyList_GET_SIZE(list); i++) {
         name = PyTuple_GET_ITEM(PyList_GET_ITEM(list, i), 0);
         item = PyTuple_GET_ITEM(PyList_GET_ITEM(list, i), 1);
-#if PY_MAJOR_VERSION < 3
-        s = PyString_AsString(name);
+#if PY_MAJOR_VERSION >= 3
+        utf8_name = PyUnicode_AsUTF8String(name);
+        if (!utf8_name) goto bad;
+        s = PyBytes_AS_STRING(utf8_name);
+        if (%(IMPORT_STAR_SET)s(item, name, s) < 0) goto bad;
+        Py_DECREF(utf8_name); utf8_name = 0;
 #else
-        s = PyUnicode_AsString(name);
-#endif
+        s = PyString_AsString(name);
         if (!s) goto bad;
         if (%(IMPORT_STAR_SET)s(item, name, s) < 0) goto bad;
+#endif
     }
     ret = 0;
     
 bad:
     Py_XDECREF(locals);
     Py_XDECREF(list);
+#if PY_MAJOR_VERSION >= 3
+    Py_XDECREF(utf8_name);
+#endif
     return ret;
 }
 """ % {'IMPORT_STAR'     : Naming.import_star,