From: Robert Bradshaw Date: Thu, 7 Jun 2007 02:22:57 +0000 (-0700) Subject: Pyrex Official version 0.9.5.1a X-Git-Tag: 0.9.6.14~29^2~181^2 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=5aab5520174a2810b68630f40d4876355648ca83;p=cython.git Pyrex Official version 0.9.5.1a --- diff --git a/Cython/Compiler/Code.py b/Cython/Compiler/Code.py index a9a79829..5158e3bc 100644 --- a/Cython/Compiler/Code.py +++ b/Cython/Compiler/Code.py @@ -22,8 +22,9 @@ class CCodeWriter: in_try_finally = 0 - def __init__(self, outfile_name): - self.f = open_new_file(outfile_name) + def __init__(self, f): + #self.f = open_new_file(outfile_name) + self.f = f self.level = 0 self.bol = 1 self.marker = None @@ -80,6 +81,7 @@ class CCodeWriter: def init_labels(self): self.label_counter = 0 + self.labels_used = {} self.return_label = self.new_label() self.new_error_label() self.continue_label = None @@ -134,9 +136,17 @@ class CCodeWriter: new_labels.append(old_label) self.set_all_labels(new_labels) return old_labels + + def use_label(self, lbl): + self.labels_used[lbl] = 1 def put_label(self, lbl): - self.putln("%s:;" % lbl) + if lbl in self.labels_used: + self.putln("%s:;" % lbl) + + def put_goto(self, lbl): + self.use_label(lbl) + self.putln("goto %s;" % lbl) def put_var_declarations(self, entries, static = 0, dll_linkage = None, definition = True): @@ -146,28 +156,23 @@ class CCodeWriter: def put_var_declaration(self, entry, static = 0, dll_linkage = None, definition = True): - #print "Code.put_var_declaration:", entry.name, "definition =", definition + #print "Code.put_var_declaration:", entry.name, "definition =", definition ### visibility = entry.visibility if visibility == 'private' and not definition: return + if not entry.used and visibility == "private": + return + storage_class = "" if visibility == 'extern': storage_class = Naming.extern_c_macro elif visibility == 'public': - if definition: - storage_class = "" - else: + if not definition: storage_class = Naming.extern_c_macro elif visibility == 'private': if static: storage_class = "static" - else: - storage_class = "" if storage_class: self.put("%s " % storage_class) - #if visibility == 'extern' or visibility == 'public' and not definition: - # self.put("%s " % Naming.extern_c_macro) - #elif static and visibility <> 'public': - # self.put("static ") if visibility <> 'public': dll_linkage = None self.put(entry.type.declaration_code(entry.cname, @@ -186,10 +191,6 @@ class CCodeWriter: def as_pyobject(self, cname, type): return typecast(py_object_type, type, cname) - #if type.is_extension_type and type.base_type: - # return "(PyObject *)" + cname - #else: - # return cname def put_incref(self, cname, type): self.putln("Py_INCREF(%s);" % self.as_pyobject(cname, type)) @@ -231,12 +232,13 @@ class CCodeWriter: self.putln("Py_XDECREF(%s); %s = 0;" % ( self.entry_as_pyobject(entry), entry.cname)) - def put_var_decrefs(self, entries): + def put_var_decrefs(self, entries, used_only = 0): for entry in entries: - if entry.xdecref_cleanup: - self.put_var_xdecref(entry) - else: - self.put_var_decref(entry) + if not used_only or entry.used: + if entry.xdecref_cleanup: + self.put_var_xdecref(entry) + else: + self.put_var_decref(entry) def put_var_xdecrefs(self, entries): for entry in entries: @@ -269,13 +271,15 @@ class CCodeWriter: term)) def error_goto(self, pos): + lbl = self.error_label + self.use_label(lbl) return "{%s = %s[%s]; %s = %s; goto %s;}" % ( Naming.filename_cname, Naming.filetable_cname, self.lookup_filename(pos[0]), Naming.lineno_cname, pos[1], - self.error_label) + lbl) def lookup_filename(self, filename): try: diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index d194335c..0456342b 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -8,7 +8,7 @@ from Errors import error, InternalError import Naming from Nodes import Node import PyrexTypes -from PyrexTypes import py_object_type, typecast +from PyrexTypes import py_object_type, c_long_type, typecast import Symtab import Options @@ -89,13 +89,23 @@ class ExprNode(Node): # - If a temporary was allocated, call release_temp on # all sub-expressions. # - # A default implementation of allocate_temps is - # provided which uses the following abstract method: + # allocate_target_temps + # - Call allocate_temps on sub-nodes and allocate any other + # temps used during assignment. + # - Fill in result_code with a C lvalue if needed. + # - If a rhs node is supplied, call release_temp on it. + # - Call release_temp on sub-nodes and release any other + # temps used during assignment. # - # calculate_result_code - # - Return a C code fragment evaluating to - # the result. This is only called when the - # result is not a temporary. + # calculate_result_code + # - Return a C code fragment evaluating to + # the result. This is only called when the + # result is not a temporary. + # + # target_code + # Called by the default implementation of allocate_target_temps. + # Should return a C lvalue for assigning to the node. The default + # implementation calls calculate_result_code. # # check_const # - Check that this node and its subnodes form a @@ -145,16 +155,6 @@ class ExprNode(Node): # - Generate code to perform the deletion. # - Call generate_disposal_code on all sub-expressions. # - # #result_as_extension_type ### OBSOLETE ### - # # Normally, the results of all nodes whose type - # # is a Python object, either generic or an extension - # # type, are returned as a generic Python object, so - # # that they can be passed directly to Python/C API - # # routines. This method is called to obtain the - # # result as the actual type of the node. It is only - # # called when the type is known to actually be an - # # extension type, and nodes whose result can never - # # be an extension type need not implement it. # is_sequence_constructor = 0 @@ -231,12 +231,12 @@ class ExprNode(Node): self.analyse_types(env) self.allocate_temps(env) - def analyse_target_expression(self, env): + def analyse_target_expression(self, env, rhs): # Convenience routine performing both the Type # Analysis and Temp Allocation phases for the LHS of # an assignment. self.analyse_target_types(env) - self.allocate_target_temps(env) + self.allocate_target_temps(env, rhs) def analyse_boolean_expression(self, env): # Analyse expression and coerce to a boolean. @@ -298,12 +298,15 @@ class ExprNode(Node): # a subnode. return self.is_temp - def allocate_target_temps(self, env): - # Perform allocate_temps for the LHS of an assignment. + def allocate_target_temps(self, env, rhs): + # Perform temp allocation for the LHS of an assignment. if debug_temp_alloc: print self, "Allocating target temps" self.allocate_subexpr_temps(env) self.result_code = self.target_code() + if rhs: + rhs.release_temp(env) + self.release_subexpr_temps(env) def allocate_temps(self, env, result = None): # Allocate temporary variables for this node and @@ -362,9 +365,9 @@ class ExprNode(Node): def calculate_result_code(self): self.not_implemented("calculate_result_code") - def release_target_temp(self, env): - # Release temporaries used by LHS of an assignment. - self.release_subexpr_temps(env) +# def release_target_temp(self, env): +# # Release temporaries used by LHS of an assignment. +# self.release_subexpr_temps(env) def release_temp(self, env): # If this node owns a temporary result, release it, @@ -463,7 +466,8 @@ class ExprNode(Node): if not src.type.is_pyobject: src = CoerceToPyTypeNode(src, env) if not src.type.subtype_of(dst_type): - src = PyTypeTestNode(src, dst_type, env) + if not isinstance(src, NoneNode): + src = PyTypeTestNode(src, dst_type, env) elif src.type.is_pyobject: src = CoerceFromPyTypeNode(dst_type, src, env) else: # neither src nor dst are py types @@ -576,7 +580,7 @@ class ConstNode(AtomicExprNode): class NullNode(ConstNode): type = PyrexTypes.c_null_ptr_type - value = "0" + value = "NULL" class CharNode(ConstNode): @@ -703,13 +707,14 @@ class NameNode(AtomicExprNode): def analyse_entry(self, env): self.check_identifier_kind() - self.type = self.entry.type - if self.entry.is_declared_generic: + entry = self.entry + self.type = entry.type + if entry.is_declared_generic: self.result_ctype = py_object_type - # Reference to C array turns into pointer to first element. - while self.type.is_array: - self.type = self.type.element_ptr_type() - if self.entry.is_pyglobal or self.entry.is_builtin: + ## Reference to C array turns into pointer to first element. + #while self.type.is_array: + # self.type = self.type.element_ptr_type() + if entry.is_pyglobal or entry.is_builtin: assert self.type.is_pyobject, "Python global or builtin not a Python object" self.is_temp = 1 if Options.intern_names: @@ -727,7 +732,9 @@ class NameNode(AtomicExprNode): self.type = PyrexTypes.error_type def check_identifier_kind(self): + #print "NameNode.check_identifier_kind:", self.entry.name ### entry = self.entry + entry.used = 1 if not (entry.is_const or entry.is_variable or entry.is_builtin or entry.is_cfunction): if self.entry.as_variable: @@ -1071,11 +1078,11 @@ class IndexNode(ExprNode): self.index.py_result(), rhs.py_result(), code.error_goto(self.pos))) - self.generate_subexpr_disposal_code(code) else: code.putln( "%s = %s;" % ( self.result_code, rhs.result_code)) + self.generate_subexpr_disposal_code(code) rhs.generate_disposal_code(code) def generate_deletion_code(self, code): @@ -1220,9 +1227,12 @@ class SimpleCallNode(ExprNode): function.obj = CloneNode(self.self) func_type = self.function_type() if func_type.is_pyobject: - self.arg_tuple = TupleNode(self.pos, args = self.args) + if self.args: + self.arg_tuple = TupleNode(self.pos, args = self.args) + self.arg_tuple.analyse_types(env) + else: + self.arg_tuple = None self.args = None - self.arg_tuple.analyse_types(env) self.type = py_object_type self.is_temp = 1 else: @@ -1309,11 +1319,15 @@ class SimpleCallNode(ExprNode): def generate_result_code(self, code): func_type = self.function_type() if func_type.is_pyobject: + if self.arg_tuple: + arg_code = self.arg_tuple.py_result() + else: + arg_code = "0" code.putln( "%s = PyObject_CallObject(%s, %s); if (!%s) %s" % ( self.result_code, self.function.py_result(), - self.arg_tuple.py_result(), + arg_code, self.result_code, code.error_goto(self.pos))) elif func_type.is_cfunction: @@ -1535,9 +1549,9 @@ class AttributeNode(ExprNode): self.analyse_attribute(env) if self.entry and self.entry.is_cmethod and not self.is_called: error(self.pos, "C method can only be called") - # Reference to C array turns into pointer to first element. - while self.type.is_array: - self.type = self.type.element_ptr_type() + ## Reference to C array turns into pointer to first element. + #while self.type.is_array: + # self.type = self.type.element_ptr_type() if self.is_py_attr: if not target: self.is_temp = 1 @@ -1568,6 +1582,8 @@ class AttributeNode(ExprNode): obj_type = PyrexTypes.error_type self.entry = entry if entry: + if obj_type.is_extension_type and entry.name == "__weakref__": + error(self.pos, "Illegal use of special attribute __weakref__") if entry.is_variable or entry.is_cmethod: self.type = entry.type self.member = entry.cname @@ -1662,7 +1678,6 @@ class AttributeNode(ExprNode): code.error_goto(self.pos))) rhs.generate_disposal_code(code) else: - #select_code = self.select_code() select_code = self.result_code if self.type.is_pyobject: rhs.make_owned_reference(code) @@ -1670,7 +1685,8 @@ class AttributeNode(ExprNode): code.putln( "%s = %s;" % ( select_code, - rhs.result_code)) + rhs.result_as(self.ctype()))) + #rhs.result_code)) rhs.generate_post_assignment_code(code) self.obj.generate_disposal_code(code) @@ -1704,6 +1720,7 @@ class SequenceNode(ExprNode): # Contains common code for performing sequence unpacking. # # args [ExprNode] + # iterator ExprNode # unpacked_items [ExprNode] or None # coerced_unpacked_items [ExprNode] or None @@ -1725,11 +1742,11 @@ class SequenceNode(ExprNode): self.is_temp = 1 def analyse_target_types(self, env): - self.unpacked_items = [] # PyTempNode(self.pos, env) + self.iterator = PyTempNode(self.pos, env) + self.unpacked_items = [] self.coerced_unpacked_items = [] for arg in self.args: arg.analyse_target_types(env) - #node = CloneNode(self.unpacked_item) unpacked_item = PyTempNode(self.pos, env) coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env) self.unpacked_items.append(unpacked_item) @@ -1737,27 +1754,39 @@ class SequenceNode(ExprNode): self.type = py_object_type env.use_utility_code(unpacking_utility_code) - def allocate_target_temps(self, env): - for arg in self.args: - arg.allocate_target_temps(env) - for node in self.coerced_unpacked_items: + def allocate_target_temps(self, env, rhs): + self.iterator.allocate_temps(env) + if rhs: + rhs.release_temp(env) + for arg, node in zip(self.args, self.coerced_unpacked_items): node.allocate_temps(env) - - def release_target_temp(self, env): - for arg in self.args: - arg.release_target_temp(env) - for node in self.coerced_unpacked_items: - node.release_temp(env) + arg.allocate_target_temps(env, node) + #arg.release_target_temp(env) + #node.release_temp(env) + self.iterator.release_temp(env) + +# def release_target_temp(self, env): +# #for arg in self.args: +# # arg.release_target_temp(env) +# #for node in self.coerced_unpacked_items: +# # node.release_temp(env) +# self.iterator.release_temp(env) def generate_result_code(self, code): self.generate_operation_code(code) def generate_assignment_code(self, rhs, code): + code.putln( + "%s = PyObject_GetIter(%s); if (!%s) %s" % ( + self.iterator.result_code, + rhs.py_result(), + self.iterator.result_code, + code.error_goto(self.pos))) + rhs.generate_disposal_code(code) for i in range(len(self.args)): item = self.unpacked_items[i] - unpack_code = "__Pyx_UnpackItem(%s, %s)" % ( - rhs.py_result(), - i) + unpack_code = "__Pyx_UnpackItem(%s)" % ( + self.iterator.py_result()) code.putln( "%s = %s; if (!%s) %s" % ( item.result_code, @@ -1768,14 +1797,13 @@ class SequenceNode(ExprNode): value_node.generate_evaluation_code(code) self.args[i].generate_assignment_code(value_node, code) code.putln( - "if (__Pyx_EndUnpack(%s, %s) < 0) %s" % ( - rhs.py_result(), - len(self.args), + "if (__Pyx_EndUnpack(%s) < 0) %s" % ( + self.iterator.py_result(), code.error_goto(self.pos))) if debug_disposal_code: print "UnpackNode.generate_assignment_code:" print "...generating disposal code for", rhs - rhs.generate_disposal_code(code) + self.iterator.generate_disposal_code(code) class TupleNode(SequenceNode): @@ -2560,10 +2588,13 @@ class CmpNode: return 1 if type1.is_pyobject: # type2 will be, too return 1 - elif type1.is_ptr: + elif type1.is_ptr or type1.is_array: return type1.is_null_ptr or type2.is_null_ptr \ - or type1.same_as(type2) - elif (type1.is_numeric and type2.is_numeric + or ((type2.is_ptr or type2.is_array) + and type1.base_type.same_as(type2.base_type)) + elif ((type1.is_numeric and type2.is_numeric + or type1.is_enum and (type1 is type2 or type2.is_int) + or type1.is_int and type2.is_enum) and op not in ('is', 'is_not')): return 1 else: @@ -2819,9 +2850,6 @@ class CastNode(CoercionNode): self.type = new_type def calculate_result_code(self): - #return "((%s)%s)" % ( - # self.type.declaration_code(""), - # self.arg.result) return self.arg.result_as(self.type) def generate_result_code(self, code): @@ -2904,12 +2932,14 @@ class CoerceFromPyTypeNode(CoercionNode): "Obtaining char * from temporary Python value") def generate_result_code(self, code): - #opnd = self.arg.py_result() function = self.type.from_py_function - code.putln('%s = %s(%s); if (PyErr_Occurred()) %s' % ( + operand = self.arg.py_result() + rhs = "%s(%s)" % (function, operand) + if self.type.is_enum: + rhs = typecast(self.type, c_long_type, rhs) + code.putln('%s = %s; if (PyErr_Occurred()) %s' % ( self.result_code, - function, - self.arg.py_result(), + rhs, code.error_goto(self.pos))) @@ -2995,8 +3025,10 @@ class CloneNode(CoercionNode): # #------------------------------------------------------------------------------------ -get_name_utility_code = \ +get_name_utility_code = [ """ +static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/ +""",""" static PyObject *__Pyx_GetName(PyObject *dict, char *name) { PyObject *result; result = PyObject_GetAttrString(dict, name); @@ -3004,10 +3036,12 @@ static PyObject *__Pyx_GetName(PyObject *dict, char *name) { PyErr_SetString(PyExc_NameError, name); return result; } -""" +"""] -get_name_interned_utility_code = \ +get_name_interned_utility_code = [ """ +static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/ +""",""" static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) { PyObject *result; result = PyObject_GetAttr(dict, name); @@ -3015,12 +3049,14 @@ static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) { PyErr_SetObject(PyExc_NameError, name); return result; } -""" +"""] #------------------------------------------------------------------------------------ -import_utility_code = \ +import_utility_code = [ """ +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/ +""",""" static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) { PyObject *__import__ = 0; PyObject *empty_list = 0; @@ -3056,12 +3092,14 @@ bad: """ % { "BUILTINS": Naming.builtins_cname, "GLOBALS": Naming.module_cname, -} +}] #------------------------------------------------------------------------------------ -get_exception_utility_code = \ +get_exception_utility_code = [ """ +static PyObject *__Pyx_GetExcValue(void); /*proto*/ +""",""" static PyObject *__Pyx_GetExcValue(void) { PyObject *type = 0, *value = 0, *tb = 0; PyObject *result = 0; @@ -3091,41 +3129,48 @@ bad: Py_XDECREF(tb); return result; } -""" +"""] #------------------------------------------------------------------------------------ -unpacking_utility_code = \ +unpacking_utility_code = [ """ +static PyObject *__Pyx_UnpackItem(PyObject *); /*proto*/ +static int __Pyx_EndUnpack(PyObject *); /*proto*/ +""",""" static void __Pyx_UnpackError(void) { PyErr_SetString(PyExc_ValueError, "unpack sequence of wrong size"); } -static PyObject *__Pyx_UnpackItem(PyObject *seq, int i) { - PyObject *item; - if (!(item = PySequence_GetItem(seq, i))) { - if (PyErr_ExceptionMatches(PyExc_IndexError)) - __Pyx_UnpackError(); - } - return item; +static PyObject *__Pyx_UnpackItem(PyObject *iter) { + PyObject *item; + if (!(item = PyIter_Next(iter))) { + if (!PyErr_Occurred()) + __Pyx_UnpackError(); + } + return item; } -static int __Pyx_EndUnpack(PyObject *seq, int i) { - PyObject *item; - if (item = PySequence_GetItem(seq, i)) { - Py_DECREF(item); - __Pyx_UnpackError(); - return -1; - } - PyErr_Clear(); - return 0; +static int __Pyx_EndUnpack(PyObject *iter) { + PyObject *item; + if ((item = PyIter_Next(iter))) { + Py_DECREF(item); + __Pyx_UnpackError(); + return -1; + } + else if (!PyErr_Occurred()) + return 0; + else + return -1; } -""" +"""] #------------------------------------------------------------------------------------ -type_test_utility_code = \ +type_test_utility_code = [ """ +static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/ +""",""" static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { if (!type) { PyErr_Format(PyExc_SystemError, "Missing type object"); @@ -3137,12 +3182,14 @@ static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { obj->ob_type->tp_name, type->tp_name); return 0; } -""" +"""] #------------------------------------------------------------------------------------ -create_class_utility_code = \ +create_class_utility_code = [ """ +static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, char *modname); /*proto*/ +""",""" static PyObject *__Pyx_CreateClass( PyObject *bases, PyObject *dict, PyObject *name, char *modname) { @@ -3159,6 +3206,6 @@ bad: Py_XDECREF(py_modname); return result; } -""" +"""] #------------------------------------------------------------------------------------ diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py new file mode 100644 index 00000000..3760e5c5 --- /dev/null +++ b/Cython/Compiler/ModuleNode.py @@ -0,0 +1,1270 @@ +# +# Pyrex - Module parse tree node +# + +import os, time +from cStringIO import StringIO + +import Code +import Naming +import Nodes +import Options +import PyrexTypes +import TypeSlots +import Version + +from Errors import error +from PyrexTypes import py_object_type +from Pyrex.Utils import open_new_file, replace_suffix + +class ModuleNode(Nodes.Node, Nodes.BlockNode): + # doc string or None + # body StatListNode + + def analyse_declarations(self, env): + env.doc = self.doc + self.body.analyse_declarations(env) + + def process_implementation(self, env, result): + self.analyse_declarations(env) + env.check_c_classes() + self.body.analyse_expressions(env) + env.return_type = PyrexTypes.c_void_type + self.generate_c_code(env, result) + self.generate_h_code(env, result) + + def generate_h_code(self, env, result): + public_vars_and_funcs = [] + public_extension_types = [] + for entry in env.var_entries: + if entry.visibility == 'public': + public_vars_and_funcs.append(entry) + for entry in env.cfunc_entries: + if entry.visibility == 'public': + public_vars_and_funcs.append(entry) + for entry in env.c_class_entries: + if entry.visibility == 'public': + public_extension_types.append(entry) + if public_vars_and_funcs or public_extension_types: + result.h_file = replace_suffix(result.c_file, ".h") + result.i_file = replace_suffix(result.c_file, ".pxi") + h_code = Code.CCodeWriter(open_new_file(result.h_file)) + i_code = Code.PyrexCodeWriter(result.i_file) + self.generate_extern_c_macro_definition(h_code) + for entry in public_vars_and_funcs: + h_code.putln("%s %s;" % ( + Naming.extern_c_macro, + entry.type.declaration_code( + entry.cname, dll_linkage = "DL_IMPORT"))) + i_code.putln("cdef extern %s" % + entry.type.declaration_code(entry.cname, pyrex = 1)) + for entry in public_extension_types: + self.generate_cclass_header_code(entry.type, h_code) + self.generate_cclass_include_code(entry.type, i_code) + h_code.putln("PyMODINIT_FUNC init%s(void);" % env.module_name) + + def generate_cclass_header_code(self, type, h_code): + #h_code.putln("extern DL_IMPORT(PyTypeObject) %s;" % type.typeobj_cname) + 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:" % ( + type.module_name, type.name)) + i_code.indent() + var_entries = type.scope.var_entries + if var_entries: + for entry in var_entries: + i_code.putln("cdef %s" % + entry.type.declaration_code(entry.cname, pyrex = 1)) + else: + i_code.putln("pass") + i_code.dedent() + + def generate_c_code(self, env, result): + modules = [] + self.find_referenced_modules(env, modules, {}) + #code = Code.CCodeWriter(result.c_file) + code = Code.CCodeWriter(StringIO()) + code.h = Code.CCodeWriter(StringIO()) + code.init_labels() + self.generate_module_preamble(env, modules, code.h) + + code.putln("") + code.putln("/* Implementation of %s */" % env.qualified_name) + self.generate_const_definitions(env, code) + self.generate_interned_name_decls(env, code) + self.generate_py_string_decls(env, code) + self.body.generate_function_definitions(env, code) + self.generate_interned_name_table(env, code) + self.generate_py_string_table(env, code) + self.generate_typeobj_definitions(env, code) + self.generate_method_table(env, code) + self.generate_filename_init_prototype(code) + self.generate_module_init_func(modules[:-1], env, code) + self.generate_filename_table(code) + self.generate_utility_functions(env, code) + + for module in modules: + self.generate_declarations_for_module(module, code.h, + definition = module is env) + + f = open_new_file(result.c_file) + f.write(code.h.f.getvalue()) + f.write("\n") + f.write(code.f.getvalue()) + f.close() + result.c_file_generated = 1 + + def find_referenced_modules(self, env, module_list, modules_seen): + if env not in modules_seen: + modules_seen[env] = 1 + for imported_module in env.cimported_modules: + self.find_referenced_modules(imported_module, module_list, modules_seen) + module_list.append(env) + + def generate_module_preamble(self, env, cimported_modules, code): + code.putln('/* Generated by Pyrex %s on %s */' % ( + Version.version, time.asctime())) + code.putln('') + for filename in env.python_include_files: + code.putln('#include "%s"' % filename) + code.putln("#ifndef PY_LONG_LONG") + code.putln(" #define PY_LONG_LONG LONG_LONG") + code.putln("#endif") + self.generate_extern_c_macro_definition(code) + code.putln("%s double pow(double, double);" % Naming.extern_c_macro) + self.generate_includes(env, cimported_modules, code) + #for filename in env.include_files: + # code.putln('#include "%s"' % filename) + code.putln('') + code.put(Nodes.utility_function_predeclarations) + #if Options.intern_names: + # code.putln(Nodes.get_name_interned_predeclaration) + #else: + # code.putln(get_name_predeclaration) + code.putln('') + code.putln('static PyObject *%s;' % env.module_cname) + code.putln('static PyObject *%s;' % Naming.builtins_cname) + code.putln('static int %s;' % Naming.lineno_cname) + code.putln('static char *%s;' % Naming.filename_cname) + code.putln('static char **%s;' % Naming.filetable_cname) + if env.doc: + code.putln('') + code.putln('static char %s[] = "%s";' % (env.doc_cname, env.doc)) + + def generate_extern_c_macro_definition(self, code): + name = Naming.extern_c_macro + code.putln("#ifdef __cplusplus") + code.putln('#define %s extern "C"' % name) + code.putln("#else") + code.putln("#define %s extern" % name) + code.putln("#endif") + + def generate_includes(self, env, cimported_modules, code): + includes = env.include_files[:] + for module in cimported_modules: + for filename in module.include_files: + if filename not in includes: + includes.append(filename) + for filename in includes: + code.putln('#include "%s"' % filename) + + def generate_filename_table(self, code): + code.putln("") + code.putln("static char *%s[] = {" % Naming.filenames_cname) + if code.filename_list: + for filename in code.filename_list: + filename = os.path.basename(filename) + escaped_filename = filename.replace("\\", "\\\\").replace('"', r'\"') + code.putln('"%s",' % + escaped_filename) + else: + # Some C compilers don't like an empty array + code.putln("0") + code.putln("};") + + def generate_declarations_for_module(self, env, code, definition): + code.putln("") + code.putln("/* Declarations from %s */" % env.qualified_name) + self.generate_type_predeclarations(env, code) + self.generate_type_definitions(env, code) + self.generate_global_declarations(env, code, definition) + self.generate_cfunction_predeclarations(env, code) + + def generate_type_predeclarations(self, env, code): + pass + + def generate_type_definitions(self, env, code): + # Generate definitions of structs/unions/enums. + for entry in env.sue_entries: + if not entry.in_cinclude: + type = entry.type + if type.is_struct_or_union: + self.generate_struct_union_definition(entry, code) + else: + self.generate_enum_definition(entry, code) + # Generate extension type object struct definitions. + for entry in env.c_class_entries: + if not entry.in_cinclude: + self.generate_typeobject_predeclaration(entry, code) + self.generate_obj_struct_definition(entry.type, code) + self.generate_exttype_vtable_struct(entry, code) + self.generate_exttype_vtabptr_declaration(entry, code) + + def sue_header_footer(self, type, kind, name): + if type.typedef_flag: + header = "typedef %s {" % kind + footer = "} %s;" % name + else: + header = "%s %s {" % (kind, name) + footer = "};" + return header, footer + + def generate_struct_union_definition(self, entry, code): + type = entry.type + scope = type.scope + if scope: + header, footer = \ + self.sue_header_footer(type, type.kind, type.cname) + code.putln("") + code.putln(header) + var_entries = scope.var_entries + if not var_entries: + error(entry.pos, + "Empty struct or union definition not allowed outside a" + " 'cdef extern from' block") + for attr in var_entries: + code.putln( + "%s;" % + attr.type.declaration_code(attr.cname)) + code.putln(footer) + + def generate_enum_definition(self, entry, code): + type = entry.type + name = entry.cname or entry.name or "" + header, footer = \ + self.sue_header_footer(type, "enum", name) + code.putln("") + code.putln(header) + enum_values = entry.enum_values + if not enum_values: + error(entry.pos, + "Empty enum definition not allowed outside a" + " 'cdef extern from' block") + else: + last_entry = enum_values[-1] + for value_entry in enum_values: + if value_entry.value == value_entry.name: + value_code = value_entry.cname + else: + value_code = ("%s = %s" % ( + value_entry.cname, + value_entry.value)) + if value_entry is not last_entry: + value_code += "," + code.putln(value_code) + code.putln(footer) + + def generate_typeobject_predeclaration(self, entry, code): + code.putln("") + name = entry.type.typeobj_cname + if name: + if entry.visibility == 'extern' and not entry.in_cinclude: + code.putln("%s DL_IMPORT(PyTypeObject) %s;" % ( + Naming.extern_c_macro, + name)) + elif entry.visibility == 'public': + #code.putln("DL_EXPORT(PyTypeObject) %s;" % name) + code.putln("%s DL_EXPORT(PyTypeObject) %s;" % ( + Naming.extern_c_macro, + name)) + # ??? Do we really need the rest of this? ??? + #else: + # code.putln("staticforward PyTypeObject %s;" % name) + + def generate_exttype_vtable_struct(self, entry, code): + # Generate struct declaration for an extension type's vtable. + type = entry.type + scope = type.scope + if type.vtabstruct_cname: + code.putln("") + code.putln( + "struct %s {" % + type.vtabstruct_cname) + if type.base_type and type.base_type.vtabstruct_cname: + code.putln("struct %s %s;" % ( + type.base_type.vtabstruct_cname, + Naming.obj_base_cname)) + for method_entry in scope.cfunc_entries: + if not method_entry.is_inherited: + code.putln( + "%s;" % method_entry.type.declaration_code("(*%s)" % method_entry.name)) + code.putln( + "};") + + def generate_exttype_vtabptr_declaration(self, entry, code): + # Generate declaration of pointer to an extension type's vtable. + type = entry.type + if type.vtabptr_cname: + code.putln("static struct %s *%s;" % ( + type.vtabstruct_cname, + type.vtabptr_cname)) + + def generate_obj_struct_definition(self, type, code): + # Generate object struct definition for an + # extension type. + if not type.scope: + return # Forward declared but never defined + header, footer = \ + self.sue_header_footer(type, "struct", type.objstruct_cname) + code.putln("") + code.putln(header) + base_type = type.base_type + if base_type: + code.putln( + "%s%s %s;" % ( + ("struct ", "")[base_type.typedef_flag], + base_type.objstruct_cname, + Naming.obj_base_cname)) + else: + code.putln( + "PyObject_HEAD") + if type.vtabslot_cname and not (type.base_type and type.base_type.vtabslot_cname): + code.putln( + "struct %s *%s;" % ( + type.vtabstruct_cname, + type.vtabslot_cname)) + for attr in type.scope.var_entries: + code.putln( + "%s;" % + attr.type.declaration_code(attr.cname)) + code.putln(footer) + + def generate_global_declarations(self, env, code, definition): + code.putln("") + for entry in env.c_class_entries: + code.putln("static PyTypeObject *%s = 0;" % + entry.type.typeptr_cname) + code.put_var_declarations(env.var_entries, static = 1, + dll_linkage = "DL_EXPORT", definition = definition) + code.put_var_declarations(env.default_entries, static = 1) + + def generate_cfunction_predeclarations(self, env, code): + for entry in env.cfunc_entries: + if not entry.in_cinclude: + if entry.visibility == 'public': + dll_linkage = "DL_EXPORT" + else: + dll_linkage = None + header = entry.type.declaration_code(entry.cname, + dll_linkage = dll_linkage) + if entry.visibility <> 'private': + storage_class = "%s " % Naming.extern_c_macro + else: + storage_class = "static " + code.putln("%s%s; /*proto*/" % ( + storage_class, + header)) + + def generate_typeobj_definitions(self, env, code): + full_module_name = env.qualified_name + for entry in env.c_class_entries: + #print "generate_typeobj_definitions:", entry.name + #print "...visibility =", entry.visibility + if entry.visibility <> 'extern': + type = entry.type + scope = type.scope + if scope: # could be None if there was an error + self.generate_exttype_vtable(scope, code) + self.generate_new_function(scope, code) + self.generate_dealloc_function(scope, code) + self.generate_traverse_function(scope, code) + self.generate_clear_function(scope, code) + if scope.defines_any(["__getitem__"]): + self.generate_getitem_int_function(scope, code) + if scope.defines_any(["__setitem__", "__delitem__"]): + self.generate_ass_subscript_function(scope, code) + if scope.defines_any(["__setslice__", "__delslice__"]): + self.generate_ass_slice_function(scope, code) + if scope.defines_any(["__getattr__"]): + self.generate_getattro_function(scope, code) + if scope.defines_any(["__setattr__", "__delattr__"]): + self.generate_setattro_function(scope, code) + if scope.defines_any(["__get__"]): + self.generate_descr_get_function(scope, code) + if scope.defines_any(["__set__", "__delete__"]): + 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) + + def generate_exttype_vtable(self, scope, code): + # Generate the definition of an extension type's vtable. + type = scope.parent_type + if type.vtable_cname: + code.putln("static struct %s %s;" % ( + type.vtabstruct_cname, + type.vtable_cname)) + + def generate_self_cast(self, scope, code): + type = scope.parent_type + code.putln( + "%s = (%s)o;" % ( + type.declaration_code("p"), + type.declaration_code(""))) + + def generate_new_function(self, scope, code): + base_type = scope.parent_type.base_type + code.putln("") + code.putln( + "static PyObject *%s(PyTypeObject *t, PyObject *a, PyObject *k) {" + % scope.mangle_internal("tp_new")) + if base_type: + code.putln( + "PyObject *o = %s->tp_new(t, a, k);" % + base_type.typeptr_cname) + else: + code.putln( + "PyObject *o = (*t->tp_alloc)(t, 0);") + type = scope.parent_type + py_attrs = [] + for entry in scope.var_entries: + if entry.type.is_pyobject: + py_attrs.append(entry) + if type.vtabslot_cname or py_attrs: + self.generate_self_cast(scope, code) + if type.vtabslot_cname: + code.putln("*(struct %s **)&p->%s = %s;" % ( + type.vtabstruct_cname, + type.vtabslot_cname, + type.vtabptr_cname)) + for entry in py_attrs: + if entry.name == "__weakref__": + code.putln("p->%s = 0;" % entry.cname) + else: + code.put_init_var_to_py_none(entry, "p->%s") + entry = scope.lookup_here("__new__") + if entry: + code.putln( + "if (%s(o, a, k) < 0) {" % + entry.func_cname) + code.put_decref_clear("o", py_object_type); + code.putln( + "}") + code.putln( + "return o;") + code.putln( + "}") + + def generate_dealloc_function(self, scope, code): + base_type = scope.parent_type.base_type + code.putln("") + code.putln( + "static void %s(PyObject *o) {" + % scope.mangle_internal("tp_dealloc")) + py_attrs = [] + for entry in scope.var_entries: + if entry.type.is_pyobject and entry.name <> "__weakref__": + py_attrs.append(entry) + if py_attrs: + self.generate_self_cast(scope, code) + self.generate_usr_dealloc_call(scope, code) + if scope.lookup_here("__weakref__"): + code.putln("PyObject_ClearWeakRefs(o);") + for entry in py_attrs: + code.put_xdecref("p->%s" % entry.cname, entry.type) + if base_type: + code.putln( + "%s->tp_dealloc(o);" % + base_type.typeptr_cname) + else: + code.putln( + "(*o->ob_type->tp_free)(o);") + code.putln( + "}") + + def generate_usr_dealloc_call(self, scope, code): + entry = scope.lookup_here("__dealloc__") + if entry: + code.putln( + "{") + code.putln( + "PyObject *etype, *eval, *etb;") + code.putln( + "PyErr_Fetch(&etype, &eval, &etb);") + code.putln( + "++o->ob_refcnt;") + code.putln( + "%s(o);" % + entry.func_cname) + code.putln( + "if (PyErr_Occurred()) PyErr_WriteUnraisable(o);") + code.putln( + "--o->ob_refcnt;") + code.putln( + "PyErr_Restore(etype, eval, etb);") + code.putln( + "}") + + def generate_traverse_function(self, scope, code): + base_type = scope.parent_type.base_type + code.putln("") + code.putln( + "static int %s(PyObject *o, visitproc v, void *a) {" + % scope.mangle_internal("tp_traverse")) + py_attrs = [] + for entry in scope.var_entries: + if entry.type.is_pyobject: + py_attrs.append(entry) + if base_type or py_attrs: + code.putln( + "int e;") + if py_attrs: + self.generate_self_cast(scope, code) + if base_type: + code.putln( + "e = %s->tp_traverse(o, v, a); if (e) return e;" % + base_type.typeptr_cname) + for entry in py_attrs: + var_code = "p->%s" % entry.cname + code.putln( + "if (%s) {" + % var_code) + if entry.type.is_extension_type: + var_code = "((PyObject*)%s)" % var_code + code.putln( + "e = (*v)(%s, a); if (e) return e;" + % var_code) + code.putln( + "}") + code.putln( + "return 0;") + code.putln( + "}") + + def generate_clear_function(self, scope, code): + base_type = scope.parent_type.base_type + code.putln("") + code.putln( + "static int %s(PyObject *o) {" + % scope.mangle_internal("tp_clear")) + py_attrs = [] + for entry in scope.var_entries: + if entry.type.is_pyobject: + py_attrs.append(entry) + if py_attrs: + self.generate_self_cast(scope, code) + if base_type: + code.putln( + "%s->tp_clear(o);" % + base_type.typeptr_cname) + for entry in py_attrs: + name = "p->%s" % entry.cname + code.put_xdecref(name, entry.type) + code.put_init_var_to_py_none(entry, "p->%s") + code.putln( + "return 0;") + code.putln( + "}") + + def generate_getitem_int_function(self, scope, code): + # This function is put into the sq_item slot when + # a __getitem__ method is present. It converts its + # argument to a Python integer and calls mp_subscript. + code.putln( + "static PyObject *%s(PyObject *o, int i) {" % + scope.mangle_internal("sq_item")) + code.putln( + "PyObject *r;") + code.putln( + "PyObject *x = PyInt_FromLong(i); if(!x) return 0;") + code.putln( + "r = o->ob_type->tp_as_mapping->mp_subscript(o, x);") + code.putln( + "Py_DECREF(x);") + code.putln( + "return r;") + code.putln( + "}") + + def generate_ass_subscript_function(self, scope, code): + # Setting and deleting an item are both done through + # the ass_subscript method, so we dispatch to user's __setitem__ + # or __delitem__, or raise an exception. + base_type = scope.parent_type.base_type + set_entry = scope.lookup_here("__setitem__") + del_entry = scope.lookup_here("__delitem__") + code.putln("") + code.putln( + "static int %s(PyObject *o, PyObject *i, PyObject *v) {" % + scope.mangle_internal("mp_ass_subscript")) + code.putln( + "if (v) {") + if set_entry: + code.putln( + "return %s(o, i, v);" % + set_entry.func_cname) + else: + self.generate_guarded_basetype_call( + base_type, "tp_as_mapping", "mp_ass_subscript", "o, i, v", code) + code.putln( + "PyErr_Format(PyExc_NotImplementedError,") + code.putln( + ' "Subscript assignment not supported by %s", o->ob_type->tp_name);') + code.putln( + "return -1;") + code.putln( + "}") + code.putln( + "else {") + if del_entry: + code.putln( + "return %s(o, i);" % + del_entry.func_cname) + else: + self.generate_guarded_basetype_call( + base_type, "tp_as_mapping", "mp_ass_subscript", "o, i, v", code) + code.putln( + "PyErr_Format(PyExc_NotImplementedError,") + code.putln( + ' "Subscript deletion not supported by %s", o->ob_type->tp_name);') + code.putln( + "return -1;") + code.putln( + "}") + code.putln( + "}") + + def generate_guarded_basetype_call( + self, base_type, substructure, slot, args, code): + if base_type: + base_tpname = base_type.typeptr_cname + if substructure: + code.putln( + "if (%s->%s && %s->%s->%s)" % ( + base_tpname, substructure, base_tpname, substructure, slot)) + code.putln( + " return %s->%s->%s(%s);" % ( + base_tpname, substructure, slot, args)) + else: + code.putln( + "if (%s->%s)" % ( + base_tpname, slot)) + code.putln( + " return %s->%s(%s);" % ( + base_tpname, slot, args)) + + def generate_ass_slice_function(self, scope, code): + # Setting and deleting a slice are both done through + # the ass_slice method, so we dispatch to user's __setslice__ + # or __delslice__, or raise an exception. + base_type = scope.parent_type.base_type + set_entry = scope.lookup_here("__setslice__") + del_entry = scope.lookup_here("__delslice__") + code.putln("") + code.putln( + "static int %s(PyObject *o, int i, int j, PyObject *v) {" % + scope.mangle_internal("sq_ass_slice")) + code.putln( + "if (v) {") + if set_entry: + code.putln( + "return %s(o, i, j, v);" % + set_entry.func_cname) + else: + self.generate_guarded_basetype_call( + base_type, "tp_as_sequence", "sq_ass_slice", "o, i, j, v", code) + code.putln( + "PyErr_Format(PyExc_NotImplementedError,") + code.putln( + ' "2-element slice assignment not supported by %s", o->ob_type->tp_name);') + code.putln( + "return -1;") + code.putln( + "}") + code.putln( + "else {") + if del_entry: + code.putln( + "return %s(o, i, j);" % + del_entry.func_cname) + else: + self.generate_guarded_basetype_call( + base_type, "tp_as_sequence", "sq_ass_slice", "o, i, j, v", code) + code.putln( + "PyErr_Format(PyExc_NotImplementedError,") + code.putln( + ' "2-element slice deletion not supported by %s", o->ob_type->tp_name);') + code.putln( + "return -1;") + code.putln( + "}") + code.putln( + "}") + + def generate_getattro_function(self, scope, code): + # First try to get the attribute using PyObject_GenericGetAttr. + # If that raises an AttributeError, call the user's __getattr__ + # method. + entry = scope.lookup_here("__getattr__") + code.putln("") + code.putln( + "static PyObject *%s(PyObject *o, PyObject *n) {" + % scope.mangle_internal("tp_getattro")) + code.putln( + "PyObject *v = PyObject_GenericGetAttr(o, n);") + code.putln( + "if (!v && PyErr_ExceptionMatches(PyExc_AttributeError)) {") + code.putln( + "PyErr_Clear();") + code.putln( + "v = %s(o, n);" % + entry.func_cname) + code.putln( + "}") + code.putln( + "return v;") + code.putln( + "}") + + def generate_setattro_function(self, scope, code): + # Setting and deleting an attribute are both done through + # the setattro method, so we dispatch to user's __setattr__ + # or __delattr__ or fall back on PyObject_GenericSetAttr. + base_type = scope.parent_type.base_type + set_entry = scope.lookup_here("__setattr__") + del_entry = scope.lookup_here("__delattr__") + code.putln("") + code.putln( + "static int %s(PyObject *o, PyObject *n, PyObject *v) {" % + scope.mangle_internal("tp_setattro")) + code.putln( + "if (v) {") + if set_entry: + code.putln( + "return %s(o, n, v);" % + set_entry.func_cname) + else: + self.generate_guarded_basetype_call( + base_type, None, "tp_setattro", "o, n, v", code) + code.putln( + "return PyObject_GenericSetAttr(o, n, v);") + code.putln( + "}") + code.putln( + "else {") + if del_entry: + code.putln( + "return %s(o, n);" % + del_entry.func_cname) + else: + self.generate_guarded_basetype_call( + base_type, None, "tp_setattro", "o, n, v", code) + code.putln( + "return PyObject_GenericSetAttr(o, n, 0);") + code.putln( + "}") + code.putln( + "}") + + def generate_descr_get_function(self, scope, code): + # The __get__ function of a descriptor object can be + # called with NULL for the second or third arguments + # under some circumstances, so we replace them with + # None in that case. + user_get_entry = scope.lookup_here("__get__") + code.putln("") + code.putln( + "static PyObject *%s(PyObject *o, PyObject *i, PyObject *c) {" % + scope.mangle_internal("tp_descr_get")) + code.putln( + "PyObject *r = 0;") + code.putln( + "if (!i) i = Py_None;") + code.putln( + "if (!c) c = Py_None;") + #code.put_incref("i", py_object_type) + #code.put_incref("c", py_object_type) + code.putln( + "r = %s(o, i, c);" % + user_get_entry.func_cname) + #code.put_decref("i", py_object_type) + #code.put_decref("c", py_object_type) + code.putln( + "return r;") + code.putln( + "}") + + def generate_descr_set_function(self, scope, code): + # Setting and deleting are both done through the __set__ + # method of a descriptor, so we dispatch to user's __set__ + # or __delete__ or raise an exception. + base_type = scope.parent_type.base_type + user_set_entry = scope.lookup_here("__set__") + user_del_entry = scope.lookup_here("__delete__") + code.putln("") + code.putln( + "static int %s(PyObject *o, PyObject *i, PyObject *v) {" % + scope.mangle_internal("tp_descr_set")) + code.putln( + "if (v) {") + if user_set_entry: + code.putln( + "return %s(o, i, v);" % + user_set_entry.func_cname) + else: + self.generate_guarded_basetype_call( + base_type, None, "tp_descr_set", "o, i, v", code) + code.putln( + 'PyErr_SetString(PyExc_NotImplementedError, "__set__");') + code.putln( + "return -1;") + code.putln( + "}") + code.putln( + "else {") + if user_del_entry: + code.putln( + "return %s(o, i);" % + user_del_entry.func_cname) + else: + self.generate_guarded_basetype_call( + base_type, None, "tp_descr_set", "o, i, v", code) + code.putln( + 'PyErr_SetString(PyExc_NotImplementedError, "__delete__");') + code.putln( + "return -1;") + code.putln( + "}") + code.putln( + "}") + + def generate_property_accessors(self, cclass_scope, code): + for entry in cclass_scope.property_entries: + property_scope = entry.scope + if property_scope.defines_any(["__get__"]): + self.generate_property_get_function(entry, code) + if property_scope.defines_any(["__set__", "__del__"]): + self.generate_property_set_function(entry, code) + + def generate_property_get_function(self, property_entry, code): + property_scope = property_entry.scope + property_entry.getter_cname = property_scope.parent_scope.mangle( + Naming.prop_get_prefix, property_entry.name) + get_entry = property_scope.lookup_here("__get__") + code.putln("") + code.putln( + "static PyObject *%s(PyObject *o, void *x) {" % + property_entry.getter_cname) + code.putln( + "return %s(o);" % + get_entry.func_cname) + code.putln( + "}") + + def generate_property_set_function(self, property_entry, code): + property_scope = property_entry.scope + property_entry.setter_cname = property_scope.parent_scope.mangle( + Naming.prop_set_prefix, property_entry.name) + set_entry = property_scope.lookup_here("__set__") + del_entry = property_scope.lookup_here("__del__") + code.putln("") + code.putln( + "static int %s(PyObject *o, PyObject *v, void *x) {" % + property_entry.setter_cname) + code.putln( + "if (v) {") + if set_entry: + code.putln( + "return %s(o, v);" % + set_entry.func_cname) + else: + code.putln( + 'PyErr_SetString(PyExc_NotImplementedError, "__set__");') + code.putln( + "return -1;") + code.putln( + "}") + code.putln( + "else {") + if del_entry: + code.putln( + "return %s(o);" % + del_entry.func_cname) + else: + code.putln( + 'PyErr_SetString(PyExc_NotImplementedError, "__del__");') + code.putln( + "return -1;") + code.putln( + "}") + code.putln( + "}") + + def generate_typeobj_definition(self, modname, entry, code): + type = entry.type + scope = type.scope + for suite in TypeSlots.substructures: + suite.generate_substructure(scope, code) + code.putln("") + if entry.visibility == 'public': + header = "DL_EXPORT(PyTypeObject) %s = {" + else: + #header = "statichere PyTypeObject %s = {" + header = "PyTypeObject %s = {" + #code.putln(header % scope.parent_type.typeobj_cname) + code.putln(header % type.typeobj_cname) + code.putln( + "PyObject_HEAD_INIT(0)") + code.putln( + "0, /*ob_size*/") + code.putln( + '"%s.%s", /*tp_name*/' % ( + modname, scope.class_name)) + 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*/" % + objstruct) + code.putln( + "0, /*tp_itemsize*/") + for slot in TypeSlots.slot_table: + slot.generate(scope, code) + code.putln( + "};") + + def generate_method_table(self, env, code): + code.putln("") + code.putln( + "static struct PyMethodDef %s[] = {" % + env.method_table_cname) + for entry in env.pyfunc_entries: + code.put_pymethoddef(entry, ",") + code.putln( + "{0, 0, 0, 0}") + 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('{"%s", %s, %s, %s, 0},' % ( + entry.name, + type_code, + "offsetof(%s, %s)" % (objstruct, entry.name), + flags)) + code.putln( + "{0, 0, 0, 0, 0}") + code.putln( + "};") + + def generate_getset_table(self, env, code): + if env.property_entries: + code.putln("") + code.putln( + "static struct PyGetSetDef %s[] = {" % + env.getset_table_cname) + for entry in env.property_entries: + code.putln( + '{"%s", %s, %s, %s, 0},' % ( + entry.name, + entry.getter_cname or "0", + entry.setter_cname or "0", + entry.doc_cname or "0")) + code.putln( + "{0, 0, 0, 0, 0}") + code.putln( + "};") + + def generate_interned_name_table(self, env, code): + items = env.intern_map.items() + if items: + items.sort() + code.putln("") + code.putln( + "static __Pyx_InternTabEntry %s[] = {" % + Naming.intern_tab_cname) + for (name, cname) in items: + code.putln( + '{&%s, "%s"},' % ( + cname, + name)) + code.putln( + "{0, 0}") + code.putln( + "};") + + def generate_py_string_table(self, env, code): + entries = env.all_pystring_entries + if entries: + code.putln("") + code.putln( + "static __Pyx_StringTabEntry %s[] = {" % + Naming.stringtab_cname) + for entry in entries: + code.putln( + "{&%s, %s, sizeof(%s)}," % ( + entry.pystring_cname, + entry.cname, + entry.cname)) + code.putln( + "{0, 0, 0}") + code.putln( + "};") + + def generate_filename_init_prototype(self, code): + code.putln(""); + code.putln("static void %s(void); /*proto*/" % Naming.fileinit_cname) + + def generate_module_init_func(self, imported_modules, env, code): + code.putln("") + header = "PyMODINIT_FUNC init%s(void)" % env.module_name + code.putln("%s; /*proto*/" % header) + code.putln("%s {" % header) + code.put_var_declarations(env.temp_entries) + #code.putln("/*--- Libary function declarations ---*/") + env.generate_library_function_declarations(code) + self.generate_filename_init_call(code) + #code.putln("/*--- Module creation code ---*/") + self.generate_module_creation_code(env, code) + #code.putln("/*--- Intern code ---*/") + self.generate_intern_code(env, code) + #code.putln("/*--- String init code ---*/") + self.generate_string_init_code(env, code) + #code.putln("/*--- Global init code ---*/") + self.generate_global_init_code(env, code) + + #code.putln("/*--- Type init code ---*/") + self.generate_type_init_code(env, code) + + #code.putln("/*--- Type import code ---*/") + for module in imported_modules: + self.generate_type_import_code_for_module(module, env, code) + + #code.putln("/*--- Execution code ---*/") + self.body.generate_execution_code(code) + code.putln("return;") + code.put_label(code.error_label) + code.put_var_xdecrefs(env.temp_entries) + code.putln('__Pyx_AddTraceback("%s");' % (env.qualified_name)) + env.use_utility_code(Nodes.traceback_utility_code) + code.putln('}') + + def generate_filename_init_call(self, code): + code.putln("%s();" % Naming.fileinit_cname) + + def generate_module_creation_code(self, env, code): + # Generate code to create the module object and + # install the builtins. + if env.doc: + doc = env.doc_cname + else: + doc = "0" + code.putln( + '%s = Py_InitModule4("%s", %s, %s, 0, PYTHON_API_VERSION);' % ( + env.module_cname, + env.module_name, + env.method_table_cname, + doc)) + code.putln( + "if (!%s) %s;" % ( + env.module_cname, + code.error_goto(self.pos))); + code.putln( + '%s = PyImport_AddModule("__builtin__");' % + Naming.builtins_cname) + code.putln( + "if (!%s) %s;" % ( + Naming.builtins_cname, + code.error_goto(self.pos))); + code.putln( + 'if (PyObject_SetAttrString(%s, "__builtins__", %s) < 0) %s;' % ( + env.module_cname, + Naming.builtins_cname, + code.error_goto(self.pos))) + + def generate_intern_code(self, env, code): + if env.intern_map: + env.use_utility_code(Nodes.init_intern_tab_utility_code); + code.putln( + "if (__Pyx_InternStrings(%s) < 0) %s;" % ( + Naming.intern_tab_cname, + code.error_goto(self.pos))) + + def generate_string_init_code(self, env, code): + if env.all_pystring_entries: + env.use_utility_code(Nodes.init_string_tab_utility_code) + code.putln( + "if (__Pyx_InitStrings(%s) < 0) %s;" % ( + Naming.stringtab_cname, + code.error_goto(self.pos))) + + def generate_global_init_code(self, env, code): + # Generate code to initialise global PyObject * + # variables to None. + for entry in env.var_entries: + if entry.visibility <> 'extern': + if entry.type.is_pyobject: + code.put_init_var_to_py_none(entry) + + def generate_type_import_code_for_module(self, module, env, code): + # Generate type import code for all extension types in + # an imported module. + if module.c_class_entries: + for entry in module.c_class_entries: + self.generate_type_import_code(env, entry.type, entry.pos, code) + + def generate_type_init_code(self, env, code): + # Generate type import code for extern extension types + # and type ready code for non-extern ones. + for entry in env.c_class_entries: + if entry.visibility == 'extern': + self.generate_type_import_code(env, entry.type, entry.pos, code) + else: + self.generate_base_type_import_code(env, entry, code) + self.generate_exttype_vtable_init_code(entry, code) + self.generate_type_ready_code(env, entry, code) + self.generate_typeptr_assignment_code(entry, code) + + def generate_base_type_import_code(self, env, entry, code): + base_type = entry.type.base_type + if base_type and base_type.module_name <> env.qualified_name: + self.generate_type_import_code(env, base_type, self.pos, code) + + def use_type_import_utility_code(self, env): + import ExprNodes + env.use_utility_code(Nodes.type_import_utility_code) + env.use_utility_code(ExprNodes.import_utility_code) + + def generate_type_import_code(self, env, type, pos, code): + # If not already done, generate code to import the typeobject of an + # extension type defined in another module, and extract its C method + # table pointer if any. + if type in env.types_imported: + return + if type.typedef_flag: + objstruct = type.objstruct_cname + else: + objstruct = "struct %s" % type.objstruct_cname + code.putln('%s = __Pyx_ImportType("%s", "%s", sizeof(%s)); if (!%s) %s' % ( + type.typeptr_cname, + type.module_name, + type.name, + objstruct, + type.typeptr_cname, + code.error_goto(pos))) + self.use_type_import_utility_code(env) + if type.vtabptr_cname: + code.putln( + "if (__Pyx_GetVtable(%s->tp_dict, &%s) < 0) %s" % ( + type.typeptr_cname, + type.vtabptr_cname, + code.error_goto(pos))) + env.use_utility_code(Nodes.get_vtable_utility_code) + env.types_imported[type] = 1 + + def generate_type_ready_code(self, env, entry, code): + # Generate a call to PyType_Ready for an extension + # type defined in this module. + type = entry.type + typeobj_cname = type.typeobj_cname + scope = type.scope + if scope: # could be None if there was an error + if entry.visibility <> 'extern': + for slot in TypeSlots.slot_table: + slot.generate_dynamic_init_code(scope, code) + code.putln( + "if (PyType_Ready(&%s) < 0) %s" % ( + typeobj_cname, + code.error_goto(entry.pos))) + if type.vtable_cname: + code.putln( + "if (__Pyx_SetVtable(%s.tp_dict, %s) < 0) %s" % ( + typeobj_cname, + type.vtabptr_cname, + code.error_goto(entry.pos))) + env.use_utility_code(Nodes.set_vtable_utility_code) + code.putln( + 'if (PyObject_SetAttrString(%s, "%s", (PyObject *)&%s) < 0) %s' % ( + Naming.module_cname, + scope.class_name, + typeobj_cname, + code.error_goto(entry.pos))) + weakref_entry = scope.lookup_here("__weakref__") + if weakref_entry: + if weakref_entry.type is py_object_type: + tp_weaklistoffset = "%s.tp_weaklistoffset" % typeobj_cname + code.putln("if (%s == 0) %s = offsetof(struct %s, %s);" % ( + tp_weaklistoffset, + tp_weaklistoffset, + type.objstruct_cname, + weakref_entry.cname)) + else: + error(weakref_entry.pos, "__weakref__ slot must be of type 'object'") + + def generate_exttype_vtable_init_code(self, entry, code): + # Generate code to initialise the C method table of an + # extension type. + type = entry.type + if type.vtable_cname: + code.putln( + "%s = &%s;" % ( + type.vtabptr_cname, + type.vtable_cname)) + if type.base_type and type.base_type.vtabptr_cname: + code.putln( + "%s.%s = *%s;" % ( + type.vtable_cname, + Naming.obj_base_cname, + type.base_type.vtabptr_cname)) + for meth_entry in type.scope.cfunc_entries: + if meth_entry.func_cname: + code.putln( + "*(void(**)())&%s.%s = (void(*)())%s;" % ( + type.vtable_cname, + meth_entry.cname, + meth_entry.func_cname)) + + def generate_typeptr_assignment_code(self, entry, code): + # Generate code to initialise the typeptr of an extension + # type defined in this module to point to its type object. + type = entry.type + if type.typeobj_cname: + code.putln( + "%s = &%s;" % ( + type.typeptr_cname, type.typeobj_cname)) + + def generate_utility_functions(self, env, code): + code.putln("") + code.putln("/* Runtime support code */") + code.putln("") + code.putln("static void %s(void) {" % Naming.fileinit_cname) + code.putln("%s = %s;" % + (Naming.filetable_cname, Naming.filenames_cname)) + code.putln("}") + for utility_code in env.utility_code_used: + code.h.put(utility_code[0]) + code.put(utility_code[1]) diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index a70f7f72..1c816d4b 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -2,7 +2,7 @@ # Pyrex - Parse tree nodes # -import os, string, sys, time +import string, sys import Code from Errors import error, InternalError @@ -11,8 +11,6 @@ import PyrexTypes from PyrexTypes import py_object_type, error_type, CTypedefType from Symtab import ModuleScope, LocalScope, \ StructOrUnionScope, PyClassScope, CClassScope -import TypeSlots -import Version from Pyrex.Utils import open_new_file, replace_suffix import Options @@ -95,1214 +93,6 @@ class BlockNode: for entry in entries: code.putln( "static PyObject *%s;" % entry.pystring_cname) - - -class ModuleNode(Node, BlockNode): - # doc string or None - # body StatListNode - - def analyse_declarations(self, env): - env.doc = self.doc - self.body.analyse_declarations(env) - - def process_implementation(self, env, result): - self.analyse_declarations(env) - env.check_c_classes() - self.body.analyse_expressions(env) - env.return_type = PyrexTypes.c_void_type - self.generate_c_code(env, result) - self.generate_h_code(env, result) - - def generate_h_code(self, env, result): - public_vars_and_funcs = [] - public_extension_types = [] - for entry in env.var_entries: - if entry.visibility == 'public': - public_vars_and_funcs.append(entry) - for entry in env.cfunc_entries: - if entry.visibility == 'public': - public_vars_and_funcs.append(entry) - for entry in env.c_class_entries: - if entry.visibility == 'public': - public_extension_types.append(entry) - if public_vars_and_funcs or public_extension_types: - result.h_file = replace_suffix(result.c_file, ".h") - result.i_file = replace_suffix(result.c_file, ".pxi") - h_code = Code.CCodeWriter(result.h_file) - i_code = Code.PyrexCodeWriter(result.i_file) - self.generate_extern_c_macro_definition(h_code) - for entry in public_vars_and_funcs: - h_code.putln("%s %s;" % ( - Naming.extern_c_macro, - entry.type.declaration_code( - entry.cname, dll_linkage = "DL_IMPORT"))) - i_code.putln("cdef extern %s" % - entry.type.declaration_code(entry.cname, pyrex = 1)) - for entry in public_extension_types: - self.generate_cclass_header_code(entry.type, h_code) - self.generate_cclass_include_code(entry.type, i_code) - h_code.putln("PyMODINIT_FUNC init%s(void);" % env.module_name) - - def generate_cclass_header_code(self, type, h_code): - #h_code.putln("extern DL_IMPORT(PyTypeObject) %s;" % type.typeobj_cname) - 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:" % ( - type.module_name, type.name)) - i_code.indent() - var_entries = type.scope.var_entries - if var_entries: - for entry in var_entries: - i_code.putln("cdef %s" % - entry.type.declaration_code(entry.cname, pyrex = 1)) - else: - i_code.putln("pass") - i_code.dedent() - - def generate_c_code(self, env, result): - modules = [] - self.find_referenced_modules(env, modules, {}) - code = Code.CCodeWriter(result.c_file) - code.init_labels() - self.generate_module_preamble(env, modules, code) - for module in modules: - self.generate_declarations_for_module(module, code, - definition = module is env) - code.putln("") - code.putln("/* Implementation of %s */" % env.qualified_name) - self.generate_const_definitions(env, code) - self.generate_interned_name_decls(env, code) - self.generate_py_string_decls(env, code) - self.body.generate_function_definitions(env, code) - self.generate_interned_name_table(env, code) - self.generate_py_string_table(env, code) - self.generate_typeobj_definitions(env, code) - self.generate_method_table(env, code) - self.generate_filename_init_prototype(code) - self.generate_module_init_func(modules[:-1], env, code) - self.generate_filename_table(code) - self.generate_utility_functions(env, code) - result.c_file_generated = 1 - - def find_referenced_modules(self, env, module_list, modules_seen): - if env not in modules_seen: - modules_seen[env] = 1 - for imported_module in env.cimported_modules: - self.find_referenced_modules(imported_module, module_list, modules_seen) - module_list.append(env) - - def generate_module_preamble(self, env, cimported_modules, code): - code.putln('/* Generated by Pyrex %s on %s */' % ( - Version.version, time.asctime())) - code.putln('') - for filename in env.python_include_files: - code.putln('#include "%s"' % filename) - code.putln("#ifndef PY_LONG_LONG") - code.putln(" #define PY_LONG_LONG LONG_LONG") - code.putln("#endif") - self.generate_extern_c_macro_definition(code) - code.putln("%s double pow(double, double);" % Naming.extern_c_macro) - self.generate_includes(env, cimported_modules, code) - #for filename in env.include_files: - # code.putln('#include "%s"' % filename) - code.putln('') - code.put(utility_function_predeclarations) - if Options.intern_names: - code.putln(get_name_interned_predeclaration) - else: - code.putln(get_name_predeclaration) - code.putln('') - code.putln('static PyObject *%s;' % env.module_cname) - code.putln('static PyObject *%s;' % Naming.builtins_cname) - code.putln('static int %s;' % Naming.lineno_cname) - code.putln('static char *%s;' % Naming.filename_cname) - code.putln('static char **%s;' % Naming.filetable_cname) - if env.doc: - code.putln('') - code.putln('static char %s[] = "%s";' % (env.doc_cname, env.doc)) - - def generate_extern_c_macro_definition(self, code): - name = Naming.extern_c_macro - code.putln("#ifdef __cplusplus") - code.putln('#define %s extern "C"' % name) - code.putln("#else") - code.putln("#define %s extern" % name) - code.putln("#endif") - - def generate_includes(self, env, cimported_modules, code): - includes = env.include_files[:] - for module in cimported_modules: - for filename in module.include_files: - if filename not in includes: - includes.append(filename) - for filename in includes: - code.putln('#include "%s"' % filename) - - def generate_filename_table(self, code): - code.putln("") - code.putln("static char *%s[] = {" % Naming.filenames_cname) - if code.filename_list: - for filename in code.filename_list: - filename = os.path.basename(filename) - escaped_filename = filename.replace("\\", "\\\\").replace('"', r'\"') - code.putln('"%s",' % - escaped_filename) - else: - # Some C compilers don't like an empty array - code.putln("0") - code.putln("};") - - def generate_declarations_for_module(self, env, code, definition): - code.putln("") - code.putln("/* Declarations from %s */" % env.qualified_name) - self.generate_type_predeclarations(env, code) - self.generate_type_definitions(env, code) - self.generate_global_declarations(env, code, definition) - self.generate_cfunction_predeclarations(env, code) - - def generate_type_predeclarations(self, env, code): - pass - - def generate_type_definitions(self, env, code): - # Generate definitions of structs/unions/enums. - for entry in env.sue_entries: - if not entry.in_cinclude: - type = entry.type - if type.is_struct_or_union: - self.generate_struct_union_definition(entry, code) - else: - self.generate_enum_definition(entry, code) - # Generate extension type object struct definitions. - for entry in env.c_class_entries: - if not entry.in_cinclude: - self.generate_typeobject_predeclaration(entry, code) - self.generate_obj_struct_definition(entry.type, code) - self.generate_exttype_vtable_struct(entry, code) - self.generate_exttype_vtabptr_declaration(entry, code) - - def sue_header_footer(self, type, kind, name): - if type.typedef_flag: - header = "typedef %s {" % kind - footer = "} %s;" % name - else: - header = "%s %s {" % (kind, name) - footer = "};" - return header, footer - - def generate_struct_union_definition(self, entry, code): - type = entry.type - scope = type.scope - if scope: - header, footer = \ - self.sue_header_footer(type, type.kind, type.cname) - code.putln("") - code.putln(header) - var_entries = scope.var_entries - if not var_entries: - error(entry.pos, - "Empty struct or union definition not allowed outside a" - " 'cdef extern from' block") - for attr in var_entries: - code.putln( - "%s;" % - attr.type.declaration_code(attr.cname)) - code.putln(footer) - - def generate_enum_definition(self, entry, code): - type = entry.type - name = entry.cname or entry.name or "" - header, footer = \ - self.sue_header_footer(type, "enum", name) - code.putln("") - code.putln(header) - enum_values = entry.enum_values - if not enum_values: - error(entry.pos, - "Empty enum definition not allowed outside a" - " 'cdef extern from' block") - for value_entry in enum_values: - if value_entry.value == value_entry.name: - code.putln( - "%s," % - value_entry.cname) - else: - code.putln( - "%s = %s," % ( - value_entry.cname, - value_entry.value)) - code.putln(footer) - - def generate_typeobject_predeclaration(self, entry, code): - code.putln("") - name = entry.type.typeobj_cname - if name: - if entry.visibility == 'extern' and not entry.in_cinclude: - code.putln("%s DL_IMPORT(PyTypeObject) %s;" % ( - Naming.extern_c_macro, - name)) - elif entry.visibility == 'public': - #code.putln("DL_EXPORT(PyTypeObject) %s;" % name) - code.putln("%s DL_EXPORT(PyTypeObject) %s;" % ( - Naming.extern_c_macro, - name)) - # ??? Do we really need the rest of this? ??? - #else: - # code.putln("staticforward PyTypeObject %s;" % name) - - def generate_exttype_vtable_struct(self, entry, code): - # Generate struct declaration for an extension type's vtable. - type = entry.type - scope = type.scope - if type.vtabstruct_cname: - code.putln("") - code.putln( - "struct %s {" % - type.vtabstruct_cname) - if type.base_type and type.base_type.vtabstruct_cname: - code.putln("struct %s %s;" % ( - type.base_type.vtabstruct_cname, - Naming.obj_base_cname)) - for method_entry in scope.cfunc_entries: - if not method_entry.is_inherited: - code.putln( - "%s;" % method_entry.type.declaration_code("(*%s)" % method_entry.name)) - code.putln( - "};") - - def generate_exttype_vtabptr_declaration(self, entry, code): - # Generate declaration of pointer to an extension type's vtable. - type = entry.type - if type.vtabptr_cname: - code.putln("static struct %s *%s;" % ( - type.vtabstruct_cname, - type.vtabptr_cname)) - - def generate_obj_struct_definition(self, type, code): - # Generate object struct definition for an - # extension type. - if not type.scope: - return # Forward declared but never defined - header, footer = \ - self.sue_header_footer(type, "struct", type.objstruct_cname) - code.putln("") - code.putln(header) - base_type = type.base_type - if base_type: - code.putln( - "%s%s %s;" % ( - ("struct ", "")[base_type.typedef_flag], - base_type.objstruct_cname, - Naming.obj_base_cname)) - else: - code.putln( - "PyObject_HEAD") - if type.vtabslot_cname and not (type.base_type and type.base_type.vtabslot_cname): - code.putln( - "struct %s *%s;" % ( - type.vtabstruct_cname, - type.vtabslot_cname)) - for attr in type.scope.var_entries: - code.putln( - "%s;" % - attr.type.declaration_code(attr.cname)) - code.putln(footer) - - def generate_global_declarations(self, env, code, definition): - code.putln("") - for entry in env.c_class_entries: - code.putln("static PyTypeObject *%s = 0;" % - entry.type.typeptr_cname) - code.put_var_declarations(env.var_entries, static = 1, - dll_linkage = "DL_EXPORT", definition = definition) - code.put_var_declarations(env.default_entries, static = 1) - - def generate_cfunction_predeclarations(self, env, code): - for entry in env.cfunc_entries: - if not entry.in_cinclude: - if entry.visibility == 'public': - dll_linkage = "DL_EXPORT" - else: - dll_linkage = None - header = entry.type.declaration_code(entry.cname, - dll_linkage = dll_linkage) - if entry.visibility <> 'private': - storage_class = "%s " % Naming.extern_c_macro - else: - storage_class = "static " - code.putln("%s%s; /*proto*/" % ( - storage_class, - header)) - - def generate_typeobj_definitions(self, env, code): - full_module_name = env.qualified_name - for entry in env.c_class_entries: - #print "generate_typeobj_definitions:", entry.name - #print "...visibility =", entry.visibility - if entry.visibility <> 'extern': - type = entry.type - scope = type.scope - if scope: # could be None if there was an error - self.generate_exttype_vtable(scope, code) - self.generate_new_function(scope, code) - self.generate_dealloc_function(scope, code) - self.generate_traverse_function(scope, code) - self.generate_clear_function(scope, code) - if scope.defines_any(["__getitem__"]): - self.generate_getitem_int_function(scope, code) - if scope.defines_any(["__setitem__", "__delitem__"]): - self.generate_ass_subscript_function(scope, code) - if scope.defines_any(["__setslice__", "__delslice__"]): - self.generate_ass_slice_function(scope, code) - if scope.defines_any(["__getattr__"]): - self.generate_getattro_function(scope, code) - if scope.defines_any(["__setattr__", "__delattr__"]): - self.generate_setattro_function(scope, code) - if scope.defines_any(["__get__"]): - self.generate_descr_get_function(scope, code) - if scope.defines_any(["__set__", "__delete__"]): - 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) - - def generate_exttype_vtable(self, scope, code): - # Generate the definition of an extension type's vtable. - type = scope.parent_type - if type.vtable_cname: - code.putln("static struct %s %s;" % ( - type.vtabstruct_cname, - type.vtable_cname)) - - def generate_self_cast(self, scope, code): - type = scope.parent_type - code.putln( - "%s = (%s)o;" % ( - type.declaration_code("p"), - type.declaration_code(""))) - - def generate_new_function(self, scope, code): - base_type = scope.parent_type.base_type - code.putln("") - code.putln( - "static PyObject *%s(PyTypeObject *t, PyObject *a, PyObject *k) {" - % scope.mangle_internal("tp_new")) - if base_type: - code.putln( - "PyObject *o = %s->tp_new(t, a, k);" % - base_type.typeptr_cname) - else: - code.putln( - "PyObject *o = (*t->tp_alloc)(t, 0);") - self.generate_self_cast(scope, code) - type = scope.parent_type - if type.vtabslot_cname: - code.putln("*(struct %s **)&p->%s = %s;" % ( - type.vtabstruct_cname, - type.vtabslot_cname, - type.vtabptr_cname)) - for entry in scope.var_entries: - if entry.type.is_pyobject: - code.put_init_var_to_py_none(entry, "p->%s") - entry = scope.lookup_here("__new__") - if entry: - code.putln( - "if (%s(o, a, k) < 0) {" % - entry.func_cname) - code.put_decref_clear("o", py_object_type); - code.putln( - "}") - code.putln( - "return o;") - code.putln( - "}") - - def generate_dealloc_function(self, scope, code): - base_type = scope.parent_type.base_type - code.putln("") - code.putln( - "static void %s(PyObject *o) {" - % scope.mangle_internal("tp_dealloc")) - self.generate_self_cast(scope, code) - self.generate_usr_dealloc_call(scope, code) - for entry in scope.var_entries: - if entry.type.is_pyobject: - code.put_xdecref("p->%s" % entry.cname, entry.type) - if base_type: - code.putln( - "%s->tp_dealloc(o);" % - base_type.typeptr_cname) - else: - code.putln( - "(*o->ob_type->tp_free)(o);") - code.putln( - "}") - - def generate_usr_dealloc_call(self, scope, code): - entry = scope.lookup_here("__dealloc__") - if entry: - code.putln( - "{") - code.putln( - "PyObject *etype, *eval, *etb;") - code.putln( - "PyErr_Fetch(&etype, &eval, &etb);") - code.putln( - "++o->ob_refcnt;") - code.putln( - "%s(o);" % - entry.func_cname) - code.putln( - "if (PyErr_Occurred()) PyErr_WriteUnraisable(o);") - code.putln( - "--o->ob_refcnt;") - code.putln( - "PyErr_Restore(etype, eval, etb);") - code.putln( - "}") - - def generate_traverse_function(self, scope, code): - base_type = scope.parent_type.base_type - code.putln("") - code.putln( - "static int %s(PyObject *o, visitproc v, void *a) {" - % scope.mangle_internal("tp_traverse")) - code.putln( - "int e;") - self.generate_self_cast(scope, code) - if base_type: - code.putln( - "e = %s->tp_traverse(o, v, a); if (e) return e;" % - base_type.typeptr_cname) - for entry in scope.var_entries: - if entry.type.is_pyobject: - var_code = "p->%s" % entry.cname - code.putln( - "if (%s) {" - % var_code) - if entry.type.is_extension_type: - var_code = "((PyObject*)%s)" % var_code - code.putln( - "e = (*v)(%s, a); if (e) return e;" - % var_code) - code.putln( - "}") - code.putln( - "return 0;") - code.putln( - "}") - - def generate_clear_function(self, scope, code): - base_type = scope.parent_type.base_type - code.putln("") - code.putln( - "static int %s(PyObject *o) {" - % scope.mangle_internal("tp_clear")) - self.generate_self_cast(scope, code) - if base_type: - code.putln( - "%s->tp_clear(o);" % - base_type.typeptr_cname) - for entry in scope.var_entries: - if entry.type.is_pyobject: - name = "p->%s" % entry.cname - code.put_xdecref(name, entry.type) - #code.put_init_to_py_none(name) - code.put_init_var_to_py_none(entry, "p->%s") - code.putln( - "return 0;") - code.putln( - "}") - - def generate_getitem_int_function(self, scope, code): - # This function is put into the sq_item slot when - # a __getitem__ method is present. It converts its - # argument to a Python integer and calls mp_subscript. - code.putln( - "static PyObject *%s(PyObject *o, int i) {" % - scope.mangle_internal("sq_item")) - code.putln( - "PyObject *r;") - code.putln( - "PyObject *x = PyInt_FromLong(i); if(!x) return 0;") - code.putln( - "r = o->ob_type->tp_as_mapping->mp_subscript(o, x);") - code.putln( - "Py_DECREF(x);") - code.putln( - "return r;") - code.putln( - "}") - - def generate_ass_subscript_function(self, scope, code): - # Setting and deleting an item are both done through - # the ass_subscript method, so we dispatch to user's __setitem__ - # or __delitem__, or raise an exception. - base_type = scope.parent_type.base_type - set_entry = scope.lookup_here("__setitem__") - del_entry = scope.lookup_here("__delitem__") - code.putln("") - code.putln( - "static int %s(PyObject *o, PyObject *i, PyObject *v) {" % - scope.mangle_internal("mp_ass_subscript")) - code.putln( - "if (v) {") - if set_entry: - code.putln( - "return %s(o, i, v);" % - set_entry.func_cname) - else: - self.generate_guarded_basetype_call( - base_type, "tp_as_mapping", "mp_ass_subscript", "o, i, v", code) - code.putln( - "PyErr_Format(PyExc_NotImplementedError,") - code.putln( - ' "Subscript assignment not supported by %s", o->ob_type->tp_name);') - code.putln( - "return -1;") - code.putln( - "}") - code.putln( - "else {") - if del_entry: - code.putln( - "return %s(o, i);" % - del_entry.func_cname) - else: - self.generate_guarded_basetype_call( - base_type, "tp_as_mapping", "mp_ass_subscript", "o, i, v", code) - code.putln( - "PyErr_Format(PyExc_NotImplementedError,") - code.putln( - ' "Subscript deletion not supported by %s", o->ob_type->tp_name);') - code.putln( - "return -1;") - code.putln( - "}") - code.putln( - "}") - - def generate_guarded_basetype_call( - self, base_type, substructure, slot, args, code): - if base_type: - base_tpname = base_type.typeptr_cname - if substructure: - code.putln( - "if (%s->%s && %s->%s->%s)" % ( - base_tpname, substructure, base_tpname, substructure, slot)) - code.putln( - " return %s->%s->%s(%s);" % ( - base_tpname, substructure, slot, args)) - else: - code.putln( - "if (%s->%s)" % ( - base_tpname, slot)) - code.putln( - " return %s->%s(%s);" % ( - base_tpname, slot, args)) - - def generate_ass_slice_function(self, scope, code): - # Setting and deleting a slice are both done through - # the ass_slice method, so we dispatch to user's __setslice__ - # or __delslice__, or raise an exception. - base_type = scope.parent_type.base_type - set_entry = scope.lookup_here("__setslice__") - del_entry = scope.lookup_here("__delslice__") - code.putln("") - code.putln( - "static int %s(PyObject *o, int i, int j, PyObject *v) {" % - scope.mangle_internal("sq_ass_slice")) - code.putln( - "if (v) {") - if set_entry: - code.putln( - "return %s(o, i, j, v);" % - set_entry.func_cname) - else: - self.generate_guarded_basetype_call( - base_type, "tp_as_sequence", "sq_ass_slice", "o, i, j, v", code) - code.putln( - "PyErr_Format(PyExc_NotImplementedError,") - code.putln( - ' "2-element slice assignment not supported by %s", o->ob_type->tp_name);') - code.putln( - "return -1;") - code.putln( - "}") - code.putln( - "else {") - if del_entry: - code.putln( - "return %s(o, i, j);" % - del_entry.func_cname) - else: - self.generate_guarded_basetype_call( - base_type, "tp_as_sequence", "sq_ass_slice", "o, i, j, v", code) - code.putln( - "PyErr_Format(PyExc_NotImplementedError,") - code.putln( - ' "2-element slice deletion not supported by %s", o->ob_type->tp_name);') - code.putln( - "return -1;") - code.putln( - "}") - code.putln( - "}") - - def generate_getattro_function(self, scope, code): - # First try to get the attribute using PyObject_GenericGetAttr. - # If that raises an AttributeError, call the user's __getattr__ - # method. - entry = scope.lookup_here("__getattr__") - code.putln("") - code.putln( - "static PyObject *%s(PyObject *o, PyObject *n) {" - % scope.mangle_internal("tp_getattro")) - code.putln( - "PyObject *v = PyObject_GenericGetAttr(o, n);") - code.putln( - "if (!v && PyErr_ExceptionMatches(PyExc_AttributeError)) {") - code.putln( - "PyErr_Clear();") - code.putln( - "v = %s(o, n);" % - entry.func_cname) - code.putln( - "}") - code.putln( - "return v;") - code.putln( - "}") - - def generate_setattro_function(self, scope, code): - # Setting and deleting an attribute are both done through - # the setattro method, so we dispatch to user's __setattr__ - # or __delattr__ or fall back on PyObject_GenericSetAttr. - base_type = scope.parent_type.base_type - set_entry = scope.lookup_here("__setattr__") - del_entry = scope.lookup_here("__delattr__") - code.putln("") - code.putln( - "static int %s(PyObject *o, PyObject *n, PyObject *v) {" % - scope.mangle_internal("tp_setattro")) - code.putln( - "if (v) {") - if set_entry: - code.putln( - "return %s(o, n, v);" % - set_entry.func_cname) - else: - self.generate_guarded_basetype_call( - base_type, None, "tp_setattro", "o, n, v", code) - code.putln( - "return PyObject_GenericSetAttr(o, n, v);") - code.putln( - "}") - code.putln( - "else {") - if del_entry: - code.putln( - "return %s(o, n);" % - del_entry.func_cname) - else: - self.generate_guarded_basetype_call( - base_type, None, "tp_setattro", "o, n, v", code) - code.putln( - "return PyObject_GenericSetAttr(o, n, 0);") - code.putln( - "}") - code.putln( - "}") - - def generate_descr_get_function(self, scope, code): - # The __get__ function of a descriptor object can be - # called with NULL for the second or third arguments - # under some circumstances, so we replace them with - # None in that case. - user_get_entry = scope.lookup_here("__get__") - code.putln("") - code.putln( - "static PyObject *%s(PyObject *o, PyObject *i, PyObject *c) {" % - scope.mangle_internal("tp_descr_get")) - code.putln( - "PyObject *r = 0;") - code.putln( - "if (!i) i = Py_None;") - code.putln( - "if (!c) c = Py_None;") - #code.put_incref("i", py_object_type) - #code.put_incref("c", py_object_type) - code.putln( - "r = %s(o, i, c);" % - user_get_entry.func_cname) - #code.put_decref("i", py_object_type) - #code.put_decref("c", py_object_type) - code.putln( - "return r;") - code.putln( - "}") - - def generate_descr_set_function(self, scope, code): - # Setting and deleting are both done through the __set__ - # method of a descriptor, so we dispatch to user's __set__ - # or __delete__ or raise an exception. - base_type = scope.parent_type.base_type - user_set_entry = scope.lookup_here("__set__") - user_del_entry = scope.lookup_here("__delete__") - code.putln("") - code.putln( - "static int %s(PyObject *o, PyObject *i, PyObject *v) {" % - scope.mangle_internal("tp_descr_set")) - code.putln( - "if (v) {") - if user_set_entry: - code.putln( - "return %s(o, i, v);" % - user_set_entry.func_cname) - else: - self.generate_guarded_basetype_call( - base_type, None, "tp_descr_set", "o, i, v", code) - code.putln( - 'PyErr_SetString(PyExc_NotImplementedError, "__set__");') - code.putln( - "return -1;") - code.putln( - "}") - code.putln( - "else {") - if user_del_entry: - code.putln( - "return %s(o, i);" % - user_del_entry.func_cname) - else: - self.generate_guarded_basetype_call( - base_type, None, "tp_descr_set", "o, i, v", code) - code.putln( - 'PyErr_SetString(PyExc_NotImplementedError, "__delete__");') - code.putln( - "return -1;") - code.putln( - "}") - code.putln( - "}") - - def generate_property_accessors(self, cclass_scope, code): - for entry in cclass_scope.property_entries: - property_scope = entry.scope - if property_scope.defines_any(["__get__"]): - self.generate_property_get_function(entry, code) - if property_scope.defines_any(["__set__", "__del__"]): - self.generate_property_set_function(entry, code) - - def generate_property_get_function(self, property_entry, code): - property_scope = property_entry.scope - property_entry.getter_cname = property_scope.parent_scope.mangle( - Naming.prop_get_prefix, property_entry.name) - get_entry = property_scope.lookup_here("__get__") - code.putln("") - code.putln( - "static PyObject *%s(PyObject *o, void *x) {" % - property_entry.getter_cname) - code.putln( - "return %s(o);" % - get_entry.func_cname) - code.putln( - "}") - - def generate_property_set_function(self, property_entry, code): - property_scope = property_entry.scope - property_entry.setter_cname = property_scope.parent_scope.mangle( - Naming.prop_set_prefix, property_entry.name) - set_entry = property_scope.lookup_here("__set__") - del_entry = property_scope.lookup_here("__del__") - code.putln("") - code.putln( - "static int %s(PyObject *o, PyObject *v, void *x) {" % - property_entry.setter_cname) - code.putln( - "if (v) {") - if set_entry: - code.putln( - "return %s(o, v);" % - set_entry.func_cname) - else: - code.putln( - 'PyErr_SetString(PyExc_NotImplementedError, "__set__");') - code.putln( - "return -1;") - code.putln( - "}") - code.putln( - "else {") - if del_entry: - code.putln( - "return %s(o);" % - del_entry.func_cname) - else: - code.putln( - 'PyErr_SetString(PyExc_NotImplementedError, "__del__");') - code.putln( - "return -1;") - code.putln( - "}") - code.putln( - "}") - - def generate_typeobj_definition(self, modname, entry, code): - type = entry.type - scope = type.scope - for suite in TypeSlots.substructures: - suite.generate_substructure(scope, code) - code.putln("") - if entry.visibility == 'public': - header = "DL_EXPORT(PyTypeObject) %s = {" - else: - #header = "statichere PyTypeObject %s = {" - header = "PyTypeObject %s = {" - #code.putln(header % scope.parent_type.typeobj_cname) - code.putln(header % type.typeobj_cname) - code.putln( - "PyObject_HEAD_INIT(0)") - code.putln( - "0, /*ob_size*/") - code.putln( - '"%s.%s", /*tp_name*/' % ( - modname, scope.class_name)) - 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*/" % - objstruct) - code.putln( - "0, /*tp_itemsize*/") - for slot in TypeSlots.slot_table: - slot.generate(scope, code) - code.putln( - "};") - - def generate_method_table(self, env, code): - code.putln("") - code.putln( - "static struct PyMethodDef %s[] = {" % - env.method_table_cname) - for entry in env.pyfunc_entries: - code.put_pymethoddef(entry, ",") - code.putln( - "{0, 0, 0, 0}") - 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('{"%s", %s, %s, %s, 0},' % ( - entry.name, - type_code, - "offsetof(%s, %s)" % (objstruct, entry.name), - flags)) - code.putln( - "{0, 0, 0, 0, 0}") - code.putln( - "};") - - def generate_getset_table(self, env, code): - if env.property_entries: - code.putln("") - code.putln( - "static struct PyGetSetDef %s[] = {" % - env.getset_table_cname) - for entry in env.property_entries: - code.putln( - '{"%s", %s, %s, %s, 0},' % ( - entry.name, - entry.getter_cname or "0", - entry.setter_cname or "0", - entry.doc_cname or "0")) - code.putln( - "{0, 0, 0, 0, 0}") - code.putln( - "};") - - def generate_interned_name_table(self, env, code): - items = env.intern_map.items() - if items: - items.sort() - code.putln("") - code.putln( - "static __Pyx_InternTabEntry %s[] = {" % - Naming.intern_tab_cname) - for (name, cname) in items: - code.putln( - '{&%s, "%s"},' % ( - cname, - name)) - code.putln( - "{0, 0}") - code.putln( - "};") - - def generate_py_string_table(self, env, code): - entries = env.all_pystring_entries - if entries: - code.putln("") - code.putln( - "static __Pyx_StringTabEntry %s[] = {" % - Naming.stringtab_cname) - for entry in entries: - code.putln( - "{&%s, %s, sizeof(%s)}," % ( - entry.pystring_cname, - entry.cname, - entry.cname)) - code.putln( - "{0, 0, 0}") - code.putln( - "};") - - def generate_filename_init_prototype(self, code): - code.putln(""); - code.putln("static void %s(void); /*proto*/" % Naming.fileinit_cname) - - def generate_module_init_func(self, imported_modules, env, code): - code.putln("") - header = "PyMODINIT_FUNC init%s(void)" % env.module_name - code.putln("%s; /*proto*/" % header) - code.putln("%s {" % header) - code.put_var_declarations(env.temp_entries) - #code.putln("/*--- Libary function declarations ---*/") - env.generate_library_function_declarations(code) - self.generate_filename_init_call(code) - #code.putln("/*--- Module creation code ---*/") - self.generate_module_creation_code(env, code) - #code.putln("/*--- Intern code ---*/") - self.generate_intern_code(env, code) - #code.putln("/*--- String init code ---*/") - self.generate_string_init_code(env, code) - #code.putln("/*--- Global init code ---*/") - self.generate_global_init_code(env, code) - #code.putln("/*--- Type import code ---*/") - for module in imported_modules: - self.generate_type_import_code_for_module(module, env, code) - #code.putln("/*--- Type init code ---*/") - self.generate_type_init_code(env, code) - #code.putln("/*--- Execution code ---*/") - self.body.generate_execution_code(code) - code.putln("return;") - code.put_label(code.error_label) - code.put_var_xdecrefs(env.temp_entries) - code.putln('__Pyx_AddTraceback("%s");' % (env.qualified_name)) - env.use_utility_code(traceback_utility_code) - code.putln('}') - - def generate_filename_init_call(self, code): - code.putln("%s();" % Naming.fileinit_cname) - - def generate_module_creation_code(self, env, code): - # Generate code to create the module object and - # install the builtins. - if env.doc: - doc = env.doc_cname - else: - doc = "0" - code.putln( - '%s = Py_InitModule4("%s", %s, %s, 0, PYTHON_API_VERSION);' % ( - env.module_cname, - env.module_name, - env.method_table_cname, - doc)) - code.putln( - "if (!%s) %s;" % ( - env.module_cname, - code.error_goto(self.pos))); - code.putln( - '%s = PyImport_AddModule("__builtin__");' % - Naming.builtins_cname) - code.putln( - "if (!%s) %s;" % ( - Naming.builtins_cname, - code.error_goto(self.pos))); - code.putln( - 'if (PyObject_SetAttrString(%s, "__builtins__", %s) < 0) %s;' % ( - env.module_cname, - Naming.builtins_cname, - code.error_goto(self.pos))) - - def generate_intern_code(self, env, code): - if env.intern_map: - env.use_utility_code(init_intern_tab_utility_code); - code.putln( - "if (__Pyx_InternStrings(%s) < 0) %s;" % ( - Naming.intern_tab_cname, - code.error_goto(self.pos))) - - def generate_string_init_code(self, env, code): - if env.all_pystring_entries: - env.use_utility_code(init_string_tab_utility_code) - code.putln( - "if (__Pyx_InitStrings(%s) < 0) %s;" % ( - Naming.stringtab_cname, - code.error_goto(self.pos))) - - def generate_global_init_code(self, env, code): - # Generate code to initialise global PyObject * - # variables to None. - for entry in env.var_entries: - if entry.visibility <> 'extern': - if entry.type.is_pyobject: - code.put_init_var_to_py_none(entry) - - def generate_type_import_code_for_module(self, module, env, code): - # Generate type import code for all extension types in - # an imported module. - if module.c_class_entries: - for entry in module.c_class_entries: - self.generate_type_import_code(env, entry, code) - - def generate_type_init_code(self, env, code): - # Generate type import code for extern extension types - # and type ready code for non-extern ones. - for entry in env.c_class_entries: - if entry.visibility == 'extern': - self.generate_type_import_code(env, entry, code) - else: - self.generate_exttype_vtable_init_code(entry, code) - self.generate_type_ready_code(env, entry, code) - self.generate_typeptr_assignment_code(entry, code) - - def use_type_import_utility_code(self, env): - import ExprNodes - env.use_utility_code(type_import_utility_code) - env.use_utility_code(ExprNodes.import_utility_code) - - def generate_type_import_code(self, env, entry, code): - # Generate code to import the typeobject of an - # extension type defined in another module, and - # extract its C method table pointer if any. - type = entry.type - if type.typedef_flag: - objstruct = type.objstruct_cname - else: - objstruct = "struct %s" % type.objstruct_cname - code.putln('%s = __Pyx_ImportType("%s", "%s", sizeof(%s)); if (!%s) %s' % ( - type.typeptr_cname, - type.module_name, - type.name, - objstruct, - type.typeptr_cname, - code.error_goto(entry.pos))) - self.use_type_import_utility_code(env) - if type.vtabptr_cname: - code.putln( - "if (__Pyx_GetVtable(%s->tp_dict, &%s) < 0) %s" % ( - type.typeptr_cname, - type.vtabptr_cname, - code.error_goto(entry.pos))) - env.use_utility_code(get_vtable_utility_code) - - def generate_type_ready_code(self, env, entry, code): - # Generate a call to PyType_Ready for an extension - # type defined in this module. - type = entry.type - typeobj_cname = type.typeobj_cname - scope = type.scope - if scope: # could be None if there was an error - if entry.visibility <> 'extern': - for slot in TypeSlots.slot_table: - slot.generate_dynamic_init_code(scope, code) - code.putln( - "if (PyType_Ready(&%s) < 0) %s" % ( - typeobj_cname, - code.error_goto(entry.pos))) - if type.vtable_cname: - code.putln( - "if (__Pyx_SetVtable(%s.tp_dict, %s) < 0) %s" % ( - typeobj_cname, - type.vtabptr_cname, - code.error_goto(entry.pos))) - env.use_utility_code(set_vtable_utility_code) - code.putln( - 'if (PyObject_SetAttrString(%s, "%s", (PyObject *)&%s) < 0) %s' % ( - Naming.module_cname, - scope.class_name, - typeobj_cname, - code.error_goto(entry.pos))) - weakref_entry = scope.lookup_here("__weakref__") - if weakref_entry: - if weakref_entry.type is py_object_type: - tp_weaklistoffset = "%s.tp_weaklistoffset" % typeobj_cname - code.putln("if (%s == 0) %s = offsetof(struct %s, %s);" % ( - tp_weaklistoffset, - tp_weaklistoffset, - type.objstruct_cname, - weakref_entry.cname)) - else: - error(weakref_entry.pos, "__weakref__ slot must be of type 'object'") - - def generate_exttype_vtable_init_code(self, entry, code): - # Generate code to initialise the C method table of an - # extension type. - type = entry.type - if type.vtable_cname: - code.putln( - "%s = &%s;" % ( - type.vtabptr_cname, - type.vtable_cname)) - if type.base_type and type.base_type.vtabptr_cname: - code.putln( - "%s.%s = *%s;" % ( - type.vtable_cname, - Naming.obj_base_cname, - type.base_type.vtabptr_cname)) - for meth_entry in type.scope.cfunc_entries: - if meth_entry.func_cname: - code.putln( - "*(void **)&%s.%s = (void *)%s;" % ( - type.vtable_cname, - meth_entry.cname, - meth_entry.func_cname)) - - def generate_typeptr_assignment_code(self, entry, code): - # Generate code to initialise the typeptr of an extension - # type defined in this module to point to its type object. - type = entry.type - if type.typeobj_cname: - code.putln( - "%s = &%s;" % ( - type.typeptr_cname, type.typeobj_cname)) - - def generate_utility_functions(self, env, code): - code.putln("") - code.putln("/* Runtime support code */") - code.putln("") - code.putln("static void %s(void) {" % Naming.fileinit_cname) - code.putln("%s = %s;" % - (Naming.filetable_cname, Naming.filenames_cname)) - code.putln("}") - for utility_code in env.utility_code_used: - code.put(utility_code) class StatListNode(Node): @@ -1697,8 +487,6 @@ class FuncDefNode(StatNode, BlockNode): # ----- Top-level constants used by this function self.generate_interned_name_decls(lenv, code) self.generate_py_string_decls(lenv, code) - #code.putln("") - #code.put_var_declarations(lenv.const_entries, static = 1) self.generate_const_definitions(lenv, code) # ----- Function header code.putln("") @@ -1721,13 +509,12 @@ class FuncDefNode(StatNode, BlockNode): # ----- Fetch arguments self.generate_argument_parsing_code(code) self.generate_argument_increfs(lenv, code) - #self.generate_stararg_getting_code(code) - self.generate_argument_conversion_code(code) # ----- Initialise local variables for entry in lenv.var_entries: - if entry.type.is_pyobject and entry.init_to_none: + if entry.type.is_pyobject and entry.init_to_none and entry.used: code.put_init_var_to_py_none(entry) - # ----- Check types of arguments + # ----- Check and convert arguments + self.generate_argument_conversion_code(code) self.generate_argument_type_tests(code) # ----- Function body self.body.generate_execution_code(code) @@ -1743,29 +530,31 @@ class FuncDefNode(StatNode, BlockNode): val = self.return_type.default_value if val: code.putln("%s = %s;" % (Naming.retval_cname, val)) - code.putln("goto %s;" % code.return_label) + #code.putln("goto %s;" % code.return_label) # ----- Error cleanup - code.put_label(code.error_label) - code.put_var_xdecrefs(lenv.temp_entries) - err_val = self.error_value() - exc_check = self.caller_will_check_exceptions() - if err_val is not None or exc_check: - code.putln( - '__Pyx_AddTraceback("%s");' % - self.entry.qualified_name) - if err_val is not None: + if code.error_label in code.labels_used: + code.put_goto(code.return_label) + code.put_label(code.error_label) + code.put_var_xdecrefs(lenv.temp_entries) + err_val = self.error_value() + exc_check = self.caller_will_check_exceptions() + if err_val is not None or exc_check: code.putln( - "%s = %s;" % ( - Naming.retval_cname, - err_val)) - else: - code.putln( - '__Pyx_WriteUnraisable("%s");' % - self.entry.qualified_name) - env.use_utility_code(unraisable_exception_utility_code) + '__Pyx_AddTraceback("%s");' % + self.entry.qualified_name) + if err_val is not None: + code.putln( + "%s = %s;" % ( + Naming.retval_cname, + err_val)) + else: + code.putln( + '__Pyx_WriteUnraisable("%s");' % + self.entry.qualified_name) + env.use_utility_code(unraisable_exception_utility_code) # ----- Return cleanup code.put_label(code.return_label) - code.put_var_decrefs(lenv.var_entries) + code.put_var_decrefs(lenv.var_entries, used_only = 1) code.put_var_decrefs(lenv.arg_entries) self.put_stararg_decrefs(code) if not self.return_type.is_void: @@ -1872,9 +661,6 @@ class CFuncDefNode(FuncDefNode): def generate_argument_parsing_code(self, code): pass -# def generate_stararg_getting_code(self, code): -# pass - def generate_argument_conversion_code(self, code): pass @@ -2015,6 +801,7 @@ class DefNode(FuncDefNode): arg.entry.init_to_none = 0 else: arg.entry = self.declare_argument(env, arg) + arg.entry.used = 1 arg.entry.is_self_arg = arg.is_self_arg if arg.hdr_type: if arg.is_self_arg or \ @@ -2025,11 +812,13 @@ class DefNode(FuncDefNode): def declare_python_arg(self, env, arg): if arg: - arg.entry = env.declare_var(arg.name, + entry = env.declare_var(arg.name, PyrexTypes.py_object_type, arg.pos) - arg.entry.init = "0" - arg.entry.init_to_none = 0 - arg.entry.xdecref_cleanup = 1 + entry.used = 1 + entry.init = "0" + entry.init_to_none = 0 + entry.xdecref_cleanup = 1 + arg.entry = entry def analyse_expressions(self, env): self.analyse_default_values(env) @@ -2044,6 +833,7 @@ class DefNode(FuncDefNode): arg.default = arg.default.coerce_to(arg.type, env) arg.default.allocate_temps(env) arg.default_entry = env.add_default_value(arg.type) + arg.default_entry.used = 1 else: error(arg.pos, "This argument cannot have a default value") @@ -2339,11 +1129,10 @@ class PyClassDefNode(StatNode, BlockNode): self.scope = cenv self.body.analyse_declarations(cenv) self.body.analyse_expressions(cenv) - self.target.analyse_target_expression(env) + self.target.analyse_target_expression(env, self.classobj) self.dict.release_temp(env) - self.classobj.release_temp(env) - self.target.release_target_temp(env) - #env.recycle_pending_temps() + #self.classobj.release_temp(env) + #self.target.release_target_temp(env) def generate_function_definitions(self, env, code): self.generate_py_string_decls(self.scope, code) @@ -2488,7 +1277,6 @@ class ExprStatNode(StatNode): def analyse_expressions(self, env): self.expr.analyse_expressions(env) self.expr.release_temp(env) - #env.recycle_pending_temps() # TEMPORARY def generate_execution_code(self, code): self.expr.generate_evaluation_code(code) @@ -2507,8 +1295,13 @@ class AssignmentNode(StatNode): # to any of the left hand sides. def analyse_expressions(self, env): - self.analyse_expressions_1(env) - self.analyse_expressions_2(env) + self.analyse_types(env) + self.allocate_rhs_temps(env) + self.allocate_lhs_temps(env) + +# def analyse_expressions(self, env): +# self.analyse_expressions_1(env) +# self.analyse_expressions_2(env) def generate_execution_code(self, code): self.generate_rhs_evaluation_code(code) @@ -2526,18 +1319,33 @@ class SingleAssignmentNode(AssignmentNode): def analyse_declarations(self, env): self.lhs.analyse_target_declaration(env) - def analyse_expressions_1(self, env, use_temp = 0): + def analyse_types(self, env, use_temp = 0): self.rhs.analyse_types(env) self.lhs.analyse_target_types(env) self.rhs = self.rhs.coerce_to(self.lhs.type, env) if use_temp: self.rhs = self.rhs.coerce_to_temp(env) + + def allocate_rhs_temps(self, env): self.rhs.allocate_temps(env) + + def allocate_lhs_temps(self, env): + self.lhs.allocate_target_temps(env, self.rhs) + #self.lhs.release_target_temp(env) + #self.rhs.release_temp(env) - def analyse_expressions_2(self, env): - self.lhs.allocate_target_temps(env) - self.lhs.release_target_temp(env) - self.rhs.release_temp(env) +# def analyse_expressions_1(self, env, use_temp = 0): +# self.rhs.analyse_types(env) +# self.lhs.analyse_target_types(env) +# self.rhs = self.rhs.coerce_to(self.lhs.type, env) +# if use_temp: +# self.rhs = self.rhs.coerce_to_temp(env) +# self.rhs.allocate_temps(env) +# +# def analyse_expressions_2(self, env): +# self.lhs.allocate_target_temps(env) +# self.lhs.release_target_temp(env) +# self.rhs.release_temp(env) def generate_rhs_evaluation_code(self, code): self.rhs.generate_evaluation_code(code) @@ -2562,31 +1370,12 @@ class CascadedAssignmentNode(AssignmentNode): for lhs in self.lhs_list: lhs.analyse_target_declaration(env) -# def analyse_expressions(self, env): -# import ExprNodes -# self.rhs.analyse_types(env) -# self.rhs = self.rhs.coerce_to_temp(env) -# self.rhs.allocate_temps(env) -# self.coerced_rhs_list = [] -# for lhs in self.lhs_list: -# lhs.analyse_target_types(env) -# coerced_rhs = ExprNodes.CloneNode(self.rhs).coerce_to(lhs.type, env) -# self.coerced_rhs_list.append(coerced_rhs) -# coerced_rhs.allocate_temps(env) -# lhs.allocate_target_temps(env) -# coerced_rhs.release_temp(env) -# lhs.release_target_temp(env) -# self.rhs.release_temp(env) - - def analyse_expressions_1(self, env, use_temp = 0): + def analyse_types(self, env, use_temp = 0): self.rhs.analyse_types(env) if use_temp: self.rhs = self.rhs.coerce_to_temp(env) else: self.rhs = self.rhs.coerce_to_simple(env) - self.rhs.allocate_temps(env) - - def analyse_expressions_2(self, env): from ExprNodes import CloneNode self.coerced_rhs_list = [] for lhs in self.lhs_list: @@ -2594,21 +1383,39 @@ class CascadedAssignmentNode(AssignmentNode): rhs = CloneNode(self.rhs) rhs = rhs.coerce_to(lhs.type, env) self.coerced_rhs_list.append(rhs) + + def allocate_rhs_temps(self, env): + self.rhs.allocate_temps(env) + + def allocate_lhs_temps(self, env): + for lhs, rhs in zip(self.lhs_list, self.coerced_rhs_list): rhs.allocate_temps(env) - lhs.allocate_target_temps(env) - lhs.release_target_temp(env) - rhs.release_temp(env) + lhs.allocate_target_temps(env, rhs) + #lhs.release_target_temp(env) + #rhs.release_temp(env) self.rhs.release_temp(env) - -# def generate_execution_code(self, code): -# self.rhs.generate_evaluation_code(code) -# for i in range(len(self.lhs_list)): -# lhs = self.lhs_list[i] -# rhs = self.coerced_rhs_list[i] -# rhs.generate_evaluation_code(code) -# lhs.generate_assignment_code(rhs, code) -# # Assignment has already disposed of the cloned RHS -# self.rhs.generate_disposal_code(code) + +# def analyse_expressions_1(self, env, use_temp = 0): +# self.rhs.analyse_types(env) +# if use_temp: +# self.rhs = self.rhs.coerce_to_temp(env) +# else: +# self.rhs = self.rhs.coerce_to_simple(env) +# self.rhs.allocate_temps(env) +# +# def analyse_expressions_2(self, env): +# from ExprNodes import CloneNode +# self.coerced_rhs_list = [] +# for lhs in self.lhs_list: +# lhs.analyse_target_types(env) +# rhs = CloneNode(self.rhs) +# rhs = rhs.coerce_to(lhs.type, env) +# self.coerced_rhs_list.append(rhs) +# rhs.allocate_temps(env) +# lhs.allocate_target_temps(env) +# lhs.release_target_temp(env) +# rhs.release_temp(env) +# self.rhs.release_temp(env) def generate_rhs_evaluation_code(self, code): self.rhs.generate_evaluation_code(code) @@ -2642,9 +1449,16 @@ class ParallelAssignmentNode(AssignmentNode): def analyse_expressions(self, env): for stat in self.stats: - stat.analyse_expressions_1(env, use_temp = 1) + stat.analyse_types(env, use_temp = 1) + stat.allocate_rhs_temps(env) for stat in self.stats: - stat.analyse_expressions_2(env) + stat.allocate_lhs_temps(env) + +# def analyse_expressions(self, env): +# for stat in self.stats: +# stat.analyse_expressions_1(env, use_temp = 1) +# for stat in self.stats: +# stat.analyse_expressions_2(env) def generate_execution_code(self, code): for stat in self.stats: @@ -2695,10 +1509,10 @@ class DelStatNode(StatNode): def analyse_expressions(self, env): for arg in self.args: - arg.analyse_target_expression(env) + arg.analyse_target_expression(env, None) if not arg.type.is_pyobject: error(arg.pos, "Deletion of non-Python object") - #env.recycle_pending_temps() # TEMPORARY + #arg.release_target_temp(env) def generate_execution_code(self, code): for arg in self.args: @@ -2726,9 +1540,10 @@ class BreakStatNode(StatNode): if not code.break_label: error(self.pos, "break statement not inside loop") else: - code.putln( - "goto %s;" % - code.break_label) + #code.putln( + # "goto %s;" % + # code.break_label) + code.put_goto(code.break_label) class ContinueStatNode(StatNode): @@ -2742,9 +1557,10 @@ class ContinueStatNode(StatNode): elif not code.continue_label: error(self.pos, "continue statement not inside loop") else: - code.putln( - "goto %s;" % - code.continue_label) + #code.putln( + # "goto %s;" % + # code.continue_label) + code.put_goto(code.continue_label) class ReturnStatNode(StatNode): @@ -2780,8 +1596,6 @@ class ReturnStatNode(StatNode): if not self.return_type: # error reported earlier return - for entry in self.temps_in_use: - code.put_var_decref_clear(entry) if self.value: self.value.generate_evaluation_code(code) self.value.make_owned_reference(code) @@ -2798,9 +1612,12 @@ class ReturnStatNode(StatNode): "%s = %s;" % ( Naming.retval_cname, self.return_type.default_value)) - code.putln( - "goto %s;" % - code.return_label) + for entry in self.temps_in_use: + code.put_var_decref_clear(entry) + #code.putln( + # "goto %s;" % + # code.return_label) + code.put_goto(code.return_label) class RaiseStatNode(StatNode): @@ -2962,9 +1779,10 @@ class IfClauseNode(Node): "if (%s) {" % self.condition.result_code) self.body.generate_execution_code(code) - code.putln( - "goto %s;" % - end_label) + #code.putln( + # "goto %s;" % + # end_label) + code.put_goto(end_label) code.putln("}") @@ -2993,12 +1811,12 @@ class WhileStatNode(StatNode): old_loop_labels = code.new_loop_labels() code.putln( "while (1) {") - code.put_label(code.continue_label) self.condition.generate_evaluation_code(code) code.putln( "if (!%s) break;" % self.condition.result_code) self.body.generate_execution_code(code) + code.put_label(code.continue_label) code.putln("}") break_label = code.break_label code.set_loop_labels(old_loop_labels) @@ -3031,12 +1849,10 @@ class ForInStatNode(StatNode): self.item = ExprNodes.NextNode(self.iterator, env) self.item = self.item.coerce_to(self.target.type, env) self.item.allocate_temps(env) - self.target.allocate_target_temps(env) - self.item.release_temp(env) - self.target.release_target_temp(env) - #env.recycle_pending_temps() # TEMPORARY + self.target.allocate_target_temps(env, self.item) + #self.item.release_temp(env) + #self.target.release_target_temp(env) self.body.analyse_expressions(env) - #env.recycle_pending_temps() # TEMPORARY if self.else_clause: self.else_clause.analyse_expressions(env) self.iterator.release_temp(env) @@ -3046,10 +1862,10 @@ class ForInStatNode(StatNode): self.iterator.generate_evaluation_code(code) code.putln( "for (;;) {") - code.put_label(code.continue_label) self.item.generate_evaluation_code(code) self.target.generate_assignment_code(self.item, code) self.body.generate_execution_code(code) + code.put_label(code.continue_label) code.putln( "}") break_label = code.break_label @@ -3075,6 +1891,7 @@ class ForFromStatNode(StatNode): # # Used internally: # + # is_py_target bool # loopvar_name string # py_loopvar_node PyTempNode or None @@ -3094,14 +1911,19 @@ class ForFromStatNode(StatNode): if not (self.bound2.is_name or self.bound2.is_literal): self.bound2 = self.bound2.coerce_to_temp(env) target_type = self.target.type - if not (target_type.is_pyobject - or target_type.assignable_from(PyrexTypes.c_int_type)): - error(self.target.pos, - "Cannot assign integer to variable of type '%s'" % target_type) + if not (target_type.is_pyobject or target_type.is_int): + error(self.target.pos, + "Integer for-loop variable must be of type int or Python object") + #if not (target_type.is_pyobject + # or target_type.assignable_from(PyrexTypes.c_int_type)): + # error(self.target.pos, + # "Cannot assign integer to variable of type '%s'" % target_type) if target_type.is_int: + self.is_py_target = 0 self.loopvar_name = self.target.entry.cname self.py_loopvar_node = None else: + self.is_py_target = 1 c_loopvar_node = ExprNodes.TempNode(self.pos, PyrexTypes.c_long_type, env) c_loopvar_node.allocate_temps(env) @@ -3110,20 +1932,18 @@ class ForFromStatNode(StatNode): ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env) self.bound1.allocate_temps(env) self.bound2.allocate_temps(env) - if self.py_loopvar_node: + if self.is_py_target: self.py_loopvar_node.allocate_temps(env) - self.target.allocate_target_temps(env) - self.target.release_target_temp(env) - if self.py_loopvar_node: - self.py_loopvar_node.release_temp(env) + self.target.allocate_target_temps(env, self.py_loopvar_node) + #self.target.release_target_temp(env) + #self.py_loopvar_node.release_temp(env) self.body.analyse_expressions(env) - if self.py_loopvar_node: + if self.is_py_target: c_loopvar_node.release_temp(env) if self.else_clause: self.else_clause.analyse_expressions(env) self.bound1.release_temp(env) self.bound2.release_temp(env) - #env.recycle_pending_temps() # TEMPORARY def generate_execution_code(self, code): old_loop_labels = code.new_loop_labels() @@ -3200,9 +2020,10 @@ class TryExceptStatNode(StatNode): self.else_clause.generate_execution_code(code) code.putln( "}") - code.putln( - "goto %s;" % - end_label) + #code.putln( + # "goto %s;" % + # end_label) + code.put_goto(end_label) code.put_label(our_error_label) code.put_var_xdecrefs_clear(self.cleanup_list) default_clause_seen = 0 @@ -3214,9 +2035,10 @@ class TryExceptStatNode(StatNode): error(except_clause.pos, "Default except clause not last") except_clause.generate_handling_code(code, end_label) if not default_clause_seen: - code.putln( - "goto %s;" % - code.error_label) + #code.putln( + # "goto %s;" % + # code.error_label) + code.put_goto(code.error_label) code.put_label(end_label) @@ -3248,11 +2070,11 @@ class ExceptClauseNode(Node): self.exc_value = ExprNodes.ExcValueNode(self.pos, env) self.exc_value.allocate_temps(env) if self.target: - self.target.analyse_target_expression(env) - self.exc_value.release_temp(env) - if self.target: - self.target.release_target_temp(env) - #env.recycle_pending_temps() # TEMPORARY + self.target.analyse_target_expression(env, self.exc_value) + else: + self.exc_value.release_temp(env) + #if self.target: + # self.target.release_target_temp(env) self.body.analyse_expressions(env) def generate_handling_code(self, code, end_label): @@ -3281,9 +2103,10 @@ class ExceptClauseNode(Node): else: self.exc_value.generate_disposal_code(code) self.body.generate_execution_code(code) - code.putln( - "goto %s;" - % end_label) + #code.putln( + # "goto %s;" + # % end_label) + code.put_goto(end_label) code.putln( "}") @@ -3353,20 +2176,23 @@ class TryFinallyStatNode(StatNode): #code.putln( # "int %s;" % # self.lineno_var) + code.use_label(catch_label) code.putln( "__pyx_why = 0; goto %s;" % catch_label) for i in range(len(new_labels)): - if new_labels[i] and new_labels[i] <> "": - if new_labels[i] == new_error_label: - self.put_error_catcher(code, - new_error_label, i+1, catch_label) - else: - code.putln( - "%s: __pyx_why = %s; goto %s;" % ( - new_labels[i], - i+1, - catch_label)) + new_label = new_labels[i] + if new_label and new_label <> "": + if new_label in code.labels_used: + if new_label == new_error_label: + self.put_error_catcher(code, + new_error_label, i+1, catch_label) + else: + code.putln( + "%s: __pyx_why = %s; goto %s;" % ( + new_label, + i+1, + catch_label)) code.put_label(catch_label) code.set_all_labels(old_labels) self.finally_clause.generate_execution_code(code) @@ -3377,6 +2203,7 @@ class TryFinallyStatNode(StatNode): if old_labels[i] == old_error_label: self.put_error_uncatcher(code, i+1, old_error_label) else: + code.use_label(old_labels[i]) code.putln( "case %s: goto %s;" % ( i+1, @@ -3400,9 +2227,10 @@ class TryFinallyStatNode(StatNode): code.putln( "%s = %s;" % ( self.lineno_var, Naming.lineno_cname)) - code.putln( - "goto %s;" % - catch_label) + #code.putln( + # "goto %s;" % + # catch_label) + code.put_goto(catch_label) code.putln( "}") @@ -3420,9 +2248,10 @@ class TryFinallyStatNode(StatNode): code.putln( "%s = 0;" % var) - code.putln( - "goto %s;" % - error_label) + #code.putln( + # "goto %s;" % + # error_label) + code.put_goto(error_label) code.putln( "}") @@ -3502,11 +2331,10 @@ class FromImportStatNode(StatNode): for name, target in self.items: if Options.intern_names: self.interned_items.append((env.intern(name), target)) - target.analyse_target_expression(env) - target.release_temp(env) + target.analyse_target_expression(env, None) + #target.release_target_temp(env) # was release_temp ?!? self.module.release_temp(env) self.item.release_temp(env) - #env.recycle_pending_temps() # TEMPORARY def generate_execution_code(self, code): self.module.generate_evaluation_code(code) @@ -3542,38 +2370,21 @@ utility_function_predeclarations = \ """ typedef struct {PyObject **p; char *s;} __Pyx_InternTabEntry; /*proto*/ typedef struct {PyObject **p; char *s; long n;} __Pyx_StringTabEntry; /*proto*/ -static PyObject *__Pyx_UnpackItem(PyObject *, int); /*proto*/ -static int __Pyx_EndUnpack(PyObject *, int); /*proto*/ -static int __Pyx_PrintItem(PyObject *); /*proto*/ -static int __Pyx_PrintNewline(void); /*proto*/ -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/ -static void __Pyx_ReRaise(void); /*proto*/ -static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/ -static PyObject *__Pyx_GetExcValue(void); /*proto*/ -static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, char *name); /*proto*/ -static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/ -static int __Pyx_GetStarArgs(PyObject **args, PyObject **kwds,\ - char *kwd_list[], int nargs, PyObject **args2, PyObject **kwds2); /*proto*/ -static void __Pyx_WriteUnraisable(char *name); /*proto*/ -static void __Pyx_AddTraceback(char *funcname); /*proto*/ -static PyTypeObject *__Pyx_ImportType(char *module_name, char *class_name, long size); /*proto*/ -static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/ -static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/ -static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, char *modname); /*proto*/ -static int __Pyx_InternStrings(__Pyx_InternTabEntry *t); /*proto*/ -static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/ """ -get_name_predeclaration = \ -"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/" +#get_name_predeclaration = \ +#"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/" -get_name_interned_predeclaration = \ -"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/" +#get_name_interned_predeclaration = \ +#"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/" #------------------------------------------------------------------------------------ -printing_utility_code = \ -r""" +printing_utility_code = [ +""" +static int __Pyx_PrintItem(PyObject *); /*proto*/ +static int __Pyx_PrintNewline(void); /*proto*/ +""",r""" static PyObject *__Pyx_GetStdout(void) { PyObject *f = PySys_GetObject("stdout"); if (!f) { @@ -3614,14 +2425,16 @@ static int __Pyx_PrintNewline(void) { PyFile_SoftSpace(f, 0); return 0; } -""" +"""] #------------------------------------------------------------------------------------ # The following function is based on do_raise() from ceval.c. -raise_utility_code = \ +raise_utility_code = [ """ +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/ +""",""" static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) { Py_XINCREF(type); Py_XINCREF(value); @@ -3648,32 +2461,28 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) { Py_INCREF(type); Py_DECREF(tmp); } - if (PyString_Check(type)) - ; - else if (PyClass_Check(type)) + if (PyString_Check(type)) { + if (PyErr_Warn(PyExc_DeprecationWarning, + "raising a string exception is deprecated")) + goto raise_error; + } + else if (PyType_Check(type) || PyClass_Check(type)) ; /*PyErr_NormalizeException(&type, &value, &tb);*/ - else if (PyInstance_Check(type)) { + else { /* Raising an instance. The value should be a dummy. */ if (value != Py_None) { PyErr_SetString(PyExc_TypeError, - "instance exception may not have a separate value"); + "instance exception may not have a separate value"); goto raise_error; } - else { - /* Normalize to raise , */ - Py_DECREF(value); - value = type; + /* Normalize to raise , */ + Py_DECREF(value); + value = type; + if (PyInstance_Check(type)) type = (PyObject*) ((PyInstanceObject*)type)->in_class; - Py_INCREF(type); - } - } - else { - /* Not something you can raise. You get an exception - anyway, just not what you specified :-) */ - PyErr_Format(PyExc_TypeError, - "exceptions must be strings, classes, or " - "instances, not %s", type->ob_type->tp_name); - goto raise_error; + else + type = (PyObject*) type->ob_type; + Py_INCREF(type); } PyErr_Restore(type, value, tb); return; @@ -3683,12 +2492,14 @@ raise_error: Py_XDECREF(tb); return; } -""" +"""] #------------------------------------------------------------------------------------ -reraise_utility_code = \ +reraise_utility_code = [ """ +static void __Pyx_ReRaise(void); /*proto*/ +""",""" static void __Pyx_ReRaise(void) { PyThreadState *tstate = PyThreadState_Get(); PyObject *type = tstate->exc_type; @@ -3699,12 +2510,14 @@ static void __Pyx_ReRaise(void) { Py_XINCREF(tb); PyErr_Restore(type, value, tb); } -""" +"""] #------------------------------------------------------------------------------------ -arg_type_test_utility_code = \ +arg_type_test_utility_code = [ """ +static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, char *name); /*proto*/ +""",""" static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, char *name) { if (!type) { PyErr_Format(PyExc_SystemError, "Missing type object"); @@ -3717,7 +2530,7 @@ static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed name, type->tp_name, obj->ob_type->tp_name); return 0; } -""" +"""] #------------------------------------------------------------------------------------ # @@ -3733,8 +2546,11 @@ static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed # reference to the same dictionary is passed back in *kwds. # -get_starargs_utility_code = \ +get_starargs_utility_code = [ """ +static int __Pyx_GetStarArgs(PyObject **args, PyObject **kwds,\ + char *kwd_list[], int nargs, PyObject **args2, PyObject **kwds2); /*proto*/ +""",""" static int __Pyx_GetStarArgs( PyObject **args, PyObject **kwds, @@ -3799,18 +2615,22 @@ static int __Pyx_GetStarArgs( bad: Py_XDECREF(args1); Py_XDECREF(kwds1); - if (*args2) + if (*args2) { Py_XDECREF(*args2); - if (*kwds2) + } + if (*kwds2) { Py_XDECREF(*kwds2); + } return -1; } -""" +"""] #------------------------------------------------------------------------------------ -unraisable_exception_utility_code = \ +unraisable_exception_utility_code = [ """ +static void __Pyx_WriteUnraisable(char *name); /*proto*/ +""",""" static void __Pyx_WriteUnraisable(char *name) { PyObject *old_exc, *old_val, *old_tb; PyObject *ctx; @@ -3821,12 +2641,14 @@ static void __Pyx_WriteUnraisable(char *name) { ctx = Py_None; PyErr_WriteUnraisable(ctx); } -""" +"""] #------------------------------------------------------------------------------------ -traceback_utility_code = \ +traceback_utility_code = [ """ +static void __Pyx_AddTraceback(char *funcname); /*proto*/ +""",""" #include "compile.h" #include "frameobject.h" #include "traceback.h" @@ -3888,12 +2710,14 @@ bad: 'FILENAME': Naming.filename_cname, 'LINENO': Naming.lineno_cname, 'GLOBALS': Naming.module_cname -} +}] #------------------------------------------------------------------------------------ -type_import_utility_code = \ +type_import_utility_code = [ """ +static PyTypeObject *__Pyx_ImportType(char *module_name, char *class_name, long size); /*proto*/ +""",""" static PyTypeObject *__Pyx_ImportType(char *module_name, char *class_name, long size) { @@ -3943,12 +2767,14 @@ done: Py_XDECREF(py_name_list); return (PyTypeObject *)result; } -""" +"""] #------------------------------------------------------------------------------------ -set_vtable_utility_code = \ +set_vtable_utility_code = [ """ +static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/ +""",""" static int __Pyx_SetVtable(PyObject *dict, void *vtable) { PyObject *pycobj = 0; int result; @@ -3967,12 +2793,14 @@ done: Py_XDECREF(pycobj); return result; } -""" +"""] #------------------------------------------------------------------------------------ -get_vtable_utility_code = \ -r""" +get_vtable_utility_code = [ +""" +static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/ +""",r""" static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) { int result; PyObject *pycobj; @@ -3992,12 +2820,14 @@ done: Py_XDECREF(pycobj); return result; } -""" +"""] #------------------------------------------------------------------------------------ -init_intern_tab_utility_code = \ +init_intern_tab_utility_code = [ """ +static int __Pyx_InternStrings(__Pyx_InternTabEntry *t); /*proto*/ +""",""" static int __Pyx_InternStrings(__Pyx_InternTabEntry *t) { while (t->p) { *t->p = PyString_InternFromString(t->s); @@ -4007,12 +2837,14 @@ static int __Pyx_InternStrings(__Pyx_InternTabEntry *t) { } return 0; } -"""; +"""] #------------------------------------------------------------------------------------ -init_string_tab_utility_code = \ +init_string_tab_utility_code = [ """ +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/ +""",""" static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { while (t->p) { *t->p = PyString_FromStringAndSize(t->s, t->n - 1); @@ -4022,6 +2854,6 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { } return 0; } -"""; +"""] #------------------------------------------------------------------------------------ diff --git a/Cython/Compiler/Parsing.py b/Cython/Compiler/Parsing.py index 827c2559..22bb490e 100644 --- a/Cython/Compiler/Parsing.py +++ b/Cython/Compiler/Parsing.py @@ -8,6 +8,7 @@ from types import ListType, TupleType from Scanning import PyrexScanner import Nodes import ExprNodes +from ModuleNode import ModuleNode from Errors import error, InternalError def p_ident(s, message = "Expected an identifier"): @@ -413,13 +414,7 @@ def p_atom(s): elif sy == '`': return p_backquote_expr(s) elif sy == 'INT': - digits = s.systring - if digits[:2] == "0x": - value = long(digits[2:], 16) - elif digits[:1] == "0": - value = int(digits, 8) - else: - value = int(s.systring) + value = s.systring s.next() return ExprNodes.IntNode(pos, value = value) elif sy == 'LONG': @@ -517,7 +512,7 @@ def p_string_literal(s): elif c == '\n': pass else: - chars.append(systr[1:]) + chars.append(r'\\' + systr[1:]) elif sy == 'NEWLINE': chars.append(r'\n') elif sy == 'END_STRING': @@ -668,7 +663,6 @@ def p_expression_or_assignment(s): if len(nodes) == 1: return nodes[0] else: - #return Nodes.StatListNode(nodes[0].pos, stats = nodes) return Nodes.ParallelAssignmentNode(nodes[0].pos, stats = nodes) def flatten_parallel_assignments(input, output): @@ -1375,19 +1369,19 @@ def p_exception_value_clause(s): if s.sy == '?': exc_check = 1 s.next() - exc_val = p_exception_value(s) + exc_val = p_simple_expr(s) #p_exception_value(s) return exc_val, exc_check -def p_exception_value(s): - sign = "" - if s.sy == "-": - sign = "-" - s.next() - if s.sy in ('INT', 'LONG', 'FLOAT', 'NULL'): - s.systring = sign + s.systring - return p_atom(s) - else: - s.error("Exception value must be an int or float literal or NULL") +#def p_exception_value(s): +# sign = "" +# if s.sy == "-": +# sign = "-" +# s.next() +# if s.sy in ('INT', 'LONG', 'FLOAT', 'NULL'): +# s.systring = sign + s.systring +# return p_atom(s) +# else: +# s.error("Exception value must be an int or float literal or NULL") c_arg_list_terminators = ('*', '**', '.', ')') c_arg_list_trailers = ('.', '*', '**') @@ -1780,7 +1774,7 @@ def p_module(s, pxd): if s.sy <> 'EOF': s.error("Syntax error in statement [%s,%s]" % ( repr(s.sy), repr(s.systring))) - return Nodes.ModuleNode(pos, doc = doc, body = body) + return ModuleNode(pos, doc = doc, body = body) #---------------------------------------------- # diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py index 88576642..e0e35947 100644 --- a/Cython/Compiler/PyrexTypes.py +++ b/Cython/Compiler/PyrexTypes.py @@ -259,14 +259,14 @@ class CType(PyrexType): from_py_function = None -class CSimpleType(CType): - # - # Base class for all unstructured C types. - # - pass +#class CSimpleType(CType): +# # +# # Base class for all unstructured C types. +# # +# pass -class CVoidType(CSimpleType): +class CVoidType(CType): is_void = 1 def __repr__(self): @@ -313,9 +313,6 @@ class CNumericType(CType): u = "unsigned " return "" % (u, rank_to_type_name[self.rank]) - def assignable_from_resolved_type(self, src_type): - return src_type.is_numeric or src_type is error_type - def declaration_code(self, entity_code, for_display = 0, dll_linkage = None, pyrex = 0): if self.signed: @@ -324,8 +321,6 @@ class CNumericType(CType): u = "unsigned " base = public_decl(u + rank_to_type_name[self.rank], dll_linkage) return "%s %s" % (base, entity_code) - -# return "%s%s %s" % (u, rank_to_type_name[self.rank], entity_code) class CIntType(CNumericType): @@ -338,6 +333,9 @@ class CIntType(CNumericType): def __init__(self, rank, signed, pymemberdef_typecode = None, is_returncode = 0): CNumericType.__init__(self, rank, signed, pymemberdef_typecode) self.is_returncode = is_returncode + + def assignable_from_resolved_type(self, src_type): + return src_type.is_int or src_type.is_enum or src_type is error_type class CUIntType(CIntType): @@ -373,6 +371,9 @@ class CFloatType(CNumericType): def __init__(self, rank, pymemberdef_typecode = None): CNumericType.__init__(self, rank, 1, pymemberdef_typecode) + def assignable_from_resolved_type(self, src_type): + return src_type.is_numeric or src_type is error_type + class CArrayType(CType): # base_type CType Element type @@ -447,6 +448,8 @@ class CPtrType(CType): return 1 elif self.base_type.is_cfunction and other_type.is_cfunction: return self.base_type.same_as(other_type) + elif other_type.is_array: + return self.base_type.same_as(other_type.base_type) elif not other_type.is_ptr: return 0 elif self.base_type.is_void: @@ -608,14 +611,16 @@ class CStructOrUnionType(CType): return self.is_complete() -class CEnumType(CIntType): +class CEnumType(CType): # name string # cname string or None # typedef_flag boolean is_enum = 1 - signed = 1 - rank = 2 + #signed = 1 + #rank = 2 + to_py_function = "PyInt_FromLong" + from_py_function = "PyInt_AsLong" def __init__(self, name, cname, typedef_flag): self.name = name diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py index 6ae4e3bf..3ac9218c 100644 --- a/Cython/Compiler/Symtab.py +++ b/Cython/Compiler/Symtab.py @@ -61,6 +61,7 @@ class Entry: # interned_cname string C name of interned name string # pystring_cname string C name of Python version of string literal # is_interned boolean For string const entries, value is interned + # used boolean borrowed = 0 init = "" @@ -91,6 +92,7 @@ class Entry: interned_cname = None pystring_cname = None is_interned = 0 + used = 0 def __init__(self, name, cname, type, pos = None, init = None): self.name = name @@ -351,6 +353,7 @@ class Scope: # Add an entry for a string constant. cname = self.new_const_cname() entry = Entry("", cname, c_char_array_type, init = value) + entry.used = 1 self.const_entries.append(entry) return entry @@ -395,6 +398,7 @@ class Scope: self.temp_counter = n + 1 cname = "%s%d" % (Naming.pyrex_prefix, n) entry = Entry("", cname, type) + entry.used = 1 if type.is_pyobject: entry.init = "0" self.cname_to_entry[entry.cname] = entry @@ -476,6 +480,7 @@ class ModuleScope(Scope): # intern_map {string : string} Mapping from Python names to interned strs # interned_names [string] Interned names pending generation of declarations # all_pystring_entries [Entry] Python string consts from all scopes + # types_imported {PyrexType : 1} Set of types for which import code generated def __init__(self, name, parent_module, context): self.parent_module = parent_module @@ -500,6 +505,7 @@ class ModuleScope(Scope): self.intern_map = {} self.interned_names = [] self.all_pystring_entries = [] + self.types_imported = {} def qualifying_scope(self): return self.parent_module @@ -565,6 +571,8 @@ class ModuleScope(Scope): # None if previously declared as something else. entry = self.lookup_here(name) if entry: + if entry.is_pyglobal and entry.as_module is scope: + return entry # Already declared as the same module if not (entry.is_pyglobal and not entry.as_module): error(pos, "'%s' redeclared" % name) return None @@ -956,6 +964,8 @@ class CClassScope(ClassScope): if visibility in ('public', 'readonly'): if type.pymemberdef_typecode: self.public_attr_entries.append(entry) + if name == "__weakref__": + error(pos, "Special attribute __weakref__ cannot be exposed to Python") else: error(pos, "C attribute of type '%s' cannot be accessed from Python" % type) diff --git a/Cython/Compiler/Version.py b/Cython/Compiler/Version.py index da966589..be15e839 100644 --- a/Cython/Compiler/Version.py +++ b/Cython/Compiler/Version.py @@ -1 +1 @@ -version = '0.9.4.1' +version = '0.9.5.1a' diff --git a/Cython/Mac/DarwinSystem.py b/Cython/Mac/DarwinSystem.py index aa34b0d2..030dea0e 100644 --- a/Cython/Mac/DarwinSystem.py +++ b/Cython/Mac/DarwinSystem.py @@ -4,7 +4,8 @@ verbose = 0 gcc_pendantic = True -gcc_warnings_are_errors = False +gcc_warnings_are_errors = True +gcc_all_warnings = True import os from Pyrex.Utils import replace_suffix @@ -23,6 +24,9 @@ if gcc_pendantic: compiler_options.extend(["-pedantic", "-Wno-long-long"]) if gcc_warnings_are_errors: compiler_options.append("-Werror") +if gcc_all_warnings: + compiler_options.append("-Wall") + compiler_options.append("-Wno-unused-function") linkers = ["gcc", "g++"] linker_options = \ @@ -45,6 +49,7 @@ def c_compile(c_file, verbose_flag = 0, cplus = 0, obj_suffix = ".o"): args = [compiler] + compiler_options + include_options + [c_file, "-o", o_file] if verbose_flag or verbose: print " ".join(args) + #print compiler, args ### status = os.spawnvp(os.P_WAIT, compiler, args) if status <> 0: raise CCompilerError("C compiler returned status %s" % status) diff --git a/Cython/Mac/Finder_Std_Suite.py b/Cython/Mac/Finder_Std_Suite.py deleted file mode 100644 index 1cec7d80..00000000 --- a/Cython/Mac/Finder_Std_Suite.py +++ /dev/null @@ -1,768 +0,0 @@ -"""Suite Standard Suite: Common terms for most applications -Level 1, version 1 - -Generated from Macintosh HD:System 8.0:Finder -AETE/AEUT resource version 0/144, language 0, script 0 -""" - -import aetools -import MacOS - -_code = 'core' - -class Finder_Std_Suite: - - _argmap_class_info = { - '_in' : 'wrcd', - } - - def class_info(self, _object=None, _attributes={}, **_arguments): - """class info: Get information about an object class - Required argument: the object class about which information is requested - Keyword argument _in: the human language and script system in which to return information - Keyword argument _attributes: AppleEvent attribute dictionary - Returns: a record containing the object's properties and elements - """ - _code = 'core' - _subcode = 'qobj' - - aetools.keysubst(_arguments, self._argmap_class_info) - _arguments['----'] = _object - - - _reply, _arguments, _attributes = self.send(_code, _subcode, - _arguments, _attributes) - if _arguments.has_key('errn'): - raise aetools.Error, aetools.decodeerror(_arguments) - # XXXX Optionally decode result - if _arguments.has_key('----'): - return _arguments['----'] - - _argmap_close = { - 'saving' : 'savo', - 'saving_in' : 'kfil', - } - - def close(self, _object, _attributes={}, **_arguments): - """close: Close an object - Required argument: the object to close - Keyword argument saving: specifies whether changes should be saved before closing - Keyword argument saving_in: the file in which to save the object - Keyword argument _attributes: AppleEvent attribute dictionary - """ - _code = 'core' - _subcode = 'clos' - - aetools.keysubst(_arguments, self._argmap_close) - _arguments['----'] = _object - - aetools.enumsubst(_arguments, 'savo', _Enum_savo) - - _reply, _arguments, _attributes = self.send(_code, _subcode, - _arguments, _attributes) - if _arguments.has_key('errn'): - raise aetools.Error, aetools.decodeerror(_arguments) - # XXXX Optionally decode result - if _arguments.has_key('----'): - return _arguments['----'] - - _argmap_count = { - 'each' : 'kocl', - } - - def count(self, _object, _attributes={}, **_arguments): - """count: Return the number of elements of a particular class within an object - Required argument: the object whose elements are to be counted - Keyword argument each: the class of the elements to be counted - Keyword argument _attributes: AppleEvent attribute dictionary - Returns: the number of elements - """ - _code = 'core' - _subcode = 'cnte' - - aetools.keysubst(_arguments, self._argmap_count) - _arguments['----'] = _object - - - _reply, _arguments, _attributes = self.send(_code, _subcode, - _arguments, _attributes) - if _arguments.has_key('errn'): - raise aetools.Error, aetools.decodeerror(_arguments) - # XXXX Optionally decode result - if _arguments.has_key('----'): - return _arguments['----'] - - _argmap_data_size = { - 'as' : 'rtyp', - } - - def data_size(self, _object, _attributes={}, **_arguments): - """data size: Return the size in bytes of an object - Required argument: the object whose data size is to be returned - Keyword argument as: the data type for which the size is calculated - Keyword argument _attributes: AppleEvent attribute dictionary - Returns: the size of the object in bytes - """ - _code = 'core' - _subcode = 'dsiz' - - aetools.keysubst(_arguments, self._argmap_data_size) - _arguments['----'] = _object - - - _reply, _arguments, _attributes = self.send(_code, _subcode, - _arguments, _attributes) - if _arguments.has_key('errn'): - raise aetools.Error, aetools.decodeerror(_arguments) - # XXXX Optionally decode result - if _arguments.has_key('----'): - return _arguments['----'] - - def delete(self, _object, _attributes={}, **_arguments): - """delete: Delete an element from an object - Required argument: the element to delete - Keyword argument _attributes: AppleEvent attribute dictionary - """ - _code = 'core' - _subcode = 'delo' - - if _arguments: raise TypeError, 'No optional args expected' - _arguments['----'] = _object - - - _reply, _arguments, _attributes = self.send(_code, _subcode, - _arguments, _attributes) - if _arguments.has_key('errn'): - raise aetools.Error, aetools.decodeerror(_arguments) - # XXXX Optionally decode result - if _arguments.has_key('----'): - return _arguments['----'] - - _argmap_duplicate = { - 'to' : 'insh', - 'replacing' : 'alrp', - 'routing_suppressed' : 'rout', - } - - def duplicate(self, _object, _attributes={}, **_arguments): - """duplicate: Duplicate object(s) - Required argument: the object(s) to duplicate - Keyword argument to: the new location for the object(s) - Keyword argument replacing: Specifies whether or not to replace items in the destination that have the same name as items being duplicated - Keyword argument routing_suppressed: Specifies whether or not to autoroute items (default is false). Only applies when copying to the system folder. - Keyword argument _attributes: AppleEvent attribute dictionary - Returns: to the duplicated object(s) - """ - _code = 'core' - _subcode = 'clon' - - aetools.keysubst(_arguments, self._argmap_duplicate) - _arguments['----'] = _object - - aetools.enumsubst(_arguments, 'alrp', _Enum_bool) - aetools.enumsubst(_arguments, 'rout', _Enum_bool) - - _reply, _arguments, _attributes = self.send(_code, _subcode, - _arguments, _attributes) - if _arguments.has_key('errn'): - raise aetools.Error, aetools.decodeerror(_arguments) - # XXXX Optionally decode result - if _arguments.has_key('----'): - return _arguments['----'] - - _argmap_event_info = { - '_in' : 'wrcd', - } - - def event_info(self, _object, _attributes={}, **_arguments): - """event info: Get information about the Apple events in a suite - Required argument: the event class of the Apple events for which to return information - Keyword argument _in: the human language and script system in which to return information - Keyword argument _attributes: AppleEvent attribute dictionary - Returns: a record containing the events and their parameters - """ - _code = 'core' - _subcode = 'gtei' - - aetools.keysubst(_arguments, self._argmap_event_info) - _arguments['----'] = _object - - - _reply, _arguments, _attributes = self.send(_code, _subcode, - _arguments, _attributes) - if _arguments.has_key('errn'): - raise aetools.Error, aetools.decodeerror(_arguments) - # XXXX Optionally decode result - if _arguments.has_key('----'): - return _arguments['----'] - - def exists(self, _object, _attributes={}, **_arguments): - """exists: Verify if an object exists - Required argument: the object in question - Keyword argument _attributes: AppleEvent attribute dictionary - Returns: true if it exists, false if not - """ - _code = 'core' - _subcode = 'doex' - - if _arguments: raise TypeError, 'No optional args expected' - _arguments['----'] = _object - - - _reply, _arguments, _attributes = self.send(_code, _subcode, - _arguments, _attributes) - if _arguments.has_key('errn'): - raise aetools.Error, aetools.decodeerror(_arguments) - # XXXX Optionally decode result - if _arguments.has_key('----'): - return _arguments['----'] - - _argmap_get = { - 'as' : 'rtyp', - } - - def get(self, _object, _attributes={}, **_arguments): - """get: Get the data for an object - Required argument: the object whose data is to be returned - Keyword argument as: the desired types for the data, in order of preference - Keyword argument _attributes: AppleEvent attribute dictionary - Returns: the data from the object - """ - _code = 'core' - _subcode = 'getd' - - aetools.keysubst(_arguments, self._argmap_get) - _arguments['----'] = _object - - - _reply, _arguments, _attributes = self.send(_code, _subcode, - _arguments, _attributes) - if _arguments.has_key('errn'): - raise aetools.Error, aetools.decodeerror(_arguments) - # XXXX Optionally decode result - if _arguments.has_key('----'): - return _arguments['----'] - - _argmap_make = { - 'new' : 'kocl', - 'at' : 'insh', - 'to' : 'to ', - 'with_data' : 'data', - 'with_properties' : 'prdt', - } - - def make(self, _no_object=None, _attributes={}, **_arguments): - """make: Make a new element - Keyword argument new: the class of the new element - Keyword argument at: the location at which to insert the element - Keyword argument to: when creating an alias file, the original item to create an alias to - Keyword argument with_data: the initial data for the element - Keyword argument with_properties: the initial values for the properties of the element - Keyword argument _attributes: AppleEvent attribute dictionary - Returns: to the new object(s) - """ - _code = 'core' - _subcode = 'crel' - - aetools.keysubst(_arguments, self._argmap_make) - if _no_object != None: raise TypeError, 'No direct arg expected' - - - _reply, _arguments, _attributes = self.send(_code, _subcode, - _arguments, _attributes) - if _arguments.has_key('errn'): - raise aetools.Error, aetools.decodeerror(_arguments) - # XXXX Optionally decode result - if _arguments.has_key('----'): - return _arguments['----'] - - _argmap_move = { - 'to' : 'insh', - 'replacing' : 'alrp', - 'positioned_at' : 'mvpl', - 'routing_suppressed' : 'rout', - } - - def move(self, _object, _attributes={}, **_arguments): - """move: Move object(s) to a new location - Required argument: the object(s) to move - Keyword argument to: the new location for the object(s) - Keyword argument replacing: Specifies whether or not to replace items in the destination that have the same name as items being moved - Keyword argument positioned_at: Gives a list (in local window coordinates) of positions for the destination items - Keyword argument routing_suppressed: Specifies whether or not to autoroute items (default is false). Only applies when moving to the system folder. - Keyword argument _attributes: AppleEvent attribute dictionary - Returns: to the object(s) after they have been moved - """ - _code = 'core' - _subcode = 'move' - - aetools.keysubst(_arguments, self._argmap_move) - _arguments['----'] = _object - - aetools.enumsubst(_arguments, 'alrp', _Enum_bool) - aetools.enumsubst(_arguments, 'mvpl', _Enum_list) - aetools.enumsubst(_arguments, 'rout', _Enum_bool) - - _reply, _arguments, _attributes = self.send(_code, _subcode, - _arguments, _attributes) - if _arguments.has_key('errn'): - raise aetools.Error, aetools.decodeerror(_arguments) - # XXXX Optionally decode result - if _arguments.has_key('----'): - return _arguments['----'] - - _argmap_open = { - 'using' : 'usin', - 'with_properties' : 'prdt', - } - - def open(self, _object, _attributes={}, **_arguments): - """open: Open the specified object(s) - Required argument: list of objects to open - Keyword argument using: the application file to open the object with - Keyword argument with_properties: the initial values for the properties, to be sent along with the open event sent to the application that opens the direct object - Keyword argument _attributes: AppleEvent attribute dictionary - """ - _code = 'aevt' - _subcode = 'odoc' - - aetools.keysubst(_arguments, self._argmap_open) - _arguments['----'] = _object - - - _reply, _arguments, _attributes = self.send(_code, _subcode, - _arguments, _attributes) - if _arguments.has_key('errn'): - raise aetools.Error, aetools.decodeerror(_arguments) - # XXXX Optionally decode result - if _arguments.has_key('----'): - return _arguments['----'] - - def _print(self, _object, _attributes={}, **_arguments): - """print: Print the specified object(s) - Required argument: list of objects to print - Keyword argument _attributes: AppleEvent attribute dictionary - """ - _code = 'aevt' - _subcode = 'pdoc' - - if _arguments: raise TypeError, 'No optional args expected' - _arguments['----'] = _object - - - _reply, _arguments, _attributes = self.send(_code, _subcode, - _arguments, _attributes) - if _arguments.has_key('errn'): - raise aetools.Error, aetools.decodeerror(_arguments) - # XXXX Optionally decode result - if _arguments.has_key('----'): - return _arguments['----'] - - _argmap_quit = { - 'saving' : 'savo', - } - - def quit(self, _no_object=None, _attributes={}, **_arguments): - """quit: Quit the Finder (direct parameter ignored) - Keyword argument saving: specifies whether to save currently open documents (not supported by Finder) - Keyword argument _attributes: AppleEvent attribute dictionary - """ - _code = 'aevt' - _subcode = 'quit' - - aetools.keysubst(_arguments, self._argmap_quit) - if _no_object != None: raise TypeError, 'No direct arg expected' - - aetools.enumsubst(_arguments, 'savo', _Enum_savo) - - _reply, _arguments, _attributes = self.send(_code, _subcode, - _arguments, _attributes) - if _arguments.has_key('errn'): - raise aetools.Error, aetools.decodeerror(_arguments) - # XXXX Optionally decode result - if _arguments.has_key('----'): - return _arguments['----'] - - _argmap_save = { - '_in' : 'kfil', - 'as' : 'fltp', - } - - def save(self, _object, _attributes={}, **_arguments): - """save: Save an object (Not supported by Finder) - Required argument: the object to save - Keyword argument _in: the file in which to save the object (not supported by Finder) - Keyword argument as: the file type of the document in which to save the data (not supported by Finder) - Keyword argument _attributes: AppleEvent attribute dictionary - """ - _code = 'core' - _subcode = 'save' - - aetools.keysubst(_arguments, self._argmap_save) - _arguments['----'] = _object - - - _reply, _arguments, _attributes = self.send(_code, _subcode, - _arguments, _attributes) - if _arguments.has_key('errn'): - raise aetools.Error, aetools.decodeerror(_arguments) - # XXXX Optionally decode result - if _arguments.has_key('----'): - return _arguments['----'] - - _argmap_set = { - 'to' : 'data', - } - - def set(self, _object, _attributes={}, **_arguments): - """set: Set an object's data - Required argument: the object to change - Keyword argument to: the new value - Keyword argument _attributes: AppleEvent attribute dictionary - """ - _code = 'core' - _subcode = 'setd' - - aetools.keysubst(_arguments, self._argmap_set) - _arguments['----'] = _object - - - _reply, _arguments, _attributes = self.send(_code, _subcode, - _arguments, _attributes) - if _arguments.has_key('errn'): - raise aetools.Error, aetools.decodeerror(_arguments) - # XXXX Optionally decode result - if _arguments.has_key('----'): - return _arguments['----'] - - _argmap_suite_info = { - '_in' : 'wrcd', - } - - def suite_info(self, _object, _attributes={}, **_arguments): - """suite info: Get information about event suite(s) - Required argument: the suite for which to return information - Keyword argument _in: the human language and script system in which to return information - Keyword argument _attributes: AppleEvent attribute dictionary - Returns: a record containing the suites and their versions - """ - _code = 'core' - _subcode = 'gtsi' - - aetools.keysubst(_arguments, self._argmap_suite_info) - _arguments['----'] = _object - - - _reply, _arguments, _attributes = self.send(_code, _subcode, - _arguments, _attributes) - if _arguments.has_key('errn'): - raise aetools.Error, aetools.decodeerror(_arguments) - # XXXX Optionally decode result - if _arguments.has_key('----'): - return _arguments['----'] - - -class application(aetools.ComponentItem): - """application - An application program""" - want = 'capp' -class about_this_computer(aetools.NProperty): - """about this computer - the "About this Computer" dialog and the list of running processes displayed in it""" - which = 'abbx' - want = 'obj ' -class apple_menu_items_folder(aetools.NProperty): - """apple menu items folder - the special folder named "Apple Menu Items," the contents of which appear in the Apple menu""" - which = 'amnu' - want = 'obj ' -class clipboard(aetools.NProperty): - """clipboard - the Finder's clipboard window""" - which = 'pcli' - want = 'obj ' -class control_panels_folder(aetools.NProperty): - """control panels folder - the special folder named 'Control Panels'""" - which = 'ctrl' - want = 'obj ' -class desktop(aetools.NProperty): - """desktop - the desktop""" - which = 'desk' - want = 'obj ' -class extensions_folder(aetools.NProperty): - """extensions folder - the special folder named 'Extensions'""" - which = 'extn' - want = 'obj ' -class file_sharing(aetools.NProperty): - """file sharing - Is file sharing on?""" - which = 'fshr' - want = 'bool' -class Finder_preferences(aetools.NProperty): - """Finder preferences - Various preferences that apply to the Finder as a whole""" - which = 'pfrp' - want = 'obj ' -class fonts_folder(aetools.NProperty): - """fonts folder - the special folder named 'Fonts'""" - which = 'ffnt' - want = 'obj ' -class frontmost(aetools.NProperty): - """frontmost - Is the Finder the frontmost process?""" - which = 'pisf' - want = 'bool' -class insertion_location(aetools.NProperty): - """insertion location - the container in which a new folder would appear if "New Folder" was selected""" - which = 'pins' - want = 'obj ' -class largest_free_block(aetools.NProperty): - """largest free block - the largest free block of process memory available to launch an application""" - which = 'mfre' - want = 'long' -class preferences_folder(aetools.NProperty): - """preferences folder - the special folder named 'Preferences'""" - which = 'pref' - want = 'obj ' -class product_version(aetools.NProperty): - """product version - the version of the System software running on this computer""" - which = 'ver2' - want = 'itxt' -class selection(aetools.NProperty): - """selection - the selection visible to the user""" - which = 'sele' - want = 'obj ' -class sharing_starting_up(aetools.NProperty): - """sharing starting up - Is file sharing in the process of starting up?""" - which = 'fsup' - want = 'bool' -class shutdown_items_folder(aetools.NProperty): - """shutdown items folder - the special folder named 'Shutdown Items'""" - which = 'shdf' - want = 'obj ' -class startup_items_folder(aetools.NProperty): - """startup items folder - the special folder named 'Startup Items'""" - which = 'strt' - want = 'obj ' -class system_folder(aetools.NProperty): - """system folder - the System folder""" - which = 'macs' - want = 'obj ' -class temporary_items_folder(aetools.NProperty): - """temporary items folder - the special folder named "Temporary Items" (invisible)""" - which = 'temp' - want = 'obj ' -class version(aetools.NProperty): - """version - the version of the Finder""" - which = 'vers' - want = 'itxt' -class view_preferences(aetools.NProperty): - """view preferences - backwards compatibility with Finder Scripting Extension. DEPRECATED -- not supported after Finder 8.0""" - which = 'pvwp' - want = 'obj ' -class visible(aetools.NProperty): - """visible - Is the Finder's layer visible?""" - which = 'pvis' - want = 'bool' -# element 'dsut' as ['indx', 'name'] -# element 'alia' as ['indx', 'name'] -# element 'appf' as ['indx', 'name', 'ID '] -# element 'clpf' as ['indx', 'name'] -# element 'lwnd' as ['indx', 'name'] -# element 'ctnr' as ['indx', 'name'] -# element 'cwnd' as ['indx', 'name'] -# element 'dwnd' as ['indx', 'name'] -# element 'ccdv' as ['indx', 'name'] -# element 'dafi' as ['indx', 'name'] -# element 'cdsk' as ['indx', 'name'] -# element 'cdis' as ['indx', 'name', 'ID '] -# element 'docf' as ['indx', 'name'] -# element 'file' as ['indx', 'name'] -# element 'cfol' as ['indx', 'name', 'ID '] -# element 'fntf' as ['indx', 'name'] -# element 'fsut' as ['indx', 'name'] -# element 'iwnd' as ['indx', 'name'] -# element 'cobj' as ['indx', 'name'] -# element 'sctr' as ['indx', 'name'] -# element 'swnd' as ['indx', 'name'] -# element 'sndf' as ['indx', 'name'] -# element 'qwnd' as ['indx', 'name'] -# element 'stcs' as ['indx', 'name'] -# element 'ctrs' as ['indx', 'name'] -# element 'cwin' as ['indx', 'name'] - -class file(aetools.ComponentItem): - """file - A file""" - want = 'file' -class creator_type(aetools.NProperty): - """creator type - the OSType identifying the application that created the item""" - which = 'fcrt' - want = 'type' -class file_type_obsolete(aetools.NProperty): - """file type obsolete - the OSType identifying the type of data contained in the item (DEPRECATED - for use with scripts compiled before Finder 8.0. Will be removed in the next release)""" - which = 'fitp' - want = 'type' -class file_type(aetools.NProperty): - """file type - the OSType identifying the type of data contained in the item""" - which = 'asty' - want = 'type' -class locked_obsolete(aetools.NProperty): - """locked obsolete - Is the file locked? (DEPRECATED - for use with scripts compiled before Finder 8.0. Will be removed in the next release)""" - which = 'islk' - want = 'bool' -class locked(aetools.NProperty): - """locked - Is the file locked?""" - which = 'aslk' - want = 'bool' -# repeated property product_version the version of the product (visible at the top of the "Get Info" window) -class stationery(aetools.NProperty): - """stationery - Is the file a stationery pad?""" - which = 'pspd' - want = 'bool' -# repeated property version the version of the file (visible at the bottom of the "Get Info" window) - -files = file - -class window(aetools.ComponentItem): - """window - A window""" - want = 'cwin' -class collapsed(aetools.NProperty): - """collapsed - Is the window collapsed (only applies to non-pop-up windows)?""" - which = 'wshd' - want = 'bool' -class popup(aetools.NProperty): - """popup - Is the window is a pop-up window?""" - which = 'drwr' - want = 'bool' -class pulled_open(aetools.NProperty): - """pulled open - Is the window pulled open (only applies to pop-up windows)?""" - which = 'pull' - want = 'bool' -# repeated property visible Is the window visible (always true for Finder windows)? -class zoomed_full_size(aetools.NProperty): - """zoomed full size - Is the window zoomed to the full size of the screen? (can only be set, not read)""" - which = 'zumf' - want = 'bool' - -windows = window -# XXXX application element 'dsut' not found!! -# XXXX application element 'alia' not found!! -# XXXX application element 'appf' not found!! -# XXXX application element 'clpf' not found!! -# XXXX application element 'lwnd' not found!! -# XXXX application element 'ctnr' not found!! -# XXXX application element 'cwnd' not found!! -# XXXX application element 'dwnd' not found!! -# XXXX application element 'ccdv' not found!! -# XXXX application element 'dafi' not found!! -# XXXX application element 'cdsk' not found!! -# XXXX application element 'cdis' not found!! -# XXXX application element 'docf' not found!! -# XXXX application element 'cfol' not found!! -# XXXX application element 'fntf' not found!! -# XXXX application element 'fsut' not found!! -# XXXX application element 'iwnd' not found!! -# XXXX application element 'cobj' not found!! -# XXXX application element 'sctr' not found!! -# XXXX application element 'swnd' not found!! -# XXXX application element 'sndf' not found!! -# XXXX application element 'qwnd' not found!! -# XXXX application element 'stcs' not found!! -# XXXX application element 'ctrs' not found!! -application._propdict = { - 'about_this_computer' : about_this_computer, - 'apple_menu_items_folder' : apple_menu_items_folder, - 'clipboard' : clipboard, - 'control_panels_folder' : control_panels_folder, - 'desktop' : desktop, - 'extensions_folder' : extensions_folder, - 'file_sharing' : file_sharing, - 'Finder_preferences' : Finder_preferences, - 'fonts_folder' : fonts_folder, - 'frontmost' : frontmost, - 'insertion_location' : insertion_location, - 'largest_free_block' : largest_free_block, - 'preferences_folder' : preferences_folder, - 'product_version' : product_version, - 'selection' : selection, - 'sharing_starting_up' : sharing_starting_up, - 'shutdown_items_folder' : shutdown_items_folder, - 'startup_items_folder' : startup_items_folder, - 'system_folder' : system_folder, - 'temporary_items_folder' : temporary_items_folder, - 'version' : version, - 'view_preferences' : view_preferences, - 'visible' : visible, -} -application._elemdict = { - 'file' : file, - 'window' : window, -} -file._propdict = { - 'creator_type' : creator_type, - 'file_type_obsolete' : file_type_obsolete, - 'file_type' : file_type, - 'locked_obsolete' : locked_obsolete, - 'locked' : locked, - 'product_version' : product_version, - 'stationery' : stationery, - 'version' : version, -} -file._elemdict = { -} -window._propdict = { - 'collapsed' : collapsed, - 'popup' : popup, - 'pulled_open' : pulled_open, - 'visible' : visible, - 'zoomed_full_size' : zoomed_full_size, -} -window._elemdict = { -} -# XXXX enum list not found!! -# XXXX enum bool not found!! -# XXXX enum savo not found!! - -# -# Indices of types declared in this module -# -_classdeclarations = { - 'cwin' : window, - 'file' : file, - 'capp' : application, -} - -_propdeclarations = { - 'amnu' : apple_menu_items_folder, - 'pvwp' : view_preferences, - 'extn' : extensions_folder, - 'pins' : insertion_location, - 'fshr' : file_sharing, - 'aslk' : locked, - 'drwr' : popup, - 'fcrt' : creator_type, - 'pcli' : clipboard, - 'asty' : file_type, - 'strt' : startup_items_folder, - 'islk' : locked_obsolete, - 'pvis' : visible, - 'pref' : preferences_folder, - 'pisf' : frontmost, - 'sele' : selection, - 'temp' : temporary_items_folder, - 'pull' : pulled_open, - 'abbx' : about_this_computer, - 'wshd' : collapsed, - 'pspd' : stationery, - 'fitp' : file_type_obsolete, - 'pfrp' : Finder_preferences, - 'desk' : desktop, - 'fsup' : sharing_starting_up, - 'mfre' : largest_free_block, - 'ctrl' : control_panels_folder, - 'zumf' : zoomed_full_size, - 'shdf' : shutdown_items_folder, - 'ffnt' : fonts_folder, - 'macs' : system_folder, - 'ver2' : product_version, - 'vers' : version, -} - -_compdeclarations = { -} - -_enumdeclarations = { -} diff --git a/Cython/Mac/MPW_Misc_Suite.py b/Cython/Mac/MPW_Misc_Suite.py deleted file mode 100644 index a11f59d9..00000000 --- a/Cython/Mac/MPW_Misc_Suite.py +++ /dev/null @@ -1,49 +0,0 @@ -"""Suite Misc Suite: Suite that adds additional features to the Application. -Level 1, version 1 - -Generated from MPW:MPW Shell -AETE/AEUT resource version 1/0, language 0, script 0 -""" - -import aetools -import MacOS - -_code = 'misc' - -class MPW_Misc_Suite: - - def DoScript(self, _object, _attributes={}, **_arguments): - """DoScript: Execute an MPW command, any command that could be executed from the command line can be sent as a script. - Required argument: The script to execute - Keyword argument _attributes: AppleEvent attribute dictionary - """ - _code = 'misc' - _subcode = 'dosc' - - if _arguments: raise TypeError, 'No optional args expected' - _arguments['----'] = _object - - - _reply, _arguments, _attributes = self.send(_code, _subcode, - _arguments, _attributes) - if _arguments.has_key('errn'): - raise aetools.Error, aetools.decodeerror(_arguments) - # XXXX Optionally decode result - if _arguments.has_key('----'): - return _arguments['----'] - - -# -# Indices of types declared in this module -# -_classdeclarations = { -} - -_propdeclarations = { -} - -_compdeclarations = { -} - -_enumdeclarations = { -} diff --git a/Cython/Mac/Makefile b/Cython/Mac/Makefile new file mode 100644 index 00000000..a7ca34b3 --- /dev/null +++ b/Cython/Mac/Makefile @@ -0,0 +1,19 @@ +# Makefile for Darwin + +# Change this to your Python source location +PYTHON := /Local/Build/Pythonic/python/2.3 + +INCLUDE := -I$(PYTHON) -I$(PYTHON)/Include -I$(PYTHON)/Mac/Include + +CCOPTS := -fno-strict-aliasing -Wno-long-double -no-cpp-precomp \ + -mno-fused-madd -fno-common -dynamic + +LDOPTS := -Wl,-F.,-w -bundle -framework Python -framework Carbon + +all: _File.so + +_File.o: _Filemodule_patched.c + gcc -c $(INCLUDE) $(OPTS) $< -o $@ + +_File.so: _File.o + gcc $(LDOPTS) $< -o $@ diff --git a/Cython/Mac/PS_Misc_Suite.py b/Cython/Mac/PS_Misc_Suite.py deleted file mode 100644 index d664ffe9..00000000 --- a/Cython/Mac/PS_Misc_Suite.py +++ /dev/null @@ -1,44 +0,0 @@ -"Apple Event suite for pyserver." - -import aetools -import MacOS - -_code = 'misc' - -class PS_Misc_Suite: - - def DoScript(self, _object, _attributes={}, **_arguments): - """DoScript: Execute a Python file, optionally with command line args. - Required argument: filename.py or [filename.py, arg, ...] - Keyword argument _attributes: AppleEvent attribute dictionary - """ - _code = 'misc' - _subcode = 'dosc' - - if _arguments: raise TypeError, 'No optional args expected' - _arguments['----'] = _object - - - _reply, _arguments, _attributes = self.send(_code, _subcode, - _arguments, _attributes) - if _arguments.has_key('errn'): - raise aetools.Error, aetools.decodeerror(_arguments) - # XXXX Optionally decode result - if _arguments.has_key('----'): - return _arguments['----'] - - -# -# Indices of types declared in this module -# -_classdeclarations = { -} - -_propdeclarations = { -} - -_compdeclarations = { -} - -_enumdeclarations = { -} diff --git a/Cython/Mac/PyServerMain.py b/Cython/Mac/PyServerMain.py deleted file mode 100644 index 9769d11e..00000000 --- a/Cython/Mac/PyServerMain.py +++ /dev/null @@ -1,86 +0,0 @@ -# -# Simple Apple-event driven Python interpreter -# - -import os, sys, traceback -from cStringIO import StringIO -from MiniAEFrame import AEServer, MiniApplication - -class PythonServer(AEServer, MiniApplication): - - def __init__(self): - MiniApplication.__init__(self) - AEServer.__init__(self) - self.installaehandler('aevt', 'oapp', ignore) - self.installaehandler('aevt', 'quit', quit) - self.installaehandler('misc', 'dosc', doscript) - - -def ignore(**kwds): - pass - -def quit(**kwds): - server._quit() - -def doscript(args, **kwds): - print "doscript:", repr(args) ### - stat = 0 - output = "" - errput = "" - #print "Normalising args" ### - if type(args) == type(""): - args = [args] - #print "Setting sys.argv" ### - sys.argv = args - #print "Finding script directory and module file" ### - dir = os.path.dirname(args[0]) - dir = os.path.join(start_dir, dir) - pyfile = os.path.basename(args[0]) - mod = os.path.splitext(pyfile)[0] - #print "dir:", repr(dir) ### - #print "mod:", repr(mod) ### - os.chdir(dir) - sys.path = start_path[:] - sys.path[0] = dir - #print "path:", sys.path ### - try: - sys.stdout = StringIO() - sys.stderr = StringIO() - try: - #sys.__stdout__.write("Path: %s\n" % sys.path) ### - #sys.__stdout__.write("Importing: %s\n" % mod) ### - try: - __import__(mod) - except KeyboardInterrupt: - raise - except SystemExit, exc: - #sys.__stdout__.write("Caught a SystemExit\n") ### - try: - stat = int(str(exc)) - except ValueError: - stat = 1 - #sys.__stdout__.write("stat = %s\n" % stat) ### - except: - traceback.print_exc() - stat = 1 - #sys.__stdout__.write("Done the import\n") ### - finally: - output = sys.stdout.getvalue() - #sys.__stdout__.write("Output:\n%s" % output) ### - errput = sys.stderr.getvalue() - finally: - sys.stdout = sys.__stdout__ - sys.stderr = sys.__stdout__ - pass - return [stat, output, errput] - -start_dir = os.getcwd() -start_path = sys.path[:] -server = PythonServer() -#print "Open for business" -try: - server.mainloop() -except: - traceback.print_exc() - #sys.exit(1) -#print "Closing shop" diff --git a/Cython/Mac/_Filemodule_patched.c b/Cython/Mac/_Filemodule_patched.c index 8e909367..d5aaf2b4 100644 --- a/Cython/Mac/_Filemodule_patched.c +++ b/Cython/Mac/_Filemodule_patched.c @@ -108,6 +108,15 @@ PyMac_BuildHFSUniStr255(HFSUniStr255 *itself) static PyObject *File_Error; +static PyTypeObject FInfo_Type; + +#define FInfo_Check(x) ((x)->ob_type == &FInfo_Type || PyObject_TypeCheck((x), &FInfo_Type)) + +typedef struct FInfoObject { + PyObject_HEAD + FInfo ob_itself; +} FInfoObject; + /* ------------------- Object type FSCatalogInfo -------------------- */ static PyTypeObject FSCatalogInfo_Type; @@ -338,16 +347,16 @@ static int FSCatalogInfo_set_userPrivileges(FSCatalogInfoObject *self, PyObject static PyObject *FSCatalogInfo_get_finderInfo(FSCatalogInfoObject *self, void *closure) { - return FInfo_New((FInfo *)self->finderInfo); + return FInfo_New((FInfo *)self->ob_itself.finderInfo); } static int FSCatalogInfo_set_finderInfo(FSCatalogInfoObject *self, PyObject *v, void *closure) { if (!FInfo_Check(v)) { - PyErr_SetString(PyTypeError, "Expected an FInfo object"); + PyErr_SetString(PyExc_TypeError, "Expected an FInfo object"); return -1; } - *(FInfo *)self->finderInfo = ((FInfoObject *)self)->ob_itself; + *(FInfo *)self->ob_itself.finderInfo = ((FInfoObject *)v)->ob_itself; return 0; } @@ -485,15 +494,6 @@ static PyTypeObject FSCatalogInfo_Type = { /* ----------------------- Object type FInfo ------------------------ */ -static PyTypeObject FInfo_Type; - -#define FInfo_Check(x) ((x)->ob_type == &FInfo_Type || PyObject_TypeCheck((x), &FInfo_Type)) - -typedef struct FInfoObject { - PyObject_HEAD - FInfo ob_itself; -} FInfoObject; - static PyObject *FInfo_New(FInfo *itself) { FInfoObject *it; @@ -3247,8 +3247,8 @@ PyMac_GetFSRef(PyObject *v, FSRef *fsr) if ( PyString_Check(v) || PyUnicode_Check(v)) { char *path = NULL; if (!PyArg_Parse(v, "et", Py_FileSystemDefaultEncoding, &path)) - return NULL; - if ( (err=FSPathMakeRef(path, fsr, NULL)) ) { + return 0; + if ( (err=FSPathMakeRef((unsigned char *)path, fsr, NULL)) ) { PyMac_Error(err); return 0; } diff --git a/Cython/Unix/LinuxSystem.py b/Cython/Unix/LinuxSystem.py new file mode 100644 index 00000000..e9722ff7 --- /dev/null +++ b/Cython/Unix/LinuxSystem.py @@ -0,0 +1,74 @@ +# +# Pyrex - Linux system interface +# + +verbose = 0 +gcc_pendantic = True +gcc_warnings_are_errors = True +gcc_all_warnings = True + +import os +from Pyrex.Utils import replace_suffix +from Pyrex.Compiler.Errors import PyrexError + +version = "%s.%s" % sys.version[:2] +py_include_dirs = [ + "%s/include/python%s" % (sys.prefix, version) +] + +compilers = ["gcc", "g++"] +compiler_options = \ + "-g -c -fno-strict-aliasing -Wno-long-double -no-cpp-precomp " \ + "-mno-fused-madd -fno-common -dynamic " \ + .split() +if gcc_pendantic: + compiler_options.extend(["-pedantic", "-Wno-long-long"]) +if gcc_warnings_are_errors: + compiler_options.append("-Werror") +if gcc_all_warnings: + compiler_options.append("-Wall") + compiler_options.append("-Wno-unused-function") + +linkers = ["gcc", "g++"] +linker_options = \ + "-shared" \ + .split() + +class CCompilerError(PyrexError): + pass + +def c_compile(c_file, verbose_flag = 0, cplus = 0, obj_suffix = ".o"): + # Compile the given C source file to produce + # an object file. Returns the pathname of the + # resulting file. + c_file = os.path.join(os.getcwd(), c_file) + o_file = replace_suffix(c_file, obj_suffix) + include_options = [] + for dir in py_include_dirs: + include_options.append("-I%s" % dir) + compiler = compilers[bool(cplus)] + args = [compiler] + compiler_options + include_options + [c_file, "-o", o_file] + if verbose_flag or verbose: + print " ".join(args) + #print compiler, args ### + status = os.spawnvp(os.P_WAIT, compiler, args) + if status <> 0: + raise CCompilerError("C compiler returned status %s" % status) + return o_file + +def c_link(obj_file, verbose_flag = 0, extra_objects = [], cplus = 0): + return c_link_list([obj_file] + extra_objects, verbose_flag, cplus) + +def c_link_list(obj_files, verbose_flag = 0, cplus = 0): + # Link the given object files into a dynamically + # loadable extension file. Returns the pathname + # of the resulting file. + out_file = replace_suffix(obj_files[0], ".so") + linker = linkers[bool(cplus)] + args = [linker] + linker_options + obj_files + ["-o", out_file] + if verbose_flag or verbose: + print " ".join(args) + status = os.spawnvp(os.P_WAIT, linker, args) + if status <> 0: + raise CCompilerError("Linker returned status %s" % status) + return out_file