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 ();
33 public CodeContext context
{ get; set; }
36 * Constructs the C function from the specified type.
38 public void init_from_type (bool plugin
) {
39 bool use_thread_safe
= !plugin
;
41 bool fundamental
= false;
42 Class cl
= get_type_declaration () as Class
;
43 if (cl
!= null && !cl
.is_compact
&& cl
.base_class
== null) {
47 string type_id_name
= "%s_type_id".printf (get_type_declaration ().get_lower_case_cname (null));
49 var type_block
= new
CCodeBlock ();
50 CCodeDeclaration cdecl
;
51 if (use_thread_safe
) {
52 cdecl
= new
CCodeDeclaration ("gsize");
53 cdecl
.add_declarator (new
CCodeVariableDeclarator (type_id_name
+ "__volatile", new
CCodeConstant ("0")));
55 cdecl
= new
CCodeDeclaration ("GType");
56 cdecl
.add_declarator (new
CCodeVariableDeclarator (type_id_name
, new
CCodeConstant ("0")));
58 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
59 if (use_thread_safe
) {
60 cdecl
.modifiers
|= CCodeModifiers
.VOLATILE
;
63 type_block
.add_statement (cdecl
);
65 source_declaration_fragment
.append (cdecl
);
70 fun
= new
CCodeFunction ("%s_get_type".printf (get_type_declaration ().get_lower_case_cname (null)), "GType");
71 fun
.attributes
= "G_GNUC_CONST";
73 /* Function will not be prototyped anyway */
74 if (get_accessibility () == SymbolAccessibility
.PRIVATE
) {
75 fun
.modifiers
= CCodeModifiers
.STATIC
;
76 // avoid C warning as this function is not always used
77 fun
.attributes
+= " G_GNUC_UNUSED";
80 fun
= new
CCodeFunction ("%s_register_type".printf (get_type_declaration ().get_lower_case_cname (null)), "GType");
81 fun
.add_parameter (new
CCodeParameter ("module", "GTypeModule *"));
83 var get_fun
= new
CCodeFunction ("%s_get_type".printf (get_type_declaration ().get_lower_case_cname (null)), "GType");
84 get_fun
.attributes
= "G_GNUC_CONST";
86 get_fun
.is_declaration
= true;
87 declaration_fragment
.append (get_fun
.copy ());
88 get_fun
.is_declaration
= false;
90 get_fun
.block
= new
CCodeBlock ();
91 get_fun
.block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier (type_id_name
)));
93 definition_fragment
.append (get_fun
);
96 string type_value_table_decl_name
= null;
97 var type_init
= new
CCodeBlock ();
100 var cgtypetabledecl
= new
CCodeDeclaration ("const GTypeValueTable");
101 cgtypetabledecl
.modifiers
= CCodeModifiers
.STATIC
;
103 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 ()))));
104 type_value_table_decl_name
= "&g_define_type_value_table";
105 type_init
.add_statement ( cgtypetabledecl
);
108 type_value_table_decl_name
= "NULL";
112 if (get_type_declaration () is ObjectTypeSymbol
) {
113 var ctypedecl
= new
CCodeDeclaration ("const GTypeInfo");
114 ctypedecl
.modifiers
= CCodeModifiers
.STATIC
;
115 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
))));
116 type_init
.add_statement (ctypedecl
);
118 var ctypefundamentaldecl
= new
CCodeDeclaration ("const GTypeFundamentalInfo");
119 ctypefundamentaldecl
.modifiers
= CCodeModifiers
.STATIC
;
120 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) }")));
121 type_init
.add_statement (ctypefundamentaldecl
);
125 type_init
.add_statement (get_type_interface_init_declaration ());
127 if (cl
!= null && cl
.has_class_private_fields
&& !context
.require_glib_version (2, 24)) {
128 CCodeFunctionCall quark_reg_call
;
131 quark_reg_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_quark_from_string"));
133 quark_reg_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_quark_from_static_string"));
136 quark_reg_call
.add_argument (new
CCodeConstant ("\"Vala%sClassPrivate\"".printf (get_type_declaration ().get_cname ())));
138 type_init
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_vala_%s_class_private_quark".printf (get_type_declaration ().get_lower_case_cname ())), quark_reg_call
)));
141 CCodeFunctionCall reg_call
;
142 if (get_type_declaration () is Struct
) {
143 reg_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_boxed_type_register_static"));
144 } else if (get_type_declaration () is Enum
) {
145 var en
= get_type_declaration () as Enum
;
147 reg_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_flags_register_static"));
149 reg_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_enum_register_static"));
151 } else if (fundamental
) {
152 reg_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_register_fundamental"));
153 reg_call
.add_argument (new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_fundamental_next")));
154 } else if (!plugin
) {
155 reg_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_register_static"));
156 reg_call
.add_argument (new
CCodeIdentifier (get_parent_type_name ()));
158 reg_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_module_register_type"));
159 reg_call
.add_argument (new
CCodeIdentifier ("module"));
160 reg_call
.add_argument (new
CCodeIdentifier (get_parent_type_name ()));
162 reg_call
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_type_declaration ().get_cname ())));
163 if (get_type_declaration () is Struct
) {
164 var st
= (Struct
) get_type_declaration ();
165 reg_call
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier (st
.get_dup_function ()), "GBoxedCopyFunc"));
166 reg_call
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier (st
.get_free_function ()), "GBoxedFreeFunc"));
167 } else if (get_type_declaration () is Enum
) {
168 var en
= get_type_declaration () as Enum
;
169 var clist
= new
CCodeInitializerList (); /* or during visit time? */
171 CCodeInitializerList clist_ev
= null;
172 foreach (EnumValue ev
in en
.get_values ()) {
173 clist_ev
= new
CCodeInitializerList ();
174 clist_ev
.append (new
CCodeConstant (ev
.get_cname ()));
175 clist_ev
.append (new
CCodeIdentifier ("\"%s\"".printf (ev
.get_cname ())));
176 clist_ev
.append (ev
.get_canonical_cconstant ());
177 clist
.append (clist_ev
);
180 clist_ev
= new
CCodeInitializerList ();
181 clist_ev
.append (new
CCodeConstant ("0"));
182 clist_ev
.append (new
CCodeConstant ("NULL"));
183 clist_ev
.append (new
CCodeConstant ("NULL"));
184 clist
.append (clist_ev
);
186 var enum_decl
= new
CCodeVariableDeclarator ("values[]", clist
);
189 cdecl
= new
CCodeDeclaration ("const GFlagsValue");
191 cdecl
= new
CCodeDeclaration ("const GEnumValue");
194 cdecl
.add_declarator (enum_decl
);
195 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
197 type_init
.add_statement (cdecl
);
199 reg_call
.add_argument (new
CCodeIdentifier ("values"));
201 reg_call
.add_argument (new
CCodeIdentifier ("&g_define_type_info"));
203 reg_call
.add_argument (new
CCodeIdentifier ("&g_define_type_fundamental_info"));
205 reg_call
.add_argument (new
CCodeConstant (get_type_flags ()));
208 if (use_thread_safe
&& !plugin
) {
209 var temp_decl
= new
CCodeDeclaration ("GType");
210 temp_decl
.add_declarator (new
CCodeVariableDeclarator (type_id_name
, reg_call
));
211 type_init
.add_statement (temp_decl
);
213 type_init
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier (type_id_name
), reg_call
)));
216 if (cl
!= null && cl
.has_class_private_fields
&& context
.require_glib_version (2, 24)) {
217 CCodeFunctionCall add_class_private_call
;
219 add_class_private_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_add_class_private"));
220 add_class_private_call
.add_argument (new
CCodeIdentifier (type_id_name
));
221 add_class_private_call
.add_argument (new
CCodeIdentifier ("sizeof (%sClassPrivate)".printf (get_type_declaration ().get_cname ())));
222 type_init
.add_statement (new
CCodeExpressionStatement (add_class_private_call
));
225 type_init
.add_statement (get_type_interface_init_statements (plugin
));
228 CCodeExpression condition
; // the condition that guards the type initialisation
229 if (use_thread_safe
) {
230 var enter
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_once_init_enter"));
231 enter
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (type_id_name
+ "__volatile")));
234 var leave
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_once_init_leave"));
235 leave
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (type_id_name
+ "__volatile")));
236 leave
.add_argument (new
CCodeIdentifier (type_id_name
));
237 type_init
.add_statement (new
CCodeExpressionStatement (leave
));
239 var id
= new
CCodeIdentifier (type_id_name
);
240 var zero
= new
CCodeConstant ("0");
241 condition
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, id
, zero
);
244 CCodeExpression cond
;
245 if (use_thread_safe
) {
248 cond
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_UNLIKELY"));
249 (cond as CCodeFunctionCall
).add_argument (condition
);
251 var cif
= new
CCodeIfStatement (cond
, type_init
);
252 type_block
.add_statement (cif
);
254 type_block
= type_init
;
257 if (use_thread_safe
) {
258 type_block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier (type_id_name
+ "__volatile")));
260 type_block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier (type_id_name
)));
263 fun
.is_declaration
= true;
264 declaration_fragment
.append (fun
.copy ());
265 fun
.is_declaration
= false;
267 fun
.block
= type_block
;
269 definition_fragment
.append (fun
);
273 * Returns the data type to be registered.
275 * @return type to be registered
277 public abstract TypeSymbol
get_type_declaration ();
280 * Returns the name of the type struct in C code.
282 * @return C struct name
284 public virtual string get_type_struct_name () {
285 assert_not_reached ();
288 * Returns the name of the base_init function in C code.
290 * @return C function name
292 public virtual string get_base_init_func_name () {
293 assert_not_reached ();
297 * Returns the name of the class_finalize function in C code.
299 * @return C function name
301 public virtual string get_class_finalize_func_name () {
302 assert_not_reached ();
306 * Returns the name of the base_finalize function in C code.
308 * @return C function name
310 public virtual string get_base_finalize_func_name () {
311 assert_not_reached ();
315 * Returns the name of the class_init function in C code.
317 * @return C function name
319 public virtual string get_class_init_func_name () {
320 assert_not_reached ();
324 * Returns the size of the instance struct in C code.
326 * @return C instance struct size
328 public virtual string get_instance_struct_size () {
329 assert_not_reached ();
333 * Returns the name of the instance_init function in C code.
335 * @return C function name
337 public virtual string get_instance_init_func_name () {
338 assert_not_reached ();
342 * Returns the name of the parent type in C code.
344 * @return C function name
346 public virtual string get_parent_type_name () {
347 assert_not_reached ();
353 * Returns the C-name of the new generated GTypeValueTable init function or null when not available.
355 * @return C function name
357 public virtual string?
get_gtype_value_table_init_function_name () {
362 * Returns the C-name of the new generated GTypeValueTable peek pointer function or null when not available.
364 * @return C function name
366 public virtual string?
get_gtype_value_table_peek_pointer_function_name () {
371 * Returns the C-name of the new generated GTypeValueTable free function or null when not available.
373 * @return C function name
375 public virtual string?
get_gtype_value_table_free_function_name () {
380 * Returns the C-name of the new generated GTypeValueTable copy function or null when not available.
382 * @return C function name
384 public virtual string?
get_gtype_value_table_copy_function_name () {
389 * Returns the C-name of the new generated GTypeValueTable lcopy function or null when not available.
391 * @return C function name
393 public virtual string?
get_gtype_value_table_lcopy_value_function_name () {
398 * Returns the C-name of the new generated GTypeValueTable collect value function or null when not available.
400 * @return C function name
402 public virtual string?
get_gtype_value_table_collect_value_function_name () {
407 * Returns the set of type flags to be applied when registering.
411 public virtual string get_type_flags () {
416 * Returns additional C declarations to setup interfaces.
418 * @return C declarations
420 public virtual CCodeFragment
get_type_interface_init_declaration () {
421 return new
CCodeFragment ();
425 * Returns additional C initialization statements to setup interfaces.
427 * @return C statements
429 public abstract CCodeFragment
get_type_interface_init_statements (bool plugin
);
431 public CCodeFragment
get_source_declaration () {
432 return source_declaration_fragment
;
436 * Returns the declaration for this type register function in C code.
438 * @return C function declaration fragment
440 public CCodeFragment
get_declaration () {
441 return declaration_fragment
;
445 * Returns the definition for this type register function in C code.
447 * @return C function definition fragment
449 public CCodeFragment
get_definition () {
450 return definition_fragment
;
454 * Returns the accessibility for this type.
456 public abstract SymbolAccessibility
get_accessibility ();