applied fix by haoyu for bug #543
[cython.git] / Cython / Compiler / ModuleNode.py
index 641c080582d0bf2d2b9a83a0f4dc2c39f71ca97f..143ccbfbbc02c6e913fbf5ad5187881a84893e17 100644 (file)
@@ -270,11 +270,14 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code = globalstate['all_the_rest']
 
         self.generate_cached_builtins_decls(env, code)
+        # generate lambda function definitions
+        for node in env.lambda_defs:
+            node.generate_function_definitions(env, code)
+        # generate normal function definitions
         self.body.generate_function_definitions(env, code)
         code.mark_pos(None)
         self.generate_typeobj_definitions(env, code)
         self.generate_method_table(env, code)
-        self.generate_filename_init_prototype(code)
         if env.has_import_star:
             self.generate_import_star(env, code)
         self.generate_pymoduledef_struct(env, code)
@@ -580,7 +583,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
 
         code.put("""
 #if PY_MAJOR_VERSION >= 3
-  #define PyMethod_New(func, self, klass) PyInstanceMethod_New(func)
+  #define PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : PyInstanceMethod_New(func))
 #endif
 
 #if PY_VERSION_HEX < 0x02050000
@@ -631,7 +634,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code.putln('static int %s = 0;' % Naming.clineno_cname)
         code.putln('static const char * %s= %s;' % (Naming.cfilenm_cname, Naming.file_c_macro))
         code.putln('static const char *%s;' % Naming.filename_cname)
-        code.putln('static const char **%s;' % Naming.filetable_cname)
 
         # XXX this is a mess
         for utility_code in PyrexTypes.c_int_from_py_function.specialize_list:
@@ -658,13 +660,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
     
     def generate_filename_table(self, code):
         code.putln("")
-        code.putln("static const char *%s[] = {" % Naming.filenames_cname)
+        code.putln("static const char *%s[] = {" % Naming.filetable_cname)
         if code.globalstate.filename_list:
             for source_desc in code.globalstate.filename_list:
                 filename = os.path.basename(source_desc.get_filenametable_entry())
                 escaped_filename = filename.replace("\\", "\\\\").replace('"', r'\"')
-                code.putln('"%s",' % 
-                    escaped_filename)
+                code.putln('"%s",' % escaped_filename)
         else:
             # Some C compilers don't like an empty array
             code.putln("0")
@@ -1003,7 +1004,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 type.vtabslot_cname,
                 struct_type_cast, type.vtabptr_cname))
         for entry in py_attrs:
-            if entry.name == "__weakref__":
+            if scope.is_internal or entry.name == "__weakref__":
+                # internal classes do not need None inits
                 code.putln("p->%s = 0;" % entry.cname)
             else:
                 code.put_init_var_to_py_none(entry, "p->%s", nanny=False)
@@ -1584,10 +1586,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             code.putln(
                 "};")
 
-    def generate_filename_init_prototype(self, code):
-        code.putln("");
-        code.putln("static void %s(void); /*proto*/" % Naming.fileinit_cname)
-        
     def generate_import_star(self, env, code):
         env.use_utility_code(streq_utility_code)
         code.putln()
@@ -1678,11 +1676,13 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code.putln("__pyx_refnanny = __Pyx_RefNanny->SetupContext(\"%s\", __LINE__, __FILE__);"% header3)
         code.putln("#endif")
 
-        self.generate_filename_init_call(code)
-
         code.putln("%s = PyTuple_New(0); %s" % (Naming.empty_tuple, code.error_goto_if_null(Naming.empty_tuple, self.pos)));
         code.putln("%s = PyBytes_FromStringAndSize(\"\", 0); %s" % (Naming.empty_bytes, code.error_goto_if_null(Naming.empty_bytes, self.pos)));
 
+        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")
+
         code.putln("/*--- Library function declarations ---*/")
         env.generate_library_function_declarations(code)
 
@@ -1771,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)
@@ -1815,9 +1816,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         module_is_main = "%s%s" % (Naming.module_is_main, self.full_module_name.replace('.', '__'))
         code.globalstate.use_utility_code(main_method.specialize(module_name=env.module_name, module_is_main=module_is_main))
 
-    def generate_filename_init_call(self, code):
-        code.putln("%s();" % Naming.fileinit_cname)
-
     def generate_pymoduledef_struct(self, env, code):
         if env.doc:
             doc = "__Pyx_DOCSTR(%s)" % code.get_string_const(env.doc)
@@ -2245,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;
@@ -2279,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)
@@ -2293,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;
@@ -2305,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))
@@ -2333,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 
@@ -2452,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;
     
@@ -2462,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,