GType: Fix C warnings for properties in interface_init
[vala-lang.git] / codegen / valagtypemodule.vala
blob9a92b63dc97533dbb297eb2c5e0a70b8e9421364
1 /* valagtypemodule.vala
3 * Copyright (C) 2006-2009 Jürg Billeter
4 * Copyright (C) 2006-2008 Raffaele Sandrini
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Author:
21 * Jürg Billeter <j@bitron.ch>
22 * Raffaele Sandrini <raffaele@sandrini.ch>
25 using Gee;
27 internal class Vala.GTypeModule : GErrorModule {
28 public GTypeModule (CCodeGenerator codegen, CCodeModule? next) {
29 base (codegen, next);
32 public override void generate_parameter (FormalParameter param, CCodeDeclarationSpace decl_space, Map<int,CCodeFormalParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
33 if (!(param.parameter_type is ObjectType)) {
34 base.generate_parameter (param, decl_space, cparam_map, carg_map);
35 return;
38 generate_type_declaration (param.parameter_type, decl_space);
40 string ctypename = param.parameter_type.get_cname ();
42 if (param.direction != ParameterDirection.IN) {
43 ctypename += "*";
46 param.ccodenode = new CCodeFormalParameter (get_variable_cname (param.name), ctypename);
48 cparam_map.set (get_param_pos (param.cparameter_position), (CCodeFormalParameter) param.ccodenode);
49 if (carg_map != null) {
50 carg_map.set (get_param_pos (param.cparameter_position), get_variable_cexpression (param.name));
54 public override void generate_class_declaration (Class cl, CCodeDeclarationSpace decl_space) {
55 if (decl_space.add_symbol_declaration (cl, cl.get_cname ())) {
56 return;
59 if (cl.base_class != null) {
60 // base class declaration
61 // necessary for ref and unref function declarations
62 generate_class_declaration (cl.base_class, decl_space);
65 bool is_gtypeinstance = !cl.is_compact;
66 bool is_fundamental = is_gtypeinstance && cl.base_class == null;
68 if (is_gtypeinstance) {
69 decl_space.add_type_declaration (new CCodeNewline ());
70 var macro = "(%s_get_type ())".printf (cl.get_lower_case_cname (null));
71 decl_space.add_type_declaration (new CCodeMacroReplacement (cl.get_type_id (), macro));
73 macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (cl.get_type_id (), cl.get_cname ());
74 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (cl.get_upper_case_cname (null)), macro));
76 macro = "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %sClass))".printf (cl.get_type_id (), cl.get_cname ());
77 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (cl.get_upper_case_cname (null)), macro));
79 macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (cl.get_type_id ());
80 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_type_check_function (cl)), macro));
82 macro = "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (cl.get_type_id ());
83 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (get_type_check_function (cl)), macro));
85 macro = "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %sClass))".printf (cl.get_type_id (), cl.get_cname ());
86 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_GET_CLASS(obj)".printf (cl.get_upper_case_cname (null)), macro));
87 decl_space.add_type_declaration (new CCodeNewline ());
90 if (cl.is_compact && cl.base_class != null) {
91 decl_space.add_type_declaration (new CCodeTypeDefinition (cl.base_class.get_cname (), new CCodeVariableDeclarator (cl.get_cname ())));
92 } else {
93 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (cl.get_cname ()), new CCodeVariableDeclarator (cl.get_cname ())));
96 if (is_fundamental) {
97 var ref_fun = new CCodeFunction (cl.get_lower_case_cprefix () + "ref", "gpointer");
98 var unref_fun = new CCodeFunction (cl.get_lower_case_cprefix () + "unref", "void");
99 if (cl.access == SymbolAccessibility.PRIVATE) {
100 ref_fun.modifiers = CCodeModifiers.STATIC;
101 unref_fun.modifiers = CCodeModifiers.STATIC;
104 ref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer"));
105 unref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer"));
107 decl_space.add_type_member_declaration (ref_fun.copy ());
108 decl_space.add_type_member_declaration (unref_fun.copy ());
110 // GParamSpec and GValue functions
111 string function_name = cl.get_lower_case_cname ("param_spec_");
113 var function = new CCodeFunction (function_name, "GParamSpec*");
114 function.add_parameter (new CCodeFormalParameter ("name", "const gchar*"));
115 function.add_parameter (new CCodeFormalParameter ("nick", "const gchar*"));
116 function.add_parameter (new CCodeFormalParameter ("blurb", "const gchar*"));
117 function.add_parameter (new CCodeFormalParameter ("object_type", "GType"));
118 function.add_parameter (new CCodeFormalParameter ("flags", "GParamFlags"));
120 if (cl.access == SymbolAccessibility.PRIVATE) {
121 function.modifiers = CCodeModifiers.STATIC;
124 decl_space.add_type_member_declaration (function);
126 function = new CCodeFunction (cl.get_set_value_function (), "void");
127 function.add_parameter (new CCodeFormalParameter ("value", "GValue*"));
128 function.add_parameter (new CCodeFormalParameter ("v_object", "gpointer"));
130 if (cl.access == SymbolAccessibility.PRIVATE) {
131 function.modifiers = CCodeModifiers.STATIC;
134 decl_space.add_type_member_declaration (function);
136 function = new CCodeFunction (cl.get_get_value_function (), "gpointer");
137 function.add_parameter (new CCodeFormalParameter ("value", "const GValue*"));
139 if (cl.access == SymbolAccessibility.PRIVATE) {
140 function.modifiers = CCodeModifiers.STATIC;
143 decl_space.add_type_member_declaration (function);
146 if (is_gtypeinstance) {
147 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%sClass".printf (cl.get_cname ()), new CCodeVariableDeclarator ("%sClass".printf (cl.get_cname ()))));
149 var type_fun = new ClassRegisterFunction (cl, context);
150 type_fun.init_from_type (in_plugin);
151 decl_space.add_type_member_declaration (type_fun.get_declaration ());
155 public override void generate_class_struct_declaration (Class cl, CCodeDeclarationSpace decl_space) {
156 if (decl_space.add_symbol_declaration (cl, "struct _" + cl.get_cname ())) {
157 return;
160 if (cl.base_class != null) {
161 // base class declaration
162 generate_class_struct_declaration (cl.base_class, decl_space);
164 foreach (DataType base_type in cl.get_base_types ()) {
165 var iface = base_type.data_type as Interface;
166 if (iface != null) {
167 generate_interface_declaration (iface, decl_space);
171 generate_class_declaration (cl, decl_space);
173 bool is_gtypeinstance = !cl.is_compact;
174 bool is_fundamental = is_gtypeinstance && cl.base_class == null;
176 var instance_struct = new CCodeStruct ("_%s".printf (cl.get_cname ()));
177 var type_struct = new CCodeStruct ("_%sClass".printf (cl.get_cname ()));
179 if (cl.base_class != null) {
180 instance_struct.add_field (cl.base_class.get_cname (), "parent_instance");
181 } else if (is_fundamental) {
182 decl_space.add_include ("glib-object.h");
183 instance_struct.add_field ("GTypeInstance", "parent_instance");
184 instance_struct.add_field ("volatile int", "ref_count");
187 if (cl.is_compact && cl.base_class == null && cl.get_fields ().size == 0) {
188 // add dummy member, C doesn't allow empty structs
189 instance_struct.add_field ("int", "dummy");
192 if (is_gtypeinstance) {
193 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %sPrivate".printf (instance_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (cl.get_cname ()))));
195 instance_struct.add_field ("%sPrivate *".printf (cl.get_cname ()), "priv");
196 if (is_fundamental) {
197 type_struct.add_field ("GTypeClass", "parent_class");
198 } else {
199 type_struct.add_field ("%sClass".printf (cl.base_class.get_cname ()), "parent_class");
202 if (is_fundamental) {
203 type_struct.add_field ("void", "(*finalize) (%s *self)".printf (cl.get_cname ()));
207 foreach (Method m in cl.get_methods ()) {
208 generate_virtual_method_declaration (m, decl_space, type_struct);
211 foreach (Signal sig in cl.get_signals ()) {
212 if (sig.default_handler != null) {
213 generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
217 foreach (Property prop in cl.get_properties ()) {
218 if (!prop.is_abstract && !prop.is_virtual) {
219 continue;
221 generate_type_declaration (prop.property_type, decl_space);
223 var t = (ObjectTypeSymbol) prop.parent_symbol;
225 var this_type = new ObjectType (t);
226 var cselfparam = new CCodeFormalParameter ("self", this_type.get_cname ());
228 if (prop.get_accessor != null) {
229 var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name));
230 vdeclarator.add_parameter (cselfparam);
231 string creturn_type;
232 if (prop.property_type.is_real_non_null_struct_type ()) {
233 var cvalueparam = new CCodeFormalParameter ("result", prop.get_accessor.value_type.get_cname () + "*");
234 vdeclarator.add_parameter (cvalueparam);
235 creturn_type = "void";
236 } else {
237 creturn_type = prop.get_accessor.value_type.get_cname ();
240 var array_type = prop.property_type as ArrayType;
241 if (array_type != null) {
242 for (int dim = 1; dim <= array_type.rank; dim++) {
243 vdeclarator.add_parameter (new CCodeFormalParameter (head.get_array_length_cname ("result", dim), "int*"));
247 var vdecl = new CCodeDeclaration (creturn_type);
248 vdecl.add_declarator (vdeclarator);
249 type_struct.add_declaration (vdecl);
251 if (prop.set_accessor != null) {
252 CCodeFormalParameter cvalueparam;
253 if (prop.property_type.is_real_non_null_struct_type ()) {
254 cvalueparam = new CCodeFormalParameter ("value", prop.get_accessor.value_type.get_cname () + "*");
255 } else {
256 cvalueparam = new CCodeFormalParameter ("value", prop.get_accessor.value_type.get_cname ());
259 var vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name));
260 vdeclarator.add_parameter (cselfparam);
261 vdeclarator.add_parameter (cvalueparam);
263 var array_type = prop.property_type as ArrayType;
264 if (array_type != null) {
265 for (int dim = 1; dim <= array_type.rank; dim++) {
266 vdeclarator.add_parameter (new CCodeFormalParameter (head.get_array_length_cname ("value", dim), "int"));
270 var vdecl = new CCodeDeclaration ("void");
271 vdecl.add_declarator (vdeclarator);
272 type_struct.add_declaration (vdecl);
276 foreach (Field f in cl.get_fields ()) {
277 string field_ctype = f.field_type.get_cname ();
278 if (f.is_volatile) {
279 field_ctype = "volatile " + field_ctype;
282 if (f.access != SymbolAccessibility.PRIVATE) {
283 if (f.binding == MemberBinding.INSTANCE) {
284 generate_type_declaration (f.field_type, decl_space);
286 instance_struct.add_field (field_ctype, f.get_cname ());
287 if (f.field_type is ArrayType && !f.no_array_length) {
288 // create fields to store array dimensions
289 var array_type = (ArrayType) f.field_type;
290 var len_type = int_type.copy ();
292 for (int dim = 1; dim <= array_type.rank; dim++) {
293 instance_struct.add_field (len_type.get_cname (), head.get_array_length_cname (f.name, dim));
296 if (array_type.rank == 1 && f.is_internal_symbol ()) {
297 instance_struct.add_field (len_type.get_cname (), head.get_array_size_cname (f.name));
299 } else if (f.field_type is DelegateType) {
300 var delegate_type = (DelegateType) f.field_type;
301 if (delegate_type.delegate_symbol.has_target) {
302 // create field to store delegate target
303 instance_struct.add_field ("gpointer", get_delegate_target_cname (f.name));
304 if (delegate_type.value_owned) {
305 instance_struct.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (f.name));
309 } else if (f.binding == MemberBinding.CLASS) {
310 type_struct.add_field (field_ctype, f.get_cname ());
315 if (!cl.is_compact || cl.base_class == null) {
316 // derived compact classes do not have a struct
317 decl_space.add_type_definition (instance_struct);
320 if (is_gtypeinstance) {
321 decl_space.add_type_definition (type_struct);
325 public virtual void generate_virtual_method_declaration (Method m, CCodeDeclarationSpace decl_space, CCodeStruct type_struct) {
326 if (!m.is_abstract && !m.is_virtual) {
327 return;
330 var creturn_type = m.return_type;
331 if (m.return_type.is_real_non_null_struct_type ()) {
332 // structs are returned via out parameter
333 creturn_type = new VoidType ();
336 // add vfunc field to the type struct
337 var vdeclarator = new CCodeFunctionDeclarator (m.vfunc_name);
338 var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
340 generate_cparameters (m, decl_space, cparam_map, new CCodeFunction ("fake"), vdeclarator);
342 var vdecl = new CCodeDeclaration (creturn_type.get_cname ());
343 vdecl.add_declarator (vdeclarator);
344 type_struct.add_declaration (vdecl);
347 void generate_class_private_declaration (Class cl, CCodeDeclarationSpace decl_space) {
348 if (decl_space.add_symbol_declaration (cl, cl.get_cname () + "Private")) {
349 return;
352 bool is_gtypeinstance = !cl.is_compact;
353 bool has_instance_locks = false;
354 bool has_class_locks = false;
356 var instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (cl.get_cname ()));
357 var type_priv_struct = new CCodeStruct ("_%sClassPrivate".printf (cl.get_cname ()));
359 if (is_gtypeinstance) {
360 /* create type, dup_func, and destroy_func fields for generic types */
361 foreach (TypeParameter type_param in cl.get_type_parameters ()) {
362 string func_name;
364 func_name = "%s_type".printf (type_param.name.down ());
365 instance_priv_struct.add_field ("GType", func_name);
367 func_name = "%s_dup_func".printf (type_param.name.down ());
368 instance_priv_struct.add_field ("GBoxedCopyFunc", func_name);
370 func_name = "%s_destroy_func".printf (type_param.name.down ());
371 instance_priv_struct.add_field ("GDestroyNotify", func_name);
375 foreach (Field f in cl.get_fields ()) {
376 string field_ctype = f.field_type.get_cname ();
377 if (f.is_volatile) {
378 field_ctype = "volatile " + field_ctype;
381 if (f.binding == MemberBinding.INSTANCE) {
382 if (f.access == SymbolAccessibility.PRIVATE) {
383 generate_type_declaration (f.field_type, decl_space);
385 instance_priv_struct.add_field (field_ctype, f.get_cname ());
386 if (f.field_type is ArrayType && !f.no_array_length) {
387 // create fields to store array dimensions
388 var array_type = (ArrayType) f.field_type;
389 var len_type = int_type.copy ();
391 for (int dim = 1; dim <= array_type.rank; dim++) {
392 instance_priv_struct.add_field (len_type.get_cname (), head.get_array_length_cname (f.name, dim));
395 if (array_type.rank == 1 && f.is_internal_symbol ()) {
396 instance_priv_struct.add_field (len_type.get_cname (), head.get_array_size_cname (f.name));
398 } else if (f.field_type is DelegateType) {
399 var delegate_type = (DelegateType) f.field_type;
400 if (delegate_type.delegate_symbol.has_target) {
401 // create field to store delegate target
402 instance_priv_struct.add_field ("gpointer", get_delegate_target_cname (f.name));
403 if (delegate_type.value_owned) {
404 instance_priv_struct.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (f.name));
410 if (f.get_lock_used ()) {
411 has_instance_locks = true;
412 // add field for mutex
413 instance_priv_struct.add_field (mutex_type.get_cname (), get_symbol_lock_name (f.name));
415 } else if (f.binding == MemberBinding.CLASS) {
416 if (f.access == SymbolAccessibility.PRIVATE) {
417 type_priv_struct.add_field (field_ctype, f.get_cname ());
420 if (f.get_lock_used ()) {
421 has_class_locks = true;
422 // add field for mutex
423 type_priv_struct.add_field (mutex_type.get_cname (), get_symbol_lock_name (f.get_cname ()));
428 if (is_gtypeinstance) {
429 if (cl.has_class_private_fields || has_class_locks) {
430 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_priv_struct.name), new CCodeVariableDeclarator ("%sClassPrivate".printf (cl.get_cname ()))));
431 var cdecl = new CCodeDeclaration ("GQuark");
432 cdecl.add_declarator (new CCodeVariableDeclarator ("_vala_%s_class_private_quark".printf (cl.get_lower_case_cname ()), new CCodeConstant ("0")));
433 cdecl.modifiers = CCodeModifiers.STATIC;
434 decl_space.add_type_declaration (cdecl);
437 /* only add the *Private struct if it is not empty, i.e. we actually have private data */
438 if (cl.has_private_fields || cl.get_type_parameters ().size > 0 || has_instance_locks) {
439 decl_space.add_type_definition (instance_priv_struct);
440 var macro = "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl.get_type_id (), cl.get_cname ());
441 decl_space.add_type_member_declaration (new CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), macro));
444 if (cl.has_class_private_fields || has_class_locks) {
445 decl_space.add_type_member_declaration (type_priv_struct);
447 var macro = "((%sClassPrivate *) g_type_get_qdata (type, _vala_%s_class_private_quark))".printf (cl.get_cname(), cl.get_lower_case_cname ());
448 decl_space.add_type_member_declaration (new CCodeMacroReplacement ("%s_GET_CLASS_PRIVATE(type)".printf (cl.get_upper_case_cname (null)), macro));
450 decl_space.add_type_member_declaration (prop_enum);
451 } else {
452 if (cl.has_private_fields) {
453 Report.error (cl.source_reference, "Private fields not supported in compact classes");
456 if (cl.base_class == null) {
457 var function = new CCodeFunction (cl.get_lower_case_cprefix () + "free", "void");
458 if (cl.access == SymbolAccessibility.PRIVATE) {
459 function.modifiers = CCodeModifiers.STATIC;
462 function.add_parameter (new CCodeFormalParameter ("self", cl.get_cname () + "*"));
464 decl_space.add_type_member_declaration (function);
469 public override void visit_class (Class cl) {
470 var old_symbol = current_symbol;
471 var old_param_spec_struct = param_spec_struct;
472 var old_prop_enum = prop_enum;
473 var old_class_init_fragment = class_init_fragment;
474 var old_base_init_fragment = base_init_fragment;
475 var old_class_finalize_fragment = class_finalize_fragment;
476 var old_base_finalize_fragment = base_finalize_fragment;
477 var old_instance_init_fragment = instance_init_fragment;
478 var old_instance_finalize_fragment = instance_finalize_fragment;
479 current_symbol = cl;
481 bool is_gtypeinstance = !cl.is_compact;
482 bool is_fundamental = is_gtypeinstance && cl.base_class == null;
484 if (cl.get_cname().len () < 3) {
485 cl.error = true;
486 Report.error (cl.source_reference, "Class name `%s' is too short".printf (cl.get_cname ()));
487 return;
490 prop_enum = new CCodeEnum ();
491 prop_enum.add_value (new CCodeEnumValue ("%s_DUMMY_PROPERTY".printf (cl.get_upper_case_cname (null))));
492 class_init_fragment = new CCodeFragment ();
493 base_init_fragment = new CCodeFragment ();
494 class_finalize_fragment = new CCodeFragment ();
495 base_finalize_fragment = new CCodeFragment ();
496 instance_init_fragment = new CCodeFragment ();
497 instance_finalize_fragment = new CCodeFragment ();
500 generate_class_struct_declaration (cl, source_declarations);
501 generate_class_private_declaration (cl, source_declarations);
503 if (!cl.is_internal_symbol ()) {
504 generate_class_struct_declaration (cl, header_declarations);
506 if (!cl.is_private_symbol ()) {
507 generate_class_struct_declaration (cl, internal_header_declarations);
510 cl.accept_children (codegen);
512 if (is_gtypeinstance) {
513 if (is_fundamental) {
514 param_spec_struct = new CCodeStruct ( "_%sParamSpec%s".printf(cl.parent_symbol.get_cprefix (), cl.name));
515 param_spec_struct.add_field ("GParamSpec", "parent_instance");
516 source_declarations.add_type_definition (param_spec_struct);
518 source_declarations.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (param_spec_struct.name), new CCodeVariableDeclarator ( "%sParamSpec%s".printf(cl.parent_symbol.get_cprefix (), cl.name))));
521 gvaluecollector_h_needed = true;
523 add_type_value_table_init_function (cl);
524 add_type_value_table_free_function (cl);
525 add_type_value_table_copy_function (cl);
526 add_type_value_table_peek_pointer_function (cl);
527 add_type_value_table_collect_value_function (cl);
528 add_type_value_table_lcopy_value_function (cl);
529 add_g_param_spec_type_function (cl);
530 add_g_value_get_function (cl);
531 add_g_value_set_function (cl);
533 var ref_count = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count"), new CCodeConstant ("1"));
534 instance_init_fragment.append (new CCodeExpressionStatement (ref_count));
538 if (cl.class_constructor != null || cl.has_class_private_fields) {
539 add_base_init_function (cl);
541 add_class_init_function (cl);
543 if (cl.class_destructor != null || cl.has_class_private_fields) {
544 add_base_finalize_function (cl);
547 if (cl.static_destructor != null) {
548 add_class_finalize_function (cl);
551 foreach (DataType base_type in cl.get_base_types ()) {
552 if (base_type.data_type is Interface) {
553 add_interface_init_function (cl, (Interface) base_type.data_type);
557 add_instance_init_function (cl);
559 if (!cl.is_compact && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) {
560 add_finalize_function (cl);
563 var type_fun = new ClassRegisterFunction (cl, context);
564 type_fun.init_from_type (in_plugin);
565 source_declarations.add_type_member_declaration (type_fun.get_source_declaration ());
566 source_type_member_definition.append (type_fun.get_definition ());
568 if (in_plugin) {
569 // FIXME resolve potential dependency issues, i.e. base types have to be registered before derived types
570 var register_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_register_type".printf (cl.get_lower_case_cname (null))));
571 register_call.add_argument (new CCodeIdentifier (module_init_param_name));
572 module_init_fragment.append (new CCodeExpressionStatement (register_call));
575 if (is_fundamental) {
576 var ref_fun = new CCodeFunction (cl.get_lower_case_cprefix () + "ref", "gpointer");
577 var unref_fun = new CCodeFunction (cl.get_lower_case_cprefix () + "unref", "void");
578 if (cl.access == SymbolAccessibility.PRIVATE) {
579 ref_fun.modifiers = CCodeModifiers.STATIC;
580 unref_fun.modifiers = CCodeModifiers.STATIC;
583 ref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer"));
584 unref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer"));
586 var ref_block = new CCodeBlock ();
587 var unref_block = new CCodeBlock ();
589 var cdecl = new CCodeDeclaration (cl.get_cname () + "*");
590 cdecl.add_declarator (new CCodeVariableDeclarator ("self", new CCodeIdentifier ("instance")));
591 ref_block.add_statement (cdecl);
592 unref_block.add_statement (cdecl);
594 var ref_count = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count");
596 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_inc"));
597 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ref_count));
598 ref_block.add_statement (new CCodeExpressionStatement (ccall));
600 ref_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("instance")));
602 var destroy_block = new CCodeBlock ();
603 var get_class = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS".printf (cl.get_upper_case_cname (null))));
604 get_class.add_argument (new CCodeIdentifier ("self"));
606 // finalize class
607 var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS".printf (cl.get_upper_case_cname (null))));
608 ccast.add_argument (new CCodeIdentifier ("self"));
609 ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize"));
610 ccall.add_argument (new CCodeIdentifier ("self"));
611 destroy_block.add_statement (new CCodeExpressionStatement (ccall));
613 // free type instance
614 var free = new CCodeFunctionCall (new CCodeIdentifier ("g_type_free_instance"));
615 free.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GTypeInstance *"));
616 destroy_block.add_statement (new CCodeExpressionStatement (free));
618 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_dec_and_test"));
619 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ref_count));
620 unref_block.add_statement (new CCodeIfStatement (ccall, destroy_block));
622 ref_fun.block = ref_block;
623 unref_fun.block = unref_block;
625 source_type_member_definition.append (ref_fun);
626 source_type_member_definition.append (unref_fun);
628 } else {
629 if (cl.base_class == null) {
630 // derived compact classes do not have fields
631 add_instance_init_function (cl);
633 var function = new CCodeFunction (cl.get_lower_case_cprefix () + "free", "void");
634 if (cl.access == SymbolAccessibility.PRIVATE) {
635 function.modifiers = CCodeModifiers.STATIC;
638 function.add_parameter (new CCodeFormalParameter ("self", cl.get_cname () + "*"));
640 var cblock = new CCodeBlock ();
642 cblock.add_statement (instance_finalize_fragment);
644 if (cl.destructor != null) {
645 cblock.add_statement (cl.destructor.ccodenode);
648 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
649 ccall.add_argument (new CCodeIdentifier (cl.get_cname ()));
650 ccall.add_argument (new CCodeIdentifier ("self"));
651 cblock.add_statement (new CCodeExpressionStatement (ccall));
653 function.block = cblock;
655 source_type_member_definition.append (function);
659 current_symbol = old_symbol;
660 param_spec_struct = old_param_spec_struct;
661 prop_enum = old_prop_enum;
662 class_init_fragment = old_class_init_fragment;
663 base_init_fragment = old_base_init_fragment;
664 class_finalize_fragment = old_class_finalize_fragment;
665 base_finalize_fragment = old_base_finalize_fragment;
666 instance_init_fragment = old_instance_init_fragment;
667 instance_finalize_fragment = old_instance_finalize_fragment;
670 private void add_type_value_table_init_function (Class cl) {
671 var function = new CCodeFunction ("%s_init".printf (cl.get_lower_case_cname ("value_")), "void");
672 function.add_parameter (new CCodeFormalParameter ("value", "GValue*"));
673 function.modifiers = CCodeModifiers.STATIC;
675 var init_block = new CCodeBlock ();
676 function.block = init_block;
678 init_block.add_statement(new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"),new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE)));
679 source_type_member_definition.append (function);
682 private void add_type_value_table_free_function (Class cl) {
683 var function = new CCodeFunction ("%s_free_value".printf (cl.get_lower_case_cname ("value_")), "void");
684 function.add_parameter (new CCodeFormalParameter ("value", "GValue*"));
685 function.modifiers = CCodeModifiers.STATIC;
687 var init_block = new CCodeBlock ();
688 function.block = init_block;
690 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
691 var ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_lower_case_cprefix () + "unref"));
692 ccall.add_argument ( vpointer );
694 var ifbody = new CCodeBlock ();
695 ifbody.add_statement ( new CCodeExpressionStatement(ccall) );
697 init_block.add_statement(new CCodeIfStatement (vpointer, ifbody));
698 source_type_member_definition.append (function);
701 private void add_type_value_table_copy_function (Class cl) {
702 var function = new CCodeFunction ("%s_copy_value".printf (cl.get_lower_case_cname ("value_")), "void");
703 function.add_parameter (new CCodeFormalParameter ("src_value", "const GValue*"));
704 function.add_parameter (new CCodeFormalParameter ("dest_value", "GValue*"));
705 function.modifiers = CCodeModifiers.STATIC;
707 var init_block = new CCodeBlock ();
708 function.block = init_block;
710 var dest_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dest_value"), "data[0]"),"v_pointer");
711 var src_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("src_value"), "data[0]"),"v_pointer");
713 var ref_ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_lower_case_cprefix () + "ref"));
714 ref_ccall.add_argument ( src_vpointer );
716 var true_stmt = new CCodeBlock ();
717 true_stmt.add_statement(new CCodeExpressionStatement(new CCodeAssignment (dest_vpointer, ref_ccall, CCodeAssignmentOperator.SIMPLE)));
719 var false_stmt = new CCodeBlock ();
720 false_stmt.add_statement (new CCodeExpressionStatement( new CCodeAssignment (dest_vpointer, new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE)));
722 var if_statement = new CCodeIfStatement (src_vpointer, true_stmt, false_stmt);
723 init_block.add_statement (if_statement);
725 source_type_member_definition.append (function);
728 private void add_type_value_table_peek_pointer_function (Class cl) {
729 var function = new CCodeFunction ("%s_peek_pointer".printf (cl.get_lower_case_cname ("value_")), "gpointer");
730 function.add_parameter (new CCodeFormalParameter ("value", "const GValue*"));
731 function.modifiers = CCodeModifiers.STATIC;
733 var init_block = new CCodeBlock ();
734 function.block = init_block;
736 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
737 var ret = new CCodeReturnStatement ( vpointer );
738 init_block.add_statement (ret);
740 source_type_member_definition.append (function);
743 private void add_type_value_table_lcopy_value_function ( Class cl ) {
744 var function = new CCodeFunction ("%s_lcopy_value".printf (cl.get_lower_case_cname ("value_")), "gchar*");
745 function.add_parameter (new CCodeFormalParameter ("value", "const GValue*"));
746 function.add_parameter (new CCodeFormalParameter ("n_collect_values", "guint"));
747 function.add_parameter (new CCodeFormalParameter ("collect_values", "GTypeCValue*"));
748 function.add_parameter (new CCodeFormalParameter ("collect_flags", "guint"));
749 function.modifiers = CCodeModifiers.STATIC;
751 var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
752 var object_p_ptr = new CCodeIdentifier ("*object_p");
753 var null_ = new CCodeConstant ("NULL");
755 var init_block = new CCodeBlock ();
757 var ctypedecl = new CCodeDeclaration (cl.get_cname () + "**");
758 ctypedecl.add_declarator (new CCodeVariableDeclarator ("object_p", new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"),"v_pointer")));
759 init_block.add_statement (ctypedecl);
761 var value_type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME"));
762 value_type_name_fct.add_argument (new CCodeConstant ("value"));
764 var assert_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("object_p"));
765 function.block = init_block;
766 var assert_true = new CCodeBlock ();
767 var assert_printf = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup_printf"));
768 assert_printf.add_argument (new CCodeConstant ("\"value location for `%s' passed as NULL\""));
769 assert_printf.add_argument (value_type_name_fct);
770 assert_true.add_statement (new CCodeReturnStatement (assert_printf));
771 var if_assert = new CCodeIfStatement (assert_condition, assert_true);
772 init_block.add_statement (if_assert);
774 var main_else_true = new CCodeBlock ();
775 var main_else_if_true = new CCodeBlock ();
776 var main_else_if_condition = new CCodeBinaryExpression (CCodeBinaryOperator.AND, new CCodeIdentifier ("collect_flags"), new CCodeIdentifier ("G_VALUE_NOCOPY_CONTENTS"));
777 var main_else_if = new CCodeIfStatement (main_else_if_condition, main_else_if_true, main_else_true);
779 var main_true = new CCodeBlock ();
780 var main_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, vpointer);
781 var if_main = new CCodeIfStatement (main_condition, main_true, main_else_if);
782 init_block.add_statement (if_main);
784 var ref_fct = new CCodeFunctionCall (new CCodeIdentifier (cl.get_ref_function()));
785 ref_fct.add_argument (vpointer);
787 main_true.add_statement (new CCodeExpressionStatement (new CCodeAssignment (object_p_ptr, null_, CCodeAssignmentOperator.SIMPLE)));
788 main_else_if_true.add_statement (new CCodeExpressionStatement (new CCodeAssignment (object_p_ptr, vpointer, CCodeAssignmentOperator.SIMPLE)));
789 main_else_true.add_statement (new CCodeExpressionStatement (new CCodeAssignment (object_p_ptr, ref_fct, CCodeAssignmentOperator.SIMPLE)));
791 init_block.add_statement (new CCodeReturnStatement (null_));
792 source_type_member_definition.append (function);
795 private void add_type_value_table_collect_value_function (Class cl) {
796 var function = new CCodeFunction ("%s_collect_value".printf (cl.get_lower_case_cname ("value_")), "gchar*");
797 function.add_parameter (new CCodeFormalParameter ("value", "GValue*"));
798 function.add_parameter (new CCodeFormalParameter ("n_collect_values", "guint"));
799 function.add_parameter (new CCodeFormalParameter ("collect_values", "GTypeCValue*"));
800 function.add_parameter (new CCodeFormalParameter ("collect_flags", "guint"));
801 function.modifiers = CCodeModifiers.STATIC;
803 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
805 var init_block = new CCodeBlock ();
806 function.block = init_block;
808 var collect_vpointer = new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"), "v_pointer");
810 var true_stmt = new CCodeBlock ();
811 var false_stmt = new CCodeBlock ();
812 var if_statement = new CCodeIfStatement (collect_vpointer, true_stmt, false_stmt);
813 init_block.add_statement (if_statement);
815 var obj_identifier = new CCodeIdentifier ("object");
817 var ctypedecl = new CCodeDeclaration (cl.get_cname () + "*");
818 ctypedecl.add_declarator (new CCodeVariableDeclarator ("object", collect_vpointer));
819 true_stmt.add_statement (ctypedecl);
821 var l_expression = new CCodeMemberAccess (new CCodeMemberAccess.pointer (obj_identifier, "parent_instance"), "g_class");
822 var sub_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, l_expression, new CCodeConstant ("NULL"));
823 var sub_true_stmt = new CCodeBlock ();
824 var sub_false_stmt = new CCodeBlock ();
826 var reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
827 var type_check = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
828 type_check.add_argument (new CCodeIdentifier ("object"));
829 reg_call.add_argument (type_check);
831 var type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("g_type_name"));
832 type_name_fct.add_argument (type_check);
834 var stored_type = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
835 stored_type.add_argument (new CCodeIdentifier ("value"));
836 reg_call.add_argument (stored_type);
838 var value_type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME"));
839 value_type_name_fct.add_argument (new CCodeConstant ("value"));
841 var true_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat"));
842 true_return.add_argument (new CCodeConstant ("\"invalid unclassed object pointer for value type `\""));
843 true_return.add_argument (value_type_name_fct);
844 true_return.add_argument (new CCodeConstant ("\"'\""));
845 true_return.add_argument (new CCodeConstant ("NULL"));
846 sub_true_stmt.add_statement (new CCodeReturnStatement (true_return));
848 var false_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat"));
849 false_return.add_argument (new CCodeConstant ("\"invalid object type `\""));
850 false_return.add_argument (type_name_fct);
851 false_return.add_argument (new CCodeConstant ("\"' for value type `\""));
852 false_return.add_argument (value_type_name_fct);
853 false_return.add_argument (new CCodeConstant ("\"'\""));
854 false_return.add_argument (new CCodeConstant ("NULL"));
855 sub_false_stmt.add_statement (new CCodeReturnStatement (false_return));
857 var sub_else_if_statement = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, reg_call), sub_false_stmt );
858 sub_else_if_statement.else_if = true;
859 var sub_if_statement = new CCodeIfStatement (sub_condition, sub_true_stmt, sub_else_if_statement);
860 true_stmt.add_statement (sub_if_statement);
862 var ref_call = new CCodeFunctionCall (new CCodeIdentifier (cl.get_ref_function ()));
863 ref_call.add_argument (new CCodeIdentifier ("object"));
865 var true_assignment = new CCodeExpressionStatement (new CCodeAssignment (vpointer, ref_call, CCodeAssignmentOperator.SIMPLE));
866 true_stmt.add_statement (true_assignment);
868 var else_assigment = new CCodeExpressionStatement (new CCodeAssignment (vpointer, new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE));
869 false_stmt.add_statement (else_assigment);
871 init_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL")));
872 source_type_member_definition.append (function);
875 private void add_g_param_spec_type_function (Class cl) {
876 string function_name = cl.get_lower_case_cname ("param_spec_");
878 var function = new CCodeFunction (function_name, "GParamSpec*");
879 function.add_parameter (new CCodeFormalParameter ("name", "const gchar*"));
880 function.add_parameter (new CCodeFormalParameter ("nick", "const gchar*"));
881 function.add_parameter (new CCodeFormalParameter ("blurb", "const gchar*"));
882 function.add_parameter (new CCodeFormalParameter ("object_type", "GType"));
883 function.add_parameter (new CCodeFormalParameter ("flags", "GParamFlags"));
885 if (cl.access == SymbolAccessibility.PRIVATE) {
886 function.modifiers = CCodeModifiers.STATIC;
889 var init_block = new CCodeBlock ();
890 function.block = init_block;
892 var ctypedecl = new CCodeDeclaration ("%sParamSpec%s*".printf (cl.parent_symbol.get_cprefix (), cl.name));
893 ctypedecl.add_declarator ( new CCodeVariableDeclarator ("spec"));
894 init_block.add_statement (ctypedecl);
896 var subccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_is_a"));
897 subccall.add_argument (new CCodeIdentifier ("object_type"));
898 subccall.add_argument (new CCodeIdentifier ( cl.get_type_id() ));
900 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail"));
901 ccall.add_argument (subccall);
902 ccall.add_argument (new CCodeIdentifier ("NULL"));
903 init_block.add_statement (new CCodeExpressionStatement (ccall));
905 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_internal"));
906 ccall.add_argument (new CCodeIdentifier ( "G_TYPE_PARAM_OBJECT" ));
907 ccall.add_argument (new CCodeIdentifier ("name"));
908 ccall.add_argument (new CCodeIdentifier ("nick"));
909 ccall.add_argument (new CCodeIdentifier ("blurb"));
910 ccall.add_argument (new CCodeIdentifier ("flags"));
912 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("spec"), ccall, CCodeAssignmentOperator.SIMPLE )));
914 ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_PARAM_SPEC"));
915 ccall.add_argument (new CCodeIdentifier ("spec"));
917 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "value_type"), new CCodeIdentifier ("object_type"), CCodeAssignmentOperator.SIMPLE )));
918 init_block.add_statement (new CCodeReturnStatement (ccall));
919 source_type_member_definition.append (function);
922 private void add_g_value_set_function (Class cl) {
923 var function = new CCodeFunction (cl.get_set_value_function (), "void");
924 function.add_parameter (new CCodeFormalParameter ("value", "GValue*"));
925 function.add_parameter (new CCodeFormalParameter ("v_object", "gpointer"));
927 if (cl.access == SymbolAccessibility.PRIVATE) {
928 function.modifiers = CCodeModifiers.STATIC;
931 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
933 var init_block = new CCodeBlock ();
934 function.block = init_block;
936 var ctypedecl = new CCodeDeclaration (cl.get_cname()+"*");
937 ctypedecl.add_declarator ( new CCodeVariableDeclarator ("old"));
938 init_block.add_statement (ctypedecl);
940 var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
941 ccall_typecheck.add_argument (new CCodeIdentifier ( "value" ));
942 ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() ));
944 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
945 ccall.add_argument (ccall_typecheck);
946 init_block.add_statement (new CCodeExpressionStatement (ccall));
948 init_block.add_statement(new CCodeExpressionStatement (new CCodeAssignment (new CCodeConstant ("old"), vpointer, CCodeAssignmentOperator.SIMPLE)));
950 var true_stmt = new CCodeBlock ();
951 var false_stmt = new CCodeBlock ();
952 var if_statement = new CCodeIfStatement (new CCodeIdentifier ("v_object"), true_stmt, false_stmt);
953 init_block.add_statement (if_statement);
956 ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
957 ccall_typecheck.add_argument (new CCodeIdentifier ( "v_object" ));
958 ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() ));
960 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
961 ccall.add_argument (ccall_typecheck);
962 true_stmt.add_statement (new CCodeExpressionStatement (ccall));
964 var ccall_typefrominstance = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
965 ccall_typefrominstance.add_argument (new CCodeIdentifier ( "v_object" ));
967 var ccall_gvaluetype = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
968 ccall_gvaluetype.add_argument (new CCodeIdentifier ( "value" ));
970 var ccall_typecompatible = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
971 ccall_typecompatible.add_argument (ccall_typefrominstance);
972 ccall_typecompatible.add_argument (ccall_gvaluetype);
974 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
975 ccall.add_argument (ccall_typecompatible);
976 true_stmt.add_statement (new CCodeExpressionStatement (ccall));
978 true_stmt.add_statement(new CCodeExpressionStatement (new CCodeAssignment (vpointer, new CCodeConstant ("v_object"), CCodeAssignmentOperator.SIMPLE)));
980 ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_ref_function ()));
981 ccall.add_argument (vpointer);
982 true_stmt.add_statement (new CCodeExpressionStatement (ccall));
984 false_stmt.add_statement(new CCodeExpressionStatement (new CCodeAssignment (vpointer, new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE)));
986 true_stmt = new CCodeBlock ();
987 if_statement = new CCodeIfStatement (new CCodeIdentifier ("old"), true_stmt);
988 init_block.add_statement (if_statement);
990 ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_unref_function ()));
991 ccall.add_argument (new CCodeIdentifier ("old"));
992 true_stmt.add_statement (new CCodeExpressionStatement (ccall));
993 source_type_member_definition.append (function);
996 private void add_g_value_get_function (Class cl) {
997 var function = new CCodeFunction (cl.get_get_value_function (), "gpointer");
998 function.add_parameter (new CCodeFormalParameter ("value", "const GValue*"));
1000 if (cl.access == SymbolAccessibility.PRIVATE) {
1001 function.modifiers = CCodeModifiers.STATIC;
1004 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
1006 var init_block = new CCodeBlock ();
1007 function.block = init_block;
1009 var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1010 ccall_typecheck.add_argument (new CCodeIdentifier ( "value" ));
1011 ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() ));
1013 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail"));
1014 ccall.add_argument (ccall_typecheck);
1015 ccall.add_argument (new CCodeIdentifier ( "NULL" ));
1016 init_block.add_statement (new CCodeExpressionStatement (ccall));
1018 init_block.add_statement (new CCodeReturnStatement ( vpointer ));
1019 source_type_member_definition.append (function);
1022 private void add_base_init_function (Class cl) {
1023 var base_init = new CCodeFunction ("%s_base_init".printf (cl.get_lower_case_cname (null)), "void");
1024 base_init.add_parameter (new CCodeFormalParameter ("klass", "%sClass *".printf (cl.get_cname ())));
1025 base_init.modifiers = CCodeModifiers.STATIC;
1027 var init_block = new CCodeBlock ();
1028 base_init.block = init_block;
1030 if (cl.has_class_private_fields) {
1031 var block = new CCodeBlock ();
1032 var cdecl = new CCodeDeclaration ("%sClassPrivate *".printf (cl.get_cname ()));
1033 cdecl.add_declarator (new CCodeVariableDeclarator ("priv"));
1034 block.add_statement (cdecl);
1035 cdecl = new CCodeDeclaration ("%sClassPrivate *".printf (cl.get_cname ()));
1036 cdecl.add_declarator (new CCodeVariableDeclarator ("parent_priv", new CCodeConstant ("NULL")));
1037 block.add_statement (cdecl);
1038 cdecl = new CCodeDeclaration ("GType");
1039 cdecl.add_declarator (new CCodeVariableDeclarator ("parent_type"));
1040 block.add_statement (cdecl);
1042 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_parent"));
1043 var ccall2 = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_CLASS"));
1044 ccall2.add_argument (new CCodeIdentifier ("klass"));
1045 ccall.add_argument (ccall2);
1046 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_type"), ccall)));
1048 var iftrue = new CCodeBlock ();
1049 ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl.get_upper_case_cname (null))));
1050 ccall.add_argument (new CCodeIdentifier ("parent_type"));
1051 iftrue.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_priv"), ccall)));
1052 block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("parent_type"), iftrue));
1054 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0"));
1055 ccall.add_argument (new CCodeIdentifier ("%sClassPrivate".printf(cl.get_cname())));
1057 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("priv"), ccall)));
1059 source_declarations.add_include ("string.h");
1061 iftrue = new CCodeBlock ();
1062 ccall = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
1063 ccall.add_argument (new CCodeIdentifier ("priv"));
1064 ccall.add_argument (new CCodeIdentifier ("parent_priv"));
1065 ccall.add_argument (new CCodeIdentifier ("sizeof (%sClassPrivate)".printf(cl.get_cname())));
1066 iftrue.add_statement (new CCodeExpressionStatement (ccall));
1068 block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("parent_priv"), iftrue));
1070 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
1071 ccall2 = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_CLASS"));
1072 ccall2.add_argument (new CCodeIdentifier ("klass"));
1073 ccall.add_argument (ccall2);
1074 ccall.add_argument (new CCodeIdentifier ("_vala_%s_class_private_quark".printf (cl.get_lower_case_cname ())));
1075 ccall.add_argument (new CCodeIdentifier ("priv"));
1076 block.add_statement (new CCodeExpressionStatement (ccall));
1078 init_block.add_statement (block);
1080 block = new CCodeBlock ();
1081 cdecl = new CCodeDeclaration ("%sClassPrivate *".printf (cl.get_cname ()));
1082 cdecl.add_declarator (new CCodeVariableDeclarator ("priv"));
1083 block.add_statement (cdecl);
1085 ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl.get_upper_case_cname (null))));
1086 ccall2 = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_CLASS"));
1087 ccall2.add_argument (new CCodeIdentifier ("klass"));
1088 ccall.add_argument (ccall2);
1089 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("priv"), ccall)));
1091 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
1092 ccall.add_argument (new CCodeIdentifier ("%sClassPrivate".printf (cl.get_cname ())));
1093 ccall.add_argument (new CCodeIdentifier ("priv"));
1094 block.add_statement (new CCodeExpressionStatement (ccall));
1095 base_finalize_fragment.append (block);
1098 init_block.add_statement (base_init_fragment);
1100 source_type_member_definition.append (base_init);
1103 public virtual void generate_class_init (Class cl, CCodeBlock init_block) {
1106 private void add_class_init_function (Class cl) {
1107 var class_init = new CCodeFunction ("%s_class_init".printf (cl.get_lower_case_cname (null)), "void");
1108 class_init.add_parameter (new CCodeFormalParameter ("klass", "%sClass *".printf (cl.get_cname ())));
1109 class_init.modifiers = CCodeModifiers.STATIC;
1111 var init_block = new CCodeBlock ();
1112 class_init.block = init_block;
1114 CCodeFunctionCall ccall;
1116 /* save pointer to parent class */
1117 var parent_decl = new CCodeDeclaration ("gpointer");
1118 var parent_var_decl = new CCodeVariableDeclarator ("%s_parent_class".printf (cl.get_lower_case_cname (null)));
1119 parent_var_decl.initializer = new CCodeConstant ("NULL");
1120 parent_decl.add_declarator (parent_var_decl);
1121 parent_decl.modifiers = CCodeModifiers.STATIC;
1122 source_declarations.add_type_member_declaration (parent_decl);
1123 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek_parent"));
1124 ccall.add_argument (new CCodeIdentifier ("klass"));
1125 var parent_assignment = new CCodeAssignment (new CCodeIdentifier ("%s_parent_class".printf (cl.get_lower_case_cname (null))), ccall);
1126 init_block.add_statement (new CCodeExpressionStatement (parent_assignment));
1129 if (!cl.is_compact && !cl.is_subtype_of (gobject_type) && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) {
1130 // set finalize function
1131 var fundamental_class = cl;
1132 while (fundamental_class.base_class != null) {
1133 fundamental_class = fundamental_class.base_class;
1136 ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (fundamental_class.get_upper_case_cname (null))));
1137 ccall.add_argument (new CCodeIdentifier ("klass"));
1138 var finalize_assignment = new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "finalize"), new CCodeIdentifier (cl.get_lower_case_cprefix () + "finalize"));
1139 init_block.add_statement (new CCodeExpressionStatement (finalize_assignment));
1142 /* add struct for private fields */
1143 if (cl.has_private_fields || cl.get_type_parameters ().size > 0) {
1144 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_add_private"));
1145 ccall.add_argument (new CCodeIdentifier ("klass"));
1146 ccall.add_argument (new CCodeConstant ("sizeof (%sPrivate)".printf (cl.get_cname ())));
1147 init_block.add_statement (new CCodeExpressionStatement (ccall));
1150 /* connect overridden methods */
1151 foreach (Method m in cl.get_methods ()) {
1152 if (m.base_method == null) {
1153 continue;
1155 var base_type = m.base_method.parent_symbol;
1157 // there is currently no default handler for abstract async methods
1158 if (m.overrides || !m.coroutine) {
1159 var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (((Class) base_type).get_upper_case_cname (null))));
1160 ccast.add_argument (new CCodeIdentifier ("klass"));
1161 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, m.base_method.vfunc_name), new CCodeIdentifier (m.get_real_cname ()))));
1163 if (m.coroutine) {
1164 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, m.base_method.get_finish_vfunc_name ()), new CCodeIdentifier (m.get_finish_real_cname ()))));
1169 /* connect default signal handlers */
1170 foreach (Signal sig in cl.get_signals ()) {
1171 if (sig.default_handler == null) {
1172 continue;
1174 var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (cl.get_upper_case_cname (null))));
1175 ccast.add_argument (new CCodeIdentifier ("klass"));
1176 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, sig.default_handler.vfunc_name), new CCodeIdentifier (sig.default_handler.get_real_cname ()))));
1179 /* connect overridden properties */
1180 foreach (Property prop in cl.get_properties ()) {
1181 if (prop.base_property == null) {
1182 continue;
1184 var base_type = prop.base_property.parent_symbol;
1186 var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (((Class) base_type).get_upper_case_cname (null))));
1187 ccast.add_argument (new CCodeIdentifier ("klass"));
1189 if (prop.get_accessor != null) {
1190 string cname = "%s_real_get_%s".printf (cl.get_lower_case_cname (null), prop.name);
1191 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "get_%s".printf (prop.name)), new CCodeIdentifier (cname))));
1193 if (prop.set_accessor != null) {
1194 string cname = "%s_real_set_%s".printf (cl.get_lower_case_cname (null), prop.name);
1195 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "set_%s".printf (prop.name)), new CCodeIdentifier (cname))));
1199 /* initialize class fields */
1200 var fields = cl.get_fields ();
1201 foreach (Field field in fields) {
1202 if (field.binding != MemberBinding.CLASS || field.initializer == null) {
1203 continue;
1206 CCodeExpression left;
1208 if (field.access == SymbolAccessibility.PRIVATE) {
1209 ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl.get_upper_case_cname ())));
1210 var ccall2 = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_CLASS"));
1211 ccall2.add_argument (new CCodeIdentifier ("klass"));
1212 ccall.add_argument (ccall2);
1213 left = new CCodeMemberAccess (ccall, field.get_cname (), true);
1214 } else {
1215 left = new CCodeMemberAccess (new CCodeIdentifier ("klass"), field.get_cname (), true);
1217 CCodeExpression right = (CCodeExpression) field.initializer.ccodenode;
1218 CCodeAssignment assign = new CCodeAssignment (left, right);
1219 init_block.add_statement (new CCodeExpressionStatement (assign));
1222 generate_class_init (cl, init_block);
1224 if (!cl.is_compact) {
1225 /* create signals */
1226 foreach (Signal sig in cl.get_signals ()) {
1227 init_block.add_statement (new CCodeExpressionStatement (head.get_signal_creation (sig, cl)));
1231 init_block.add_statement (head.register_dbus_info (cl));
1232 init_block.add_statement (class_init_fragment);
1234 source_type_member_definition.append (class_init);
1237 private void add_interface_init_function (Class cl, Interface iface) {
1238 var iface_init = new CCodeFunction ("%s_%s_interface_init".printf (cl.get_lower_case_cname (null), iface.get_lower_case_cname (null)), "void");
1239 iface_init.add_parameter (new CCodeFormalParameter ("iface", "%s *".printf (iface.get_type_cname ())));
1240 iface_init.modifiers = CCodeModifiers.STATIC;
1242 var init_block = new CCodeBlock ();
1243 iface_init.block = init_block;
1245 CCodeFunctionCall ccall;
1247 /* save pointer to parent vtable */
1248 string parent_iface_var = "%s_%s_parent_iface".printf (cl.get_lower_case_cname (null), iface.get_lower_case_cname (null));
1249 var parent_decl = new CCodeDeclaration (iface.get_type_cname () + "*");
1250 var parent_var_decl = new CCodeVariableDeclarator (parent_iface_var);
1251 parent_var_decl.initializer = new CCodeConstant ("NULL");
1252 parent_decl.add_declarator (parent_var_decl);
1253 parent_decl.modifiers = CCodeModifiers.STATIC;
1254 source_declarations.add_type_member_declaration (parent_decl);
1255 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_interface_peek_parent"));
1256 ccall.add_argument (new CCodeIdentifier ("iface"));
1257 var parent_assignment = new CCodeAssignment (new CCodeIdentifier (parent_iface_var), ccall);
1258 init_block.add_statement (new CCodeExpressionStatement (parent_assignment));
1260 foreach (Method m in cl.get_methods ()) {
1261 if (m.base_interface_method == null) {
1262 continue;
1265 var base_type = m.base_interface_method.parent_symbol;
1266 if (base_type != iface) {
1267 continue;
1270 var ciface = new CCodeIdentifier ("iface");
1271 CCodeExpression cfunc;
1272 if (m.is_abstract || m.is_virtual) {
1273 cfunc = new CCodeIdentifier (m.get_cname ());
1274 // Cast the function pointer to match the interface
1275 string cast = m.return_type.get_cname () + " (*)";
1276 string cast_args = iface.get_cname () + "*";
1278 var vdeclarator = new CCodeFunctionDeclarator (m.vfunc_name);
1279 var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
1281 generate_cparameters (m, source_declarations, cparam_map, new CCodeFunction ("fake"), vdeclarator);
1283 // append C arguments in the right order
1284 int last_pos = -1;
1285 int min_pos;
1286 while (true) {
1287 min_pos = -1;
1288 foreach (int pos in cparam_map.get_keys ()) {
1289 if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
1290 min_pos = pos;
1293 if (last_pos != -1) { // Skip the 1st parameter
1294 if (min_pos == -1) {
1295 break;
1297 cast_args += " ," + cparam_map.get (min_pos).type_name;
1299 last_pos = min_pos;
1301 cast += "(" + cast_args + ")";
1302 cfunc = new CCodeCastExpression (cfunc, cast);
1303 } else {
1304 cfunc = new CCodeIdentifier (m.get_real_cname ());
1306 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, m.base_interface_method.vfunc_name), cfunc)));
1308 if (m.coroutine) {
1309 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, m.base_interface_method.get_finish_vfunc_name ()), new CCodeIdentifier (m.get_finish_real_cname ()))));
1313 // connect inherited implementations
1314 foreach (Method m in iface.get_methods ()) {
1315 if (m.is_abstract) {
1316 Method cl_method = null;
1317 var base_class = cl;
1318 while (base_class != null && cl_method == null) {
1319 cl_method = base_class.scope.lookup (m.name) as Method;
1320 base_class = base_class.base_class;
1322 if (base_class != null && cl_method.parent_symbol != cl) {
1323 // method inherited from base class
1325 var base_method = cl_method;
1326 if (cl_method.base_method != null) {
1327 base_method = cl_method.base_method;
1328 } else if (cl_method.base_interface_method != null) {
1329 base_method = cl_method.base_interface_method;
1332 generate_method_declaration (base_method, source_declarations);
1334 var ciface = new CCodeIdentifier ("iface");
1335 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, m.vfunc_name), new CCodeIdentifier (base_method.get_cname ()))));
1340 foreach (Property prop in cl.get_properties ()) {
1341 if (prop.base_interface_property == null) {
1342 continue;
1345 var base_type = (ObjectTypeSymbol) prop.base_interface_property.parent_symbol;
1346 if (base_type != iface) {
1347 continue;
1350 var ciface = new CCodeIdentifier ("iface");
1352 if (prop.get_accessor != null) {
1353 string cname = "%s_real_get_%s".printf (cl.get_lower_case_cname (null), prop.name);
1354 if (prop.is_abstract || prop.is_virtual) {
1355 cname = "%s_get_%s".printf (cl.get_lower_case_cname (null), prop.name);
1358 CCodeExpression cfunc = new CCodeIdentifier (cname);
1359 if (prop.is_abstract || prop.is_virtual) {
1360 cfunc = cast_property_accessor_pointer (prop.get_accessor, cfunc, base_type);
1362 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), cfunc)));
1364 if (prop.set_accessor != null) {
1365 string cname = "%s_real_set_%s".printf (cl.get_lower_case_cname (null), prop.name);
1366 if (prop.is_abstract || prop.is_virtual) {
1367 cname = "%s_set_%s".printf (cl.get_lower_case_cname (null), prop.name);
1370 CCodeExpression cfunc = new CCodeIdentifier (cname);
1371 if (prop.is_abstract || prop.is_virtual) {
1372 cfunc = cast_property_accessor_pointer (prop.set_accessor, cfunc, base_type);
1374 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), cfunc)));
1378 foreach (Property prop in iface.get_properties ()) {
1379 if (!prop.is_abstract) {
1380 continue;
1383 Property cl_prop = null;
1384 var base_class = cl;
1385 while (base_class != null && cl_prop == null) {
1386 cl_prop = base_class.scope.lookup (prop.name) as Property;
1387 base_class = base_class.base_class;
1389 if (base_class != null && cl_prop.parent_symbol != cl) {
1390 // property inherited from base class
1392 var base_property = cl_prop;
1393 if (cl_prop.base_property != null) {
1394 base_property = cl_prop.base_property;
1395 } else if (cl_prop.base_interface_property != null) {
1396 base_property = cl_prop.base_interface_property;
1399 var ciface = new CCodeIdentifier ("iface");
1401 if (base_property.get_accessor != null) {
1402 generate_property_accessor_declaration (base_property.get_accessor, source_declarations);
1404 string cname = base_property.get_accessor.get_cname ();
1405 CCodeExpression cfunc = new CCodeIdentifier (cname);
1406 cfunc = cast_property_accessor_pointer (prop.get_accessor, cfunc, iface);
1407 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), cfunc)));
1409 if (base_property.set_accessor != null) {
1410 generate_property_accessor_declaration (base_property.set_accessor, source_declarations);
1412 string cname = base_property.set_accessor.get_cname ();
1413 CCodeExpression cfunc = new CCodeIdentifier (cname);
1414 cfunc = cast_property_accessor_pointer (prop.set_accessor, cfunc, iface);
1415 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), cfunc)));
1420 source_type_member_definition.append (iface_init);
1423 CCodeExpression cast_property_accessor_pointer (PropertyAccessor acc, CCodeExpression cfunc, ObjectTypeSymbol base_type) {
1424 string cast;
1425 if (acc.readable && acc.value_type.is_real_non_null_struct_type ()) {
1426 cast = "void (*) (%s *, %s *)".printf (base_type.get_cname (), acc.value_type.get_cname ());
1427 } else if (acc.readable) {
1428 cast = "%s (*) (%s *)".printf (acc.value_type.get_cname (), base_type.get_cname ());
1429 } else if (acc.value_type.is_real_non_null_struct_type ()) {
1430 cast = "void (*) (%s *, %s *)".printf (base_type.get_cname (), acc.value_type.get_cname ());
1431 } else {
1432 cast = "void (*) (%s *, %s)".printf (base_type.get_cname (), acc.value_type.get_cname ());
1434 return new CCodeCastExpression (cfunc, cast);
1437 private void add_instance_init_function (Class cl) {
1438 var instance_init = new CCodeFunction ("%s_instance_init".printf (cl.get_lower_case_cname (null)), "void");
1439 instance_init.add_parameter (new CCodeFormalParameter ("self", "%s *".printf (cl.get_cname ())));
1440 instance_init.modifiers = CCodeModifiers.STATIC;
1442 if (cl.is_compact) {
1443 // Add declaration, since the instance_init function is explicitly called
1444 // by the creation methods
1445 source_declarations.add_type_member_declaration (instance_init.copy ());
1448 var init_block = new CCodeBlock ();
1449 instance_init.block = init_block;
1451 if (!cl.is_compact && (cl.has_private_fields || cl.get_type_parameters ().size > 0)) {
1452 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_PRIVATE".printf (cl.get_upper_case_cname (null))));
1453 ccall.add_argument (new CCodeIdentifier ("self"));
1454 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall)));
1457 init_block.add_statement (instance_init_fragment);
1459 source_type_member_definition.append (instance_init);
1462 private void add_class_finalize_function (Class cl) {
1463 var function = new CCodeFunction ("%s_class_finalize".printf (cl.get_lower_case_cname (null)), "void");
1464 function.modifiers = CCodeModifiers.STATIC;
1466 function.add_parameter (new CCodeFormalParameter ("klass", cl.get_cname () + "Class *"));
1467 source_declarations.add_type_member_declaration (function.copy ());
1469 var cblock = new CCodeBlock ();
1471 if (cl.class_destructor != null) {
1472 cblock.add_statement (cl.class_destructor.ccodenode);
1475 cblock.add_statement (class_finalize_fragment);
1477 function.block = cblock;
1478 source_type_member_definition.append (function);
1481 private void add_base_finalize_function (Class cl) {
1482 var function = new CCodeFunction ("%s_base_finalize".printf (cl.get_lower_case_cname (null)), "void");
1483 function.modifiers = CCodeModifiers.STATIC;
1485 function.add_parameter (new CCodeFormalParameter ("klass", cl.get_cname () + "Class *"));
1486 source_declarations.add_type_member_declaration (function.copy ());
1488 var cblock = new CCodeBlock ();
1490 if (cl.class_destructor != null) {
1491 cblock.add_statement (cl.class_destructor.ccodenode);
1494 cblock.add_statement (base_finalize_fragment);
1496 function.block = cblock;
1497 source_type_member_definition.append (function);
1500 private void add_finalize_function (Class cl) {
1501 var function = new CCodeFunction ("%s_finalize".printf (cl.get_lower_case_cname (null)), "void");
1502 function.modifiers = CCodeModifiers.STATIC;
1504 var fundamental_class = cl;
1505 while (fundamental_class.base_class != null) {
1506 fundamental_class = fundamental_class.base_class;
1509 function.add_parameter (new CCodeFormalParameter ("obj", fundamental_class.get_cname () + "*"));
1511 source_declarations.add_type_member_declaration (function.copy ());
1514 var cblock = new CCodeBlock ();
1516 CCodeFunctionCall ccall = generate_instance_cast (new CCodeIdentifier ("obj"), cl);
1518 var cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ()));
1519 cdecl.add_declarator (new CCodeVariableDeclarator ("self", ccall));
1521 cblock.add_statement (cdecl);
1523 if (cl.destructor != null) {
1524 cblock.add_statement (cl.destructor.ccodenode);
1527 cblock.add_statement (instance_finalize_fragment);
1529 // chain up to finalize function of the base class
1530 if (cl.base_class != null) {
1531 var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (fundamental_class.get_upper_case_cname ())));
1532 ccast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (cl.get_lower_case_cname (null))));
1533 ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize"));
1534 ccall.add_argument (new CCodeIdentifier ("obj"));
1535 cblock.add_statement (new CCodeExpressionStatement (ccall));
1539 function.block = cblock;
1541 source_type_member_definition.append (function);
1544 public override CCodeFunctionCall get_param_spec (Property prop) {
1545 var cspec = new CCodeFunctionCall ();
1546 cspec.add_argument (prop.get_canonical_cconstant ());
1547 cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.nick)));
1548 cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.blurb)));
1551 if (prop.property_type.data_type is Class || prop.property_type.data_type is Interface) {
1552 string param_spec_name = prop.property_type.data_type.get_param_spec_function ();
1553 cspec.call = new CCodeIdentifier (param_spec_name);
1554 if (prop.property_type.data_type == string_type.data_type) {
1555 cspec.add_argument (new CCodeConstant ("NULL"));
1556 } else if (prop.property_type.data_type.get_type_id () != "G_TYPE_POINTER") {
1557 cspec.add_argument (new CCodeIdentifier (prop.property_type.data_type.get_type_id ()));
1559 } else if (prop.property_type.data_type is Enum) {
1560 var e = prop.property_type.data_type as Enum;
1561 if (e.has_type_id) {
1562 if (e.is_flags) {
1563 cspec.call = new CCodeIdentifier ("g_param_spec_flags");
1564 } else {
1565 cspec.call = new CCodeIdentifier ("g_param_spec_enum");
1567 cspec.add_argument (new CCodeIdentifier (e.get_type_id ()));
1568 } else {
1569 if (e.is_flags) {
1570 cspec.call = new CCodeIdentifier ("g_param_spec_uint");
1571 cspec.add_argument (new CCodeConstant ("0"));
1572 cspec.add_argument (new CCodeConstant ("G_MAXUINT"));
1573 } else {
1574 cspec.call = new CCodeIdentifier ("g_param_spec_int");
1575 cspec.add_argument (new CCodeConstant ("G_MININT"));
1576 cspec.add_argument (new CCodeConstant ("G_MAXINT"));
1580 if (prop.default_expression != null) {
1581 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1582 } else {
1583 cspec.add_argument (new CCodeConstant (prop.property_type.data_type.get_default_value ()));
1585 } else if (prop.property_type.data_type is Struct) {
1586 var st = (Struct) prop.property_type.data_type;
1587 if (st.get_type_id () == "G_TYPE_INT") {
1588 cspec.call = new CCodeIdentifier ("g_param_spec_int");
1589 cspec.add_argument (new CCodeConstant ("G_MININT"));
1590 cspec.add_argument (new CCodeConstant ("G_MAXINT"));
1591 if (prop.default_expression != null) {
1592 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1593 } else {
1594 cspec.add_argument (new CCodeConstant ("0"));
1596 } else if (st.get_type_id () == "G_TYPE_UINT") {
1597 cspec.call = new CCodeIdentifier ("g_param_spec_uint");
1598 cspec.add_argument (new CCodeConstant ("0"));
1599 cspec.add_argument (new CCodeConstant ("G_MAXUINT"));
1600 if (prop.default_expression != null) {
1601 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1602 } else {
1603 cspec.add_argument (new CCodeConstant ("0U"));
1605 } else if (st.get_type_id () == "G_TYPE_INT64") {
1606 cspec.call = new CCodeIdentifier ("g_param_spec_int64");
1607 cspec.add_argument (new CCodeConstant ("G_MININT64"));
1608 cspec.add_argument (new CCodeConstant ("G_MAXINT64"));
1609 if (prop.default_expression != null) {
1610 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1611 } else {
1612 cspec.add_argument (new CCodeConstant ("0"));
1614 } else if (st.get_type_id () == "G_TYPE_UINT64") {
1615 cspec.call = new CCodeIdentifier ("g_param_spec_uint64");
1616 cspec.add_argument (new CCodeConstant ("0"));
1617 cspec.add_argument (new CCodeConstant ("G_MAXUINT64"));
1618 if (prop.default_expression != null) {
1619 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1620 } else {
1621 cspec.add_argument (new CCodeConstant ("0U"));
1623 } else if (st.get_type_id () == "G_TYPE_LONG") {
1624 cspec.call = new CCodeIdentifier ("g_param_spec_long");
1625 cspec.add_argument (new CCodeConstant ("G_MINLONG"));
1626 cspec.add_argument (new CCodeConstant ("G_MAXLONG"));
1627 if (prop.default_expression != null) {
1628 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1629 } else {
1630 cspec.add_argument (new CCodeConstant ("0L"));
1632 } else if (st.get_type_id () == "G_TYPE_ULONG") {
1633 cspec.call = new CCodeIdentifier ("g_param_spec_ulong");
1634 cspec.add_argument (new CCodeConstant ("0"));
1635 cspec.add_argument (new CCodeConstant ("G_MAXULONG"));
1636 if (prop.default_expression != null) {
1637 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1638 } else {
1639 cspec.add_argument (new CCodeConstant ("0UL"));
1641 } else if (st.get_type_id () == "G_TYPE_BOOLEAN") {
1642 cspec.call = new CCodeIdentifier ("g_param_spec_boolean");
1643 if (prop.default_expression != null) {
1644 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1645 } else {
1646 cspec.add_argument (new CCodeConstant ("FALSE"));
1648 } else if (st.get_type_id () == "G_TYPE_CHAR") {
1649 cspec.call = new CCodeIdentifier ("g_param_spec_char");
1650 cspec.add_argument (new CCodeConstant ("G_MININT8"));
1651 cspec.add_argument (new CCodeConstant ("G_MAXINT8"));
1652 if (prop.default_expression != null) {
1653 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1654 } else {
1655 cspec.add_argument (new CCodeConstant ("0"));
1657 } else if (st.get_type_id () == "G_TYPE_UCHAR") {
1658 cspec.call = new CCodeIdentifier ("g_param_spec_uchar");
1659 cspec.add_argument (new CCodeConstant ("0"));
1660 cspec.add_argument (new CCodeConstant ("G_MAXUINT8"));
1661 if (prop.default_expression != null) {
1662 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1663 } else {
1664 cspec.add_argument (new CCodeConstant ("0"));
1666 }else if (st.get_type_id () == "G_TYPE_FLOAT") {
1667 cspec.call = new CCodeIdentifier ("g_param_spec_float");
1668 cspec.add_argument (new CCodeConstant ("-G_MAXFLOAT"));
1669 cspec.add_argument (new CCodeConstant ("G_MAXFLOAT"));
1670 if (prop.default_expression != null) {
1671 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1672 } else {
1673 cspec.add_argument (new CCodeConstant ("0.0F"));
1675 } else if (st.get_type_id () == "G_TYPE_DOUBLE") {
1676 cspec.call = new CCodeIdentifier ("g_param_spec_double");
1677 cspec.add_argument (new CCodeConstant ("-G_MAXDOUBLE"));
1678 cspec.add_argument (new CCodeConstant ("G_MAXDOUBLE"));
1679 if (prop.default_expression != null) {
1680 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1681 } else {
1682 cspec.add_argument (new CCodeConstant ("0.0"));
1684 } else if (st.get_type_id () == "G_TYPE_GTYPE") {
1685 cspec.call = new CCodeIdentifier ("g_param_spec_gtype");
1686 if (prop.default_expression != null) {
1687 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1688 } else {
1689 cspec.add_argument (new CCodeConstant ("G_TYPE_NONE"));
1691 } else {
1692 cspec.call = new CCodeIdentifier ("g_param_spec_boxed");
1693 cspec.add_argument (new CCodeIdentifier (st.get_type_id ()));
1695 } else {
1696 cspec.call = new CCodeIdentifier ("g_param_spec_pointer");
1699 var pflags = "G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB";
1700 if (prop.get_accessor != null && prop.get_accessor.access != SymbolAccessibility.PRIVATE) {
1701 pflags = "%s%s".printf (pflags, " | G_PARAM_READABLE");
1703 if (prop.set_accessor != null && prop.set_accessor.access != SymbolAccessibility.PRIVATE) {
1704 pflags = "%s%s".printf (pflags, " | G_PARAM_WRITABLE");
1705 if (prop.set_accessor.construction) {
1706 if (prop.set_accessor.writable) {
1707 pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT");
1708 } else {
1709 pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT_ONLY");
1713 cspec.add_argument (new CCodeConstant (pflags));
1715 return cspec;
1718 public override void generate_interface_declaration (Interface iface, CCodeDeclarationSpace decl_space) {
1719 if (decl_space.add_symbol_declaration (iface, iface.get_cname ())) {
1720 return;
1723 foreach (DataType prerequisite in iface.get_prerequisites ()) {
1724 var prereq_cl = prerequisite.data_type as Class;
1725 var prereq_iface = prerequisite.data_type as Interface;
1726 if (prereq_cl != null) {
1727 generate_class_declaration (prereq_cl, decl_space);
1728 } else if (prereq_iface != null) {
1729 generate_interface_declaration (prereq_iface, decl_space);
1733 var type_struct = new CCodeStruct ("_%s".printf (iface.get_type_cname ()));
1735 decl_space.add_type_declaration (new CCodeNewline ());
1736 var macro = "(%s_get_type ())".printf (iface.get_lower_case_cname (null));
1737 decl_space.add_type_declaration (new CCodeMacroReplacement (iface.get_type_id (), macro));
1739 macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (iface.get_type_id (), iface.get_cname ());
1740 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (iface.get_upper_case_cname (null)), macro));
1742 macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (iface.get_type_id ());
1743 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_type_check_function (iface)), macro));
1745 macro = "(G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, %s))".printf (iface.get_type_id (), iface.get_type_cname ());
1746 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_GET_INTERFACE(obj)".printf (iface.get_upper_case_cname (null)), macro));
1747 decl_space.add_type_declaration (new CCodeNewline ());
1749 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (iface.get_cname ()), new CCodeVariableDeclarator (iface.get_cname ())));
1750 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_struct.name), new CCodeVariableDeclarator (iface.get_type_cname ())));
1752 type_struct.add_field ("GTypeInterface", "parent_iface");
1754 foreach (Method m in iface.get_methods ()) {
1755 generate_virtual_method_declaration (m, decl_space, type_struct);
1758 foreach (Property prop in iface.get_properties ()) {
1759 if (!prop.is_abstract && !prop.is_virtual) {
1760 continue;
1762 generate_type_declaration (prop.property_type, decl_space);
1764 var t = (ObjectTypeSymbol) prop.parent_symbol;
1766 bool returns_real_struct = prop.property_type.is_real_non_null_struct_type ();
1768 var this_type = new ObjectType (t);
1769 var cselfparam = new CCodeFormalParameter ("self", this_type.get_cname ());
1771 if (prop.get_accessor != null) {
1772 var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name));
1773 vdeclarator.add_parameter (cselfparam);
1774 string creturn_type;
1775 if (returns_real_struct) {
1776 var cvalueparam = new CCodeFormalParameter ("value", prop.get_accessor.value_type.get_cname () + "*");
1777 vdeclarator.add_parameter (cvalueparam);
1778 creturn_type = "void";
1779 } else {
1780 creturn_type = prop.get_accessor.value_type.get_cname ();
1783 var array_type = prop.property_type as ArrayType;
1784 if (array_type != null) {
1785 for (int dim = 1; dim <= array_type.rank; dim++) {
1786 vdeclarator.add_parameter (new CCodeFormalParameter (head.get_array_length_cname ("result", dim), "int*"));
1790 var vdecl = new CCodeDeclaration (creturn_type);
1791 vdecl.add_declarator (vdeclarator);
1792 type_struct.add_declaration (vdecl);
1794 if (prop.set_accessor != null) {
1795 var vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name));
1796 vdeclarator.add_parameter (cselfparam);
1797 if (returns_real_struct) {
1798 var cvalueparam = new CCodeFormalParameter ("value", prop.set_accessor.value_type.get_cname () + "*");
1799 vdeclarator.add_parameter (cvalueparam);
1800 } else {
1801 var cvalueparam = new CCodeFormalParameter ("value", prop.set_accessor.value_type.get_cname ());
1802 vdeclarator.add_parameter (cvalueparam);
1805 var array_type = prop.property_type as ArrayType;
1806 if (array_type != null) {
1807 for (int dim = 1; dim <= array_type.rank; dim++) {
1808 vdeclarator.add_parameter (new CCodeFormalParameter (head.get_array_length_cname ("value", dim), "int"));
1812 var vdecl = new CCodeDeclaration ("void");
1813 vdecl.add_declarator (vdeclarator);
1814 type_struct.add_declaration (vdecl);
1818 decl_space.add_type_definition (type_struct);
1820 var type_fun = create_interface_register_function (iface);
1821 type_fun.init_from_type ();
1822 decl_space.add_type_member_declaration (type_fun.get_declaration ());
1825 public override void visit_interface (Interface iface) {
1826 var old_symbol = current_symbol;
1827 current_symbol = iface;
1829 if (iface.get_cname().len () < 3) {
1830 iface.error = true;
1831 Report.error (iface.source_reference, "Interface name `%s' is too short".printf (iface.get_cname ()));
1832 return;
1835 generate_interface_declaration (iface, source_declarations);
1836 if (!iface.is_internal_symbol ()) {
1837 generate_interface_declaration (iface, header_declarations);
1839 if (!iface.is_private_symbol ()) {
1840 generate_interface_declaration (iface, internal_header_declarations);
1843 iface.accept_children (codegen);
1845 add_interface_base_init_function (iface);
1847 var type_fun = create_interface_register_function (iface);
1848 type_fun.init_from_type ();
1849 source_type_member_definition.append (type_fun.get_definition ());
1851 current_symbol = old_symbol;
1854 public virtual TypeRegisterFunction create_interface_register_function (Interface iface) {
1855 return new InterfaceRegisterFunction (iface, context);
1858 private void add_interface_base_init_function (Interface iface) {
1859 var base_init = new CCodeFunction ("%s_base_init".printf (iface.get_lower_case_cname (null)), "void");
1860 base_init.add_parameter (new CCodeFormalParameter ("iface", "%sIface *".printf (iface.get_cname ())));
1861 base_init.modifiers = CCodeModifiers.STATIC;
1863 var init_block = new CCodeBlock ();
1865 /* make sure not to run the initialization code twice */
1866 base_init.block = new CCodeBlock ();
1867 var decl = new CCodeDeclaration (bool_type.get_cname ());
1868 decl.modifiers |= CCodeModifiers.STATIC;
1869 decl.add_declarator (new CCodeVariableDeclarator ("initialized", new CCodeConstant ("FALSE")));
1870 base_init.block.add_statement (decl);
1871 var cif = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("initialized")), init_block);
1872 base_init.block.add_statement (cif);
1873 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("initialized"), new CCodeConstant ("TRUE"))));
1875 if (iface.is_subtype_of (gobject_type)) {
1876 /* create properties */
1877 var props = iface.get_properties ();
1878 foreach (Property prop in props) {
1879 if (prop.is_abstract) {
1881 if (prop.property_type is ArrayType) {
1882 continue;
1885 var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_interface_install_property"));
1886 cinst.add_argument (new CCodeIdentifier ("iface"));
1887 cinst.add_argument (head.get_param_spec (prop));
1889 init_block.add_statement (new CCodeExpressionStatement (cinst));
1894 /* create signals */
1895 foreach (Signal sig in iface.get_signals ()) {
1896 init_block.add_statement (new CCodeExpressionStatement (head.get_signal_creation (sig, iface)));
1899 // connect default implementations
1900 foreach (Method m in iface.get_methods ()) {
1901 if (m.is_virtual) {
1902 var ciface = new CCodeIdentifier ("iface");
1903 var cname = m.get_real_cname ();
1904 base_init.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, m.vfunc_name), new CCodeIdentifier (cname))));
1908 init_block.add_statement (head.register_dbus_info (iface));
1910 source_type_member_definition.append (base_init);
1913 public override void visit_struct (Struct st) {
1914 base.visit_struct (st);
1916 if (st.has_type_id) {
1917 var type_fun = new StructRegisterFunction (st, context);
1918 type_fun.init_from_type (false);
1919 source_type_member_definition.append (type_fun.get_definition ());