示例#1
0
        public override CCodeFragment get_type_interface_init_declaration()
        {
            var frag = new CCodeFragment();

            foreach (DataType base_type in class_reference.get_base_types())
            {
                if (!(base_type.data_type is Interface))
                {
                    continue;
                }

                var iface = (Interface)base_type.data_type;

                var iface_info_name = "%s_info".printf(CCodeBaseModule.get_ccode_lower_case_name(iface, null));

                var ctypedecl = new CCodeDeclaration("const GInterfaceInfo");
                ctypedecl.modifiers = CCodeModifiers.STATIC;
                ctypedecl.add_declarator(new CCodeVariableDeclarator(iface_info_name, new CCodeConstant("{ (GInterfaceInitFunc) %s_%s_interface_init, (GInterfaceFinalizeFunc) NULL, NULL}".printf(CCodeBaseModule.get_ccode_lower_case_name(class_reference), CCodeBaseModule.get_ccode_lower_case_name(iface)))));
                frag.append(ctypedecl);
            }

            return(frag);
        }
示例#2
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);
        }