Пример #1
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);
        }
Пример #2
0
        void add_struct_free_function(Struct st)
        {
            var function = new CCodeFunction(get_ccode_free_function(st), "void");

            if (st.is_private_symbol())
            {
                function.modifiers = CCodeModifiers.STATIC;
            }
            else if (context.hide_internal && st.is_internal_symbol())
            {
                function.modifiers = CCodeModifiers.INTERNAL;
            }

            function.add_parameter(new CCodeParameter("self", get_ccode_name(st) + "*"));

            push_function(function);

            if (st.is_disposable())
            {
                var destroy_call = new CCodeFunctionCall(new CCodeIdentifier(get_ccode_destroy_function(st)));
                destroy_call.add_argument(new CCodeIdentifier("self"));
                ccode.add_expression(destroy_call);
            }

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

            free_call.add_argument(new CCodeIdentifier("self"));
            ccode.add_expression(free_call);

            pop_function();

            cfile.add_function(function);
        }
Пример #3
0
        public override string get_dynamic_signal_connect_after_wrapper_name(DynamicSignal sig)
        {
            if (sig.dynamic_type.data_type == null ||
                !sig.dynamic_type.data_type.is_subtype_of(gobject_type))
            {
                return(base.get_dynamic_signal_connect_wrapper_name(sig));
            }

            string connect_wrapper_name = "_%sconnect_after".printf(get_dynamic_signal_cname(sig));
            var    func = new CCodeFunction(connect_wrapper_name, "gulong");

            func.add_parameter(new CCodeParameter("obj", "gpointer"));
            func.add_parameter(new CCodeParameter("signal_name", "const char *"));
            func.add_parameter(new CCodeParameter("handler", "GCallback"));
            func.add_parameter(new CCodeParameter("data", "gpointer"));
            push_function(func);
            generate_gobject_connect_wrapper(sig, true);
            pop_function();

            // append to C source file
            cfile.add_function_declaration(func);
            cfile.add_function(func);

            return(connect_wrapper_name);
        }
Пример #4
0
        public CCodeFunction generate_enum_to_string_function(ValaEnum en)
        {
            var to_string_name = "%s_to_string".printf(get_ccode_lower_case_name(en, null));

            var to_string_func = new CCodeFunction(to_string_name, "const char*");

            to_string_func.add_parameter(new CCodeParameter("value", get_ccode_name(en)));

            push_function(to_string_func);

            ccode.add_declaration("const char *", new CCodeVariableDeclarator("str"));

            ccode.open_switch(new CCodeIdentifier("value"));
            foreach (EnumValue enum_value in en.get_values())
            {
                string dbus_value = get_dbus_value(enum_value, enum_value.name);
                ccode.add_case(new CCodeIdentifier(get_ccode_name(enum_value)));
                ccode.add_assignment(new CCodeIdentifier("str"), new CCodeConstant("\"%s\"".printf(dbus_value)));
                ccode.add_break();
            }

            ccode.close();

            ccode.add_return(new CCodeIdentifier("str"));

            pop_function();
            return(to_string_func);
        }
Пример #5
0
        public override string get_dynamic_property_setter_cname(DynamicProperty prop)
        {
            if (prop.dynamic_type.data_type == null ||
                !prop.dynamic_type.data_type.is_subtype_of(gobject_type))
            {
                return(base.get_dynamic_property_setter_cname(prop));
            }

            string setter_cname = "_dynamic_set_%s%d".printf(prop.name, dynamic_property_id++);

            var func = new CCodeFunction(setter_cname, "void");

            func.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.INLINE;
            func.add_parameter(new CCodeParameter("obj", get_ccode_name(prop.dynamic_type)));
            func.add_parameter(new CCodeParameter("value", get_ccode_name(prop.property_type)));

            push_function(func);

            var call = new CCodeFunctionCall(new CCodeIdentifier("g_object_set"));

            call.add_argument(new CCodeIdentifier("obj"));
            call.add_argument(get_property_canonical_cconstant(prop));
            call.add_argument(new CCodeIdentifier("value"));
            call.add_argument(new CCodeConstant("NULL"));

            ccode.add_expression(call);

            pop_function();

            // append to C source file
            cfile.add_function_declaration(func);
            cfile.add_function(func);

            return(setter_cname);
        }
Пример #6
0
        public override void generate_error_domain_declaration(ErrorDomain edomain, CCodeFile decl_space)
        {
            if (add_symbol_declaration(decl_space, edomain, get_ccode_name(edomain)))
            {
                return;
            }

            var cenum = new CCodeEnum(get_ccode_name(edomain));

            foreach (ErrorCode ecode in edomain.get_codes())
            {
                if (ecode.value == null)
                {
                    cenum.add_value(new CCodeEnumValue(get_ccode_name(ecode)));
                }
                else
                {
                    ecode.value.emit(this);
                    cenum.add_value(new CCodeEnumValue(get_ccode_name(ecode), get_cvalue(ecode.value)));
                }
            }

            decl_space.add_type_definition(cenum);

            string quark_fun_name = get_ccode_lower_case_prefix(edomain) + "quark";

            var error_domain_define = new CCodeMacroReplacement(get_ccode_upper_case_name(edomain), quark_fun_name + " ()");

            decl_space.add_type_definition(error_domain_define);

            var cquark_fun = new CCodeFunction(quark_fun_name, get_ccode_name(gquark_type.data_type));

            decl_space.add_function_declaration(cquark_fun);
        }
Пример #7
0
        public override void visit_error_domain(ErrorDomain edomain)
        {
            if (edomain.comment != null)
            {
                cfile.add_type_definition(new CCodeComment(edomain.comment.content));
            }

            generate_error_domain_declaration(edomain, cfile);

            if (!edomain.is_internal_symbol())
            {
                generate_error_domain_declaration(edomain, header_file);
            }
            if (!edomain.is_private_symbol())
            {
                generate_error_domain_declaration(edomain, internal_header_file);
            }

            string quark_fun_name = get_ccode_lower_case_prefix(edomain) + "quark";

            var cquark_fun = new CCodeFunction(quark_fun_name, get_ccode_name(gquark_type.data_type));

            push_function(cquark_fun);

            var cquark_call = new CCodeFunctionCall(new CCodeIdentifier("g_quark_from_static_string"));

            cquark_call.add_argument(new CCodeConstant("\"" + CCodeBaseModule.get_quark_name(edomain) + "\""));

            ccode.add_return(cquark_call);

            pop_function();
            cfile.add_function(cquark_fun);
        }
Пример #8
0
        string generate_array_copy_wrapper(ArrayType array_type)
        {
            string dup_func = "_vala_array_copy%d".printf(++next_array_dup_id);

            if (!add_wrapper(dup_func))
            {
                // wrapper already defined
                return(dup_func);
            }

            // declaration

            var function = new CCodeFunction(dup_func, "void");

            function.modifiers = CCodeModifiers.STATIC;

            function.add_parameter(new CCodeParameter("self", "%s *".printf(get_ccode_name(array_type))));
            function.add_parameter(new CCodeParameter("dest", "%s *".printf(get_ccode_name(array_type))));

            // definition

            push_context(new EmitContext());
            push_function(function);

            if (requires_copy(array_type.element_type))
            {
                ccode.add_declaration("int", new CCodeVariableDeclarator("i"));

                ccode.open_for(new CCodeAssignment(new CCodeIdentifier("i"), new CCodeConstant("0")),
                               new CCodeBinaryExpression(CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier("i"), get_ccodenode(array_type.length)),
                               new CCodeUnaryExpression(CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier("i")));


                ccode.add_assignment(new CCodeElementAccess(new CCodeIdentifier("dest"), new CCodeIdentifier("i")), get_cvalue_(copy_value(new GLibValue(array_type.element_type, new CCodeElementAccess(new CCodeIdentifier("self"), new CCodeIdentifier("i")), true), array_type)));
            }
            else
            {
                cfile.add_include("string.h");

                var dup_call = new CCodeFunctionCall(new CCodeIdentifier("memcpy"));
                dup_call.add_argument(new CCodeIdentifier("dest"));
                dup_call.add_argument(new CCodeIdentifier("self"));

                var sizeof_call = new CCodeFunctionCall(new CCodeIdentifier("sizeof"));
                sizeof_call.add_argument(new CCodeIdentifier(get_ccode_name(array_type.element_type)));
                dup_call.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.MUL, get_ccodenode(array_type.length), sizeof_call));

                ccode.add_expression(dup_call);
            }

            // append to file

            cfile.add_function_declaration(function);
            cfile.add_function(function);

            pop_context();

            return(dup_func);
        }
Пример #9
0
        public override void append_vala_array_free()
        {
            // _vala_array_destroy only frees elements but not the array itself

            var fun = new CCodeFunction("_vala_array_destroy", "void");

            fun.modifiers = CCodeModifiers.STATIC;
            fun.add_parameter(new CCodeParameter("array", "gpointer"));
            fun.add_parameter(new CCodeParameter("array_length", "gint"));
            fun.add_parameter(new CCodeParameter("destroy_func", "GDestroyNotify"));

            push_function(fun);

            var ccondarr  = new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier("array"), new CCodeConstant("NULL"));
            var ccondfunc = new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier("destroy_func"), new CCodeConstant("NULL"));

            ccode.open_if(new CCodeBinaryExpression(CCodeBinaryOperator.AND, ccondarr, ccondfunc));

            ccode.add_declaration("int", new CCodeVariableDeclarator("i"));
            append_vala_array_free_loop();

            ccode.close();

            pop_function();

            cfile.add_function_declaration(fun);
            cfile.add_function(fun);

            // _vala_array_free frees elements and array

            fun           = new CCodeFunction("_vala_array_free", "void");
            fun.modifiers = CCodeModifiers.STATIC;
            fun.add_parameter(new CCodeParameter("array", "gpointer"));
            fun.add_parameter(new CCodeParameter("array_length", "gint"));
            fun.add_parameter(new CCodeParameter("destroy_func", "GDestroyNotify"));

            push_function(fun);

            // call _vala_array_destroy to free the array elements
            var ccall = new CCodeFunctionCall(new CCodeIdentifier("_vala_array_destroy"));

            ccall.add_argument(new CCodeIdentifier("array"));
            ccall.add_argument(new CCodeIdentifier("array_length"));
            ccall.add_argument(new CCodeIdentifier("destroy_func"));
            ccode.add_expression(ccall);

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

            carrfree.add_argument(new CCodeIdentifier("array"));
            ccode.add_expression(carrfree);

            pop_function();

            cfile.add_function_declaration(fun);
            cfile.add_function(fun);
        }
Пример #10
0
        public CCodeFunction generate_enum_to_string_function_declaration(ValaEnum en)
        {
            var to_string_name = "%s_to_string".printf(get_ccode_lower_case_name(en, null));

            var to_string_func = new CCodeFunction(to_string_name, "const char*");

            to_string_func.add_parameter(new CCodeParameter("value", get_ccode_name(en)));

            return(to_string_func);
        }
Пример #11
0
        public CCodeFunction generate_enum_from_string_function_declaration(ValaEnum en)
        {
            var from_string_name = "%s_from_string".printf(get_ccode_lower_case_name(en, null));

            var from_string_func = new CCodeFunction(from_string_name, get_ccode_name(en));

            from_string_func.add_parameter(new CCodeParameter("str", "const char*"));
            from_string_func.add_parameter(new CCodeParameter("error", "GError**"));

            return(from_string_func);
        }
Пример #12
0
        public CCodeFunction generate_enum_from_string_function(ValaEnum en)
        {
            var from_string_name = "%s_from_string".printf(get_ccode_lower_case_name(en, null));

            var from_string_func = new CCodeFunction(from_string_name, get_ccode_name(en));

            from_string_func.add_parameter(new CCodeParameter("str", "const char*"));
            from_string_func.add_parameter(new CCodeParameter("error", "GError**"));

            push_function(from_string_func);

            ccode.add_declaration(get_ccode_name(en), CCodeVariableDeclarator.zero("value", new CCodeConstant("0")));

            bool firstif = true;

            foreach (EnumValue enum_value in en.get_values())
            {
                string dbus_value        = get_dbus_value(enum_value, enum_value.name);
                var    string_comparison = new CCodeFunctionCall(new CCodeIdentifier("strcmp"));
                string_comparison.add_argument(new CCodeIdentifier("str"));
                string_comparison.add_argument(new CCodeConstant("\"%s\"".printf(dbus_value)));
                var cond = new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, string_comparison, new CCodeConstant("0"));
                if (firstif)
                {
                    ccode.open_if(cond);
                    firstif = false;
                }
                else
                {
                    ccode.else_if(cond);
                }
                ccode.add_assignment(new CCodeIdentifier("value"), new CCodeIdentifier(get_ccode_name(enum_value)));
            }

            ccode.add_else();
            var set_error = new CCodeFunctionCall(new CCodeIdentifier("g_set_error"));

            set_error.add_argument(new CCodeIdentifier("error"));
            set_error.add_argument(new CCodeIdentifier("G_DBUS_ERROR"));
            set_error.add_argument(new CCodeIdentifier("G_DBUS_ERROR_INVALID_ARGS"));
            set_error.add_argument(new CCodeConstant("\"Invalid value for enum `%s'\"".printf(get_ccode_name(en))));
            ccode.add_expression(set_error);
            ccode.close();

            ccode.add_return(new CCodeIdentifier("value"));

            pop_function();
            return(from_string_func);
        }
Пример #13
0
        void add_struct_dup_function(Struct st)
        {
            var function = new CCodeFunction(get_ccode_dup_function(st), get_ccode_name(st) + "*");

            if (st.access == SymbolAccessibility.PRIVATE)
            {
                function.modifiers = CCodeModifiers.STATIC;
            }

            function.add_parameter(new CCodeParameter("self", "const " + get_ccode_name(st) + "*"));

            push_function(function);

            ccode.add_declaration(get_ccode_name(st) + "*", new CCodeVariableDeclarator("dup"));

            var creation_call = new CCodeFunctionCall(new CCodeIdentifier("g_new0"));

            creation_call.add_argument(new CCodeConstant(get_ccode_name(st)));
            creation_call.add_argument(new CCodeConstant("1"));
            ccode.add_assignment(new CCodeIdentifier("dup"), creation_call);

            if (st.is_disposable())
            {
                var copy_call = new CCodeFunctionCall(new CCodeIdentifier(get_ccode_copy_function(st)));
                copy_call.add_argument(new CCodeIdentifier("self"));
                copy_call.add_argument(new CCodeIdentifier("dup"));
                ccode.add_expression(copy_call);
            }
            else
            {
                cfile.add_include("string.h");

                var sizeof_call = new CCodeFunctionCall(new CCodeIdentifier("sizeof"));
                sizeof_call.add_argument(new CCodeConstant(get_ccode_name(st)));

                var copy_call = new CCodeFunctionCall(new CCodeIdentifier("memcpy"));
                copy_call.add_argument(new CCodeIdentifier("dup"));
                copy_call.add_argument(new CCodeIdentifier("self"));
                copy_call.add_argument(sizeof_call);
                ccode.add_expression(copy_call);
            }

            ccode.add_return(new CCodeIdentifier("dup"));

            pop_function();

            cfile.add_function(function);
        }
Пример #14
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);
        }
Пример #15
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);
        }
Пример #16
0
        public string generate_async_callback_wrapper()
        {
            string async_callback_wrapper_func = "_vala_g_async_ready_callback";

            if (!add_wrapper(async_callback_wrapper_func))
            {
                return(async_callback_wrapper_func);
            }

            var function = new CCodeFunction(async_callback_wrapper_func, "void");

            function.modifiers = CCodeModifiers.STATIC;

            function.add_parameter(new CCodeParameter("*source_object", "GObject"));
            function.add_parameter(new CCodeParameter("*res", "GAsyncResult"));
            function.add_parameter(new CCodeParameter("*user_data", "void"));

            push_function(function);

            var res_ref = new CCodeFunctionCall(new CCodeIdentifier("g_object_ref"));

            res_ref.add_argument(new CCodeIdentifier("res"));

            CCodeFunctionCall ccall = null;

            // store reference to async result of inner async function in out async result
            ccall = new CCodeFunctionCall(new CCodeIdentifier("g_task_return_pointer"));
            ccall.add_argument(new CCodeIdentifier("user_data"));
            ccall.add_argument(res_ref);
            ccall.add_argument(new CCodeIdentifier("g_object_unref"));
            ccode.add_expression(ccall);

            // free async result
            ccall = new CCodeFunctionCall(new CCodeIdentifier("g_object_unref"));
            ccall.add_argument(new CCodeIdentifier("user_data"));
            ccode.add_expression(ccall);

            pop_function();

            cfile.add_function_declaration(function);
            cfile.add_function(function);

            return(async_callback_wrapper_func);
        }
Пример #17
0
        void add_struct_copy_function(Struct st)
        {
            var function = new CCodeFunction(get_ccode_copy_function(st), "void");

            if (st.is_private_symbol())
            {
                function.modifiers = CCodeModifiers.STATIC;
            }
            else if (context.hide_internal && st.is_internal_symbol())
            {
                function.modifiers = CCodeModifiers.INTERNAL;
            }

            function.add_parameter(new CCodeParameter("self", "const " + get_ccode_name(st) + "*"));
            function.add_parameter(new CCodeParameter("dest", get_ccode_name(st) + "*"));

            push_function(function);

            var dest_struct = new GLibValue(get_data_type_for_symbol(st), new CCodeIdentifier("(*dest)"), true);

            foreach (var f in st.get_fields())
            {
                if (f.binding == MemberBinding.INSTANCE)
                {
                    var value = load_field(f, load_this_parameter((TypeSymbol)st));
                    if (requires_copy(f.variable_type))
                    {
                        value = copy_value(value, f);
                        if (value == null)
                        {
                            // error case, continue to avoid critical
                            continue;
                        }
                    }
                    store_field(f, dest_struct, value);
                }
            }

            pop_function();

            cfile.add_function(function);
        }
Пример #18
0
        void begin_struct_destroy_function(Struct st)
        {
            push_context(instance_finalize_context);

            var function = new CCodeFunction(get_ccode_destroy_function(st), "void");

            if (st.is_private_symbol())
            {
                function.modifiers = CCodeModifiers.STATIC;
            }
            else if (context.hide_internal && st.is_internal_symbol())
            {
                function.modifiers = CCodeModifiers.INTERNAL;
            }

            function.add_parameter(new CCodeParameter("self", get_ccode_name(st) + "*"));

            push_function(function);

            pop_context();
        }
Пример #19
0
        public override string append_struct_array_free(Struct st)
        {
            string cname = "_vala_%s_array_free".printf(get_ccode_name(st));

            if (cfile.add_declaration(cname))
            {
                return(cname);
            }

            var fun = new CCodeFunction(cname, "void");

            fun.modifiers = CCodeModifiers.STATIC;
            fun.add_parameter(new CCodeParameter("array", "%s *".printf(get_ccode_name(st))));
            fun.add_parameter(new CCodeParameter("array_length", "gint"));

            push_function(fun);

            var ccondarr = new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier("array"), new CCodeConstant("NULL"));

            ccode.open_if(ccondarr);

            ccode.add_declaration("int", new CCodeVariableDeclarator("i"));
            append_struct_array_free_loop(st);

            ccode.close();

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

            carrfree.add_argument(new CCodeIdentifier("array"));
            ccode.add_expression(carrfree);

            pop_function();

            cfile.add_function_declaration(fun);
            cfile.add_function(fun);

            return(cname);
        }
Пример #20
0
        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);
        }
Пример #21
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);
        }
Пример #22
0
        public override void visit_error_domain(ErrorDomain edomain)
        {
            var edomain_dbus_name = get_dbus_name(edomain);

            if (edomain_dbus_name == null)
            {
                base.visit_error_domain(edomain);
                return;
            }

            cfile.add_include("gio/gio.h");

            generate_error_domain_declaration(edomain, cfile);

            if (!edomain.is_internal_symbol())
            {
                generate_error_domain_declaration(edomain, header_file);
            }
            if (!edomain.is_private_symbol())
            {
                generate_error_domain_declaration(edomain, internal_header_file);
            }

            var error_entries = new CCodeInitializerList();

            foreach (ErrorCode ecode in edomain.get_codes())
            {
                var ecode_dbus_name = get_dbus_name(ecode);
                if (ecode_dbus_name == null)
                {
                    ecode_dbus_name = Symbol.lower_case_to_camel_case(ecode.name.ToLower());
                }

                var error_entry = new CCodeInitializerList();
                error_entry.append(new CCodeIdentifier(get_ccode_name(ecode)));
                error_entry.append(new CCodeConstant("\"%s.%s\"".printf(edomain_dbus_name, ecode_dbus_name)));
                error_entries.append(error_entry);
            }

            var cdecl = new CCodeDeclaration("const GDBusErrorEntry");

            cdecl.add_declarator(new CCodeVariableDeclarator(get_ccode_lower_case_name(edomain) + "_entries[]", error_entries));
            cdecl.modifiers = CCodeModifiers.STATIC;
            cfile.add_constant_declaration(cdecl);

            string quark_fun_name = get_ccode_lower_case_prefix(edomain) + "quark";

            var cquark_fun = new CCodeFunction(quark_fun_name, get_ccode_name(gquark_type.data_type));

            push_function(cquark_fun);

            string quark_name = "%squark_volatile".printf(get_ccode_lower_case_prefix(edomain));

            ccode.add_declaration("gsize", new CCodeVariableDeclarator(quark_name, new CCodeConstant("0")), CCodeModifiers.STATIC | CCodeModifiers.VOLATILE);

            var register_call = new CCodeFunctionCall(new CCodeIdentifier("g_dbus_error_register_error_domain"));

            register_call.add_argument(new CCodeConstant("\"" + CCodeBaseModule.get_quark_name(edomain) + "\""));
            register_call.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier(quark_name)));
            register_call.add_argument(new CCodeIdentifier(get_ccode_lower_case_name(edomain) + "_entries"));
            var nentries = new CCodeFunctionCall(new CCodeIdentifier("G_N_ELEMENTS"));

            nentries.add_argument(new CCodeIdentifier(get_ccode_lower_case_name(edomain) + "_entries"));
            register_call.add_argument(nentries);
            ccode.add_expression(register_call);

            ccode.add_return(new CCodeCastExpression(new CCodeIdentifier(quark_name), "GQuark"));

            pop_function();
            cfile.add_function(cquark_fun);
        }
Пример #23
0
        /// <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);
        }
Пример #24
0
        void generate_marshaller(List <Parameter> _params, DataType return_type)
        {
            string signature;
            int    n_params, i;

            /* check whether a signal with the same signature already exists for this source file (or predefined) */
            signature = get_marshaller_signature(_params, return_type);
            if (predefined_marshal_set.Contains(signature) || user_marshal_set.Contains(signature))
            {
                return;
            }

            var signal_marshaller = new CCodeFunction(get_marshaller_function(_params, return_type, null), "void");

            signal_marshaller.modifiers = CCodeModifiers.STATIC;

            signal_marshaller.add_parameter(new CCodeParameter("closure", "GClosure *"));
            signal_marshaller.add_parameter(new CCodeParameter("return_value", "GValue *"));
            signal_marshaller.add_parameter(new CCodeParameter("n_param_values", "guint"));
            signal_marshaller.add_parameter(new CCodeParameter("param_values", "const GValue *"));
            signal_marshaller.add_parameter(new CCodeParameter("invocation_hint", "gpointer"));
            signal_marshaller.add_parameter(new CCodeParameter("marshal_data", "gpointer"));

            push_function(signal_marshaller);

            var callback_decl = new CCodeFunctionDeclarator(get_marshaller_function(_params, return_type, "GMarshalFunc"));

            callback_decl.add_parameter(new CCodeParameter("data1", "gpointer"));
            n_params = 1;
            foreach (Parameter p in _params)
            {
                callback_decl.add_parameter(new CCodeParameter("arg_%d".printf(n_params), get_value_type_name_from_parameter(p)));
                n_params++;
                if (p.variable_type.is_array())
                {
                    for (var j = 0; j < ((ArrayType)p.variable_type).rank; j++)
                    {
                        callback_decl.add_parameter(new CCodeParameter("arg_%d".printf(n_params), "gint"));
                        n_params++;
                    }
                }
            }
            callback_decl.add_parameter(new CCodeParameter("data2", "gpointer"));
            ccode.add_statement(new CCodeTypeDefinition(get_value_type_name_from_type_reference(return_type), callback_decl));

            ccode.add_declaration(get_marshaller_function(_params, return_type, "GMarshalFunc"), new CCodeVariableDeclarator("callback"), CCodeModifiers.REGISTER);

            ccode.add_declaration("GCClosure *", new CCodeVariableDeclarator("cc", new CCodeCastExpression(new CCodeIdentifier("closure"), "GCClosure *")), CCodeModifiers.REGISTER);

            ccode.add_declaration("gpointer", new CCodeVariableDeclarator("data1"), CCodeModifiers.REGISTER);
            ccode.add_declaration("gpointer", new CCodeVariableDeclarator("data2"), CCodeModifiers.REGISTER);

            CCodeFunctionCall fc;

            if (return_type.data_type != null || return_type.is_array())
            {
                ccode.add_declaration(get_value_type_name_from_type_reference(return_type), new CCodeVariableDeclarator("v_return"));

                fc = new CCodeFunctionCall(new CCodeIdentifier("g_return_if_fail"));
                fc.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier("return_value"), new CCodeConstant("NULL")));
                ccode.add_expression(fc);
            }

            fc = new CCodeFunctionCall(new CCodeIdentifier("g_return_if_fail"));
            fc.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, new CCodeIdentifier("n_param_values"), new CCodeConstant(n_params.ToString())));
            ccode.add_expression(fc);

            var data  = new CCodeMemberAccess(new CCodeIdentifier("closure"), "data", true);
            var param = new CCodeMemberAccess(new CCodeMemberAccess(new CCodeIdentifier("param_values"), "data[0]", true), "v_pointer");
            var cond  = new CCodeFunctionCall(new CCodeConstant("G_CCLOSURE_SWAP_DATA"));

            cond.add_argument(new CCodeIdentifier("closure"));
            ccode.open_if(cond);
            ccode.add_assignment(new CCodeIdentifier("data1"), data);
            ccode.add_assignment(new CCodeIdentifier("data2"), param);
            ccode.add_else();
            ccode.add_assignment(new CCodeIdentifier("data1"), param);
            ccode.add_assignment(new CCodeIdentifier("data2"), data);
            ccode.close();

            var c_assign_rhs = new CCodeCastExpression(new CCodeConditionalExpression(new CCodeIdentifier("marshal_data"), new CCodeIdentifier("marshal_data"), new CCodeMemberAccess(new CCodeIdentifier("cc"), "callback", true)), get_marshaller_function(_params, return_type, "GMarshalFunc"));

            ccode.add_assignment(new CCodeIdentifier("callback"), c_assign_rhs);

            fc = new CCodeFunctionCall(new CCodeIdentifier("callback"));
            fc.add_argument(new CCodeIdentifier("data1"));
            i = 1;
            foreach (Parameter p in _params)
            {
                string get_value_function;
                bool   is_array = p.variable_type.is_array();
                if (p.direction != ParameterDirection.IN)
                {
                    get_value_function = "g_value_get_pointer";
                }
                else if (is_array)
                {
                    if (((ArrayType)p.variable_type).element_type.data_type == string_type.data_type)
                    {
                        get_value_function = "g_value_get_boxed";
                    }
                    else
                    {
                        get_value_function = "g_value_get_pointer";
                    }
                }
                else if (p.variable_type is PointerType || p.variable_type.type_parameter != null)
                {
                    get_value_function = "g_value_get_pointer";
                }
                else if (p.variable_type is ErrorType)
                {
                    get_value_function = "g_value_get_pointer";
                }
                else if (p.variable_type is ValaValueType && p.variable_type.nullable)
                {
                    get_value_function = "g_value_get_pointer";
                }
                else
                {
                    get_value_function = get_ccode_get_value_function(p.variable_type.data_type);
                }
                var inner_fc = new CCodeFunctionCall(new CCodeIdentifier(get_value_function));
                inner_fc.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, new CCodeIdentifier("param_values"), new CCodeIdentifier(i.ToString())));
                fc.add_argument(inner_fc);
                i++;
                if (is_array)
                {
                    for (var j = 0; j < ((ArrayType)p.variable_type).rank; j++)
                    {
                        inner_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_get_int"));
                        inner_fc.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, new CCodeIdentifier("param_values"), new CCodeIdentifier(i.ToString())));
                        fc.add_argument(inner_fc);
                        i++;
                    }
                }
            }
            fc.add_argument(new CCodeIdentifier("data2"));

            if (return_type.data_type != null || return_type.is_array())
            {
                ccode.add_assignment(new CCodeIdentifier("v_return"), fc);

                CCodeFunctionCall set_fc;
                if (return_type.is_array())
                {
                    if (((ArrayType)return_type).element_type.data_type == string_type.data_type)
                    {
                        set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_take_boxed"));
                    }
                    else
                    {
                        set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_set_pointer"));
                    }
                }
                else if (return_type.type_parameter != null)
                {
                    set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_set_pointer"));
                }
                else if (return_type is ErrorType)
                {
                    set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_set_pointer"));
                }
                else if (return_type.data_type == string_type.data_type)
                {
                    set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_take_string"));
                }
                else if (return_type.data_type is Class || return_type.data_type is Interface)
                {
                    set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_take_object"));
                }
                else if (return_type is ValaValueType && return_type.nullable)
                {
                    set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_set_pointer"));
                }
                else
                {
                    set_fc = new CCodeFunctionCall(new CCodeIdentifier(get_ccode_set_value_function(return_type.data_type)));
                }
                set_fc.add_argument(new CCodeIdentifier("return_value"));
                set_fc.add_argument(new CCodeIdentifier("v_return"));

                ccode.add_expression(set_fc);
            }
            else
            {
                ccode.add_expression(fc);
            }

            pop_function();

            cfile.add_function_declaration(signal_marshaller);
            cfile.add_function(signal_marshaller);
            user_marshal_set.Add(signature);
        }
Пример #25
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);
        }
Пример #26
0
        public override void visit_constructor(Constructor c)
        {
            push_line(c.source_reference);

            var cl = (Class)c.parent_symbol;

            if (c.binding == MemberBinding.INSTANCE)
            {
                if (!cl.is_subtype_of(gobject_type))
                {
                    Report.error(c.source_reference, "construct blocks require GLib.Object");
                    c.error = true;
                    return;
                }

                push_context(new EmitContext(c));

                var function = new CCodeFunction("%s_constructor".printf(get_ccode_lower_case_name(cl, null)), "GObject *");
                function.modifiers = CCodeModifiers.STATIC;

                function.add_parameter(new CCodeParameter("type", "GType"));
                function.add_parameter(new CCodeParameter("n_construct_properties", "guint"));
                function.add_parameter(new CCodeParameter("construct_properties", "GObjectConstructParam *"));

                cfile.add_function_declaration(function);

                push_function(function);

                ccode.add_declaration("GObject *", new CCodeVariableDeclarator("obj"));
                ccode.add_declaration("GObjectClass *", new CCodeVariableDeclarator("parent_class"));

                var ccast = new CCodeFunctionCall(new CCodeIdentifier("G_OBJECT_CLASS"));
                ccast.add_argument(new CCodeIdentifier("%s_parent_class".printf(get_ccode_lower_case_name(cl, null))));
                ccode.add_assignment(new CCodeIdentifier("parent_class"), ccast);

                var ccall = new CCodeFunctionCall(CCodeMemberAccess.pointer(new CCodeIdentifier("parent_class"), "constructor"));
                ccall.add_argument(new CCodeIdentifier("type"));
                ccall.add_argument(new CCodeIdentifier("n_construct_properties"));
                ccall.add_argument(new CCodeIdentifier("construct_properties"));
                ccode.add_assignment(new CCodeIdentifier("obj"), ccall);


                ccall = generate_instance_cast(new CCodeIdentifier("obj"), cl);

                ccode.add_declaration("%s *".printf(get_ccode_name(cl)), new CCodeVariableDeclarator("self"));
                ccode.add_assignment(new CCodeIdentifier("self"), ccall);

                c.body.emit(this);

                if (current_method_inner_error)
                {
                    /* always separate error parameter and inner_error local variable
                     * as error may be set to NULL but we're always interested in inner errors
                     */
                    ccode.add_declaration("GError *", CCodeVariableDeclarator.zero("_inner_error_", new CCodeConstant("NULL")));
                }

                ccode.add_return(new CCodeIdentifier("obj"));

                pop_function();
                cfile.add_function(function);

                pop_context();
            }
            else if (c.binding == MemberBinding.CLASS)
            {
                // class constructor

                if (cl.is_compact)
                {
                    Report.error(c.source_reference, "class constructors are not supported in compact classes");
                    c.error = true;
                    return;
                }

                push_context(base_init_context);

                c.body.emit(this);

                if (current_method_inner_error)
                {
                    /* always separate error parameter and inner_error local variable
                     * as error may be set to NULL but we're always interested in inner errors
                     */
                    ccode.add_declaration("GError *", CCodeVariableDeclarator.zero("_inner_error_", new CCodeConstant("NULL")));
                }

                pop_context();
            }
            else if (c.binding == MemberBinding.STATIC)
            {
                // static class constructor
                // add to class_init

                if (cl.is_compact)
                {
                    Report.error(c.source_reference, "static constructors are not supported in compact classes");
                    c.error = true;
                    return;
                }

                push_context(class_init_context);

                c.body.emit(this);

                if (current_method_inner_error)
                {
                    /* always separate error parameter and inner_error local variable
                     * as error may be set to NULL but we're always interested in inner errors
                     */
                    ccode.add_declaration("GError *", CCodeVariableDeclarator.zero("_inner_error_", new CCodeConstant("NULL")));
                }

                pop_context();
            }
            else
            {
                Report.error(c.source_reference, "internal error: constructors must have instance, class, or static binding");
            }

            pop_line();
        }
Пример #27
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);
        }
Пример #28
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);
        }
Пример #29
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);
        }
Пример #30
0
        public override void generate_struct_declaration(Struct st, CCodeFile decl_space)
        {
            if (add_symbol_declaration(decl_space, st, get_ccode_name(st)))
            {
                return;
            }

            if (st.is_boolean_type() || st.is_integer_type() || st.is_floating_type())
            {
                if (st.base_struct != null)
                {
                    generate_struct_declaration(st.base_struct, decl_space);
                    decl_space.add_type_declaration(new CCodeTypeDefinition(get_ccode_name(st.base_struct), new CCodeVariableDeclarator(get_ccode_name(st))));
                }
                else
                {
                    string typename = null;
                    if (st.is_boolean_type())
                    {
                        // typedef for boolean types
                        decl_space.add_include("stdbool.h");
                        typename = "bool";
                    }
                    else if (st.is_integer_type())
                    {
                        // typedef for integral types
                        decl_space.add_include("stdint.h");
                        typename = "%sint%d_t".printf(st.signed ? "" : "u", st.width);
                    }
                    else if (st.is_floating_type())
                    {
                        // typedef for floating types
                        typename = (st.width == 64 ? "double" : "float");
                    }
                    decl_space.add_type_declaration(new CCodeTypeDefinition(typename, new CCodeVariableDeclarator(get_ccode_name(st))));
                }
                return;
            }

            if (get_ccode_has_type_id(st))
            {
                decl_space.add_include("glib-object.h");
                decl_space.add_type_declaration(new CCodeNewline());
                var macro = "(%s_get_type ())".printf(get_ccode_lower_case_name(st, null));
                decl_space.add_type_declaration(new CCodeMacroReplacement(get_ccode_type_id(st), macro));

                var type_fun = new StructRegisterFunction(st, context);
                type_fun.init_from_type(false, true);
                decl_space.add_type_member_declaration(type_fun.get_declaration());
            }

            var instance_struct = new CCodeStruct("_%s".printf(get_ccode_name(st)));

            instance_struct.modifiers |= (st.version.deprecated ? CCodeModifiers.DEPRECATED : 0);

            foreach (Field f in st.get_fields())
            {
                if (f.binding == MemberBinding.INSTANCE)
                {
                    generate_type_declaration(f.variable_type, decl_space);
                    CCodeModifiers modifiers = (f.is_volatile ? CCodeModifiers.VOLATILE : 0) | (f.version.deprecated ? CCodeModifiers.DEPRECATED : 0);
                    instance_struct.add_field(get_ccode_name(f.variable_type), get_ccode_name(f), modifiers, get_ccode_declarator_suffix(f.variable_type));
                    if (f.variable_type is ArrayType && get_ccode_array_length(f))
                    {
                        // create fields to store array dimensions
                        var array_type = (ArrayType)f.variable_type;

                        if (!array_type.fixed_length)
                        {
                            var len_type = int_type.copy();

                            for (int dim = 1; dim <= array_type.rank; dim++)
                            {
                                string length_cname;
                                if (get_ccode_array_length_name(f) != null)
                                {
                                    length_cname = get_ccode_array_length_name(f);
                                }
                                else
                                {
                                    length_cname = get_array_length_cname(get_ccode_name(f), dim);
                                }
                                instance_struct.add_field(get_ccode_name(len_type), length_cname);
                            }

                            if (array_type.rank == 1 && f.is_internal_symbol())
                            {
                                instance_struct.add_field(get_ccode_name(len_type), get_array_size_cname(get_ccode_name(f)));
                            }
                        }
                    }
                    else if (f.variable_type is DelegateType)
                    {
                        var delegate_type = (DelegateType)f.variable_type;
                        if (delegate_type.delegate_symbol.has_target)
                        {
                            // create field to store delegate target
                            instance_struct.add_field("gpointer", get_ccode_delegate_target_name(f));
                            if (delegate_type.is_disposable())
                            {
                                instance_struct.add_field("GDestroyNotify", get_delegate_target_destroy_notify_cname(get_ccode_name(f)));
                            }
                        }
                    }
                }
            }

            if (st.base_struct == null)
            {
                decl_space.add_type_declaration(new CCodeTypeDefinition("struct _%s".printf(get_ccode_name(st)), new CCodeVariableDeclarator(get_ccode_name(st))));

                decl_space.add_type_definition(instance_struct);
            }
            else
            {
                decl_space.add_type_declaration(new CCodeTypeDefinition(get_ccode_name(st.base_struct), new CCodeVariableDeclarator(get_ccode_name(st))));
            }

            var function = new CCodeFunction(get_ccode_dup_function(st), get_ccode_name(st) + "*");

            if (st.is_private_symbol())
            {
                function.modifiers = CCodeModifiers.STATIC;
            }
            else if (context.hide_internal && st.is_internal_symbol())
            {
                function.modifiers = CCodeModifiers.INTERNAL;
            }
            function.add_parameter(new CCodeParameter("self", "const " + get_ccode_name(st) + "*"));
            decl_space.add_function_declaration(function);

            function = new CCodeFunction(get_ccode_free_function(st), "void");
            if (st.is_private_symbol())
            {
                function.modifiers = CCodeModifiers.STATIC;
            }
            else if (context.hide_internal && st.is_internal_symbol())
            {
                function.modifiers = CCodeModifiers.INTERNAL;
            }
            function.add_parameter(new CCodeParameter("self", get_ccode_name(st) + "*"));
            decl_space.add_function_declaration(function);

            if (st.is_disposable())
            {
                function = new CCodeFunction(get_ccode_copy_function(st), "void");
                if (st.is_private_symbol())
                {
                    function.modifiers = CCodeModifiers.STATIC;
                }
                else if (context.hide_internal && st.is_internal_symbol())
                {
                    function.modifiers = CCodeModifiers.INTERNAL;
                }
                function.add_parameter(new CCodeParameter("self", "const " + get_ccode_name(st) + "*"));
                function.add_parameter(new CCodeParameter("dest", get_ccode_name(st) + "*"));
                decl_space.add_function_declaration(function);

                function = new CCodeFunction(get_ccode_destroy_function(st), "void");
                if (st.is_private_symbol())
                {
                    function.modifiers = CCodeModifiers.STATIC;
                }
                else if (context.hide_internal && st.is_internal_symbol())
                {
                    function.modifiers = CCodeModifiers.INTERNAL;
                }
                function.add_parameter(new CCodeParameter("self", get_ccode_name(st) + "*"));
                decl_space.add_function_declaration(function);
            }
        }