Beispiel #1
0
        CCodeExpression deserialize_array(ArrayType array_type, CCodeExpression variant_expr, CCodeExpression expr)
        {
            if (array_type.rank == 1 && get_type_signature(array_type) == "ay")
            {
                return(deserialize_buffer_array(array_type, variant_expr, expr));
            }

            string temp_name = "_tmp%d_".printf(next_temp_var_id++);

            var new_call = new CCodeFunctionCall(new CCodeIdentifier("g_new"));

            new_call.add_argument(new CCodeIdentifier(get_ccode_name(array_type.element_type)));
            // add one extra element for NULL-termination
            new_call.add_argument(new CCodeConstant("5"));

            ccode.add_declaration(get_ccode_name(array_type), new CCodeVariableDeclarator(temp_name, new_call));
            ccode.add_declaration("int", new CCodeVariableDeclarator(temp_name + "_length", new CCodeConstant("0")));
            ccode.add_declaration("int", new CCodeVariableDeclarator(temp_name + "_size", new CCodeConstant("4")));

            deserialize_array_dim(array_type, 1, temp_name, variant_expr, expr);

            if (array_type.element_type.is_reference_type_or_type_parameter())
            {
                // NULL terminate array
                var length         = new CCodeIdentifier(temp_name + "_length");
                var element_access = new CCodeElementAccess(new CCodeIdentifier(temp_name), length);
                ccode.add_assignment(element_access, new CCodeIdentifier("NULL"));
            }

            return(new CCodeIdentifier(temp_name));
        }
Beispiel #2
0
        CCodeExpression deserialize_buffer_array(ArrayType array_type, CCodeExpression variant_expr, CCodeExpression expr)
        {
            string temp_name = "_tmp%d_".printf(next_temp_var_id++);

            var get_data_call = new CCodeFunctionCall(new CCodeIdentifier("g_variant_get_data"));

            get_data_call.add_argument(variant_expr);

            var get_size_call = new CCodeFunctionCall(new CCodeIdentifier("g_variant_get_size"));

            get_size_call.add_argument(variant_expr);
            ccode.add_declaration("gsize", new CCodeVariableDeclarator(temp_name + "_length", get_size_call));
            var length = new CCodeIdentifier(temp_name + "_length");

            var dup_call = new CCodeFunctionCall(new CCodeIdentifier("g_memdup"));

            dup_call.add_argument(get_data_call);
            dup_call.add_argument(length);

            ccode.add_declaration(get_ccode_name(array_type), new CCodeVariableDeclarator(temp_name, dup_call));
            if (expr != null)
            {
                ccode.add_assignment(get_array_length(expr, 1), length);
            }

            return(new CCodeIdentifier(temp_name));
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        public override void generate_cparameters(Method m, CCodeFile decl_space, Dictionary <int, CCodeParameter> cparam_map, CCodeFunction func, CCodeFunctionDeclarator vdeclarator = null, Dictionary <int, CCodeExpression> carg_map = null, CCodeFunctionCall vcall = null, int direction = 3)
        {
            if (m.coroutine)
            {
                decl_space.add_include("gio/gio.h");

                if (direction == 1)
                {
                    cparam_map[get_param_pos(-1)]   = new CCodeParameter("_callback_", "GAsyncReadyCallback");
                    cparam_map[get_param_pos(-0.9)] = new CCodeParameter("_user_data_", "gpointer");
                    if (carg_map != null)
                    {
                        carg_map[get_param_pos(-1)]   = new CCodeIdentifier("_callback_");
                        carg_map[get_param_pos(-0.9)] = new CCodeIdentifier("_user_data_");
                    }
                }
                else if (direction == 2)
                {
                    cparam_map[get_param_pos(0.1)] = new CCodeParameter("_res_", "GAsyncResult*");
                    if (carg_map != null)
                    {
                        carg_map[get_param_pos(0.1)] = new CCodeIdentifier("_res_");
                    }
                }
            }
            base.generate_cparameters(m, decl_space, cparam_map, func, vdeclarator, carg_map, vcall, direction);
        }
Beispiel #5
0
        private CCodeExpression get_signal_id_cexpression(Signal sig)
        {
            var cl                = (TypeSymbol)sig.parent_symbol;
            var signal_array      = new CCodeIdentifier("%s_signals".printf(get_ccode_lower_case_name(cl)));
            var signal_enum_value = new CCodeIdentifier("%s_%s_SIGNAL".printf(get_ccode_upper_case_name(cl), get_ccode_upper_case_name(sig)));

            return(new CCodeElementAccess(signal_array, signal_enum_value));
        }
Beispiel #6
0
        public void receive_dbus_value(DataType type, CCodeExpression message_expr, CCodeExpression iter_expr, CCodeExpression target_expr, Symbol sym, out bool may_fail, CCodeExpression error_expr = null)
        {
            may_fail = true;

            var fd_list = new CCodeFunctionCall(new CCodeIdentifier("g_dbus_message_get_unix_fd_list"));

            fd_list.add_argument(message_expr);

            var fd_var = new CCodeIdentifier("_fd");

            var stream = create_from_file_descriptor(type, fd_var);

            if (stream != null)
            {
                var fd_list_var = new CCodeIdentifier("_fd_list");

                var fd = new CCodeFunctionCall(new CCodeIdentifier("g_unix_fd_list_get"));
                fd.add_argument(fd_list_var);
                fd.add_argument(new CCodeIdentifier("_fd_index"));
                fd.add_argument(error_expr);

                ccode.add_assignment(fd_list_var, fd_list);
                ccode.open_if(fd_list_var);

                var get_fd = new CCodeFunctionCall(new CCodeIdentifier("g_variant_iter_next"));
                get_fd.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, iter_expr));
                get_fd.add_argument(new CCodeConstant("\"h\""));
                get_fd.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier("_fd_index")));
                ccode.add_expression(get_fd);

                ccode.add_assignment(fd_var, fd);
                ccode.open_if(new CCodeBinaryExpression(CCodeBinaryOperator.GREATER_THAN_OR_EQUAL, fd_var, new CCodeConstant("0")));

                ccode.add_assignment(target_expr, stream);
                may_fail = true;

                ccode.close();

                ccode.add_else();
                var set_error = new CCodeFunctionCall(new CCodeIdentifier("g_set_error_literal"));
                set_error.add_argument(error_expr);
                set_error.add_argument(new CCodeIdentifier("G_IO_ERROR"));
                set_error.add_argument(new CCodeIdentifier("G_IO_ERROR_FAILED"));
                set_error.add_argument(new CCodeConstant("\"FD List is NULL\""));
                ccode.add_expression(set_error);
                ccode.close();
            }
            else
            {
                read_expression(type, iter_expr, target_expr, sym, out may_fail, error_expr);
            }
        }
Beispiel #7
0
        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);
        }
Beispiel #8
0
        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);
        }
Beispiel #9
0
        void append_struct_array_free_loop(Struct st)
        {
            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 CCodeIdentifier("array");
            var cea       = new CCodeElementAccess(cptrarray, new CCodeIdentifier("i"));

            var cfreecall = new CCodeFunctionCall(get_destroy_func_expression(new StructValueType(st)));

            cfreecall.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, cea));
            ccode.add_expression(cfreecall);

            ccode.close();
        }
Beispiel #10
0
        public void read_expression(DataType type, CCodeExpression iter_expr, CCodeExpression target_expr, Symbol sym, out bool may_fail, CCodeExpression error_expr = null)
        {
            var iter_call = new CCodeFunctionCall(new CCodeIdentifier("g_variant_iter_next_value"));

            iter_call.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, iter_expr));

            may_fail = true;

            if (sym != null && get_dbus_signature(sym) != null)
            {
                // raw GVariantf
                ccode.add_assignment(target_expr, iter_call);
                may_fail = false;
                return;
            }

            string temp_name = "_tmp%d_".printf(next_temp_var_id++);

            ccode.add_declaration("GVariant*", new CCodeVariableDeclarator(temp_name));

            var variant_expr = new CCodeIdentifier(temp_name);

            ccode.add_assignment(variant_expr, iter_call);

            var result = deserialize_expression(type, variant_expr, target_expr, out may_fail, error_expr);

            if (result == null)
            {
                // error already reported
                return;
            }

            ccode.add_assignment(target_expr, result);

            var unref = new CCodeFunctionCall(new CCodeIdentifier("g_variant_unref"));

            unref.add_argument(variant_expr);
            ccode.add_expression(unref);
        }
Beispiel #11
0
        public override CCodeExpression get_signal_creation(Signal sig, TypeSymbol type)
        {
            var csignew = new CCodeFunctionCall(new CCodeIdentifier("g_signal_new"));

            csignew.add_argument(new CCodeConstant("\"%s\"".printf(get_ccode_name(sig))));
            csignew.add_argument(new CCodeIdentifier(get_ccode_type_id(type)));
            List <string> flags    = new List <string>();
            var           run_type = sig.get_attribute_string("Signal", "run");

            if (run_type == "first")
            {
                flags.Add("G_SIGNAL_RUN_FIRST");
            }
            else if (run_type == "cleanup")
            {
                flags.Add("G_SIGNAL_RUN_CLEANUP");
            }
            else
            {
                flags.Add("G_SIGNAL_RUN_LAST");
            }
            if (sig.get_attribute_bool("Signal", "detailed"))
            {
                flags.Add("G_SIGNAL_DETAILED");
            }

            if (sig.get_attribute_bool("Signal", "no_recurse"))
            {
                flags.Add("G_SIGNAL_NO_RECURSE");
            }

            if (sig.get_attribute_bool("Signal", "action"))
            {
                flags.Add("G_SIGNAL_ACTION");
            }

            if (sig.get_attribute_bool("Signal", "no_hooks"))
            {
                flags.Add("G_SIGNAL_NO_HOOKS");
            }

            if (sig.version.deprecated)
            {
                flags.Add("G_SIGNAL_DEPRECATED");
            }

            csignew.add_argument(new CCodeConstant(string.Join(" | ", flags)));

            if (sig.default_handler == null)
            {
                csignew.add_argument(new CCodeConstant("0"));
            }
            else
            {
                var struct_offset = new CCodeFunctionCall(new CCodeIdentifier("G_STRUCT_OFFSET"));
                if (type is Class)
                {
                    struct_offset.add_argument(new CCodeIdentifier("%sClass".printf(get_ccode_name(type))));
                }
                else
                {
                    // interface
                    struct_offset.add_argument(new CCodeIdentifier(get_ccode_type_name((Interface)type)));
                }
                struct_offset.add_argument(new CCodeIdentifier(get_ccode_vfunc_name(sig.default_handler)));
                csignew.add_argument(struct_offset);
            }
            csignew.add_argument(new CCodeConstant("NULL"));
            csignew.add_argument(new CCodeConstant("NULL"));

            string marshaller = get_marshaller_function(sig.get_parameters(), sig.return_type);

            var marshal_arg = new CCodeIdentifier(marshaller);

            csignew.add_argument(marshal_arg);

            var _params = sig.get_parameters();

            if (sig.return_type is PointerType || sig.return_type.type_parameter != null)
            {
                csignew.add_argument(new CCodeConstant("G_TYPE_POINTER"));
            }
            else if (sig.return_type is ErrorType)
            {
                csignew.add_argument(new CCodeConstant("G_TYPE_POINTER"));
            }
            else if (sig.return_type is ValaValueType && sig.return_type.nullable)
            {
                csignew.add_argument(new CCodeConstant("G_TYPE_POINTER"));
            }
            else if (sig.return_type.data_type == null)
            {
                csignew.add_argument(new CCodeConstant("G_TYPE_NONE"));
            }
            else
            {
                csignew.add_argument(new CCodeConstant(get_ccode_type_id(sig.return_type.data_type)));
            }

            int params_len = 0;

            foreach (Parameter param in _params)
            {
                params_len++;
                if (param.variable_type.is_array())
                {
                    params_len += ((ArrayType)param.variable_type).rank;
                }
            }

            csignew.add_argument(new CCodeConstant("%d".printf(params_len)));
            foreach (Parameter param in _params)
            {
                if (param.variable_type.is_array())
                {
                    if (((ArrayType)param.variable_type).element_type.data_type == string_type.data_type)
                    {
                        csignew.add_argument(new CCodeConstant("G_TYPE_STRV"));
                    }
                    else
                    {
                        csignew.add_argument(new CCodeConstant("G_TYPE_POINTER"));
                    }
                    for (var i = 0; i < ((ArrayType)param.variable_type).rank; i++)
                    {
                        csignew.add_argument(new CCodeConstant("G_TYPE_INT"));
                    }
                }
                else if (param.variable_type is PointerType || param.variable_type.type_parameter != null || param.direction != ParameterDirection.IN)
                {
                    csignew.add_argument(new CCodeConstant("G_TYPE_POINTER"));
                }
                else if (param.variable_type is ErrorType)
                {
                    csignew.add_argument(new CCodeConstant("G_TYPE_POINTER"));
                }
                else if (param.variable_type is ValaValueType && param.variable_type.nullable)
                {
                    csignew.add_argument(new CCodeConstant("G_TYPE_POINTER"));
                }
                else
                {
                    csignew.add_argument(new CCodeConstant(get_ccode_type_id(param.variable_type.data_type)));
                }
            }

            marshal_arg.name = marshaller;

            return(new CCodeAssignment(get_signal_id_cexpression(sig), csignew));
        }
Beispiel #12
0
        void generate_async_function(Method m)
        {
            push_context(new EmitContext());

            string callback_wrapper = null;

            if (!context.require_glib_version(2, 44))
            {
                callback_wrapper = get_ccode_real_name(m) + "_async_ready_wrapper";
                generate_async_ready_callback_wrapper(m, callback_wrapper);
            }

            var dataname   = Symbol.lower_case_to_camel_case(get_ccode_name(m)) + "Data";
            var asyncfunc  = new CCodeFunction(get_ccode_real_name(m), "void");
            var cparam_map = new Dictionary <int, CCodeParameter>();

            cparam_map[get_param_pos(-1)]   = new CCodeParameter("_callback_", "GAsyncReadyCallback");
            cparam_map[get_param_pos(-0.9)] = new CCodeParameter("_user_data_", "gpointer");

            generate_cparameters(m, cfile, cparam_map, asyncfunc, null, null, null, 1);

            if (m.base_method != null || m.base_interface_method != null)
            {
                // declare *_real_* function
                asyncfunc.modifiers |= CCodeModifiers.STATIC;
                cfile.add_function_declaration(asyncfunc);
            }
            else if (m.is_private_symbol())
            {
                asyncfunc.modifiers |= CCodeModifiers.STATIC;
            }
            else if (context.hide_internal && m.is_internal_symbol())
            {
                asyncfunc.modifiers |= CCodeModifiers.INTERNAL;
            }

            push_function(asyncfunc);

            // logic copied from valaccodemethodmodule
            if (m.overrides || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual))
            {
                Method base_method;

                if (m.overrides)
                {
                    base_method = m.base_method;
                }
                else
                {
                    base_method = m.base_interface_method;
                }

                var base_expression_type = new ObjectType((ObjectTypeSymbol)base_method.parent_symbol);
                var type_symbol          = m.parent_symbol as ObjectTypeSymbol;

                var self_target_type = new ObjectType(type_symbol);
                var cself            = get_cvalue_(transform_value(new GLibValue(base_expression_type, new CCodeIdentifier("base"), true), self_target_type, m));
                ccode.add_declaration("%s *".printf(get_ccode_name(type_symbol)), new CCodeVariableDeclarator("self"));
                ccode.add_assignment(new CCodeIdentifier("self"), cself);
            }

            var dataalloc = new CCodeFunctionCall(new CCodeIdentifier("g_slice_new0"));

            dataalloc.add_argument(new CCodeIdentifier(dataname));

            var data_var = new CCodeIdentifier("_data_");

            ccode.add_declaration(dataname + "*", new CCodeVariableDeclarator("_data_"));
            ccode.add_assignment(data_var, dataalloc);

            if (!context.require_glib_version(2, 44))
            {
                ccode.add_assignment(CCodeMemberAccess.pointer(data_var, "_callback_"), new CCodeConstant("_callback_"));
            }

            var create_result = new CCodeFunctionCall(new CCodeIdentifier("g_task_new"));

            var t = m.parent_symbol as TypeSymbol;

            if (!(m is CreationMethod) && m.binding == MemberBinding.INSTANCE &&
                t != null && t.is_subtype_of(gobject_type))
            {
                var gobject_cast = new CCodeFunctionCall(new CCodeIdentifier("G_OBJECT"));
                gobject_cast.add_argument(new CCodeIdentifier("self"));

                create_result.add_argument(gobject_cast);
            }
            else
            {
                create_result.add_argument(new CCodeConstant("NULL"));
            }

            Parameter cancellable_param = null;

            foreach (Parameter param in m.get_parameters())
            {
                if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name() == "GLib.Cancellable")
                {
                    cancellable_param = param;
                    break;
                }
            }

            if (cancellable_param == null)
            {
                create_result.add_argument(new CCodeConstant("NULL"));
            }
            else
            {
                create_result.add_argument(new CCodeIdentifier(get_variable_cname(cancellable_param.name)));
            }

            if (context.require_glib_version(2, 44))
            {
                create_result.add_argument(new CCodeIdentifier("_callback_"));
            }
            else
            {
                create_result.add_argument(new CCodeIdentifier(callback_wrapper));
            }
            create_result.add_argument(new CCodeIdentifier("_user_data_"));

            ccode.add_assignment(CCodeMemberAccess.pointer(data_var, "_async_result"), create_result);

            if (!context.require_glib_version(2, 44))
            {
                var task_completed_var = CCodeMemberAccess.pointer(data_var, "_task_complete_");
                var callback           = new CCodeIdentifier("_callback_");
                var callback_is_null   = new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, callback, new CCodeConstant("NULL"));

                ccode.open_if(callback_is_null);
                ccode.add_assignment(task_completed_var, new CCodeConstant("TRUE"));
                ccode.close();
            }

            var attach_data_call = new CCodeFunctionCall(new CCodeIdentifier("g_task_set_task_data"));

            attach_data_call.add_argument(CCodeMemberAccess.pointer(data_var, "_async_result"));
            attach_data_call.add_argument(data_var);
            attach_data_call.add_argument(new CCodeIdentifier(get_ccode_real_name(m) + "_data_free"));
            ccode.add_expression(attach_data_call);

            if (m is CreationMethod)
            {
                ccode.add_assignment(CCodeMemberAccess.pointer(data_var, "object_type"), new CCodeIdentifier("object_type"));
            }
            else if (m.binding == MemberBinding.INSTANCE)
            {
                var this_type = m.this_parameter.variable_type.copy();
                this_type.value_owned = true;

                // create copy if necessary as variables in async methods may need to be kept alive
                CCodeExpression cself = new CCodeIdentifier("self");
                if (this_type.is_real_non_null_struct_type())
                {
                    cself = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, cself);
                }
                if (requires_copy(this_type))
                {
                    cself = get_cvalue_(copy_value(new GLibValue(m.this_parameter.variable_type, cself, true), m.this_parameter));
                }

                ccode.add_assignment(CCodeMemberAccess.pointer(data_var, "self"), cself);
            }

            emit_context.push_symbol(m);
            foreach (Parameter param in m.get_parameters())
            {
                if (param.direction != ParameterDirection.OUT)
                {
                    // create copy if necessary as variables in async methods may need to be kept alive
                    var old_captured = param.captured;
                    param.captured           = false;
                    current_method.coroutine = false;

                    TargetValue value;
                    if (param.variable_type.value_owned)
                    {
                        // do not use load_parameter for reference/ownership transfer
                        // otherwise delegate destroy notify will not be moved
                        value = get_parameter_cvalue(param);
                    }
                    else
                    {
                        value = load_parameter(param);
                    }

                    current_method.coroutine = true;

                    store_parameter(param, value);

                    param.captured = old_captured;
                }
            }
            emit_context.pop_symbol();

            foreach (var type_param in m.get_type_parameters())
            {
                var type         = "%s_type".printf(type_param.name.ToLower());
                var dup_func     = "%s_dup_func".printf(type_param.name.ToLower());
                var destroy_func = "%s_destroy_func".printf(type_param.name.ToLower());
                ccode.add_assignment(CCodeMemberAccess.pointer(data_var, type), new CCodeIdentifier(type));
                ccode.add_assignment(CCodeMemberAccess.pointer(data_var, dup_func), new CCodeIdentifier(dup_func));
                ccode.add_assignment(CCodeMemberAccess.pointer(data_var, destroy_func), new CCodeIdentifier(destroy_func));
            }

            var ccall = new CCodeFunctionCall(new CCodeIdentifier(get_ccode_real_name(m) + "_co"));

            ccall.add_argument(data_var);
            ccode.add_expression(ccall);

            cfile.add_function(asyncfunc);

            pop_context();
        }
Beispiel #13
0
        void generate_finish_function(Method m)
        {
            push_context(new EmitContext());

            string dataname = Symbol.lower_case_to_camel_case(get_ccode_name(m)) + "Data";

            var finishfunc = new CCodeFunction(get_ccode_finish_real_name(m));

            var cparam_map = new Dictionary <int, CCodeParameter>();

            cparam_map[get_param_pos(0.1)] = new CCodeParameter("_res_", "GAsyncResult*");

            generate_cparameters(m, cfile, cparam_map, finishfunc, null, null, null, 2);

            if (m.is_private_symbol() || m.base_method != null || m.base_interface_method != null)
            {
                finishfunc.modifiers |= CCodeModifiers.STATIC;
            }
            else if (context.hide_internal && m.is_internal_symbol())
            {
                finishfunc.modifiers |= CCodeModifiers.INTERNAL;
            }

            push_function(finishfunc);

            var return_type = m.return_type;

            if (m is CreationMethod)
            {
                var type_sym = (TypeSymbol)m.parent_symbol;
                if (type_sym is ObjectTypeSymbol)
                {
                    ccode.add_declaration(get_ccode_name(type_sym) + "*", new CCodeVariableDeclarator("result"));
                }
            }
            else if (!(return_type is VoidType) && !return_type.is_real_non_null_struct_type())
            {
                ccode.add_declaration(get_ccode_name(m.return_type), new CCodeVariableDeclarator("result"));
            }

            var data_var = new CCodeIdentifier("_data_");

            ccode.add_declaration(dataname + "*", new CCodeVariableDeclarator("_data_"));

            var async_result_cast = new CCodeFunctionCall(new CCodeIdentifier("G_TASK"));

            async_result_cast.add_argument(new CCodeIdentifier("_res_"));

            var ccall = new CCodeFunctionCall(new CCodeIdentifier("g_task_propagate_pointer"));

            ccall.add_argument(async_result_cast);

            if (m.get_error_types().Count > 0)
            {
                ccall.add_argument(new CCodeIdentifier("error"));
            }
            else
            {
                ccall.add_argument(new CCodeConstant("NULL"));
            }

            ccode.add_assignment(data_var, ccall);

            bool has_cancellable = false;

            foreach (Parameter param in m.get_parameters())
            {
                if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name() == "GLib.Cancellable")
                {
                    has_cancellable = true;
                    break;
                }
            }

            // If a task is cancelled, g_task_propagate_pointer returns NULL
            if (m.get_error_types().Count > 0 || has_cancellable)
            {
                var is_null = new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, new CCodeConstant("NULL"), data_var);

                ccode.open_if(is_null);
                return_default_value(return_type);
                ccode.close();
            }

            emit_context.push_symbol(m);
            foreach (Parameter param in m.get_parameters())
            {
                if (param.direction != ParameterDirection.IN)
                {
                    return_out_parameter(param);
                    if (!(param.variable_type is ValaValueType) || param.variable_type.nullable)
                    {
                        ccode.add_assignment(CCodeMemberAccess.pointer(data_var, get_variable_cname(param.name)), new CCodeConstant("NULL"));
                    }
                }
            }
            emit_context.pop_symbol();

            if (m is CreationMethod)
            {
                ccode.add_assignment(new CCodeIdentifier("result"), CCodeMemberAccess.pointer(data_var, "self"));
                ccode.add_assignment(CCodeMemberAccess.pointer(data_var, "self"), new CCodeConstant("NULL"));
                ccode.add_return(new CCodeIdentifier("result"));
            }
            else if (return_type.is_real_non_null_struct_type())
            {
                // structs are returned via out parameter
                CCodeExpression cexpr = CCodeMemberAccess.pointer(data_var, "result");
                if (requires_copy(return_type))
                {
                    cexpr = get_cvalue_(copy_value(new GLibValue(return_type, cexpr, true), return_type));
                }
                ccode.add_assignment(new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier("result")), cexpr);
            }
            else if (!(return_type is VoidType))
            {
                ccode.add_assignment(new CCodeIdentifier("result"), CCodeMemberAccess.pointer(data_var, "result"));
                if (return_type is ArrayType)
                {
                    var array_type = (ArrayType)return_type;
                    if (get_ccode_array_length(m))
                    {
                        for (int dim = 1; dim <= array_type.rank; dim++)
                        {
                            ccode.add_assignment(new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier(get_array_length_cname("result", dim))), CCodeMemberAccess.pointer(data_var, get_array_length_cname("result", dim)));
                        }
                    }
                }
                else if (return_type is DelegateType && ((DelegateType)return_type).delegate_symbol.has_target)
                {
                    ccode.add_assignment(new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier(get_delegate_target_cname("result"))), CCodeMemberAccess.pointer(data_var, get_delegate_target_cname("result")));
                }
                if (!(return_type is ValaValueType) || return_type.nullable)
                {
                    ccode.add_assignment(CCodeMemberAccess.pointer(data_var, "result"), new CCodeConstant("NULL"));
                }
                ccode.add_return(new CCodeIdentifier("result"));
            }

            pop_function();

            cfile.add_function(finishfunc);

            pop_context();
        }
        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);
        }
Beispiel #15
0
        void visit_string_switch_statement(SwitchStatement stmt)
        {
            // we need a temporary variable to save the property value
            var temp_value = create_temp_value(stmt.expression.value_type, false, stmt);
            var ctemp      = get_cvalue_(temp_value);

            var cinit = new CCodeAssignment(ctemp, get_cvalue(stmt.expression));
            var czero = new CCodeConstant("0");

            var free_call = new CCodeFunctionCall(new CCodeIdentifier("g_free"));

            free_call.add_argument(ctemp);

            var cisnull = new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, new CCodeConstant("NULL"), ctemp);
            var cquark  = new CCodeFunctionCall(new CCodeIdentifier("g_quark_from_string"));

            cquark.add_argument(ctemp);

            var ccond = new CCodeConditionalExpression(cisnull, new CCodeConstant("0"), cquark);

            int label_temp_id = next_temp_var_id++;

            temp_value = create_temp_value(gquark_type, true, stmt);

            int label_count = 0;

            foreach (SwitchSection section in stmt.get_sections())
            {
                if (section.has_default_label())
                {
                    continue;
                }

                foreach (SwitchLabel label in section.get_labels())
                {
                    label.expression.emit(this);
                    var cexpr = get_cvalue(label.expression);

                    if (is_constant_ccode_expression(cexpr))
                    {
                        var cname = "_tmp%d_label%d".printf(label_temp_id, label_count++);

                        ccode.add_declaration(get_ccode_name(gquark_type), new CCodeVariableDeclarator(cname, czero), CCodeModifiers.STATIC);
                    }
                }
            }

            ccode.add_expression(cinit);

            ctemp = get_cvalue_(temp_value);
            cinit = new CCodeAssignment(ctemp, ccond);

            ccode.add_expression(cinit);

            if (stmt.expression.value_type.value_owned)
            {
                // free owned string
                ccode.add_expression(free_call);
            }

            SwitchSection default_section = null;

            label_count = 0;

            int n = 0;

            foreach (SwitchSection section in stmt.get_sections())
            {
                if (section.has_default_label())
                {
                    default_section = section;
                    continue;
                }

                CCodeBinaryExpression cor = null;
                foreach (SwitchLabel label in section.get_labels())
                {
                    label.expression.emit(this);
                    var cexpr = get_cvalue(label.expression);

                    if (is_constant_ccode_expression(cexpr))
                    {
                        var cname      = new CCodeIdentifier("_tmp%d_label%d".printf(label_temp_id, label_count++));
                        var ccondition = new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, czero, cname);
                        var ccall      = new CCodeFunctionCall(new CCodeIdentifier("g_quark_from_static_string"));
                        cinit = new CCodeAssignment(cname, ccall);

                        ccall.add_argument(cexpr);

                        cexpr = new CCodeConditionalExpression(ccondition, cname, cinit);
                    }
                    else
                    {
                        var ccall = new CCodeFunctionCall(new CCodeIdentifier("g_quark_from_string"));
                        ccall.add_argument(cexpr);
                        cexpr = ccall;
                    }

                    var ccmp = new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, ctemp, cexpr);

                    if (cor == null)
                    {
                        cor = ccmp;
                    }
                    else
                    {
                        cor = new CCodeBinaryExpression(CCodeBinaryOperator.OR, cor, ccmp);
                    }
                }

                if (n > 0)
                {
                    ccode.else_if(cor);
                }
                else
                {
                    ccode.open_if(cor);
                }

                ccode.open_switch(new CCodeConstant("0"));
                ccode.add_default();

                section.emit(this);

                ccode.close();

                n++;
            }

            if (default_section != null)
            {
                if (n > 0)
                {
                    ccode.add_else();
                }

                ccode.open_switch(new CCodeConstant("0"));
                ccode.add_default();

                default_section.emit(this);

                ccode.close();
            }

            if (n > 0)
            {
                ccode.close();
            }
        }
Beispiel #16
0
        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);
        }
Beispiel #17
0
        /* Returns access values to the given parameter */
        public override TargetValue get_parameter_cvalue(Parameter param)
        {
            var result = new GLibValue(param.variable_type.copy());

            result.lvalue = true;
            result.array_null_terminated = get_ccode_array_null_terminated(param);
            if (get_ccode_array_length_expr(param) != null)
            {
                result.array_length_cexpr = new CCodeConstant(get_ccode_array_length_expr(param));
            }
            result.ctype = get_ccode_type(param);

            var array_type    = result.value_type as ArrayType;
            var delegate_type = result.value_type as DelegateType;

            bool is_unowned_delegate = delegate_type != null && !param.variable_type.value_owned;

            if ((param.captured || is_in_coroutine()) && !is_unowned_delegate)
            {
                result.value_type.value_owned = true;
            }

            if (param.name == "this")
            {
                if (is_in_coroutine())
                {
                    // use closure
                    result.cvalue = CCodeMemberAccess.pointer(new CCodeIdentifier("_data_"), "self");
                }
                else
                {
                    var st = result.value_type.data_type as Struct;
                    if (st != null && !st.is_simple_type())
                    {
                        result.cvalue = new CCodeIdentifier("(*self)");
                    }
                    else
                    {
                        result.cvalue = new CCodeIdentifier("self");
                    }
                }
            }
            else
            {
                string name = param.name;

                if (param.captured)
                {
                    // captured variables are stored on the heap
                    var block = param.parent_symbol as Block;
                    if (block == null)
                    {
                        block = ((Method)param.parent_symbol).body;
                    }
                    result.cvalue = CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_variable_cname(param.name));
                    if (array_type != null && get_ccode_array_length(param))
                    {
                        for (int dim = 1; dim <= array_type.rank; dim++)
                        {
                            result.append_array_length_cvalue(CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_parameter_array_length_cname(param, dim)));
                        }
                    }
                    else if (delegate_type != null && delegate_type.delegate_symbol.has_target)
                    {
                        result.delegate_target_cvalue = CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_ccode_delegate_target_name(param));
                        if (result.value_type.is_disposable())
                        {
                            result.delegate_target_destroy_notify_cvalue = CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_delegate_target_destroy_notify_cname(get_variable_cname(param.name)));
                        }
                    }
                }
                else if (is_in_coroutine())
                {
                    // use closure
                    result.cvalue = get_variable_cexpression(param.name);
                    if (delegate_type != null && delegate_type.delegate_symbol.has_target)
                    {
                        result.delegate_target_cvalue = CCodeMemberAccess.pointer(new CCodeIdentifier("_data_"), get_ccode_delegate_target_name(param));
                        if (delegate_type.is_disposable())
                        {
                            result.delegate_target_destroy_notify_cvalue = CCodeMemberAccess.pointer(new CCodeIdentifier("_data_"), get_delegate_target_destroy_notify_cname(get_variable_cname(param.name)));
                        }
                    }
                }
                else
                {
                    var type_as_struct = result.value_type.data_type as Struct;

                    if (param.direction == ParameterDirection.OUT)
                    {
                        name = "_vala_%s".printf(name);
                    }

                    if (param.direction == ParameterDirection.REF ||
                        (param.direction == ParameterDirection.IN && type_as_struct != null && !type_as_struct.is_simple_type() && !result.value_type.nullable))
                    {
                        result.cvalue = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier(get_variable_cname(name)));
                    }
                    else
                    {
                        // Property setters of non simple structs shall replace all occurrences
                        // of the "value" formal parameter with a dereferencing version of that
                        // parameter.
                        if (current_property_accessor != null &&
                            current_property_accessor.writable &&
                            current_property_accessor.value_parameter == param &&
                            current_property_accessor.prop.property_type.is_real_struct_type() &&
                            !current_property_accessor.prop.property_type.nullable)
                        {
                            result.cvalue = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier("value"));
                        }
                        else
                        {
                            result.cvalue = get_variable_cexpression(name);
                        }
                    }
                    if (delegate_type != null && delegate_type.delegate_symbol.has_target)
                    {
                        var target_cname = get_ccode_delegate_target_name(param);
                        if (param.direction == ParameterDirection.OUT)
                        {
                            target_cname = "_vala_%s".printf(target_cname);
                        }
                        CCodeExpression target_expr = new CCodeIdentifier(target_cname);
                        CCodeExpression delegate_target_destroy_notify = new CCodeIdentifier(get_delegate_target_destroy_notify_cname(get_variable_cname(name)));
                        if (param.direction == ParameterDirection.REF)
                        {
                            // accessing argument of ref param
                            target_expr = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, target_expr);
                            delegate_target_destroy_notify = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, delegate_target_destroy_notify);
                        }
                        result.delegate_target_cvalue = target_expr;
                        if (result.value_type.is_disposable())
                        {
                            result.delegate_target_destroy_notify_cvalue = delegate_target_destroy_notify;
                        }
                    }
                }
                if (!param.captured && array_type != null)
                {
                    if (get_ccode_array_length(param) && !get_ccode_array_null_terminated(param))
                    {
                        for (int dim = 1; dim <= array_type.rank; dim++)
                        {
                            CCodeExpression length_expr = get_variable_cexpression(get_parameter_array_length_cname(param, dim));
                            if (param.direction == ParameterDirection.OUT)
                            {
                                length_expr = get_variable_cexpression(get_array_length_cname(get_variable_cname(name), dim));
                            }
                            else if (param.direction == ParameterDirection.REF)
                            {
                                // accessing argument of ref param
                                length_expr = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, length_expr);
                            }
                            result.append_array_length_cvalue(length_expr);
                        }
                    }
                }
            }

            return(result);
        }
Beispiel #18
0
        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);
        }
Beispiel #19
0
        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);
        }
        /// <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);
        }
Beispiel #21
0
        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);
        }
Beispiel #22
0
        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);
        }
Beispiel #23
0
        /* Returns lvalue access to the given field */
        public override TargetValue get_field_cvalue(Field field, TargetValue instance)
        {
            var value_type = field.variable_type.copy();

            var result = new GLibValue(value_type);

            if (instance != null)
            {
                result.actual_value_type = field.variable_type.get_actual_type(instance.value_type, null, field);
            }
            result.lvalue = true;
            result.array_null_terminated = get_ccode_array_null_terminated(field);
            if (get_ccode_array_length_expr(field) != null)
            {
                result.array_length_cexpr = new CCodeConstant(get_ccode_array_length_expr(field));
            }
            result.ctype = get_ccode_type(field);

            var array_type    = result.value_type as ArrayType;
            var delegate_type = result.value_type as DelegateType;

            if (field.binding == MemberBinding.INSTANCE)
            {
                CCodeExpression pub_inst = null;

                if (instance != null)
                {
                    pub_inst = get_cvalue_(instance);
                }

                var instance_target_type = get_data_type_for_symbol((TypeSymbol)field.parent_symbol);

                var  cl = instance_target_type.data_type as Class;
                bool is_gtypeinstance = ((instance_target_type.data_type == cl) && (cl == null || !cl.is_compact));

                CCodeExpression inst;
                if (is_gtypeinstance && field.access == SymbolAccessibility.PRIVATE)
                {
                    inst = CCodeMemberAccess.pointer(pub_inst, "priv");
                }
                else
                {
                    if (cl != null)
                    {
                        generate_class_struct_declaration(cl, cfile);
                    }
                    inst = pub_inst;
                }
                if (instance_target_type.data_type.is_reference_type() || (instance != null && instance.value_type is PointerType))
                {
                    result.cvalue = CCodeMemberAccess.pointer(inst, get_ccode_name(field));
                }
                else
                {
                    result.cvalue = new CCodeMemberAccess(inst, get_ccode_name(field));
                }

                if (array_type != null && get_ccode_array_length(field))
                {
                    for (int dim = 1; dim <= array_type.rank; dim++)
                    {
                        CCodeExpression length_expr = null;

                        string length_cname;
                        if (get_ccode_array_length_name(field) != null)
                        {
                            length_cname = get_ccode_array_length_name(field);
                        }
                        else
                        {
                            length_cname = get_array_length_cname(get_ccode_name(field), dim);
                        }

                        if (((TypeSymbol)field.parent_symbol).is_reference_type())
                        {
                            length_expr = CCodeMemberAccess.pointer(inst, length_cname);
                        }
                        else
                        {
                            length_expr = new CCodeMemberAccess(inst, length_cname);
                        }

                        result.append_array_length_cvalue(length_expr);
                    }
                    if (array_type.rank == 1 && field.is_internal_symbol())
                    {
                        string size_cname = get_array_size_cname(get_ccode_name(field));

                        if (((TypeSymbol)field.parent_symbol).is_reference_type())
                        {
                            set_array_size_cvalue(result, CCodeMemberAccess.pointer(inst, size_cname));
                        }
                        else
                        {
                            set_array_size_cvalue(result, new CCodeMemberAccess(inst, size_cname));
                        }
                    }
                }
                else if (delegate_type != null && delegate_type.delegate_symbol.has_target && get_ccode_delegate_target(field))
                {
                    string target_cname = get_ccode_delegate_target_name(field);
                    string target_destroy_notify_cname = get_delegate_target_destroy_notify_cname(get_ccode_name(field));

                    if (((TypeSymbol)field.parent_symbol).is_reference_type())
                    {
                        result.delegate_target_cvalue = CCodeMemberAccess.pointer(inst, target_cname);
                        if (result.value_type.is_disposable())
                        {
                            result.delegate_target_destroy_notify_cvalue = CCodeMemberAccess.pointer(inst, target_destroy_notify_cname);
                        }
                    }
                    else
                    {
                        result.delegate_target_cvalue = new CCodeMemberAccess(inst, target_cname);
                        if (result.value_type.is_disposable())
                        {
                            result.delegate_target_destroy_notify_cvalue = new CCodeMemberAccess(inst, target_destroy_notify_cname);
                        }
                    }
                }
            }
            else if (field.binding == MemberBinding.CLASS)
            {
                var cl   = (Class)field.parent_symbol;
                var cast = new CCodeFunctionCall(new CCodeIdentifier(get_ccode_upper_case_name(cl, null) + "_CLASS"));

                CCodeExpression klass;
                if (instance == null)
                {
                    if (get_this_type() == null)
                    {
                        // Accessing the field from a static or class constructor
                        klass = new CCodeIdentifier("klass");
                    }
                    else
                    {
                        // Accessing the field from within an instance method
                        var k = new CCodeFunctionCall(new CCodeIdentifier("G_OBJECT_GET_CLASS"));
                        k.add_argument(new CCodeIdentifier("self"));
                        klass = k;
                    }
                }
                else
                {
                    // Accessing the field of an instance
                    var k = new CCodeFunctionCall(new CCodeIdentifier("G_OBJECT_GET_CLASS"));
                    k.add_argument(get_cvalue_(instance));
                    klass = k;
                }
                cast.add_argument(klass);

                if (field.access == SymbolAccessibility.PRIVATE)
                {
                    var ccall = new CCodeFunctionCall(new CCodeIdentifier("%s_GET_CLASS_PRIVATE".printf(get_ccode_upper_case_name(cl))));
                    ccall.add_argument(klass);
                    result.cvalue = CCodeMemberAccess.pointer(ccall, get_ccode_name(field));
                }
                else
                {
                    result.cvalue = CCodeMemberAccess.pointer(cast, get_ccode_name(field));
                }
            }
            else
            {
                generate_field_declaration(field, cfile);

                result.cvalue = new CCodeIdentifier(get_ccode_name(field));

                if (array_type != null && get_ccode_array_length(field))
                {
                    for (int dim = 1; dim <= array_type.rank; dim++)
                    {
                        string length_cname;
                        if (get_ccode_array_length_name(field) != null)
                        {
                            length_cname = get_ccode_array_length_name(field);
                        }
                        else
                        {
                            length_cname = get_array_length_cname(get_ccode_name(field), dim);
                        }

                        result.append_array_length_cvalue(new CCodeIdentifier(length_cname));
                    }
                    if (array_type.rank == 1 && field.is_internal_symbol())
                    {
                        set_array_size_cvalue(result, new CCodeIdentifier(get_array_size_cname(get_ccode_name(field))));
                    }
                }
                else if (delegate_type != null && delegate_type.delegate_symbol.has_target && get_ccode_delegate_target(field))
                {
                    result.delegate_target_cvalue = new CCodeIdentifier(get_ccode_delegate_target_name(field));
                    if (result.value_type.is_disposable())
                    {
                        result.delegate_target_destroy_notify_cvalue = new CCodeIdentifier(get_delegate_target_destroy_notify_cname(get_ccode_name(field)));
                    }
                }
            }

            return(result);
        }