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); }
/// <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); }