コード例 #1
0
        public override CCodeExpression get_array_length_cvalue(TargetValue value, int dim = -1)
        {
            var array_type = value.value_type as ArrayType;

            if (array_type != null && array_type.fixed_length)
            {
                return(get_ccodenode(array_type.length));
            }

            // dim == -1 => total size over all dimensions
            if (dim == -1)
            {
                if (array_type != null && array_type.rank > 1)
                {
                    CCodeExpression cexpr = get_array_length_cvalue(value, 1);
                    for (dim = 2; dim <= array_type.rank; dim++)
                    {
                        cexpr = new CCodeBinaryExpression(CCodeBinaryOperator.MUL, cexpr, get_array_length_cvalue(value, dim));
                    }
                    return(cexpr);
                }
                else
                {
                    dim = 1;
                }
            }

            List <CCodeExpression> size = ((GLibValue)value).array_length_cvalues;

            Debug.Assert(size != null && size.Count >= dim);
            return(size[dim - 1]);
        }
コード例 #2
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);
        }
コード例 #3
0
ファイル: GVariantModule.cs プロジェクト: smx-smx/ValaSharp
        CCodeExpression serialize_array_dim(ArrayType array_type, int dim, CCodeExpression array_expr, CCodeExpression array_iter_expr)
        {
            string builder_name = "_tmp%d_".printf(next_temp_var_id++);
            string index_name   = "_tmp%d_".printf(next_temp_var_id++);

            ccode.add_declaration("GVariantBuilder", new CCodeVariableDeclarator(builder_name));
            ccode.add_declaration("int", new CCodeVariableDeclarator(index_name));

            var gvariant_type = new CCodeFunctionCall(new CCodeIdentifier("G_VARIANT_TYPE"));

            gvariant_type.add_argument(new CCodeConstant("\"%s\"".printf(get_type_signature(array_type))));

            var builder_init = new CCodeFunctionCall(new CCodeIdentifier("g_variant_builder_init"));

            builder_init.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier(builder_name)));
            builder_init.add_argument(gvariant_type);
            ccode.add_expression(builder_init);

            var cforinit = new CCodeAssignment(new CCodeIdentifier(index_name), new CCodeConstant("0"));
            var cforcond = new CCodeBinaryExpression(CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier(index_name), get_array_length(array_expr, dim));
            var cforiter = new CCodeUnaryExpression(CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier(index_name));

            ccode.open_for(cforinit, cforcond, cforiter);

            CCodeExpression element_variant;

            if (dim < array_type.rank)
            {
                element_variant = serialize_array_dim(array_type, dim + 1, array_expr, array_iter_expr);
            }
            else
            {
                var element_expr = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, array_iter_expr);
                element_variant = serialize_expression(array_type.element_type, element_expr);
            }

            var builder_add = new CCodeFunctionCall(new CCodeIdentifier("g_variant_builder_add_value"));

            builder_add.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier(builder_name)));
            builder_add.add_argument(element_variant);
            ccode.add_expression(builder_add);

            if (dim == array_type.rank)
            {
                var array_iter_incr = new CCodeUnaryExpression(CCodeUnaryOperator.POSTFIX_INCREMENT, array_iter_expr);
                ccode.add_expression(array_iter_incr);
            }

            ccode.close();

            var builder_end = new CCodeFunctionCall(new CCodeIdentifier("g_variant_builder_end"));

            builder_end.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier(builder_name)));
            return(builder_end);
        }
コード例 #4
0
        public override void visit_slice_expression(SliceExpression expr)
        {
            var ccontainer = get_cvalue(expr.container);
            var cstart     = get_cvalue(expr.start);
            var cstop      = get_cvalue(expr.stop);

            var cstartpointer = new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, ccontainer, cstart);
            var splicelen     = new CCodeBinaryExpression(CCodeBinaryOperator.MINUS, cstop, cstart);

            set_cvalue(expr, cstartpointer);
            append_array_length(expr, splicelen);
        }
コード例 #5
0
ファイル: GVariantModule.cs プロジェクト: smx-smx/ValaSharp
        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);
        }
コード例 #6
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);
        }
コード例 #7
0
        void append_struct_array_free_loop(Struct st)
        {
            var cforinit = new CCodeAssignment(new CCodeIdentifier("i"), new CCodeConstant("0"));
            var cforcond = new CCodeBinaryExpression(CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier("i"), new CCodeIdentifier("array_length"));
            var cforiter = new CCodeAssignment(new CCodeIdentifier("i"), new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, new CCodeIdentifier("i"), new CCodeConstant("1")));

            ccode.open_for(cforinit, cforcond, cforiter);

            var cptrarray = new CCodeIdentifier("array");
            var cea       = new CCodeElementAccess(cptrarray, new CCodeIdentifier("i"));

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

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

            ccode.close();
        }
コード例 #8
0
        public override void visit_element_access(ElementAccess expr)
        {
            List <Expression> indices = expr.get_indices();
            int rank = indices.Count;

            var ccontainer = get_cvalue(expr.container);
            var cindex     = get_cvalue(indices[0]);

            if (expr.container.symbol_reference is ArrayLengthField)
            {
                /* Figure if cindex is a constant expression and calculate dim...*/
                var lit          = indices[0] as IntegerLiteral;
                var memberaccess = expr.container as MemberAccess;
                if (lit != null && memberaccess != null)
                {
                    int dim = int.Parse(lit.value);
                    set_cvalue(expr, get_array_length_cexpression(memberaccess.inner, dim + 1));
                }
                else
                {
                    Report.error(expr.source_reference, "only integer literals supported as index");
                }
            }
            else
            {
                // access to element in an array
                for (int i = 1; i < rank; i++)
                {
                    var cmul = new CCodeBinaryExpression(CCodeBinaryOperator.MUL, cindex, get_array_length_cexpression(expr.container, i + 1));
                    cindex = new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, cmul, get_cvalue(indices[i]));
                }
                set_cvalue(expr, new CCodeElementAccess(ccontainer, cindex));
            }

            expr.target_value.value_type = expr.value_type.copy();
            if (!expr.lvalue)
            {
                expr.target_value = store_temp_value(expr.target_value, expr);
            }
            ((GLibValue)expr.target_value).lvalue = true;
        }
コード例 #9
0
        void append_vala_array_free_loop()
        {
            var cforinit = new CCodeAssignment(new CCodeIdentifier("i"), new CCodeConstant("0"));
            var cforcond = new CCodeBinaryExpression(CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier("i"), new CCodeIdentifier("array_length"));
            var cforiter = new CCodeAssignment(new CCodeIdentifier("i"), new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, new CCodeIdentifier("i"), new CCodeConstant("1")));

            ccode.open_for(cforinit, cforcond, cforiter);

            var cptrarray = new CCodeCastExpression(new CCodeIdentifier("array"), "gpointer*");
            var cea       = new CCodeElementAccess(cptrarray, new CCodeIdentifier("i"));

            var cfreecond = new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, cea, new CCodeConstant("NULL"));

            ccode.open_if(cfreecond);

            var cfreecall = new CCodeFunctionCall(new CCodeIdentifier("destroy_func"));

            cfreecall.add_argument(cea);
            ccode.add_expression(cfreecall);

            ccode.close();
        }
コード例 #10
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);
        }
コード例 #11
0
ファイル: GErrorModule.cs プロジェクト: smx-smx/ValaSharp
        public override void add_simple_check(CodeNode node, bool always_fails = false)
        {
            current_method_inner_error = true;

            var inner_error = get_variable_cexpression("_inner_error_");

            if (always_fails)
            {
                // inner_error is always set, avoid unnecessary if statement
                // eliminates C warnings
            }
            else
            {
                var ccond    = new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, inner_error, new CCodeConstant("NULL"));
                var unlikely = new CCodeFunctionCall(new CCodeIdentifier("G_UNLIKELY"));
                unlikely.add_argument(ccond);
                ccode.open_if(unlikely);
            }

            if (current_try != null)
            {
                // surrounding try found

                // free local variables
                if (is_in_catch)
                {
                    append_local_free(current_symbol, false, current_catch);
                }
                else
                {
                    append_local_free(current_symbol, false, current_try);
                }

                var error_types = new List <DataType>();
                foreach (DataType node_error_type in node.get_error_types())
                {
                    error_types.Add(node_error_type);
                }

                bool has_general_catch_clause = false;

                if (!is_in_catch)
                {
                    var handled_error_types = new List <DataType>();
                    foreach (CatchClause clause in current_try.get_catch_clauses())
                    {
                        // keep track of unhandled error types
                        foreach (DataType node_error_type in error_types)
                        {
                            if (clause.error_type == null || node_error_type.compatible(clause.error_type))
                            {
                                handled_error_types.Add(node_error_type);
                            }
                        }
                        foreach (DataType handled_error_type in handled_error_types)
                        {
                            error_types.Remove(handled_error_type);
                        }
                        handled_error_types.Clear();

                        if (clause.error_type.equals(gerror_type))
                        {
                            // general catch clause, this should be the last one
                            has_general_catch_clause = true;
                            ccode.add_goto(clause.clabel_name);
                            break;
                        }
                        else
                        {
                            var catch_type = clause.error_type as ErrorType;

                            if (catch_type.error_code != null)
                            {
                                /* catch clause specifies a specific error code */
                                var error_match = new CCodeFunctionCall(new CCodeIdentifier("g_error_matches"));
                                error_match.add_argument(inner_error);
                                error_match.add_argument(new CCodeIdentifier(get_ccode_upper_case_name(catch_type.data_type)));
                                error_match.add_argument(new CCodeIdentifier(get_ccode_name(catch_type.error_code)));

                                ccode.open_if(error_match);
                            }
                            else
                            {
                                /* catch clause specifies a full error domain */
                                var ccond = new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY,
                                                                      CCodeMemberAccess.pointer(inner_error, "domain"), new CCodeIdentifier
                                                                          (get_ccode_upper_case_name(clause.error_type.data_type)));

                                ccode.open_if(ccond);
                            }

                            // go to catch clause if error domain matches
                            ccode.add_goto(clause.clabel_name);
                            ccode.close();
                        }
                    }
                }

                if (has_general_catch_clause)
                {
                    // every possible error is already caught
                    // as there is a general catch clause
                    // no need to do anything else
                }
                else if (error_types.Count > 0)
                {
                    // go to finally clause if no catch clause matches
                    // and there are still unhandled error types
                    ccode.add_goto("__finally%d".printf(current_try_id));
                }
                else if (in_finally_block(node))
                {
                    // do not check unexpected errors happening within finally blocks
                    // as jump out of finally block is not supported
                }
                else
                {
                    // should never happen with correct bindings
                    uncaught_error_statement(inner_error, true);
                }
            }
            else if (current_method != null && current_method.get_error_types().Count > 0)
            {
                // current method can fail, propagate error
                CCodeBinaryExpression ccond = null;

                foreach (DataType error_type in current_method.get_error_types())
                {
                    // If GLib.Error is allowed we propagate everything
                    if (error_type.equals(gerror_type))
                    {
                        ccond = null;
                        break;
                    }

                    // Check the allowed error domains to propagate
                    var domain_check = new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, CCodeMemberAccess.pointer
                                                                     (inner_error, "domain"), new CCodeIdentifier(get_ccode_upper_case_name(error_type.data_type)));
                    if (ccond == null)
                    {
                        ccond = domain_check;
                    }
                    else
                    {
                        ccond = new CCodeBinaryExpression(CCodeBinaryOperator.OR, ccond, domain_check);
                    }
                }

                if (ccond != null)
                {
                    ccode.open_if(ccond);
                    return_with_exception(inner_error);

                    ccode.add_else();
                    uncaught_error_statement(inner_error);
                    ccode.close();
                }
                else
                {
                    return_with_exception(inner_error);
                }
            }
            else
            {
                uncaught_error_statement(inner_error);
            }

            if (!always_fails)
            {
                ccode.close();
            }
        }
コード例 #12
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);
        }
コード例 #13
0
ファイル: GtkModule.cs プロジェクト: smx-smx/ValaSharp
        public override void visit_field(Field f)
        {
            base.visit_field(f);

            var cl = current_class;

            if (cl == null || cl.error)
            {
                return;
            }

            if (f.binding != MemberBinding.INSTANCE || f.get_attribute("GtkChild") == null)
            {
                return;
            }

            /* If the field has a [GtkChild] attribute but its class doesn'thave a
             *       [GtkTemplate] attribute, we throw an error */
            if (!is_gtk_template(cl))
            {
                Report.error(f.source_reference, "[GtkChild] is only allowed in classes with a [GtkTemplate] attribute");
                return;
            }

            push_context(class_init_context);

            /* Map ui widget to a class field */
            var gtk_name    = f.get_attribute_string("GtkChild", "name", f.name);
            var child_class = current_child_to_class_map[gtk_name];

            if (child_class == null)
            {
                Report.error(f.source_reference, "could not find child `%s'".printf(gtk_name));
                return;
            }

            /* We allow Gtk child to have stricter type than class field */
            var field_class = f.variable_type.data_type as Class;

            if (field_class == null || !child_class.is_subtype_of(field_class))
            {
                Report.error(f.source_reference, "cannot convert from Gtk child type `%s' to `%s'".printf(child_class.get_full_name(), field_class.get_full_name()));
                return;
            }

            var internal_child = f.get_attribute_bool("GtkChild", "internal");

            CCodeExpression offset;

            if (f.is_private_symbol())
            {
                // new glib api, we add the private struct offset to get the final field offset out of the instance
                var private_field_offset = new CCodeFunctionCall(new CCodeIdentifier("G_STRUCT_OFFSET"));
                private_field_offset.add_argument(new CCodeIdentifier("%sPrivate".printf(get_ccode_name(cl))));
                private_field_offset.add_argument(new CCodeIdentifier(get_ccode_name(f)));
                offset = new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, new CCodeIdentifier("%s_private_offset".printf(get_ccode_name(cl))), private_field_offset);
            }
            else
            {
                var offset_call = new CCodeFunctionCall(new CCodeIdentifier("G_STRUCT_OFFSET"));
                offset_call.add_argument(new CCodeIdentifier(get_ccode_name(cl)));
                offset_call.add_argument(new CCodeIdentifier(get_ccode_name(f)));
                offset = offset_call;
            }

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

            call.add_argument(new CCodeIdentifier("GTK_WIDGET_CLASS (klass)"));
            call.add_argument(new CCodeConstant("\"%s\"".printf(gtk_name)));
            call.add_argument(new CCodeConstant(internal_child ? "TRUE" : "FALSE"));
            call.add_argument(offset);
            ccode.add_expression(call);

            pop_context();

            if (!field_class.external && !field_class.external_package)
            {
                current_required_app_classes.Add(field_class);
            }
        }
コード例 #14
0
        void generate_finish_function(Method m)
        {
            push_context(new EmitContext());

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

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

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

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

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

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

            push_function(finishfunc);

            var return_type = m.return_type;

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

            var data_var = new CCodeIdentifier("_data_");

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

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

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

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

            ccall.add_argument(async_result_cast);

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

            ccode.add_assignment(data_var, ccall);

            bool has_cancellable = false;

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

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

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

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

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

            pop_function();

            cfile.add_function(finishfunc);

            pop_context();
        }
コード例 #15
0
ファイル: GVariantModule.cs プロジェクト: smx-smx/ValaSharp
        void deserialize_array_dim(ArrayType array_type, int dim, string temp_name, CCodeExpression variant_expr, CCodeExpression expr)
        {
            string subiter_name = "_tmp%d_".printf(next_temp_var_id++);
            string element_name = "_tmp%d_".printf(next_temp_var_id++);

            ccode.add_declaration("int", new CCodeVariableDeclarator("%s_length%d".printf(temp_name, dim), new CCodeConstant("0")));
            ccode.add_declaration("GVariantIter", new CCodeVariableDeclarator(subiter_name));
            ccode.add_declaration("GVariant*", new CCodeVariableDeclarator(element_name));

            var iter_call = new CCodeFunctionCall(new CCodeIdentifier("g_variant_iter_init"));

            iter_call.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier(subiter_name)));
            iter_call.add_argument(variant_expr);
            ccode.add_expression(iter_call);

            iter_call = new CCodeFunctionCall(new CCodeIdentifier("g_variant_iter_next_value"));
            iter_call.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier(subiter_name)));

            var cforcond = new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, new CCodeAssignment(new CCodeIdentifier(element_name), iter_call), new CCodeConstant("NULL"));
            var cforiter = new CCodeUnaryExpression(CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier("%s_length%d".printf(temp_name, dim)));

            ccode.open_for(null, cforcond, cforiter);

            if (dim < array_type.rank)
            {
                deserialize_array_dim(array_type, dim + 1, temp_name, new CCodeIdentifier(element_name), expr);
            }
            else
            {
                var size_check = new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, new CCodeIdentifier(temp_name + "_size"), new CCodeIdentifier(temp_name + "_length"));

                ccode.open_if(size_check);

                // tmp_size = (2 * tmp_size);
                var new_size = new CCodeBinaryExpression(CCodeBinaryOperator.MUL, new CCodeConstant("2"), new CCodeIdentifier(temp_name + "_size"));
                ccode.add_assignment(new CCodeIdentifier(temp_name + "_size"), new_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(new CCodeIdentifier(temp_name));
                // add one extra element for NULL-termination
                renew_call.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, new CCodeIdentifier(temp_name + "_size"), new CCodeConstant("1")));
                ccode.add_assignment(new CCodeIdentifier(temp_name), renew_call);

                ccode.close();

                var  element_access = new CCodeElementAccess(new CCodeIdentifier(temp_name), new CCodeUnaryExpression(CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier(temp_name + "_length")));
                bool may_fail;
                var  element_expr = deserialize_expression(array_type.element_type, new CCodeIdentifier(element_name), null, out may_fail, null);
                ccode.add_assignment(element_access, element_expr);
            }

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

            unref.add_argument(new CCodeIdentifier(element_name));
            ccode.add_expression(unref);

            ccode.close();

            if (expr != null)
            {
                ccode.add_assignment(get_array_length(expr, dim), new CCodeIdentifier("%s_length%d".printf(temp_name, dim)));
            }
        }
コード例 #16
0
        public override void visit_foreach_statement(ForeachStatement stmt)
        {
            ccode.open_block();

            var collection_backup = stmt.collection_variable;
            var collection_type   = collection_backup.variable_type;

            var array_type = collection_type as ArrayType;

            if (array_type != null)
            {
                // avoid assignment issues
                array_type.inline_allocated = false;
                array_type.fixed_length     = false;
            }

            visit_local_variable(collection_backup);
            ccode.add_assignment(get_variable_cexpression(get_local_cname(collection_backup)), get_cvalue(stmt.collection));

            if (stmt.tree_can_fail && stmt.collection.tree_can_fail)
            {
                // exception handling
                add_simple_check(stmt.collection);
            }

            if (stmt.collection.value_type is ArrayType)
            {
                array_type = (ArrayType)stmt.collection.value_type;

                var array_len = get_array_length_cexpression(stmt.collection);

                // store array length for use by _vala_array_free
                ccode.add_assignment(get_variable_cexpression(get_array_length_cname(get_local_cname(collection_backup), 1)), array_len);

                var iterator_variable = new LocalVariable(int_type.copy(), stmt.variable_name + "_it");
                visit_local_variable(iterator_variable);
                var it_name = get_local_cname(iterator_variable);

                var ccond = new CCodeBinaryExpression(CCodeBinaryOperator.LESS_THAN, get_variable_cexpression(it_name), array_len);

                ccode.open_for(new CCodeAssignment(get_variable_cexpression(it_name), new CCodeConstant("0")),
                               ccond,
                               new CCodeAssignment(get_variable_cexpression(it_name), new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, get_variable_cexpression(it_name), new CCodeConstant("1"))));

                CCodeExpression element_expr = new CCodeElementAccess(get_variable_cexpression(get_local_cname(collection_backup)), get_variable_cexpression(it_name));

                var element_type = array_type.element_type.copy();
                element_type.value_owned = false;
                element_expr             = get_cvalue_(transform_value(new GLibValue(element_type, element_expr, true), stmt.type_reference, stmt));

                visit_local_variable(stmt.element_variable);
                ccode.add_assignment(get_variable_cexpression(get_local_cname(stmt.element_variable)), element_expr);

                // set array length for stacked arrays
                if (stmt.type_reference is ArrayType)
                {
                    var inner_array_type = (ArrayType)stmt.type_reference;
                    for (int dim = 1; dim <= inner_array_type.rank; dim++)
                    {
                        ccode.add_assignment(get_variable_cexpression(get_array_length_cname(get_local_cname(stmt.element_variable), dim)), new CCodeConstant("-1"));
                    }
                }

                stmt.body.emit(this);

                ccode.close();
            }
            else if (stmt.collection.value_type.compatible(new ObjectType(glist_type)) || stmt.collection.value_type.compatible(new ObjectType(gslist_type)))
            {
                // iterating over a GList or GSList

                var iterator_variable = new LocalVariable(collection_type.copy(), stmt.variable_name + "_it");
                visit_local_variable(iterator_variable);
                var it_name = get_local_cname(iterator_variable);

                var ccond = new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, get_variable_cexpression(it_name), new CCodeConstant("NULL"));

                ccode.open_for(new CCodeAssignment(get_variable_cexpression(it_name), get_variable_cexpression(get_local_cname(collection_backup))),
                               ccond,
                               new CCodeAssignment(get_variable_cexpression(it_name), CCodeMemberAccess.pointer(get_variable_cexpression(it_name), "next")));

                CCodeExpression element_expr = CCodeMemberAccess.pointer(get_variable_cexpression(it_name), "data");

                if (collection_type.get_type_arguments().Count != 1)
                {
                    Report.error(stmt.source_reference, "internal error: missing generic type argument");
                    stmt.error = true;
                    return;
                }

                var element_data_type = collection_type.get_type_arguments()[0].copy();
                element_data_type.value_owned = false;
                element_expr = convert_from_generic_pointer(element_expr, element_data_type);
                element_expr = get_cvalue_(transform_value(new GLibValue(element_data_type, element_expr), stmt.type_reference, stmt));

                visit_local_variable(stmt.element_variable);
                ccode.add_assignment(get_variable_cexpression(get_local_cname(stmt.element_variable)), element_expr);

                stmt.body.emit(this);

                ccode.close();
            }
            else if (stmt.collection.value_type.compatible(new ObjectType(gvaluearray_type)))
            {
                // iterating over a GValueArray

                var iterator_variable = new LocalVariable(uint_type.copy(), "%s_index".printf(stmt.variable_name));
                visit_local_variable(iterator_variable);
                var arr_index = get_variable_cname(get_local_cname(iterator_variable));

                var ccond = new CCodeBinaryExpression(CCodeBinaryOperator.LESS_THAN, get_variable_cexpression(arr_index), CCodeMemberAccess.pointer(get_variable_cexpression(get_local_cname(collection_backup)), "n_values"));

                ccode.open_for(new CCodeAssignment(get_variable_cexpression(arr_index), new CCodeConstant("0")),
                               ccond,
                               new CCodeAssignment(get_variable_cexpression(arr_index), new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, get_variable_cexpression(arr_index), new CCodeConstant("1"))));

                var get_item = new CCodeFunctionCall(new CCodeIdentifier("g_value_array_get_nth"));
                get_item.add_argument(get_variable_cexpression(get_local_cname(collection_backup)));
                get_item.add_argument(get_variable_cexpression(arr_index));

                CCodeExpression element_expr = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, get_item);

                if (stmt.type_reference.value_owned)
                {
                    element_expr = get_cvalue_(copy_value(new GLibValue(stmt.type_reference, element_expr), new StructValueType(gvalue_type)));
                }

                visit_local_variable(stmt.element_variable);
                ccode.add_assignment(get_variable_cexpression(get_local_cname(stmt.element_variable)), element_expr);

                stmt.body.emit(this);

                ccode.close();
            }

            foreach (LocalVariable local in stmt.get_local_variables())
            {
                if (requires_destroy(local.variable_type))
                {
                    ccode.add_expression(destroy_local(local));
                }
            }

            ccode.close();
        }
コード例 #17
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);
        }
コード例 #18
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);
        }
コード例 #19
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);
        }
コード例 #20
0
        public override void visit_array_creation_expression(ArrayCreationExpression expr)
        {
            var             array_type = expr.target_type as ArrayType;
            LocalVariable   temp_var;
            CCodeExpression name_cnode;
            int             i;

            if (array_type != null && array_type.fixed_length)
            {
                // no heap allocation for fixed-length arrays

                temp_var   = get_temp_variable(array_type, true, expr);
                name_cnode = get_variable_cexpression(temp_var.name);
                i          = 0;

                emit_temp_var(temp_var);

                append_initializer_list(name_cnode, expr.initializer_list, expr.rank, ref i);

                set_cvalue(expr, name_cnode);

                return;
            }

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

            gnew.add_argument(new CCodeIdentifier(get_ccode_name(expr.element_type)));

            bool            first = true;
            CCodeExpression cexpr = null;

            // iterate over each dimension
            foreach (Expression size in expr.get_sizes())
            {
                CCodeExpression csize = get_cvalue(size);
                append_array_length(expr, csize);

                if (first)
                {
                    cexpr = csize;
                    first = false;
                }
                else
                {
                    cexpr = new CCodeBinaryExpression(CCodeBinaryOperator.MUL, cexpr, csize);
                }
            }

            // add extra item to have array NULL-terminated for all reference types
            if (expr.element_type.data_type != null && expr.element_type.data_type.is_reference_type())
            {
                cexpr = new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, cexpr, new CCodeConstant("1"));
            }

            gnew.add_argument(cexpr);

            temp_var   = get_temp_variable(expr.value_type, true, expr);
            name_cnode = get_variable_cexpression(temp_var.name);
            i          = 0;

            emit_temp_var(temp_var);

            ccode.add_assignment(name_cnode, gnew);

            if (expr.initializer_list != null)
            {
                append_initializer_list(name_cnode, expr.initializer_list, expr.rank, ref i);
            }

            set_cvalue(expr, name_cnode);
        }
コード例 #21
0
        void visit_string_switch_statement(SwitchStatement stmt)
        {
            // we need a temporary variable to save the property value
            var temp_value = create_temp_value(stmt.expression.value_type, false, stmt);
            var ctemp      = get_cvalue_(temp_value);

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

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

            free_call.add_argument(ctemp);

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

            cquark.add_argument(ctemp);

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

            int label_temp_id = next_temp_var_id++;

            temp_value = create_temp_value(gquark_type, true, stmt);

            int label_count = 0;

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

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

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

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

            ccode.add_expression(cinit);

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

            ccode.add_expression(cinit);

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

            SwitchSection default_section = null;

            label_count = 0;

            int n = 0;

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

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

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

                        ccall.add_argument(cexpr);

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

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

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

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

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

                section.emit(this);

                ccode.close();

                n++;
            }

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

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

                default_section.emit(this);

                ccode.close();
            }

            if (n > 0)
            {
                ccode.close();
            }
        }
コード例 #22
0
        void generate_async_function(Method m)
        {
            push_context(new EmitContext());

            string callback_wrapper = null;

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

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

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

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

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

            push_function(asyncfunc);

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

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

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

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

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

            dataalloc.add_argument(new CCodeIdentifier(dataname));

            var data_var = new CCodeIdentifier("_data_");

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

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

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

            var t = m.parent_symbol as TypeSymbol;

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

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

            Parameter cancellable_param = null;

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

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

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

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

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

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

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

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

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

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

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

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

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

                    current_method.coroutine = true;

                    store_parameter(param, value);

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

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

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

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

            cfile.add_function(asyncfunc);

            pop_context();
        }
コード例 #23
0
		public override void store_value(TargetValue lvalue, TargetValue value, SourceReference source_reference = null) {
			var array_type = lvalue.value_type as ArrayType;

			if (array_type != null && array_type.fixed_length) {
				cfile.add_include("string.h");

				// it is necessary to use memcpy for fixed-length (stack-allocated) arrays
				// simple assignments do not work in C
				var sizeof_call = new CCodeFunctionCall(new CCodeIdentifier("sizeof"));
				sizeof_call.add_argument(new CCodeIdentifier(get_ccode_name(array_type.element_type)));
				var size = new CCodeBinaryExpression(CCodeBinaryOperator.MUL, get_ccodenode(array_type.length), sizeof_call);

				var ccopy = new CCodeFunctionCall(new CCodeIdentifier("memcpy"));
				ccopy.add_argument(get_cvalue_(lvalue));
				ccopy.add_argument(get_cvalue_(value));
				ccopy.add_argument(size);
				ccode.add_expression(ccopy);

				return;
			}

			var cexpr = get_cvalue_(value);
			if (get_ctype(lvalue) != null) {
				cexpr = new CCodeCastExpression(cexpr, get_ctype(lvalue));
			}

			/*
			 * If this is a SimpleType struct being passed by value
			 * and the user specified a custom user function
			 * use the specified function instead to do assignments rather than dest = source
			 */
			var st_left = lvalue.value_type.data_type as Struct;
			var st_right = value.value_type.data_type as Struct;
			if (
				st_left != null &&
				st_right != null &&
				lvalue.value_type.compatible(value.value_type) &&
				st_left.is_simple_type() &&
				lvalue.value_type is StructValueType &&
				st_left.has_attribute_argument("CCode", "copy_function")
			) {
				//copy_function (src, dest)
				var copy_call = new CCodeFunctionCall(new CCodeIdentifier(get_ccode_copy_function(st_left)));
				copy_call.add_argument(get_cvalue_(value));
				copy_call.add_argument(get_cvalue_(lvalue));
				ccode.add_expression(copy_call);
				return;
			}

			ccode.add_assignment(get_cvalue_(lvalue), cexpr);

			if (array_type != null && ((GLibValue)lvalue).array_length_cvalues != null) {
				var glib_value = (GLibValue)value;
				if (glib_value.array_length_cvalues != null) {
					for (int dim = 1; dim <= array_type.rank; dim++) {
						ccode.add_assignment(get_array_length_cvalue(lvalue, dim), get_array_length_cvalue(value, dim));
					}
				} else if (glib_value.array_null_terminated) {
					requires_array_length = true;
					var len_call = new CCodeFunctionCall(new CCodeIdentifier("_vala_array_length"));
					len_call.add_argument(get_cvalue_(value));

					ccode.add_assignment(get_array_length_cvalue(lvalue, 1), len_call);
				} else {
					for (int dim = 1; dim <= array_type.rank; dim++) {
						ccode.add_assignment(get_array_length_cvalue(lvalue, dim), new CCodeConstant("-1"));
					}
				}

				if (array_type.rank == 1 && get_array_size_cvalue(lvalue) != null) {
					ccode.add_assignment(get_array_size_cvalue(lvalue), get_array_length_cvalue(lvalue, 1));
				}
			}

			var delegate_type = lvalue.value_type as DelegateType;
			if (delegate_type != null && delegate_type.delegate_symbol.has_target) {
				var lvalue_target = get_delegate_target_cvalue(lvalue);
				var rvalue_target = get_delegate_target_cvalue(value);
				if (lvalue_target != null) {
					if (rvalue_target != null) {
						ccode.add_assignment(lvalue_target, rvalue_target);
					} else {
						Report.error(source_reference, "Assigning delegate without required target in scope");
						ccode.add_assignment(lvalue_target, new CCodeInvalidExpression());
					}
					var lvalue_destroy_notify = get_delegate_target_destroy_notify_cvalue(lvalue);
					var rvalue_destroy_notify = get_delegate_target_destroy_notify_cvalue(value);
					if (lvalue_destroy_notify != null) {
						if (rvalue_destroy_notify != null) {
							ccode.add_assignment(lvalue_destroy_notify, rvalue_destroy_notify);
						} else {
							ccode.add_assignment(lvalue_destroy_notify, new CCodeConstant("NULL"));
						}
					}
				}
			}
		}
コード例 #24
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);
        }