public override void append_vala_array_length() { var fun = new CCodeFunction("_vala_array_length", "gint"); fun.modifiers = CCodeModifiers.STATIC; fun.add_parameter(new CCodeParameter("array", "gpointer")); push_function(fun); ccode.add_declaration("int", new CCodeVariableDeclarator("length", new CCodeConstant("0"))); // return 0 if the array is NULL // avoids an extra NULL check on the caller side var array_check = new CCodeIdentifier("array"); ccode.open_if(array_check); var array_element_check = new CCodeElementAccess(new CCodeCastExpression(new CCodeIdentifier("array"), "gpointer*"), new CCodeConstant("length")); ccode.open_while(array_element_check); ccode.add_expression(new CCodeUnaryExpression(CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier("length"))); ccode.close(); ccode.close(); ccode.add_return(new CCodeIdentifier("length")); pop_function(); cfile.add_function_declaration(fun); cfile.add_function(fun); }
void add_struct_free_function(Struct st) { var function = new CCodeFunction(get_ccode_free_function(st), "void"); if (st.is_private_symbol()) { function.modifiers = CCodeModifiers.STATIC; } else if (context.hide_internal && st.is_internal_symbol()) { function.modifiers = CCodeModifiers.INTERNAL; } function.add_parameter(new CCodeParameter("self", get_ccode_name(st) + "*")); push_function(function); if (st.is_disposable()) { var destroy_call = new CCodeFunctionCall(new CCodeIdentifier(get_ccode_destroy_function(st))); destroy_call.add_argument(new CCodeIdentifier("self")); ccode.add_expression(destroy_call); } var free_call = new CCodeFunctionCall(new CCodeIdentifier("g_free")); free_call.add_argument(new CCodeIdentifier("self")); ccode.add_expression(free_call); pop_function(); cfile.add_function(function); }
public override string get_dynamic_signal_connect_after_wrapper_name(DynamicSignal sig) { if (sig.dynamic_type.data_type == null || !sig.dynamic_type.data_type.is_subtype_of(gobject_type)) { return(base.get_dynamic_signal_connect_wrapper_name(sig)); } string connect_wrapper_name = "_%sconnect_after".printf(get_dynamic_signal_cname(sig)); var func = new CCodeFunction(connect_wrapper_name, "gulong"); func.add_parameter(new CCodeParameter("obj", "gpointer")); func.add_parameter(new CCodeParameter("signal_name", "const char *")); func.add_parameter(new CCodeParameter("handler", "GCallback")); func.add_parameter(new CCodeParameter("data", "gpointer")); push_function(func); generate_gobject_connect_wrapper(sig, true); pop_function(); // append to C source file cfile.add_function_declaration(func); cfile.add_function(func); return(connect_wrapper_name); }
public CCodeFunction generate_enum_to_string_function(ValaEnum en) { var to_string_name = "%s_to_string".printf(get_ccode_lower_case_name(en, null)); var to_string_func = new CCodeFunction(to_string_name, "const char*"); to_string_func.add_parameter(new CCodeParameter("value", get_ccode_name(en))); push_function(to_string_func); ccode.add_declaration("const char *", new CCodeVariableDeclarator("str")); ccode.open_switch(new CCodeIdentifier("value")); foreach (EnumValue enum_value in en.get_values()) { string dbus_value = get_dbus_value(enum_value, enum_value.name); ccode.add_case(new CCodeIdentifier(get_ccode_name(enum_value))); ccode.add_assignment(new CCodeIdentifier("str"), new CCodeConstant("\"%s\"".printf(dbus_value))); ccode.add_break(); } ccode.close(); ccode.add_return(new CCodeIdentifier("str")); pop_function(); return(to_string_func); }
public override string get_dynamic_property_setter_cname(DynamicProperty prop) { if (prop.dynamic_type.data_type == null || !prop.dynamic_type.data_type.is_subtype_of(gobject_type)) { return(base.get_dynamic_property_setter_cname(prop)); } string setter_cname = "_dynamic_set_%s%d".printf(prop.name, dynamic_property_id++); var func = new CCodeFunction(setter_cname, "void"); func.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.INLINE; func.add_parameter(new CCodeParameter("obj", get_ccode_name(prop.dynamic_type))); func.add_parameter(new CCodeParameter("value", get_ccode_name(prop.property_type))); push_function(func); var call = new CCodeFunctionCall(new CCodeIdentifier("g_object_set")); call.add_argument(new CCodeIdentifier("obj")); call.add_argument(get_property_canonical_cconstant(prop)); call.add_argument(new CCodeIdentifier("value")); call.add_argument(new CCodeConstant("NULL")); ccode.add_expression(call); pop_function(); // append to C source file cfile.add_function_declaration(func); cfile.add_function(func); return(setter_cname); }
public override void generate_error_domain_declaration(ErrorDomain edomain, CCodeFile decl_space) { if (add_symbol_declaration(decl_space, edomain, get_ccode_name(edomain))) { return; } var cenum = new CCodeEnum(get_ccode_name(edomain)); foreach (ErrorCode ecode in edomain.get_codes()) { if (ecode.value == null) { cenum.add_value(new CCodeEnumValue(get_ccode_name(ecode))); } else { ecode.value.emit(this); cenum.add_value(new CCodeEnumValue(get_ccode_name(ecode), get_cvalue(ecode.value))); } } decl_space.add_type_definition(cenum); string quark_fun_name = get_ccode_lower_case_prefix(edomain) + "quark"; var error_domain_define = new CCodeMacroReplacement(get_ccode_upper_case_name(edomain), quark_fun_name + " ()"); decl_space.add_type_definition(error_domain_define); var cquark_fun = new CCodeFunction(quark_fun_name, get_ccode_name(gquark_type.data_type)); decl_space.add_function_declaration(cquark_fun); }
public override void visit_error_domain(ErrorDomain edomain) { if (edomain.comment != null) { cfile.add_type_definition(new CCodeComment(edomain.comment.content)); } generate_error_domain_declaration(edomain, cfile); if (!edomain.is_internal_symbol()) { generate_error_domain_declaration(edomain, header_file); } if (!edomain.is_private_symbol()) { generate_error_domain_declaration(edomain, internal_header_file); } string quark_fun_name = get_ccode_lower_case_prefix(edomain) + "quark"; var cquark_fun = new CCodeFunction(quark_fun_name, get_ccode_name(gquark_type.data_type)); push_function(cquark_fun); var cquark_call = new CCodeFunctionCall(new CCodeIdentifier("g_quark_from_static_string")); cquark_call.add_argument(new CCodeConstant("\"" + CCodeBaseModule.get_quark_name(edomain) + "\"")); ccode.add_return(cquark_call); pop_function(); cfile.add_function(cquark_fun); }
string generate_array_copy_wrapper(ArrayType array_type) { string dup_func = "_vala_array_copy%d".printf(++next_array_dup_id); if (!add_wrapper(dup_func)) { // wrapper already defined return(dup_func); } // declaration var function = new CCodeFunction(dup_func, "void"); function.modifiers = CCodeModifiers.STATIC; function.add_parameter(new CCodeParameter("self", "%s *".printf(get_ccode_name(array_type)))); function.add_parameter(new CCodeParameter("dest", "%s *".printf(get_ccode_name(array_type)))); // definition push_context(new EmitContext()); push_function(function); if (requires_copy(array_type.element_type)) { ccode.add_declaration("int", new CCodeVariableDeclarator("i")); ccode.open_for(new CCodeAssignment(new CCodeIdentifier("i"), new CCodeConstant("0")), new CCodeBinaryExpression(CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier("i"), get_ccodenode(array_type.length)), new CCodeUnaryExpression(CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier("i"))); ccode.add_assignment(new CCodeElementAccess(new CCodeIdentifier("dest"), new CCodeIdentifier("i")), get_cvalue_(copy_value(new GLibValue(array_type.element_type, new CCodeElementAccess(new CCodeIdentifier("self"), new CCodeIdentifier("i")), true), array_type))); } else { cfile.add_include("string.h"); var dup_call = new CCodeFunctionCall(new CCodeIdentifier("memcpy")); dup_call.add_argument(new CCodeIdentifier("dest")); dup_call.add_argument(new CCodeIdentifier("self")); var sizeof_call = new CCodeFunctionCall(new CCodeIdentifier("sizeof")); sizeof_call.add_argument(new CCodeIdentifier(get_ccode_name(array_type.element_type))); dup_call.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.MUL, get_ccodenode(array_type.length), sizeof_call)); ccode.add_expression(dup_call); } // append to file cfile.add_function_declaration(function); cfile.add_function(function); pop_context(); return(dup_func); }
public override void append_vala_array_free() { // _vala_array_destroy only frees elements but not the array itself var fun = new CCodeFunction("_vala_array_destroy", "void"); fun.modifiers = CCodeModifiers.STATIC; fun.add_parameter(new CCodeParameter("array", "gpointer")); fun.add_parameter(new CCodeParameter("array_length", "gint")); fun.add_parameter(new CCodeParameter("destroy_func", "GDestroyNotify")); push_function(fun); var ccondarr = new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier("array"), new CCodeConstant("NULL")); var ccondfunc = new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier("destroy_func"), new CCodeConstant("NULL")); ccode.open_if(new CCodeBinaryExpression(CCodeBinaryOperator.AND, ccondarr, ccondfunc)); ccode.add_declaration("int", new CCodeVariableDeclarator("i")); append_vala_array_free_loop(); ccode.close(); pop_function(); cfile.add_function_declaration(fun); cfile.add_function(fun); // _vala_array_free frees elements and array fun = new CCodeFunction("_vala_array_free", "void"); fun.modifiers = CCodeModifiers.STATIC; fun.add_parameter(new CCodeParameter("array", "gpointer")); fun.add_parameter(new CCodeParameter("array_length", "gint")); fun.add_parameter(new CCodeParameter("destroy_func", "GDestroyNotify")); push_function(fun); // call _vala_array_destroy to free the array elements var ccall = new CCodeFunctionCall(new CCodeIdentifier("_vala_array_destroy")); ccall.add_argument(new CCodeIdentifier("array")); ccall.add_argument(new CCodeIdentifier("array_length")); ccall.add_argument(new CCodeIdentifier("destroy_func")); ccode.add_expression(ccall); var carrfree = new CCodeFunctionCall(new CCodeIdentifier("g_free")); carrfree.add_argument(new CCodeIdentifier("array")); ccode.add_expression(carrfree); pop_function(); cfile.add_function_declaration(fun); cfile.add_function(fun); }
public CCodeFunction generate_enum_to_string_function_declaration(ValaEnum en) { var to_string_name = "%s_to_string".printf(get_ccode_lower_case_name(en, null)); var to_string_func = new CCodeFunction(to_string_name, "const char*"); to_string_func.add_parameter(new CCodeParameter("value", get_ccode_name(en))); return(to_string_func); }
public CCodeFunction generate_enum_from_string_function_declaration(ValaEnum en) { var from_string_name = "%s_from_string".printf(get_ccode_lower_case_name(en, null)); var from_string_func = new CCodeFunction(from_string_name, get_ccode_name(en)); from_string_func.add_parameter(new CCodeParameter("str", "const char*")); from_string_func.add_parameter(new CCodeParameter("error", "GError**")); return(from_string_func); }
public CCodeFunction generate_enum_from_string_function(ValaEnum en) { var from_string_name = "%s_from_string".printf(get_ccode_lower_case_name(en, null)); var from_string_func = new CCodeFunction(from_string_name, get_ccode_name(en)); from_string_func.add_parameter(new CCodeParameter("str", "const char*")); from_string_func.add_parameter(new CCodeParameter("error", "GError**")); push_function(from_string_func); ccode.add_declaration(get_ccode_name(en), CCodeVariableDeclarator.zero("value", new CCodeConstant("0"))); bool firstif = true; foreach (EnumValue enum_value in en.get_values()) { string dbus_value = get_dbus_value(enum_value, enum_value.name); var string_comparison = new CCodeFunctionCall(new CCodeIdentifier("strcmp")); string_comparison.add_argument(new CCodeIdentifier("str")); string_comparison.add_argument(new CCodeConstant("\"%s\"".printf(dbus_value))); var cond = new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, string_comparison, new CCodeConstant("0")); if (firstif) { ccode.open_if(cond); firstif = false; } else { ccode.else_if(cond); } ccode.add_assignment(new CCodeIdentifier("value"), new CCodeIdentifier(get_ccode_name(enum_value))); } ccode.add_else(); var set_error = new CCodeFunctionCall(new CCodeIdentifier("g_set_error")); set_error.add_argument(new CCodeIdentifier("error")); set_error.add_argument(new CCodeIdentifier("G_DBUS_ERROR")); set_error.add_argument(new CCodeIdentifier("G_DBUS_ERROR_INVALID_ARGS")); set_error.add_argument(new CCodeConstant("\"Invalid value for enum `%s'\"".printf(get_ccode_name(en)))); ccode.add_expression(set_error); ccode.close(); ccode.add_return(new CCodeIdentifier("value")); pop_function(); return(from_string_func); }
void add_struct_dup_function(Struct st) { var function = new CCodeFunction(get_ccode_dup_function(st), get_ccode_name(st) + "*"); if (st.access == SymbolAccessibility.PRIVATE) { function.modifiers = CCodeModifiers.STATIC; } function.add_parameter(new CCodeParameter("self", "const " + get_ccode_name(st) + "*")); push_function(function); ccode.add_declaration(get_ccode_name(st) + "*", new CCodeVariableDeclarator("dup")); var creation_call = new CCodeFunctionCall(new CCodeIdentifier("g_new0")); creation_call.add_argument(new CCodeConstant(get_ccode_name(st))); creation_call.add_argument(new CCodeConstant("1")); ccode.add_assignment(new CCodeIdentifier("dup"), creation_call); if (st.is_disposable()) { var copy_call = new CCodeFunctionCall(new CCodeIdentifier(get_ccode_copy_function(st))); copy_call.add_argument(new CCodeIdentifier("self")); copy_call.add_argument(new CCodeIdentifier("dup")); ccode.add_expression(copy_call); } else { cfile.add_include("string.h"); var sizeof_call = new CCodeFunctionCall(new CCodeIdentifier("sizeof")); sizeof_call.add_argument(new CCodeConstant(get_ccode_name(st))); var copy_call = new CCodeFunctionCall(new CCodeIdentifier("memcpy")); copy_call.add_argument(new CCodeIdentifier("dup")); copy_call.add_argument(new CCodeIdentifier("self")); copy_call.add_argument(sizeof_call); ccode.add_expression(copy_call); } ccode.add_return(new CCodeIdentifier("dup")); pop_function(); cfile.add_function(function); }
void generate_async_ready_callback_wrapper(Method m, string function_name) { var function = new CCodeFunction(function_name, "void"); function.modifiers = CCodeModifiers.STATIC; function.add_parameter(new CCodeParameter("*source_object", "GObject")); function.add_parameter(new CCodeParameter("*res", "GAsyncResult")); function.add_parameter(new CCodeParameter("*user_data", "void")); push_function(function); // Set _task_complete_ to false after calling back to the real func var async_result_cast = new CCodeFunctionCall(new CCodeIdentifier("G_TASK")); async_result_cast.add_argument(new CCodeIdentifier("res")); var dataname = Symbol.lower_case_to_camel_case(get_ccode_name(m)) + "Data"; ccode.add_declaration(dataname + "*", new CCodeVariableDeclarator("_task_data_")); var get_data_call = new CCodeFunctionCall(new CCodeIdentifier("g_task_get_task_data")); get_data_call.add_argument(async_result_cast); var data_var = new CCodeIdentifier("_task_data_"); ccode.add_assignment(data_var, get_data_call); var task_inner_callback = CCodeMemberAccess.pointer(data_var, "_callback_"); var callback_is_nonnull = new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, task_inner_callback, new CCodeConstant("NULL")); ccode.open_if(callback_is_nonnull); var nested_callback = new CCodeFunctionCall(task_inner_callback); nested_callback.add_argument(new CCodeIdentifier("source_object")); nested_callback.add_argument(new CCodeIdentifier("res")); nested_callback.add_argument(new CCodeIdentifier("user_data")); ccode.add_expression(nested_callback); ccode.close(); ccode.add_assignment(CCodeMemberAccess.pointer(data_var, "_task_complete_"), new CCodeConstant("TRUE")); pop_function(); cfile.add_function_declaration(function); cfile.add_function(function); }
public override string generate_ready_function(Method m) { // generate ready callback handler var dataname = Symbol.lower_case_to_camel_case(get_ccode_name(m)) + "Data"; var readyfunc = new CCodeFunction(get_ccode_name(m) + "_ready", "void"); if (!add_wrapper(readyfunc.name)) { // wrapper already defined return(readyfunc.name); } readyfunc.add_parameter(new CCodeParameter("source_object", "GObject*")); readyfunc.add_parameter(new CCodeParameter("_res_", "GAsyncResult*")); readyfunc.add_parameter(new CCodeParameter("_user_data_", "gpointer")); push_function(readyfunc); var data_var = new CCodeIdentifier("_data_"); ccode.add_declaration(dataname + "*", new CCodeVariableDeclarator("_data_")); ccode.add_assignment(data_var, new CCodeIdentifier("_user_data_")); ccode.add_assignment(CCodeMemberAccess.pointer(data_var, "_source_object_"), new CCodeIdentifier("source_object")); ccode.add_assignment(CCodeMemberAccess.pointer(data_var, "_res_"), new CCodeIdentifier("_res_")); if (!context.require_glib_version(2, 44)) { ccode.add_assignment(CCodeMemberAccess.pointer(data_var, "_task_complete_"), new CCodeConstant("TRUE")); } var ccall = new CCodeFunctionCall(new CCodeIdentifier(get_ccode_real_name(m) + "_co")); ccall.add_argument(data_var); ccode.add_expression(ccall); readyfunc.modifiers |= CCodeModifiers.STATIC; pop_function(); cfile.add_function_declaration(readyfunc); cfile.add_function(readyfunc); return(readyfunc.name); }
public string generate_async_callback_wrapper() { string async_callback_wrapper_func = "_vala_g_async_ready_callback"; if (!add_wrapper(async_callback_wrapper_func)) { return(async_callback_wrapper_func); } var function = new CCodeFunction(async_callback_wrapper_func, "void"); function.modifiers = CCodeModifiers.STATIC; function.add_parameter(new CCodeParameter("*source_object", "GObject")); function.add_parameter(new CCodeParameter("*res", "GAsyncResult")); function.add_parameter(new CCodeParameter("*user_data", "void")); push_function(function); var res_ref = new CCodeFunctionCall(new CCodeIdentifier("g_object_ref")); res_ref.add_argument(new CCodeIdentifier("res")); CCodeFunctionCall ccall = null; // store reference to async result of inner async function in out async result ccall = new CCodeFunctionCall(new CCodeIdentifier("g_task_return_pointer")); ccall.add_argument(new CCodeIdentifier("user_data")); ccall.add_argument(res_ref); ccall.add_argument(new CCodeIdentifier("g_object_unref")); ccode.add_expression(ccall); // free async result ccall = new CCodeFunctionCall(new CCodeIdentifier("g_object_unref")); ccall.add_argument(new CCodeIdentifier("user_data")); ccode.add_expression(ccall); pop_function(); cfile.add_function_declaration(function); cfile.add_function(function); return(async_callback_wrapper_func); }
void add_struct_copy_function(Struct st) { var function = new CCodeFunction(get_ccode_copy_function(st), "void"); if (st.is_private_symbol()) { function.modifiers = CCodeModifiers.STATIC; } else if (context.hide_internal && st.is_internal_symbol()) { function.modifiers = CCodeModifiers.INTERNAL; } function.add_parameter(new CCodeParameter("self", "const " + get_ccode_name(st) + "*")); function.add_parameter(new CCodeParameter("dest", get_ccode_name(st) + "*")); push_function(function); var dest_struct = new GLibValue(get_data_type_for_symbol(st), new CCodeIdentifier("(*dest)"), true); foreach (var f in st.get_fields()) { if (f.binding == MemberBinding.INSTANCE) { var value = load_field(f, load_this_parameter((TypeSymbol)st)); if (requires_copy(f.variable_type)) { value = copy_value(value, f); if (value == null) { // error case, continue to avoid critical continue; } } store_field(f, dest_struct, value); } } pop_function(); cfile.add_function(function); }
void begin_struct_destroy_function(Struct st) { push_context(instance_finalize_context); var function = new CCodeFunction(get_ccode_destroy_function(st), "void"); if (st.is_private_symbol()) { function.modifiers = CCodeModifiers.STATIC; } else if (context.hide_internal && st.is_internal_symbol()) { function.modifiers = CCodeModifiers.INTERNAL; } function.add_parameter(new CCodeParameter("self", get_ccode_name(st) + "*")); push_function(function); pop_context(); }
public override string append_struct_array_free(Struct st) { string cname = "_vala_%s_array_free".printf(get_ccode_name(st)); if (cfile.add_declaration(cname)) { return(cname); } var fun = new CCodeFunction(cname, "void"); fun.modifiers = CCodeModifiers.STATIC; fun.add_parameter(new CCodeParameter("array", "%s *".printf(get_ccode_name(st)))); fun.add_parameter(new CCodeParameter("array_length", "gint")); push_function(fun); var ccondarr = new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier("array"), new CCodeConstant("NULL")); ccode.open_if(ccondarr); ccode.add_declaration("int", new CCodeVariableDeclarator("i")); append_struct_array_free_loop(st); ccode.close(); var carrfree = new CCodeFunctionCall(new CCodeIdentifier("g_free")); carrfree.add_argument(new CCodeIdentifier("array")); ccode.add_expression(carrfree); pop_function(); cfile.add_function_declaration(fun); cfile.add_function(fun); return(cname); }
public string generate_delegate_wrapper(Method m, DelegateType dt, CodeNode node) { var d = dt.delegate_symbol; string delegate_name; var sig = d.parent_symbol as Signal; var dynamic_sig = sig as DynamicSignal; if (dynamic_sig != null) { delegate_name = get_dynamic_signal_cname(dynamic_sig); } else if (sig != null) { delegate_name = get_ccode_lower_case_prefix(sig.parent_symbol) + get_ccode_lower_case_name(sig); } else { delegate_name = Symbol.camel_case_to_lower_case(get_ccode_name(d)); } string wrapper_name = "_%s_%s".printf(get_ccode_name(m), delegate_name); if (!add_wrapper(wrapper_name)) { // wrapper already defined return(wrapper_name); } // declaration string return_type_cname = get_ccode_name(d.return_type); if (d.return_type.is_real_non_null_struct_type()) { // structs are returned via out parameter return_type_cname = "void"; } var function = new CCodeFunction(wrapper_name, return_type_cname); function.modifiers = CCodeModifiers.STATIC; push_function(function); var cparam_map = new Dictionary <int, CCodeParameter>(); if (d.has_target) { var cparam = new CCodeParameter("self", "gpointer"); cparam_map[get_param_pos(get_ccode_instance_pos(d))] = cparam; } if (d.sender_type != null) { var param = new Parameter("_sender", d.sender_type); generate_parameter(param, cfile, cparam_map, null); } var d_params = d.get_parameters(); foreach (Parameter param in d_params) { if (dynamic_sig != null && param.variable_type is ArrayType && ((ArrayType)param.variable_type).element_type.data_type == string_type.data_type) { // use null-terminated string arrays for dynamic signals for compatibility reasons param.set_attribute_bool("CCode", "array_length", false); param.set_attribute_bool("CCode", "array_null_terminated", true); } generate_parameter(param, cfile, cparam_map, null); } if (get_ccode_array_length(d) && d.return_type is ArrayType) { // return array length if appropriate var array_type = (ArrayType)d.return_type; var array_length_type = get_ccode_array_length_type(d) != null?get_ccode_array_length_type(d) : "int"; array_length_type += "*"; for (int dim = 1; dim <= array_type.rank; dim++) { var cparam = new CCodeParameter(get_array_length_cname("result", dim), array_length_type); cparam_map[get_param_pos(get_ccode_array_length_pos(d) + 0.01 * dim)] = cparam; } } else if (d.return_type is DelegateType) { // return delegate target if appropriate var deleg_type = (DelegateType)d.return_type; if (deleg_type.delegate_symbol.has_target) { var cparam = new CCodeParameter(get_delegate_target_cname("result"), "void**"); cparam_map[get_param_pos(get_ccode_delegate_target_pos(d))] = cparam; if (deleg_type.is_disposable()) { cparam = new CCodeParameter(get_delegate_target_destroy_notify_cname("result"), "GDestroyNotify*"); cparam_map[get_param_pos(get_ccode_delegate_target_pos(d) + 0.01)] = cparam; } } } else if (d.return_type.is_real_non_null_struct_type()) { var cparam = new CCodeParameter("result", "%s*".printf(get_ccode_name(d.return_type))); cparam_map[get_param_pos(-3)] = cparam; } if (m.get_error_types().Count > 0) { var cparam = new CCodeParameter("error", "GError**"); cparam_map[get_param_pos(-1)] = cparam; } // append C parameters in the right order int last_pos = -1; int min_pos; while (true) { min_pos = -1; foreach (int pos in cparam_map.Keys) { if (pos > last_pos && (min_pos == -1 || pos < min_pos)) { min_pos = pos; } } if (min_pos == -1) { break; } function.add_parameter(cparam_map[min_pos]); last_pos = min_pos; } // definition var carg_map = new Dictionary <int, CCodeExpression>(); int i = 0; if (m.binding == MemberBinding.INSTANCE || m.closure) { CCodeExpression arg; if (d.has_target) { arg = new CCodeIdentifier("self"); if (!m.closure && m.this_parameter != null) { arg = convert_from_generic_pointer(arg, m.this_parameter.variable_type); } } else { // use first delegate parameter as instance if (d_params.Count == 0 || m.closure) { Report.error(node != null ? node.source_reference : null, "Cannot create delegate without target for instance method or closure"); arg = new CCodeConstant("NULL"); } else { arg = new CCodeIdentifier(get_variable_cname(d_params[0].name)); i = 1; } } carg_map[get_param_pos(get_ccode_instance_pos(m))] = arg; } bool first = true; foreach (Parameter param in m.get_parameters()) { if (first && d.sender_type != null && m.get_parameters().Count == d.get_parameters().Count + 1) { // sender parameter carg_map[get_param_pos(get_ccode_pos(param))] = new CCodeIdentifier("_sender"); first = false; continue; } CCodeExpression arg; arg = new CCodeIdentifier(get_variable_cname(d_params[i].name)); if (d_params[i].variable_type is GenericType) { arg = convert_from_generic_pointer(arg, param.variable_type); } carg_map[get_param_pos(get_ccode_pos(param))] = arg; // handle array arguments if (get_ccode_array_length(param) && param.variable_type is ArrayType) { var array_type = (ArrayType)param.variable_type; for (int dim = 1; dim <= array_type.rank; dim++) { CCodeExpression clength; if (get_ccode_array_null_terminated(d_params[i])) { requires_array_length = true; var len_call = new CCodeFunctionCall(new CCodeIdentifier("_vala_array_length")); len_call.add_argument(new CCodeIdentifier(d_params[i].name)); clength = len_call; } else if (!get_ccode_array_length(d_params[i])) { clength = new CCodeConstant("-1"); } else { clength = new CCodeIdentifier(get_parameter_array_length_cname(d_params[i], dim)); } carg_map[get_param_pos(get_ccode_array_length_pos(param) + 0.01 * dim)] = clength; } } else if (param.variable_type is DelegateType) { var deleg_type = (DelegateType)param.variable_type; if (deleg_type.delegate_symbol.has_target) { var ctarget = new CCodeIdentifier(get_ccode_delegate_target_name(d_params[i])); carg_map[get_param_pos(get_ccode_delegate_target_pos(param))] = ctarget; if (deleg_type.is_disposable()) { var ctarget_destroy_notify = new CCodeIdentifier(get_delegate_target_destroy_notify_cname(d_params[i].name)); carg_map[get_param_pos(get_ccode_delegate_target_pos(m) + 0.01)] = ctarget_destroy_notify; } } } i++; } if (get_ccode_array_length(m) && m.return_type is ArrayType) { var array_type = (ArrayType)m.return_type; for (int dim = 1; dim <= array_type.rank; dim++) { CCodeExpression clength; if (!get_ccode_array_length(d)) { clength = new CCodeConstant("NULL"); } else { clength = new CCodeIdentifier(get_array_length_cname("result", dim)); } carg_map[get_param_pos(get_ccode_array_length_pos(m) + 0.01 * dim)] = clength; } } else if (m.return_type is DelegateType) { var deleg_type = (DelegateType)m.return_type; if (deleg_type.delegate_symbol.has_target) { var ctarget = new CCodeIdentifier(get_delegate_target_cname("result")); carg_map[get_param_pos(get_ccode_delegate_target_pos(m))] = ctarget; if (deleg_type.is_disposable()) { var ctarget_destroy_notify = new CCodeIdentifier(get_delegate_target_destroy_notify_cname("result")); carg_map[get_param_pos(get_ccode_delegate_target_pos(m) + 0.01)] = ctarget_destroy_notify; } } } else if (m.return_type.is_real_non_null_struct_type()) { carg_map[get_param_pos(-3)] = new CCodeIdentifier("result"); } if (m.get_error_types().Count > 0) { carg_map[get_param_pos(-1)] = new CCodeIdentifier("error"); } var ccall = new CCodeFunctionCall(new CCodeIdentifier(get_ccode_name(m))); // append C arguments in the right order last_pos = -1; while (true) { min_pos = -1; foreach (int pos in carg_map.Keys) { if (pos > last_pos && (min_pos == -1 || pos < min_pos)) { min_pos = pos; } } if (min_pos == -1) { break; } ccall.add_argument(carg_map[min_pos]); last_pos = min_pos; } if (m.coroutine) { ccall.add_argument(new CCodeConstant("NULL")); ccall.add_argument(new CCodeConstant("NULL")); } if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type()) { ccode.add_expression(ccall); if (!(d.return_type is VoidType || d.return_type.is_real_non_null_struct_type())) { // return a default value ccode.add_declaration(return_type_cname, new CCodeVariableDeclarator("result", default_value_for_type(d.return_type, true))); } } else { CCodeExpression result = ccall; if (d.return_type is GenericType) { result = convert_to_generic_pointer(result, m.return_type); } ccode.add_declaration(return_type_cname, new CCodeVariableDeclarator("result", result)); } if (d.has_target /* TODO: && dt.value_owned */ && dt.is_called_once) { // destroy notify "self" after the call CCodeExpression destroy_notify = null; if (m.closure) { int block_id = get_block_id(current_closure_block); destroy_notify = new CCodeIdentifier("block%d_data_unref".printf(block_id)); } else if (get_this_type() != null && m.binding != MemberBinding.STATIC && !m.is_async_callback && is_reference_counting(m.this_parameter.variable_type.data_type)) { destroy_notify = get_destroy_func_expression(m.this_parameter.variable_type); } if (destroy_notify != null) { var unref_call = new CCodeFunctionCall(destroy_notify); unref_call.add_argument(new CCodeIdentifier("self")); ccode.add_expression(unref_call); } } if (!(m.return_type is VoidType || m.return_type.is_real_non_null_struct_type()) || !(d.return_type is VoidType || d.return_type.is_real_non_null_struct_type())) { ccode.add_return(new CCodeIdentifier("result")); } pop_function(); // append to file cfile.add_function_declaration(function); cfile.add_function(function); return(wrapper_name); }
private void add_get_property_function(Class cl) { var get_prop = new CCodeFunction("_vala_%s_get_property".printf(get_ccode_lower_case_name(cl, null)), "void"); get_prop.modifiers = CCodeModifiers.STATIC; get_prop.add_parameter(new CCodeParameter("object", "GObject *")); get_prop.add_parameter(new CCodeParameter("property_id", "guint")); get_prop.add_parameter(new CCodeParameter("value", "GValue *")); get_prop.add_parameter(new CCodeParameter("pspec", "GParamSpec *")); push_function(get_prop); CCodeFunctionCall ccall = generate_instance_cast(new CCodeIdentifier("object"), cl); ccode.add_declaration("%s *".printf(get_ccode_name(cl)), new CCodeVariableDeclarator("self", ccall)); ccode.open_switch(new CCodeIdentifier("property_id")); var props = cl.get_properties(); foreach (Property prop in props) { if (prop.get_accessor == null || prop.is_abstract) { continue; } if (!is_gobject_property(prop)) { // don't register private properties continue; } Property base_prop = prop; CCodeExpression cself = new CCodeIdentifier("self"); if (prop.base_property != null) { var base_type = (Class)prop.base_property.parent_symbol; base_prop = prop.base_property; cself = get_cvalue_(transform_value(new GLibValue(new ObjectType(cl), cself, true), new ObjectType(base_type), prop)); generate_property_accessor_declaration(prop.base_property.get_accessor, cfile); } else if (prop.base_interface_property != null) { var base_type = (Interface)prop.base_interface_property.parent_symbol; base_prop = prop.base_interface_property; cself = get_cvalue_(transform_value(new GLibValue(new ObjectType(cl), cself, true), new ObjectType(base_type), prop)); generate_property_accessor_declaration(prop.base_interface_property.get_accessor, cfile); } CCodeExpression cfunc; if (!get_ccode_no_accessor_method(base_prop) && !get_ccode_concrete_accessor(base_prop)) { cfunc = new CCodeIdentifier(get_ccode_name(base_prop.get_accessor)); } else { // use the static real function as helper cfunc = new CCodeIdentifier(get_ccode_real_name(prop.get_accessor)); } ccode.add_case(new CCodeIdentifier(get_ccode_upper_case_name(prop))); if (prop.property_type.is_real_struct_type()) { var st = prop.property_type.data_type as Struct; ccode.open_block(); ccode.add_declaration(get_ccode_name(st), new CCodeVariableDeclarator("boxed")); ccall = new CCodeFunctionCall(cfunc); ccall.add_argument(cself); var boxed_addr = new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier("boxed")); ccall.add_argument(boxed_addr); ccode.add_expression(ccall); var csetcall = new CCodeFunctionCall(); csetcall.call = get_value_setter_function(prop.property_type); csetcall.add_argument(new CCodeIdentifier("value")); csetcall.add_argument(boxed_addr); add_guarded_expression(prop, csetcall); if (requires_destroy(prop.get_accessor.value_type)) { ccode.add_expression(destroy_value(new GLibValue(prop.get_accessor.value_type, new CCodeIdentifier("boxed"), true))); } ccode.close(); } else { ccall = new CCodeFunctionCall(cfunc); ccall.add_argument(cself); var array_type = prop.property_type as ArrayType; if (array_type != null && array_type.element_type.data_type == string_type.data_type) { // G_TYPE_STRV ccode.open_block(); ccode.add_declaration("int", new CCodeVariableDeclarator("length")); ccall.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier("length"))); } var csetcall = new CCodeFunctionCall(); if (prop.get_accessor.value_type.value_owned) { csetcall.call = get_value_taker_function(prop.property_type); } else { csetcall.call = get_value_setter_function(prop.property_type); } csetcall.add_argument(new CCodeIdentifier("value")); csetcall.add_argument(ccall); add_guarded_expression(prop, csetcall); if (array_type != null && array_type.element_type.data_type == string_type.data_type) { ccode.close(); } } ccode.add_break(); } ccode.add_default(); emit_invalid_property_id_warn(); ccode.add_break(); ccode.close(); pop_function(); cfile.add_function_declaration(get_prop); cfile.add_function(get_prop); }
public override void visit_error_domain(ErrorDomain edomain) { var edomain_dbus_name = get_dbus_name(edomain); if (edomain_dbus_name == null) { base.visit_error_domain(edomain); return; } cfile.add_include("gio/gio.h"); generate_error_domain_declaration(edomain, cfile); if (!edomain.is_internal_symbol()) { generate_error_domain_declaration(edomain, header_file); } if (!edomain.is_private_symbol()) { generate_error_domain_declaration(edomain, internal_header_file); } var error_entries = new CCodeInitializerList(); foreach (ErrorCode ecode in edomain.get_codes()) { var ecode_dbus_name = get_dbus_name(ecode); if (ecode_dbus_name == null) { ecode_dbus_name = Symbol.lower_case_to_camel_case(ecode.name.ToLower()); } var error_entry = new CCodeInitializerList(); error_entry.append(new CCodeIdentifier(get_ccode_name(ecode))); error_entry.append(new CCodeConstant("\"%s.%s\"".printf(edomain_dbus_name, ecode_dbus_name))); error_entries.append(error_entry); } var cdecl = new CCodeDeclaration("const GDBusErrorEntry"); cdecl.add_declarator(new CCodeVariableDeclarator(get_ccode_lower_case_name(edomain) + "_entries[]", error_entries)); cdecl.modifiers = CCodeModifiers.STATIC; cfile.add_constant_declaration(cdecl); string quark_fun_name = get_ccode_lower_case_prefix(edomain) + "quark"; var cquark_fun = new CCodeFunction(quark_fun_name, get_ccode_name(gquark_type.data_type)); push_function(cquark_fun); string quark_name = "%squark_volatile".printf(get_ccode_lower_case_prefix(edomain)); ccode.add_declaration("gsize", new CCodeVariableDeclarator(quark_name, new CCodeConstant("0")), CCodeModifiers.STATIC | CCodeModifiers.VOLATILE); var register_call = new CCodeFunctionCall(new CCodeIdentifier("g_dbus_error_register_error_domain")); register_call.add_argument(new CCodeConstant("\"" + CCodeBaseModule.get_quark_name(edomain) + "\"")); register_call.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier(quark_name))); register_call.add_argument(new CCodeIdentifier(get_ccode_lower_case_name(edomain) + "_entries")); var nentries = new CCodeFunctionCall(new CCodeIdentifier("G_N_ELEMENTS")); nentries.add_argument(new CCodeIdentifier(get_ccode_lower_case_name(edomain) + "_entries")); register_call.add_argument(nentries); ccode.add_expression(register_call); ccode.add_return(new CCodeCastExpression(new CCodeIdentifier(quark_name), "GQuark")); pop_function(); cfile.add_function(cquark_fun); }
/// <summary> /// Constructs the C function from the specified type. /// </summary> public void init_from_type(bool plugin, bool declaration_only) { bool use_thread_safe = !plugin; bool fundamental = false; Class cl = get_type_declaration() as Class; if (cl != null && !cl.is_compact && cl.base_class == null) { fundamental = true; } string type_id_name = "%s_type_id".printf(CCodeBaseModule.get_ccode_lower_case_name(get_type_declaration())); var type_block = new CCodeBlock(); CCodeDeclaration cdecl; if (use_thread_safe) { cdecl = new CCodeDeclaration("gsize"); cdecl.add_declarator(new CCodeVariableDeclarator(type_id_name + "__volatile", new CCodeConstant("0"))); } else { cdecl = new CCodeDeclaration("GType"); cdecl.add_declarator(new CCodeVariableDeclarator(type_id_name, new CCodeConstant("0"))); } cdecl.modifiers = CCodeModifiers.STATIC; if (use_thread_safe) { cdecl.modifiers |= CCodeModifiers.VOLATILE; } if (!plugin) { type_block.add_statement(cdecl); } else { source_declaration_fragment.append(cdecl); } CCodeFunction fun; if (!plugin) { fun = new CCodeFunction("%s_get_type".printf(CCodeBaseModule.get_ccode_lower_case_name(get_type_declaration())), "GType"); fun.modifiers = CCodeModifiers.CONST; /* Function will not be prototyped anyway */ if (get_accessibility() == SymbolAccessibility.PRIVATE) { // avoid C warning as this function is not always used fun.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.UNUSED; } else if (context.hide_internal && get_accessibility() == SymbolAccessibility.INTERNAL) { // avoid C warning as this function is not always used fun.modifiers |= CCodeModifiers.INTERNAL | CCodeModifiers.UNUSED; } fun.is_declaration = true; declaration_fragment.append(fun.copy()); fun.is_declaration = false; } else { fun = new CCodeFunction("%s_register_type".printf(CCodeBaseModule.get_ccode_lower_case_name(get_type_declaration())), "GType"); fun.add_parameter(new CCodeParameter("module", "GTypeModule *")); var get_fun = new CCodeFunction("%s_get_type".printf(CCodeBaseModule.get_ccode_lower_case_name(get_type_declaration())), "GType"); get_fun.modifiers = CCodeModifiers.CONST; get_fun.is_declaration = true; declaration_fragment.append(get_fun.copy()); get_fun.is_declaration = false; get_fun.block = new CCodeBlock(); get_fun.block.add_statement(new CCodeReturnStatement(new CCodeIdentifier(type_id_name))); definition_fragment.append(get_fun); } string type_value_table_decl_name = null; var type_init = new CCodeBlock(); if (fundamental) { var cgtypetabledecl = new CCodeDeclaration("const GTypeValueTable"); cgtypetabledecl.modifiers = CCodeModifiers.STATIC; cgtypetabledecl.add_declarator(new CCodeVariableDeclarator("g_define_type_value_table", new CCodeConstant("{ %s, %s, %s, %s, \"p\", %s, \"p\", %s }".printf(get_gtype_value_table_init_function_name(), get_gtype_value_table_free_function_name(), get_gtype_value_table_copy_function_name(), get_gtype_value_table_peek_pointer_function_name(), get_gtype_value_table_collect_value_function_name(), get_gtype_value_table_lcopy_value_function_name())))); type_value_table_decl_name = "&g_define_type_value_table"; type_init.add_statement(cgtypetabledecl); } else { type_value_table_decl_name = "NULL"; } if (get_type_declaration() is ObjectTypeSymbol) { var ctypedecl = new CCodeDeclaration("const GTypeInfo"); ctypedecl.modifiers = CCodeModifiers.STATIC; ctypedecl.add_declarator(new CCodeVariableDeclarator("g_define_type_info", new CCodeConstant("{ sizeof (%s), (GBaseInitFunc) %s, (GBaseFinalizeFunc) %s, (GClassInitFunc) %s, (GClassFinalizeFunc) %s, NULL, %s, 0, (GInstanceInitFunc) %s, %s }".printf(get_type_struct_name(), get_base_init_func_name(), (plugin) ? get_base_finalize_func_name() : "NULL", get_class_init_func_name(), get_class_finalize_func_name(), get_instance_struct_size(), get_instance_init_func_name(), type_value_table_decl_name)))); type_init.add_statement(ctypedecl); if (fundamental) { var ctypefundamentaldecl = new CCodeDeclaration("const GTypeFundamentalInfo"); ctypefundamentaldecl.modifiers = CCodeModifiers.STATIC; ctypefundamentaldecl.add_declarator(new CCodeVariableDeclarator("g_define_type_fundamental_info", new CCodeConstant("{ (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }"))); type_init.add_statement(ctypefundamentaldecl); } } type_init.add_statement(get_type_interface_init_declaration()); CCodeFunctionCall reg_call; if (get_type_declaration() is Struct) { reg_call = new CCodeFunctionCall(new CCodeIdentifier("g_boxed_type_register_static")); } else if (get_type_declaration() is ValaEnum) { var en = get_type_declaration() as ValaEnum; if (en.is_flags) { reg_call = new CCodeFunctionCall(new CCodeIdentifier("g_flags_register_static")); } else { reg_call = new CCodeFunctionCall(new CCodeIdentifier("g_enum_register_static")); } } else if (fundamental) { reg_call = new CCodeFunctionCall(new CCodeIdentifier("g_type_register_fundamental")); reg_call.add_argument(new CCodeFunctionCall(new CCodeIdentifier("g_type_fundamental_next"))); } else if (!plugin) { reg_call = new CCodeFunctionCall(new CCodeIdentifier("g_type_register_static")); reg_call.add_argument(new CCodeIdentifier(get_parent_type_name())); } else { reg_call = new CCodeFunctionCall(new CCodeIdentifier("g_type_module_register_type")); reg_call.add_argument(new CCodeIdentifier("module")); reg_call.add_argument(new CCodeIdentifier(get_parent_type_name())); } reg_call.add_argument(new CCodeConstant("\"%s\"".printf(CCodeBaseModule.get_ccode_name(get_type_declaration())))); if (get_type_declaration() is Struct) { var st = (Struct)get_type_declaration(); reg_call.add_argument(new CCodeCastExpression(new CCodeIdentifier(CCodeBaseModule.get_ccode_dup_function(st)), "GBoxedCopyFunc")); reg_call.add_argument(new CCodeCastExpression(new CCodeIdentifier(CCodeBaseModule.get_ccode_free_function(st)), "GBoxedFreeFunc")); } else if (get_type_declaration() is ValaEnum) { var en = get_type_declaration() as ValaEnum; var clist = new CCodeInitializerList(); /* or during visit time? */ CCodeInitializerList clist_ev = null; foreach (EnumValue ev in en.get_values()) { clist_ev = new CCodeInitializerList(); clist_ev.append(new CCodeConstant(CCodeBaseModule.get_ccode_name(ev))); clist_ev.append(new CCodeIdentifier("\"%s\"".printf(CCodeBaseModule.get_ccode_name(ev)))); clist_ev.append(CCodeBaseModule.get_enum_value_canonical_cconstant(ev)); clist.append(clist_ev); } clist_ev = new CCodeInitializerList(); clist_ev.append(new CCodeConstant("0")); clist_ev.append(new CCodeConstant("NULL")); clist_ev.append(new CCodeConstant("NULL")); clist.append(clist_ev); var enum_decl = new CCodeVariableDeclarator("values[]", clist); if (en.is_flags) { cdecl = new CCodeDeclaration("const GFlagsValue"); } else { cdecl = new CCodeDeclaration("const GEnumValue"); } cdecl.add_declarator(enum_decl); cdecl.modifiers = CCodeModifiers.STATIC; type_init.add_statement(cdecl); reg_call.add_argument(new CCodeIdentifier("values")); } else { reg_call.add_argument(new CCodeIdentifier("&g_define_type_info")); if (fundamental) { reg_call.add_argument(new CCodeIdentifier("&g_define_type_fundamental_info")); } reg_call.add_argument(new CCodeConstant(get_type_flags())); } if (use_thread_safe && !plugin) { var temp_decl = new CCodeDeclaration("GType"); temp_decl.add_declarator(new CCodeVariableDeclarator(type_id_name, reg_call)); type_init.add_statement(temp_decl); } else { type_init.add_statement(new CCodeExpressionStatement(new CCodeAssignment(new CCodeIdentifier(type_id_name), reg_call))); } if (cl != null && cl.has_class_private_fields) { CCodeFunctionCall add_class_private_call; add_class_private_call = new CCodeFunctionCall(new CCodeIdentifier("g_type_add_class_private")); add_class_private_call.add_argument(new CCodeIdentifier(type_id_name)); add_class_private_call.add_argument(new CCodeIdentifier("sizeof (%sClassPrivate)".printf(CCodeBaseModule.get_ccode_name(get_type_declaration())))); type_init.add_statement(new CCodeExpressionStatement(add_class_private_call)); } if (!declaration_only) { get_type_interface_init_statements(type_init, plugin); } if (!plugin) { CCodeExpression condition; // the condition that guards the type initialisation if (use_thread_safe) { var enter = new CCodeFunctionCall(new CCodeIdentifier("g_once_init_enter")); enter.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier(type_id_name + "__volatile"))); condition = enter; var leave = new CCodeFunctionCall(new CCodeIdentifier("g_once_init_leave")); leave.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier(type_id_name + "__volatile"))); leave.add_argument(new CCodeIdentifier(type_id_name)); type_init.add_statement(new CCodeExpressionStatement(leave)); } else { var id = new CCodeIdentifier(type_id_name); var zero = new CCodeConstant("0"); condition = new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, id, zero); } CCodeExpression cond; if (use_thread_safe) { cond = condition; } else { cond = new CCodeFunctionCall(new CCodeIdentifier("G_UNLIKELY")); (cond as CCodeFunctionCall).add_argument(condition); } var cif = new CCodeIfStatement(cond, type_init); type_block.add_statement(cif); } else { type_block = type_init; } if (use_thread_safe) { type_block.add_statement(new CCodeReturnStatement(new CCodeIdentifier(type_id_name + "__volatile"))); } else { type_block.add_statement(new CCodeReturnStatement(new CCodeIdentifier(type_id_name))); } fun.block = type_block; definition_fragment.append(fun); }
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); }
private void add_set_property_function(Class cl) { var set_prop = new CCodeFunction("_vala_%s_set_property".printf(get_ccode_lower_case_name(cl, null)), "void"); set_prop.modifiers = CCodeModifiers.STATIC; set_prop.add_parameter(new CCodeParameter("object", "GObject *")); set_prop.add_parameter(new CCodeParameter("property_id", "guint")); set_prop.add_parameter(new CCodeParameter("value", "const GValue *")); set_prop.add_parameter(new CCodeParameter("pspec", "GParamSpec *")); push_function(set_prop); CCodeFunctionCall ccall = generate_instance_cast(new CCodeIdentifier("object"), cl); ccode.add_declaration("%s *".printf(get_ccode_name(cl)), new CCodeVariableDeclarator("self", ccall)); ccode.open_switch(new CCodeIdentifier("property_id")); var props = cl.get_properties(); foreach (Property prop in props) { if (prop.set_accessor == null || prop.is_abstract) { continue; } if (!is_gobject_property(prop)) { continue; } Property base_prop = prop; CCodeExpression cself = new CCodeIdentifier("self"); if (prop.base_property != null) { var base_type = (Class)prop.base_property.parent_symbol; base_prop = prop.base_property; cself = get_cvalue_(transform_value(new GLibValue(new ObjectType(cl), cself, true), new ObjectType(base_type), prop)); generate_property_accessor_declaration(prop.base_property.set_accessor, cfile); } else if (prop.base_interface_property != null) { var base_type = (Interface)prop.base_interface_property.parent_symbol; base_prop = prop.base_interface_property; cself = get_cvalue_(transform_value(new GLibValue(new ObjectType(cl), cself, true), new ObjectType(base_type), prop)); generate_property_accessor_declaration(prop.base_interface_property.set_accessor, cfile); } CCodeExpression cfunc; if (!get_ccode_no_accessor_method(base_prop) && !get_ccode_concrete_accessor(base_prop)) { cfunc = new CCodeIdentifier(get_ccode_name(base_prop.set_accessor)); } else { // use the static real function as helper cfunc = new CCodeIdentifier(get_ccode_real_name(prop.set_accessor)); } ccode.add_case(new CCodeIdentifier(get_ccode_upper_case_name(prop))); ccall = new CCodeFunctionCall(cfunc); ccall.add_argument(cself); if (prop.property_type is ArrayType && ((ArrayType)prop.property_type).element_type.data_type == string_type.data_type) { ccode.open_block(); ccode.add_declaration("gpointer", new CCodeVariableDeclarator("boxed")); var cgetcall = new CCodeFunctionCall(new CCodeIdentifier("g_value_get_boxed")); cgetcall.add_argument(new CCodeIdentifier("value")); ccode.add_assignment(new CCodeIdentifier("boxed"), cgetcall); ccall.add_argument(new CCodeIdentifier("boxed")); var cisnull = new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, new CCodeIdentifier("boxed"), new CCodeConstant("NULL")); var cstrvlen = new CCodeFunctionCall(new CCodeIdentifier("g_strv_length")); cstrvlen.add_argument(new CCodeIdentifier("boxed")); var ccond = new CCodeConditionalExpression(cisnull, new CCodeConstant("0"), cstrvlen); ccall.add_argument(ccond); add_guarded_expression(prop, ccall); ccode.close(); } else { var cgetcall = new CCodeFunctionCall(); if (prop.property_type.data_type != null) { cgetcall.call = new CCodeIdentifier(get_ccode_get_value_function(prop.property_type.data_type)); } else { cgetcall.call = new CCodeIdentifier("g_value_get_pointer"); } cgetcall.add_argument(new CCodeIdentifier("value")); ccall.add_argument(cgetcall); add_guarded_expression(prop, ccall); } ccode.add_break(); } /* type, dup func, and destroy func properties for generic types */ foreach (TypeParameter type_param in cl.get_type_parameters()) { string func_name, enum_value; CCodeMemberAccess cfield; CCodeFunctionCall cgetcall; func_name = "%s_type".printf(type_param.name.ToLower()); enum_value = "%s_%s".printf(get_ccode_lower_case_name(cl, null), func_name).ToUpper(); ccode.add_case(new CCodeIdentifier(enum_value)); cfield = CCodeMemberAccess.pointer(CCodeMemberAccess.pointer(new CCodeIdentifier("self"), "priv"), func_name); cgetcall = new CCodeFunctionCall(new CCodeIdentifier("g_value_get_gtype")); cgetcall.add_argument(new CCodeIdentifier("value")); ccode.add_assignment(cfield, cgetcall); ccode.add_break(); func_name = "%s_dup_func".printf(type_param.name.ToLower()); enum_value = "%s_%s".printf(get_ccode_lower_case_name(cl, null), func_name).ToUpper(); ccode.add_case(new CCodeIdentifier(enum_value)); cfield = CCodeMemberAccess.pointer(CCodeMemberAccess.pointer(new CCodeIdentifier("self"), "priv"), func_name); cgetcall = new CCodeFunctionCall(new CCodeIdentifier("g_value_get_pointer")); cgetcall.add_argument(new CCodeIdentifier("value")); ccode.add_assignment(cfield, cgetcall); ccode.add_break(); func_name = "%s_destroy_func".printf(type_param.name.ToLower()); enum_value = "%s_%s".printf(get_ccode_lower_case_name(cl, null), func_name).ToUpper(); ccode.add_case(new CCodeIdentifier(enum_value)); cfield = CCodeMemberAccess.pointer(CCodeMemberAccess.pointer(new CCodeIdentifier("self"), "priv"), func_name); cgetcall = new CCodeFunctionCall(new CCodeIdentifier("g_value_get_pointer")); cgetcall.add_argument(new CCodeIdentifier("value")); ccode.add_assignment(cfield, cgetcall); ccode.add_break(); } ccode.add_default(); emit_invalid_property_id_warn(); ccode.add_break(); ccode.close(); pop_function(); cfile.add_function_declaration(set_prop); cfile.add_function(set_prop); }
public override void visit_constructor(Constructor c) { push_line(c.source_reference); var cl = (Class)c.parent_symbol; if (c.binding == MemberBinding.INSTANCE) { if (!cl.is_subtype_of(gobject_type)) { Report.error(c.source_reference, "construct blocks require GLib.Object"); c.error = true; return; } push_context(new EmitContext(c)); var function = new CCodeFunction("%s_constructor".printf(get_ccode_lower_case_name(cl, null)), "GObject *"); function.modifiers = CCodeModifiers.STATIC; function.add_parameter(new CCodeParameter("type", "GType")); function.add_parameter(new CCodeParameter("n_construct_properties", "guint")); function.add_parameter(new CCodeParameter("construct_properties", "GObjectConstructParam *")); cfile.add_function_declaration(function); push_function(function); ccode.add_declaration("GObject *", new CCodeVariableDeclarator("obj")); ccode.add_declaration("GObjectClass *", new CCodeVariableDeclarator("parent_class")); var ccast = new CCodeFunctionCall(new CCodeIdentifier("G_OBJECT_CLASS")); ccast.add_argument(new CCodeIdentifier("%s_parent_class".printf(get_ccode_lower_case_name(cl, null)))); ccode.add_assignment(new CCodeIdentifier("parent_class"), ccast); var ccall = new CCodeFunctionCall(CCodeMemberAccess.pointer(new CCodeIdentifier("parent_class"), "constructor")); ccall.add_argument(new CCodeIdentifier("type")); ccall.add_argument(new CCodeIdentifier("n_construct_properties")); ccall.add_argument(new CCodeIdentifier("construct_properties")); ccode.add_assignment(new CCodeIdentifier("obj"), ccall); ccall = generate_instance_cast(new CCodeIdentifier("obj"), cl); ccode.add_declaration("%s *".printf(get_ccode_name(cl)), new CCodeVariableDeclarator("self")); ccode.add_assignment(new CCodeIdentifier("self"), ccall); c.body.emit(this); if (current_method_inner_error) { /* always separate error parameter and inner_error local variable * as error may be set to NULL but we're always interested in inner errors */ ccode.add_declaration("GError *", CCodeVariableDeclarator.zero("_inner_error_", new CCodeConstant("NULL"))); } ccode.add_return(new CCodeIdentifier("obj")); pop_function(); cfile.add_function(function); pop_context(); } else if (c.binding == MemberBinding.CLASS) { // class constructor if (cl.is_compact) { Report.error(c.source_reference, "class constructors are not supported in compact classes"); c.error = true; return; } push_context(base_init_context); c.body.emit(this); if (current_method_inner_error) { /* always separate error parameter and inner_error local variable * as error may be set to NULL but we're always interested in inner errors */ ccode.add_declaration("GError *", CCodeVariableDeclarator.zero("_inner_error_", new CCodeConstant("NULL"))); } pop_context(); } else if (c.binding == MemberBinding.STATIC) { // static class constructor // add to class_init if (cl.is_compact) { Report.error(c.source_reference, "static constructors are not supported in compact classes"); c.error = true; return; } push_context(class_init_context); c.body.emit(this); if (current_method_inner_error) { /* always separate error parameter and inner_error local variable * as error may be set to NULL but we're always interested in inner errors */ ccode.add_declaration("GError *", CCodeVariableDeclarator.zero("_inner_error_", new CCodeConstant("NULL"))); } pop_context(); } else { Report.error(c.source_reference, "internal error: constructors must have instance, class, or static binding"); } pop_line(); }
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); }
string generate_array_dup_wrapper(ArrayType array_type) { string dup_func = "_vala_array_dup%d".printf(++next_array_dup_id); if (!add_wrapper(dup_func)) { // wrapper already defined return(dup_func); } // declaration var function = new CCodeFunction(dup_func, get_ccode_name(array_type)); function.modifiers = CCodeModifiers.STATIC; function.add_parameter(new CCodeParameter("self", get_ccode_name(array_type))); // total length over all dimensions function.add_parameter(new CCodeParameter("length", "int")); if (array_type.element_type is GenericType) { // dup function array elements string func_name = "%s_dup_func".printf(array_type.element_type.type_parameter.name.ToLower()); function.add_parameter(new CCodeParameter(func_name, "GBoxedCopyFunc")); } // definition push_context(new EmitContext()); push_function(function); if (requires_copy(array_type.element_type)) { var cvardecl = new CCodeVariableDeclarator("result"); var gnew = new CCodeFunctionCall(new CCodeIdentifier("g_new0")); gnew.add_argument(new CCodeIdentifier(get_ccode_name(array_type.element_type))); CCodeExpression length_expr = new CCodeIdentifier("length"); // add extra item to have array NULL-terminated for all reference types if (array_type.element_type.data_type != null && array_type.element_type.data_type.is_reference_type()) { length_expr = new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, length_expr, new CCodeConstant("1")); } gnew.add_argument(length_expr); ccode.add_declaration(get_ccode_name(array_type), cvardecl); ccode.add_assignment(new CCodeIdentifier("result"), gnew); ccode.add_declaration("int", new CCodeVariableDeclarator("i")); ccode.open_for(new CCodeAssignment(new CCodeIdentifier("i"), new CCodeConstant("0")), new CCodeBinaryExpression(CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier("i"), new CCodeIdentifier("length")), new CCodeUnaryExpression(CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier("i"))); ccode.add_assignment(new CCodeElementAccess(new CCodeIdentifier("result"), new CCodeIdentifier("i")), get_cvalue_(copy_value(new GLibValue(array_type.element_type, new CCodeElementAccess(new CCodeIdentifier("self"), new CCodeIdentifier("i")), true), array_type))); ccode.close(); ccode.add_return(new CCodeIdentifier("result")); } else { var dup_call = new CCodeFunctionCall(new CCodeIdentifier("g_memdup")); dup_call.add_argument(new CCodeIdentifier("self")); var sizeof_call = new CCodeFunctionCall(new CCodeIdentifier("sizeof")); sizeof_call.add_argument(new CCodeIdentifier(get_ccode_name(array_type.element_type))); dup_call.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.MUL, new CCodeIdentifier("length"), sizeof_call)); ccode.add_return(dup_call); } // append to file cfile.add_function_declaration(function); cfile.add_function(function); pop_context(); return(dup_func); }
string generate_array_add_wrapper(ArrayType array_type) { string add_func = "_vala_array_add%d".printf(++next_array_add_id); if (!add_wrapper(add_func)) { // wrapper already defined return(add_func); } var function = new CCodeFunction(add_func, "void"); function.modifiers = CCodeModifiers.STATIC; function.add_parameter(new CCodeParameter("array", "%s *".printf(get_ccode_name(array_type)))); function.add_parameter(new CCodeParameter("length", "int*")); function.add_parameter(new CCodeParameter("size", "int*")); push_function(function); string typename = get_ccode_name(array_type.element_type); CCodeExpression value = new CCodeIdentifier("value"); if (array_type.element_type.is_real_struct_type()) { if (!array_type.element_type.nullable || !array_type.element_type.value_owned) { typename = "const " + typename; } if (!array_type.element_type.nullable) { typename += "*"; value = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, value); } } function.add_parameter(new CCodeParameter("value", typename)); var array = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier("array")); var length = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier("length")); var size = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier("size")); var renew_call = new CCodeFunctionCall(new CCodeIdentifier("g_renew")); renew_call.add_argument(new CCodeIdentifier(get_ccode_name(array_type.element_type))); renew_call.add_argument(array); if (array_type.element_type.is_reference_type_or_type_parameter()) { // NULL terminate array renew_call.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, size, new CCodeConstant("1"))); } else { renew_call.add_argument(size); } var csizecheck = new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, length, size); ccode.open_if(csizecheck); ccode.add_assignment(size, new CCodeConditionalExpression(size, new CCodeBinaryExpression(CCodeBinaryOperator.MUL, new CCodeConstant("2"), size), new CCodeConstant("4"))); ccode.add_assignment(array, renew_call); ccode.close(); ccode.add_assignment(new CCodeElementAccess(array, new CCodeUnaryExpression(CCodeUnaryOperator.POSTFIX_INCREMENT, length)), value); if (array_type.element_type.is_reference_type_or_type_parameter()) { // NULL terminate array ccode.add_assignment(new CCodeElementAccess(array, length), new CCodeConstant("NULL")); } pop_function(); cfile.add_function_declaration(function); cfile.add_function(function); return(add_func); }
public override void generate_struct_declaration(Struct st, CCodeFile decl_space) { if (add_symbol_declaration(decl_space, st, get_ccode_name(st))) { return; } if (st.is_boolean_type() || st.is_integer_type() || st.is_floating_type()) { if (st.base_struct != null) { generate_struct_declaration(st.base_struct, decl_space); decl_space.add_type_declaration(new CCodeTypeDefinition(get_ccode_name(st.base_struct), new CCodeVariableDeclarator(get_ccode_name(st)))); } else { string typename = null; if (st.is_boolean_type()) { // typedef for boolean types decl_space.add_include("stdbool.h"); typename = "bool"; } else if (st.is_integer_type()) { // typedef for integral types decl_space.add_include("stdint.h"); typename = "%sint%d_t".printf(st.signed ? "" : "u", st.width); } else if (st.is_floating_type()) { // typedef for floating types typename = (st.width == 64 ? "double" : "float"); } decl_space.add_type_declaration(new CCodeTypeDefinition(typename, new CCodeVariableDeclarator(get_ccode_name(st)))); } return; } if (get_ccode_has_type_id(st)) { decl_space.add_include("glib-object.h"); decl_space.add_type_declaration(new CCodeNewline()); var macro = "(%s_get_type ())".printf(get_ccode_lower_case_name(st, null)); decl_space.add_type_declaration(new CCodeMacroReplacement(get_ccode_type_id(st), macro)); var type_fun = new StructRegisterFunction(st, context); type_fun.init_from_type(false, true); decl_space.add_type_member_declaration(type_fun.get_declaration()); } var instance_struct = new CCodeStruct("_%s".printf(get_ccode_name(st))); instance_struct.modifiers |= (st.version.deprecated ? CCodeModifiers.DEPRECATED : 0); foreach (Field f in st.get_fields()) { if (f.binding == MemberBinding.INSTANCE) { generate_type_declaration(f.variable_type, decl_space); CCodeModifiers modifiers = (f.is_volatile ? CCodeModifiers.VOLATILE : 0) | (f.version.deprecated ? CCodeModifiers.DEPRECATED : 0); instance_struct.add_field(get_ccode_name(f.variable_type), get_ccode_name(f), modifiers, get_ccode_declarator_suffix(f.variable_type)); if (f.variable_type is ArrayType && get_ccode_array_length(f)) { // create fields to store array dimensions var array_type = (ArrayType)f.variable_type; if (!array_type.fixed_length) { var len_type = int_type.copy(); for (int dim = 1; dim <= array_type.rank; dim++) { string length_cname; if (get_ccode_array_length_name(f) != null) { length_cname = get_ccode_array_length_name(f); } else { length_cname = get_array_length_cname(get_ccode_name(f), dim); } instance_struct.add_field(get_ccode_name(len_type), length_cname); } if (array_type.rank == 1 && f.is_internal_symbol()) { instance_struct.add_field(get_ccode_name(len_type), get_array_size_cname(get_ccode_name(f))); } } } else if (f.variable_type is DelegateType) { var delegate_type = (DelegateType)f.variable_type; if (delegate_type.delegate_symbol.has_target) { // create field to store delegate target instance_struct.add_field("gpointer", get_ccode_delegate_target_name(f)); if (delegate_type.is_disposable()) { instance_struct.add_field("GDestroyNotify", get_delegate_target_destroy_notify_cname(get_ccode_name(f))); } } } } } if (st.base_struct == null) { decl_space.add_type_declaration(new CCodeTypeDefinition("struct _%s".printf(get_ccode_name(st)), new CCodeVariableDeclarator(get_ccode_name(st)))); decl_space.add_type_definition(instance_struct); } else { decl_space.add_type_declaration(new CCodeTypeDefinition(get_ccode_name(st.base_struct), new CCodeVariableDeclarator(get_ccode_name(st)))); } var function = new CCodeFunction(get_ccode_dup_function(st), get_ccode_name(st) + "*"); if (st.is_private_symbol()) { function.modifiers = CCodeModifiers.STATIC; } else if (context.hide_internal && st.is_internal_symbol()) { function.modifiers = CCodeModifiers.INTERNAL; } function.add_parameter(new CCodeParameter("self", "const " + get_ccode_name(st) + "*")); decl_space.add_function_declaration(function); function = new CCodeFunction(get_ccode_free_function(st), "void"); if (st.is_private_symbol()) { function.modifiers = CCodeModifiers.STATIC; } else if (context.hide_internal && st.is_internal_symbol()) { function.modifiers = CCodeModifiers.INTERNAL; } function.add_parameter(new CCodeParameter("self", get_ccode_name(st) + "*")); decl_space.add_function_declaration(function); if (st.is_disposable()) { function = new CCodeFunction(get_ccode_copy_function(st), "void"); if (st.is_private_symbol()) { function.modifiers = CCodeModifiers.STATIC; } else if (context.hide_internal && st.is_internal_symbol()) { function.modifiers = CCodeModifiers.INTERNAL; } function.add_parameter(new CCodeParameter("self", "const " + get_ccode_name(st) + "*")); function.add_parameter(new CCodeParameter("dest", get_ccode_name(st) + "*")); decl_space.add_function_declaration(function); function = new CCodeFunction(get_ccode_destroy_function(st), "void"); if (st.is_private_symbol()) { function.modifiers = CCodeModifiers.STATIC; } else if (context.hide_internal && st.is_internal_symbol()) { function.modifiers = CCodeModifiers.INTERNAL; } function.add_parameter(new CCodeParameter("self", get_ccode_name(st) + "*")); decl_space.add_function_declaration(function); } }