void append_vala_array_free_loop() { var cforinit = new CCodeAssignment(new CCodeIdentifier("i"), new CCodeConstant("0")); var cforcond = new CCodeBinaryExpression(CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier("i"), new CCodeIdentifier("array_length")); var cforiter = new CCodeAssignment(new CCodeIdentifier("i"), new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, new CCodeIdentifier("i"), new CCodeConstant("1"))); ccode.open_for(cforinit, cforcond, cforiter); var cptrarray = new CCodeCastExpression(new CCodeIdentifier("array"), "gpointer*"); var cea = new CCodeElementAccess(cptrarray, new CCodeIdentifier("i")); var cfreecond = new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, cea, new CCodeConstant("NULL")); ccode.open_if(cfreecond); var cfreecall = new CCodeFunctionCall(new CCodeIdentifier("destroy_func")); cfreecall.add_argument(cea); ccode.add_expression(cfreecall); ccode.close(); }
void generate_marshaller(List <Parameter> _params, DataType return_type) { string signature; int n_params, i; /* check whether a signal with the same signature already exists for this source file (or predefined) */ signature = get_marshaller_signature(_params, return_type); if (predefined_marshal_set.Contains(signature) || user_marshal_set.Contains(signature)) { return; } var signal_marshaller = new CCodeFunction(get_marshaller_function(_params, return_type, null), "void"); signal_marshaller.modifiers = CCodeModifiers.STATIC; signal_marshaller.add_parameter(new CCodeParameter("closure", "GClosure *")); signal_marshaller.add_parameter(new CCodeParameter("return_value", "GValue *")); signal_marshaller.add_parameter(new CCodeParameter("n_param_values", "guint")); signal_marshaller.add_parameter(new CCodeParameter("param_values", "const GValue *")); signal_marshaller.add_parameter(new CCodeParameter("invocation_hint", "gpointer")); signal_marshaller.add_parameter(new CCodeParameter("marshal_data", "gpointer")); push_function(signal_marshaller); var callback_decl = new CCodeFunctionDeclarator(get_marshaller_function(_params, return_type, "GMarshalFunc")); callback_decl.add_parameter(new CCodeParameter("data1", "gpointer")); n_params = 1; foreach (Parameter p in _params) { callback_decl.add_parameter(new CCodeParameter("arg_%d".printf(n_params), get_value_type_name_from_parameter(p))); n_params++; if (p.variable_type.is_array()) { for (var j = 0; j < ((ArrayType)p.variable_type).rank; j++) { callback_decl.add_parameter(new CCodeParameter("arg_%d".printf(n_params), "gint")); n_params++; } } } callback_decl.add_parameter(new CCodeParameter("data2", "gpointer")); ccode.add_statement(new CCodeTypeDefinition(get_value_type_name_from_type_reference(return_type), callback_decl)); ccode.add_declaration(get_marshaller_function(_params, return_type, "GMarshalFunc"), new CCodeVariableDeclarator("callback"), CCodeModifiers.REGISTER); ccode.add_declaration("GCClosure *", new CCodeVariableDeclarator("cc", new CCodeCastExpression(new CCodeIdentifier("closure"), "GCClosure *")), CCodeModifiers.REGISTER); ccode.add_declaration("gpointer", new CCodeVariableDeclarator("data1"), CCodeModifiers.REGISTER); ccode.add_declaration("gpointer", new CCodeVariableDeclarator("data2"), CCodeModifiers.REGISTER); CCodeFunctionCall fc; if (return_type.data_type != null || return_type.is_array()) { ccode.add_declaration(get_value_type_name_from_type_reference(return_type), new CCodeVariableDeclarator("v_return")); fc = new CCodeFunctionCall(new CCodeIdentifier("g_return_if_fail")); fc.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier("return_value"), new CCodeConstant("NULL"))); ccode.add_expression(fc); } fc = new CCodeFunctionCall(new CCodeIdentifier("g_return_if_fail")); fc.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, new CCodeIdentifier("n_param_values"), new CCodeConstant(n_params.ToString()))); ccode.add_expression(fc); var data = new CCodeMemberAccess(new CCodeIdentifier("closure"), "data", true); var param = new CCodeMemberAccess(new CCodeMemberAccess(new CCodeIdentifier("param_values"), "data[0]", true), "v_pointer"); var cond = new CCodeFunctionCall(new CCodeConstant("G_CCLOSURE_SWAP_DATA")); cond.add_argument(new CCodeIdentifier("closure")); ccode.open_if(cond); ccode.add_assignment(new CCodeIdentifier("data1"), data); ccode.add_assignment(new CCodeIdentifier("data2"), param); ccode.add_else(); ccode.add_assignment(new CCodeIdentifier("data1"), param); ccode.add_assignment(new CCodeIdentifier("data2"), data); ccode.close(); var c_assign_rhs = new CCodeCastExpression(new CCodeConditionalExpression(new CCodeIdentifier("marshal_data"), new CCodeIdentifier("marshal_data"), new CCodeMemberAccess(new CCodeIdentifier("cc"), "callback", true)), get_marshaller_function(_params, return_type, "GMarshalFunc")); ccode.add_assignment(new CCodeIdentifier("callback"), c_assign_rhs); fc = new CCodeFunctionCall(new CCodeIdentifier("callback")); fc.add_argument(new CCodeIdentifier("data1")); i = 1; foreach (Parameter p in _params) { string get_value_function; bool is_array = p.variable_type.is_array(); if (p.direction != ParameterDirection.IN) { get_value_function = "g_value_get_pointer"; } else if (is_array) { if (((ArrayType)p.variable_type).element_type.data_type == string_type.data_type) { get_value_function = "g_value_get_boxed"; } else { get_value_function = "g_value_get_pointer"; } } else if (p.variable_type is PointerType || p.variable_type.type_parameter != null) { get_value_function = "g_value_get_pointer"; } else if (p.variable_type is ErrorType) { get_value_function = "g_value_get_pointer"; } else if (p.variable_type is ValaValueType && p.variable_type.nullable) { get_value_function = "g_value_get_pointer"; } else { get_value_function = get_ccode_get_value_function(p.variable_type.data_type); } var inner_fc = new CCodeFunctionCall(new CCodeIdentifier(get_value_function)); inner_fc.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, new CCodeIdentifier("param_values"), new CCodeIdentifier(i.ToString()))); fc.add_argument(inner_fc); i++; if (is_array) { for (var j = 0; j < ((ArrayType)p.variable_type).rank; j++) { inner_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_get_int")); inner_fc.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, new CCodeIdentifier("param_values"), new CCodeIdentifier(i.ToString()))); fc.add_argument(inner_fc); i++; } } } fc.add_argument(new CCodeIdentifier("data2")); if (return_type.data_type != null || return_type.is_array()) { ccode.add_assignment(new CCodeIdentifier("v_return"), fc); CCodeFunctionCall set_fc; if (return_type.is_array()) { if (((ArrayType)return_type).element_type.data_type == string_type.data_type) { set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_take_boxed")); } else { set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_set_pointer")); } } else if (return_type.type_parameter != null) { set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_set_pointer")); } else if (return_type is ErrorType) { set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_set_pointer")); } else if (return_type.data_type == string_type.data_type) { set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_take_string")); } else if (return_type.data_type is Class || return_type.data_type is Interface) { set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_take_object")); } else if (return_type is ValaValueType && return_type.nullable) { set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_set_pointer")); } else { set_fc = new CCodeFunctionCall(new CCodeIdentifier(get_ccode_set_value_function(return_type.data_type))); } set_fc.add_argument(new CCodeIdentifier("return_value")); set_fc.add_argument(new CCodeIdentifier("v_return")); ccode.add_expression(set_fc); } else { ccode.add_expression(fc); } pop_function(); cfile.add_function_declaration(signal_marshaller); cfile.add_function(signal_marshaller); user_marshal_set.Add(signature); }
public override void append_vala_array_move() { cfile.add_include("string.h"); // assumes that overwritten array elements are null before invocation // FIXME will leak memory if that's not the case var fun = new CCodeFunction("_vala_array_move", "void"); fun.modifiers = CCodeModifiers.STATIC; fun.add_parameter(new CCodeParameter("array", "gpointer")); fun.add_parameter(new CCodeParameter("element_size", "gsize")); fun.add_parameter(new CCodeParameter("src", "gint")); fun.add_parameter(new CCodeParameter("dest", "gint")); fun.add_parameter(new CCodeParameter("length", "gint")); push_function(fun); var array = new CCodeCastExpression(new CCodeIdentifier("array"), "char*"); var element_size = new CCodeIdentifier("element_size"); var length = new CCodeIdentifier("length"); var src = new CCodeIdentifier("src"); var src_end = new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, src, length); var dest = new CCodeIdentifier("dest"); var dest_end = new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, dest, length); var src_address = new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, array, new CCodeBinaryExpression(CCodeBinaryOperator.MUL, src, element_size)); var dest_address = new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, array, new CCodeBinaryExpression(CCodeBinaryOperator.MUL, dest, element_size)); var dest_end_address = new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, array, new CCodeBinaryExpression(CCodeBinaryOperator.MUL, dest_end, element_size)); var ccall = new CCodeFunctionCall(new CCodeIdentifier("g_memmove")); ccall.add_argument(dest_address); ccall.add_argument(src_address); ccall.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.MUL, length, element_size)); ccode.add_expression(ccall); ccode.open_if(new CCodeBinaryExpression(CCodeBinaryOperator.AND, new CCodeBinaryExpression(CCodeBinaryOperator.LESS_THAN, src, dest), new CCodeBinaryExpression(CCodeBinaryOperator.GREATER_THAN, src_end, dest))); var czero1 = new CCodeFunctionCall(new CCodeIdentifier("memset")); czero1.add_argument(src_address); czero1.add_argument(new CCodeConstant("0")); czero1.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.MUL, new CCodeBinaryExpression(CCodeBinaryOperator.MINUS, dest, src), element_size)); ccode.add_expression(czero1); ccode.else_if(new CCodeBinaryExpression(CCodeBinaryOperator.AND, new CCodeBinaryExpression(CCodeBinaryOperator.GREATER_THAN, src, dest), new CCodeBinaryExpression(CCodeBinaryOperator.LESS_THAN, src, dest_end))); var czero2 = new CCodeFunctionCall(new CCodeIdentifier("memset")); czero2.add_argument(dest_end_address); czero2.add_argument(new CCodeConstant("0")); czero2.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.MUL, new CCodeBinaryExpression(CCodeBinaryOperator.MINUS, src, dest), element_size)); ccode.add_expression(czero2); ccode.else_if(new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, src, dest)); var czero3 = new CCodeFunctionCall(new CCodeIdentifier("memset")); czero3.add_argument(src_address); czero3.add_argument(new CCodeConstant("0")); czero3.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.MUL, length, element_size)); ccode.add_expression(czero3); ccode.close(); pop_function(); cfile.add_function_declaration(fun); cfile.add_function(fun); }
public override void store_value(TargetValue lvalue, TargetValue value, SourceReference source_reference = null) { var array_type = lvalue.value_type as ArrayType; if (array_type != null && array_type.fixed_length) { cfile.add_include("string.h"); // it is necessary to use memcpy for fixed-length (stack-allocated) arrays // simple assignments do not work in C var sizeof_call = new CCodeFunctionCall(new CCodeIdentifier("sizeof")); sizeof_call.add_argument(new CCodeIdentifier(get_ccode_name(array_type.element_type))); var size = new CCodeBinaryExpression(CCodeBinaryOperator.MUL, get_ccodenode(array_type.length), sizeof_call); var ccopy = new CCodeFunctionCall(new CCodeIdentifier("memcpy")); ccopy.add_argument(get_cvalue_(lvalue)); ccopy.add_argument(get_cvalue_(value)); ccopy.add_argument(size); ccode.add_expression(ccopy); return; } var cexpr = get_cvalue_(value); if (get_ctype(lvalue) != null) { cexpr = new CCodeCastExpression(cexpr, get_ctype(lvalue)); } /* * If this is a SimpleType struct being passed by value * and the user specified a custom user function * use the specified function instead to do assignments rather than dest = source */ var st_left = lvalue.value_type.data_type as Struct; var st_right = value.value_type.data_type as Struct; if ( st_left != null && st_right != null && lvalue.value_type.compatible(value.value_type) && st_left.is_simple_type() && lvalue.value_type is StructValueType && st_left.has_attribute_argument("CCode", "copy_function") ) { //copy_function (src, dest) var copy_call = new CCodeFunctionCall(new CCodeIdentifier(get_ccode_copy_function(st_left))); copy_call.add_argument(get_cvalue_(value)); copy_call.add_argument(get_cvalue_(lvalue)); ccode.add_expression(copy_call); return; } ccode.add_assignment(get_cvalue_(lvalue), cexpr); if (array_type != null && ((GLibValue)lvalue).array_length_cvalues != null) { var glib_value = (GLibValue)value; if (glib_value.array_length_cvalues != null) { for (int dim = 1; dim <= array_type.rank; dim++) { ccode.add_assignment(get_array_length_cvalue(lvalue, dim), get_array_length_cvalue(value, dim)); } } else if (glib_value.array_null_terminated) { requires_array_length = true; var len_call = new CCodeFunctionCall(new CCodeIdentifier("_vala_array_length")); len_call.add_argument(get_cvalue_(value)); ccode.add_assignment(get_array_length_cvalue(lvalue, 1), len_call); } else { for (int dim = 1; dim <= array_type.rank; dim++) { ccode.add_assignment(get_array_length_cvalue(lvalue, dim), new CCodeConstant("-1")); } } if (array_type.rank == 1 && get_array_size_cvalue(lvalue) != null) { ccode.add_assignment(get_array_size_cvalue(lvalue), get_array_length_cvalue(lvalue, 1)); } } var delegate_type = lvalue.value_type as DelegateType; if (delegate_type != null && delegate_type.delegate_symbol.has_target) { var lvalue_target = get_delegate_target_cvalue(lvalue); var rvalue_target = get_delegate_target_cvalue(value); if (lvalue_target != null) { if (rvalue_target != null) { ccode.add_assignment(lvalue_target, rvalue_target); } else { Report.error(source_reference, "Assigning delegate without required target in scope"); ccode.add_assignment(lvalue_target, new CCodeInvalidExpression()); } var lvalue_destroy_notify = get_delegate_target_destroy_notify_cvalue(lvalue); var rvalue_destroy_notify = get_delegate_target_destroy_notify_cvalue(value); if (lvalue_destroy_notify != null) { if (rvalue_destroy_notify != null) { ccode.add_assignment(lvalue_destroy_notify, rvalue_destroy_notify); } else { ccode.add_assignment(lvalue_destroy_notify, new CCodeConstant("NULL")); } } } } }