1 /* valatyperegisterfunction.vala
3 * Copyright (C) 2006-2010 Jürg Billeter
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Jürg Billeter <j@bitron.ch>
26 * C function to register a type at runtime.
28 public abstract class Vala.TypeRegisterFunction {
29 CCodeFragment source_declaration_fragment = new CCodeFragment ();
30 CCodeFragment declaration_fragment = new CCodeFragment ();
31 CCodeFragment definition_fragment = new CCodeFragment ();
34 * Constructs the C function from the specified type.
36 public void init_from_type (CodeContext context, bool plugin, bool declaration_only) {
37 var type_symbol = get_type_declaration ();
39 bool fundamental = false;
40 unowned Class? cl = type_symbol as Class;
41 if (cl != null && !cl.is_compact && cl.base_class == null) {
45 string type_id_name = "%s_type_id".printf (get_ccode_lower_case_name (type_symbol));
47 var type_block = new CCodeBlock ();
48 var type_once_block = new CCodeBlock ();
49 CCodeDeclaration cdecl;
51 cdecl = new CCodeDeclaration ("gsize");
52 cdecl.add_declarator (new CCodeVariableDeclarator (type_id_name + "__once", new CCodeConstant ("0")));
53 if (context.require_glib_version (2, 68)) {
54 cdecl.modifiers = CCodeModifiers.STATIC;
56 cdecl.modifiers = CCodeModifiers.STATIC | CCodeModifiers.VOLATILE;
58 type_block.add_statement (cdecl);
60 cdecl = new CCodeDeclaration ("GType");
61 cdecl.add_declarator (new CCodeVariableDeclarator (type_id_name, new CCodeConstant ("0")));
62 cdecl.modifiers = CCodeModifiers.STATIC;
63 source_declaration_fragment.append (cdecl);
67 CCodeFunction fun_once = null;
69 fun = new CCodeFunction (get_ccode_type_function (type_symbol), "GType");
70 fun.modifiers = CCodeModifiers.CONST;
72 /* Function will not be prototyped anyway */
73 if (get_accessibility () == SymbolAccessibility.PRIVATE) {
74 // avoid C warning as this function is not always used
75 fun.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
76 } else if (context.hide_internal && get_accessibility () == SymbolAccessibility.INTERNAL) {
77 // avoid C warning as this function is not always used
78 fun.modifiers |= CCodeModifiers.INTERNAL | CCodeModifiers.UNUSED;
80 fun.modifiers |= CCodeModifiers.EXTERN;
83 fun.is_declaration = true;
84 declaration_fragment.append (fun.copy ());
85 fun.is_declaration = false;
87 fun_once = new CCodeFunction ("%s_once".printf (fun.name), "GType");
88 fun_once.modifiers = CCodeModifiers.STATIC;
89 if (context.require_glib_version (2, 58)) {
90 fun_once.modifiers |= CCodeModifiers.NO_INLINE;
93 fun_once.is_declaration = true;
94 source_declaration_fragment.append (fun_once.copy ());
95 fun_once.is_declaration = false;
97 fun = new CCodeFunction ("%s_register_type".printf (get_ccode_lower_case_name (type_symbol)), "GType");
98 fun.add_parameter (new CCodeParameter ("module", "GTypeModule *"));
100 fun.is_declaration = true;
101 declaration_fragment.append (fun.copy ());
102 fun.is_declaration = false;
104 var get_fun = new CCodeFunction (get_ccode_type_function (type_symbol), "GType");
105 get_fun.modifiers = CCodeModifiers.CONST | CCodeModifiers.EXTERN;
107 get_fun.is_declaration = true;
108 declaration_fragment.append (get_fun.copy ());
109 get_fun.is_declaration = false;
111 get_fun.block = new CCodeBlock ();
112 get_fun.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier (type_id_name)));
114 definition_fragment.append (get_fun);
117 string type_value_table_decl_name = null;
118 var type_init = new CCodeBlock ();
121 var cgtypetabledecl = new CCodeDeclaration ("const GTypeValueTable");
122 cgtypetabledecl.modifiers = CCodeModifiers.STATIC;
124 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 ()))));
125 type_value_table_decl_name = "&g_define_type_value_table";
126 type_init.add_statement ( cgtypetabledecl );
129 type_value_table_decl_name = "NULL";
133 if (type_symbol is ObjectTypeSymbol) {
134 var ctypedecl = new CCodeDeclaration ("const GTypeInfo");
135 ctypedecl.modifiers = CCodeModifiers.STATIC;
136 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))));
137 type_init.add_statement (ctypedecl);
139 var ctypefundamentaldecl = new CCodeDeclaration ("const GTypeFundamentalInfo");
140 ctypefundamentaldecl.modifiers = CCodeModifiers.STATIC;
141 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) }")));
142 type_init.add_statement (ctypefundamentaldecl);
146 type_init.add_statement (get_type_interface_init_declaration ());
148 CCodeFunctionCall reg_call;
149 if (type_symbol is Struct) {
150 reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_boxed_type_register_static"));
151 } else if (type_symbol is Enum) {
152 unowned Enum en = (Enum) type_symbol;
154 reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_flags_register_static"));
156 reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_enum_register_static"));
158 } else if (fundamental) {
159 reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_register_fundamental"));
160 reg_call.add_argument (new CCodeFunctionCall (new CCodeIdentifier ("g_type_fundamental_next")));
161 } else if (!plugin) {
162 reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_register_static"));
163 reg_call.add_argument (new CCodeIdentifier (get_parent_type_name ()));
165 reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_module_register_type"));
166 reg_call.add_argument (new CCodeIdentifier ("module"));
167 reg_call.add_argument (new CCodeIdentifier (get_parent_type_name ()));
169 reg_call.add_argument (new CCodeConstant ("\"%s\"".printf (get_ccode_name (type_symbol))));
170 if (type_symbol is Struct) {
171 var st = (Struct) type_symbol;
172 reg_call.add_argument (new CCodeCastExpression (new CCodeIdentifier (get_ccode_dup_function (st)), "GBoxedCopyFunc"));
173 reg_call.add_argument (new CCodeCastExpression (new CCodeIdentifier (get_ccode_free_function (st)), "GBoxedFreeFunc"));
174 } else if (type_symbol is Enum) {
175 unowned Enum en = (Enum) type_symbol;
176 var clist = new CCodeInitializerList (); /* or during visit time? */
178 CCodeInitializerList clist_ev = null;
179 foreach (EnumValue ev in en.get_values ()) {
180 clist_ev = new CCodeInitializerList ();
181 clist_ev.append (new CCodeConstant (get_ccode_name (ev)));
182 clist_ev.append (new CCodeConstant ("\"%s\"".printf (get_ccode_name (ev))));
183 clist_ev.append (new CCodeConstant ("\"%s\"".printf (ev.nick)));
184 clist.append (clist_ev);
187 clist_ev = new CCodeInitializerList ();
188 clist_ev.append (new CCodeConstant ("0"));
189 clist_ev.append (new CCodeConstant ("NULL"));
190 clist_ev.append (new CCodeConstant ("NULL"));
191 clist.append (clist_ev);
193 var enum_decl = new CCodeVariableDeclarator ("values[]", clist);
196 cdecl = new CCodeDeclaration ("const GFlagsValue");
198 cdecl = new CCodeDeclaration ("const GEnumValue");
201 cdecl.add_declarator (enum_decl);
202 cdecl.modifiers = CCodeModifiers.STATIC;
204 type_init.add_statement (cdecl);
206 reg_call.add_argument (new CCodeIdentifier ("values"));
208 reg_call.add_argument (new CCodeIdentifier ("&g_define_type_info"));
210 reg_call.add_argument (new CCodeIdentifier ("&g_define_type_fundamental_info"));
212 reg_call.add_argument (new CCodeConstant (get_type_flags ()));
215 var once_call_block = new CCodeBlock ();
217 var temp_decl = new CCodeDeclaration ("GType");
218 temp_decl.add_declarator (new CCodeVariableDeclarator (type_id_name, reg_call));
219 type_init.add_statement (temp_decl);
220 temp_decl = new CCodeDeclaration ("GType");
221 temp_decl.add_declarator (new CCodeVariableDeclarator (type_id_name, new CCodeFunctionCall (new CCodeIdentifier (fun_once.name))));
222 once_call_block.add_statement (temp_decl);
224 type_init.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier (type_id_name), reg_call)));
227 if (cl != null && cl.has_class_private_fields) {
228 CCodeFunctionCall add_class_private_call;
230 add_class_private_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_add_class_private"));
231 add_class_private_call.add_argument (new CCodeIdentifier (type_id_name));
232 add_class_private_call.add_argument (new CCodeIdentifier ("sizeof (%sPrivate)".printf (get_ccode_type_name (cl))));
233 type_init.add_statement (new CCodeExpressionStatement (add_class_private_call));
236 if (!declaration_only) {
237 get_type_interface_init_statements (context, type_init, plugin);
240 if (cl != null && (cl.has_private_fields || cl.has_type_parameters ())) {
242 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_add_instance_private"));
243 ccall.add_argument (new CCodeIdentifier (type_id_name));
244 ccall.add_argument (new CCodeIdentifier ("sizeof (%sPrivate)".printf (get_ccode_name (cl))));
245 type_init.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("%s_private_offset".printf (get_ccode_name (cl))), ccall)));
247 type_init.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("%s_private_offset".printf (get_ccode_name (cl))), new CCodeIdentifier ("sizeof (%sPrivate)".printf (get_ccode_name (cl))))));
252 // the condition that guards the type initialisation
253 var enter = new CCodeFunctionCall (new CCodeIdentifier ("g_once_init_enter"));
254 enter.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (type_id_name + "__once")));
256 var leave = new CCodeFunctionCall (new CCodeIdentifier ("g_once_init_leave"));
257 leave.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (type_id_name + "__once")));
258 leave.add_argument (new CCodeIdentifier (type_id_name));
259 once_call_block.add_statement (new CCodeExpressionStatement (leave));
261 var cif = new CCodeIfStatement (enter, once_call_block);
262 type_block.add_statement (cif);
263 type_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier (type_id_name + "__once")));
265 type_once_block = type_init;
266 type_once_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier (type_id_name)));
268 type_block = type_init;
269 type_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier (type_id_name)));
273 fun_once.block = type_once_block;
274 definition_fragment.append (fun_once);
277 fun.block = type_block;
278 definition_fragment.append (fun);
282 * Returns the data type to be registered.
284 * @return type to be registered
286 public abstract TypeSymbol get_type_declaration ();
289 * Returns the name of the type struct in C code.
291 * @return C struct name
293 public virtual string get_type_struct_name () {
294 assert_not_reached ();
297 * Returns the name of the base_init function in C code.
299 * @return C function name
301 public virtual string get_base_init_func_name () {
302 assert_not_reached ();
306 * Returns the name of the class_finalize function in C code.
308 * @return C function name
310 public virtual string get_class_finalize_func_name () {
311 assert_not_reached ();
315 * Returns the name of the base_finalize function in C code.
317 * @return C function name
319 public virtual string get_base_finalize_func_name () {
320 assert_not_reached ();
324 * Returns the name of the class_init function in C code.
326 * @return C function name
328 public virtual string get_class_init_func_name () {
329 assert_not_reached ();
333 * Returns the size of the instance struct in C code.
335 * @return C instance struct size
337 public virtual string get_instance_struct_size () {
338 assert_not_reached ();
342 * Returns the name of the instance_init function in C code.
344 * @return C function name
346 public virtual string get_instance_init_func_name () {
347 assert_not_reached ();
351 * Returns the name of the parent type in C code.
353 * @return C function name
355 public virtual string get_parent_type_name () {
356 assert_not_reached ();
362 * Returns the C-name of the new generated GTypeValueTable init function or null when not available.
364 * @return C function name
366 public virtual string? get_gtype_value_table_init_function_name () {
371 * Returns the C-name of the new generated GTypeValueTable peek pointer function or null when not available.
373 * @return C function name
375 public virtual string? get_gtype_value_table_peek_pointer_function_name () {
380 * Returns the C-name of the new generated GTypeValueTable free function or null when not available.
382 * @return C function name
384 public virtual string? get_gtype_value_table_free_function_name () {
389 * Returns the C-name of the new generated GTypeValueTable copy function or null when not available.
391 * @return C function name
393 public virtual string? get_gtype_value_table_copy_function_name () {
398 * Returns the C-name of the new generated GTypeValueTable lcopy function or null when not available.
400 * @return C function name
402 public virtual string? get_gtype_value_table_lcopy_value_function_name () {
407 * Returns the C-name of the new generated GTypeValueTable collect value function or null when not available.
409 * @return C function name
411 public virtual string? get_gtype_value_table_collect_value_function_name () {
416 * Returns the set of type flags to be applied when registering.
420 public virtual string get_type_flags () {
425 * Returns additional C declarations to setup interfaces.
427 * @return C declarations
429 public virtual CCodeFragment get_type_interface_init_declaration () {
430 return new CCodeFragment ();
434 * Returns additional C initialization statements to setup interfaces.
436 public virtual void get_type_interface_init_statements (CodeContext context, CCodeBlock block, bool plugin) {
439 public CCodeFragment get_source_declaration () {
440 return source_declaration_fragment;
444 * Returns the declaration for this type register function in C code.
446 * @return C function declaration fragment
448 public CCodeFragment get_declaration () {
449 return declaration_fragment;
453 * Returns the definition for this type register function in C code.
455 * @return C function definition fragment
457 public CCodeFragment get_definition () {
458 return definition_fragment;
462 * Returns the accessibility for this type.
464 public abstract SymbolAccessibility get_accessibility ();