Fix order of commandline arguments passed to C compiler, patch by
[vala-lang.git] / gobject / valagobjectmodule.vala
blobd636dcb16aa88eedbbe234f2a0cbba60dd8c9245
1 /* valagobjectmodule.vala
3 * Copyright (C) 2006-2008 Jürg Billeter, Raffaele Sandrini
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
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
21 * Raffaele Sandrini <raffaele@sandrini.ch>
24 using GLib;
26 public class Vala.GObjectModule : GTypeModule {
27 int dynamic_property_id;
28 int signal_wrapper_id;
30 public GObjectModule (CCodeGenerator codegen, CCodeModule? next) {
31 base (codegen, next);
34 public override void visit_class (Class cl) {
35 var old_symbol = current_symbol;
36 var old_type_symbol = current_type_symbol;
37 var old_class = current_class;
38 var old_instance_struct = instance_struct;
39 var old_param_spec_struct = param_spec_struct;
40 var old_type_struct = type_struct;
41 var old_instance_priv_struct = instance_priv_struct;
42 var old_prop_enum = prop_enum;
43 var old_class_init_fragment = class_init_fragment;
44 var old_instance_init_fragment = instance_init_fragment;
45 var old_instance_finalize_fragment = instance_finalize_fragment;
46 current_symbol = cl;
47 current_type_symbol = cl;
48 current_class = cl;
50 bool is_gtypeinstance = !cl.is_compact;
51 bool is_gobject = cl.is_subtype_of (gobject_type);
52 bool is_fundamental = is_gtypeinstance && cl.base_class == null;
54 if (cl.get_cname().len () < 3) {
55 cl.error = true;
56 Report.error (cl.source_reference, "Class name `%s' is too short".printf (cl.get_cname ()));
57 return;
61 instance_struct = new CCodeStruct ("_%s".printf (cl.get_cname ()));
62 type_struct = new CCodeStruct ("_%sClass".printf (cl.get_cname ()));
63 instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (cl.get_cname ()));
64 prop_enum = new CCodeEnum ();
65 prop_enum.add_value (new CCodeEnumValue ("%s_DUMMY_PROPERTY".printf (cl.get_upper_case_cname (null))));
66 class_init_fragment = new CCodeFragment ();
67 instance_init_fragment = new CCodeFragment ();
68 instance_finalize_fragment = new CCodeFragment ();
71 CCodeFragment decl_frag;
72 CCodeFragment def_frag;
73 if (cl.access != SymbolAccessibility.PRIVATE) {
74 decl_frag = header_type_declaration;
75 def_frag = header_type_definition;
76 } else {
77 decl_frag = source_type_declaration;
78 def_frag = source_type_definition;
81 if (is_gtypeinstance) {
82 decl_frag.append (new CCodeNewline ());
83 var macro = "(%s_get_type ())".printf (cl.get_lower_case_cname (null));
84 decl_frag.append (new CCodeMacroReplacement (cl.get_type_id (), macro));
86 macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (cl.get_type_id (), cl.get_cname ());
87 decl_frag.append (new CCodeMacroReplacement ("%s(obj)".printf (cl.get_upper_case_cname (null)), macro));
89 macro = "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %sClass))".printf (cl.get_type_id (), cl.get_cname ());
90 decl_frag.append (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (cl.get_upper_case_cname (null)), macro));
92 macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (cl.get_type_id ());
93 decl_frag.append (new CCodeMacroReplacement ("%s(obj)".printf (get_type_check_function (cl)), macro));
95 macro = "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (cl.get_type_id ());
96 decl_frag.append (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (get_type_check_function (cl)), macro));
98 macro = "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %sClass))".printf (cl.get_type_id (), cl.get_cname ());
99 decl_frag.append (new CCodeMacroReplacement ("%s_GET_CLASS(obj)".printf (cl.get_upper_case_cname (null)), macro));
100 decl_frag.append (new CCodeNewline ());
104 if (cl.source_reference.file.cycle == null) {
105 decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (instance_struct.name), new CCodeVariableDeclarator (cl.get_cname ())));
108 if (cl.base_class != null) {
109 instance_struct.add_field (cl.base_class.get_cname (), "parent_instance");
110 } else if (is_fundamental) {
111 instance_struct.add_field ("GTypeInstance", "parent_instance");
112 instance_struct.add_field ("volatile int", "ref_count");
115 if (cl.is_compact && cl.base_class == null && cl.get_fields ().size == 0) {
116 // add dummy member, C doesn't allow empty structs
117 instance_struct.add_field ("int", "dummy");
120 if (is_gtypeinstance) {
121 if (cl.source_reference.file.cycle == null) {
122 decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (type_struct.name), new CCodeVariableDeclarator ("%sClass".printf (cl.get_cname ()))));
124 decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (instance_priv_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (cl.get_cname ()))));
126 instance_struct.add_field ("%sPrivate *".printf (cl.get_cname ()), "priv");
127 if (is_fundamental) {
128 type_struct.add_field ("GTypeClass", "parent_class");
129 type_struct.add_field ("void", "(*finalize) (%s *self)".printf (cl.get_cname ()));
130 } else {
131 type_struct.add_field ("%sClass".printf (cl.base_class.get_cname ()), "parent_class");
135 if (cl.source_reference.comment != null) {
136 def_frag.append (new CCodeComment (cl.source_reference.comment));
138 def_frag.append (instance_struct);
140 if (is_gtypeinstance) {
141 def_frag.append (type_struct);
142 /* only add the *Private struct if it is not empty, i.e. we actually have private data */
143 if (cl.has_private_fields || cl.get_type_parameters ().size > 0) {
144 source_type_member_declaration.append (instance_priv_struct);
145 var macro = "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl.get_type_id (), cl.get_cname ());
146 source_type_member_declaration.append (new CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), macro));
148 source_type_member_declaration.append (prop_enum);
151 cl.accept_children (codegen);
153 if (is_gtypeinstance) {
154 if (is_fundamental) {
155 param_spec_struct = new CCodeStruct ( "_%sParamSpec%s".printf(cl.parent_symbol.get_cprefix (), cl.name));
156 param_spec_struct.add_field ("GParamSpec", "parent_instance");
157 def_frag.append (param_spec_struct);
159 decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (param_spec_struct.name), new CCodeVariableDeclarator ( "%sParamSpec%s".printf(cl.parent_symbol.get_cprefix (), cl.name))));
162 gvaluecollector_h_needed = true;
164 add_type_value_table_init_function (cl);
165 add_type_value_table_free_function (cl);
166 add_type_value_table_copy_function (cl);
167 add_type_value_table_peek_pointer_function (cl);
168 add_type_value_table_collect_value_function (cl);
169 add_type_value_table_lcopy_value_function (cl);
170 add_g_param_spec_type_function (cl);
171 add_g_value_get_function (cl);
172 add_g_value_set_function (cl);
174 var ref_count = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count"), new CCodeConstant ("1"));
175 instance_init_fragment.append (new CCodeExpressionStatement (ref_count));
176 } else if (is_gobject) {
177 if (class_has_readable_properties (cl) || cl.get_type_parameters ().size > 0) {
178 add_get_property_function (cl);
180 if (class_has_writable_properties (cl) || cl.get_type_parameters ().size > 0) {
181 add_set_property_function (cl);
184 add_class_init_function (cl);
186 foreach (DataType base_type in cl.get_base_types ()) {
187 if (base_type.data_type is Interface) {
188 add_interface_init_function (cl, (Interface) base_type.data_type);
192 add_instance_init_function (cl);
194 if (!cl.is_compact && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) {
195 add_finalize_function (cl);
198 var type_fun = new ClassRegisterFunction (cl, context);
199 type_fun.init_from_type (in_plugin);
200 if (cl.access != SymbolAccessibility.PRIVATE) {
201 header_type_member_declaration.append (type_fun.get_declaration ());
202 } else {
203 source_type_member_declaration.append (type_fun.get_declaration ());
205 source_type_member_definition.append (type_fun.get_definition ());
207 if (in_plugin) {
208 // FIXME resolve potential dependency issues, i.e. base types have to be registered before derived types
209 var register_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_register_type".printf (cl.get_lower_case_cname (null))));
210 register_call.add_argument (new CCodeIdentifier (module_init_param_name));
211 module_init_fragment.append (new CCodeExpressionStatement (register_call));
214 if (is_fundamental) {
215 var ref_fun = new CCodeFunction (cl.get_lower_case_cprefix () + "ref", "gpointer");
216 var unref_fun = new CCodeFunction (cl.get_lower_case_cprefix () + "unref", "void");
217 if (cl.access == SymbolAccessibility.PRIVATE) {
218 ref_fun.modifiers = CCodeModifiers.STATIC;
219 unref_fun.modifiers = CCodeModifiers.STATIC;
222 ref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer"));
223 unref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer"));
225 if (cl.access != SymbolAccessibility.PRIVATE) {
226 header_type_member_declaration.append (ref_fun.copy ());
227 header_type_member_declaration.append (unref_fun.copy ());
228 } else {
229 source_type_member_declaration.append (ref_fun.copy ());
230 source_type_member_declaration.append (unref_fun.copy ());
233 var ref_block = new CCodeBlock ();
234 var unref_block = new CCodeBlock ();
236 var cdecl = new CCodeDeclaration (cl.get_cname () + "*");
237 cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", new CCodeIdentifier ("instance")));
238 ref_block.add_statement (cdecl);
239 unref_block.add_statement (cdecl);
241 var ref_count = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count");
243 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_inc"));
244 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ref_count));
245 ref_block.add_statement (new CCodeExpressionStatement (ccall));
247 ref_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("instance")));
249 var destroy_block = new CCodeBlock ();
250 var get_class = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS".printf (cl.get_upper_case_cname (null))));
251 get_class.add_argument (new CCodeIdentifier ("self"));
253 // finalize class
254 var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS".printf (cl.get_upper_case_cname (null))));
255 ccast.add_argument (new CCodeIdentifier ("self"));
256 ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize"));
257 ccall.add_argument (new CCodeIdentifier ("self"));
258 destroy_block.add_statement (new CCodeExpressionStatement (ccall));
260 // free type instance
261 var free = new CCodeFunctionCall (new CCodeIdentifier ("g_type_free_instance"));
262 free.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GTypeInstance *"));
263 destroy_block.add_statement (new CCodeExpressionStatement (free));
265 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_dec_and_test"));
266 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ref_count));
267 unref_block.add_statement (new CCodeIfStatement (ccall, destroy_block));
269 ref_fun.block = ref_block;
270 unref_fun.block = unref_block;
272 source_type_member_definition.append (ref_fun);
273 source_type_member_definition.append (unref_fun);
275 } else {
276 add_instance_init_function (cl);
278 var function = new CCodeFunction (cl.get_lower_case_cprefix () + "free", "void");
279 if (cl.access == SymbolAccessibility.PRIVATE) {
280 function.modifiers = CCodeModifiers.STATIC;
283 function.add_parameter (new CCodeFormalParameter ("self", cl.get_cname () + "*"));
285 if (cl.access != SymbolAccessibility.PRIVATE) {
286 header_type_member_declaration.append (function.copy ());
287 } else {
288 source_type_member_declaration.append (function.copy ());
291 var cblock = new CCodeBlock ();
293 cblock.add_statement (instance_finalize_fragment);
295 if (cl.destructor != null) {
296 cblock.add_statement (cl.destructor.ccodenode);
299 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
300 ccall.add_argument (new CCodeIdentifier (cl.get_cname ()));
301 ccall.add_argument (new CCodeIdentifier ("self"));
302 cblock.add_statement (new CCodeExpressionStatement (ccall));
304 function.block = cblock;
306 source_type_member_definition.append (function);
309 current_symbol = old_symbol;
310 current_type_symbol = old_type_symbol;
311 current_class = old_class;
312 instance_struct = old_instance_struct;
313 param_spec_struct = old_param_spec_struct;
314 type_struct = old_type_struct;
315 instance_priv_struct = old_instance_priv_struct;
316 prop_enum = old_prop_enum;
317 class_init_fragment = old_class_init_fragment;
318 instance_init_fragment = old_instance_init_fragment;
319 instance_finalize_fragment = old_instance_finalize_fragment;
322 private void add_type_value_table_init_function (Class cl) {
323 var function = new CCodeFunction ("%s_init".printf (cl.get_lower_case_cname ("value_")), "void");
324 function.add_parameter (new CCodeFormalParameter ("value", "GValue*"));
325 function.modifiers = CCodeModifiers.STATIC;
327 var init_block = new CCodeBlock ();
328 function.block = init_block;
330 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)));
331 source_type_member_definition.append (function);
334 private void add_type_value_table_free_function (Class cl) {
335 var function = new CCodeFunction ("%s_free_value".printf (cl.get_lower_case_cname ("value_")), "void");
336 function.add_parameter (new CCodeFormalParameter ("value", "GValue*"));
337 function.modifiers = CCodeModifiers.STATIC;
339 var init_block = new CCodeBlock ();
340 function.block = init_block;
342 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
343 var ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_lower_case_cprefix () + "unref"));
344 ccall.add_argument ( vpointer );
346 var ifbody = new CCodeBlock ();
347 ifbody.add_statement ( new CCodeExpressionStatement(ccall) );
349 init_block.add_statement(new CCodeIfStatement (vpointer, ifbody));
350 source_type_member_definition.append (function);
353 private void add_type_value_table_copy_function (Class cl) {
354 var function = new CCodeFunction ("%s_copy_value".printf (cl.get_lower_case_cname ("value_")), "void");
355 function.add_parameter (new CCodeFormalParameter ("src_value", "const GValue*"));
356 function.add_parameter (new CCodeFormalParameter ("dest_value", "GValue*"));
357 function.modifiers = CCodeModifiers.STATIC;
359 var init_block = new CCodeBlock ();
360 function.block = init_block;
362 var dest_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dest_value"), "data[0]"),"v_pointer");
363 var src_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("src_value"), "data[0]"),"v_pointer");
365 var ref_ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_lower_case_cprefix () + "ref"));
366 ref_ccall.add_argument ( src_vpointer );
368 var true_stmt = new CCodeBlock ();
369 true_stmt.add_statement(new CCodeExpressionStatement(new CCodeAssignment (dest_vpointer, ref_ccall, CCodeAssignmentOperator.SIMPLE)));
371 var false_stmt = new CCodeBlock ();
372 false_stmt.add_statement (new CCodeExpressionStatement( new CCodeAssignment (dest_vpointer, new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE)));
374 var if_statement = new CCodeIfStatement (src_vpointer, true_stmt, false_stmt);
375 init_block.add_statement (if_statement);
377 source_type_member_definition.append (function);
380 private void add_type_value_table_peek_pointer_function (Class cl) {
381 var function = new CCodeFunction ("%s_peek_pointer".printf (cl.get_lower_case_cname ("value_")), "gpointer");
382 function.add_parameter (new CCodeFormalParameter ("value", "const GValue*"));
383 function.modifiers = CCodeModifiers.STATIC;
385 var init_block = new CCodeBlock ();
386 function.block = init_block;
388 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
389 var ret = new CCodeReturnStatement ( vpointer );
390 init_block.add_statement (ret);
392 source_type_member_definition.append (function);
395 private void add_type_value_table_lcopy_value_function ( Class cl ) {
396 var function = new CCodeFunction ("%s_lcopy_value".printf (cl.get_lower_case_cname ("value_")), "gchar*");
397 function.add_parameter (new CCodeFormalParameter ("value", "const GValue*"));
398 function.add_parameter (new CCodeFormalParameter ("n_collect_values", "guint"));
399 function.add_parameter (new CCodeFormalParameter ("collect_values", "GTypeCValue*"));
400 function.add_parameter (new CCodeFormalParameter ("collect_flags", "guint"));
401 function.modifiers = CCodeModifiers.STATIC;
403 var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
404 var object_p_ptr = new CCodeIdentifier ("*object_p");
405 var null_ = new CCodeConstant ("NULL");
407 var init_block = new CCodeBlock ();
409 var ctypedecl = new CCodeDeclaration (cl.get_cname () + "**");
410 ctypedecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("object_p", new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"),"v_pointer")));
411 init_block.add_statement (ctypedecl);
413 var value_type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME"));
414 value_type_name_fct.add_argument (new CCodeConstant ("value"));
416 var assert_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("object_p"));
417 function.block = init_block;
418 var assert_true = new CCodeBlock ();
419 var assert_printf = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup_printf"));
420 assert_printf.add_argument (new CCodeConstant ("\"value location for `%s' passed as NULL\""));
421 assert_printf.add_argument (value_type_name_fct);
422 assert_true.add_statement (new CCodeReturnStatement (assert_printf));
423 var if_assert = new CCodeIfStatement (assert_condition, assert_true);
424 init_block.add_statement (if_assert);
426 var main_else_true = new CCodeBlock ();
427 var main_else_if_true = new CCodeBlock ();
428 var main_else_if_condition = new CCodeBinaryExpression (CCodeBinaryOperator.AND, new CCodeIdentifier ("collect_flags"), new CCodeIdentifier ("G_VALUE_NOCOPY_CONTENTS"));
429 var main_else_if = new CCodeIfStatement (main_else_if_condition, main_else_if_true, main_else_true);
431 var main_true = new CCodeBlock ();
432 var main_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, vpointer);
433 var if_main = new CCodeIfStatement (main_condition, main_true, main_else_if);
434 init_block.add_statement (if_main);
436 var ref_fct = new CCodeFunctionCall (new CCodeIdentifier (cl.get_ref_function()));
437 ref_fct.add_argument (vpointer);
439 main_true.add_statement (new CCodeExpressionStatement (new CCodeAssignment (object_p_ptr, null_, CCodeAssignmentOperator.SIMPLE)));
440 main_else_if_true.add_statement (new CCodeExpressionStatement (new CCodeAssignment (object_p_ptr, vpointer, CCodeAssignmentOperator.SIMPLE)));
441 main_else_true.add_statement (new CCodeExpressionStatement (new CCodeAssignment (object_p_ptr, ref_fct, CCodeAssignmentOperator.SIMPLE)));
443 init_block.add_statement (new CCodeReturnStatement (null_));
444 source_type_member_definition.append (function);
447 private void add_type_value_table_collect_value_function (Class cl) {
448 var function = new CCodeFunction ("%s_collect_value".printf (cl.get_lower_case_cname ("value_")), "gchar*");
449 function.add_parameter (new CCodeFormalParameter ("value", "GValue*"));
450 function.add_parameter (new CCodeFormalParameter ("n_collect_values", "guint"));
451 function.add_parameter (new CCodeFormalParameter ("collect_values", "GTypeCValue*"));
452 function.add_parameter (new CCodeFormalParameter ("collect_flags", "guint"));
453 function.modifiers = CCodeModifiers.STATIC;
455 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
457 var init_block = new CCodeBlock ();
458 function.block = init_block;
460 var collect_vpointer = new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"), "v_pointer");
462 var true_stmt = new CCodeBlock ();
463 var false_stmt = new CCodeBlock ();
464 var if_statement = new CCodeIfStatement (collect_vpointer, true_stmt, false_stmt);
465 init_block.add_statement (if_statement);
467 var obj_identifier = new CCodeIdentifier ("object");
469 var ctypedecl = new CCodeDeclaration (cl.get_cname () + "*");
470 ctypedecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("object", collect_vpointer));
471 true_stmt.add_statement (ctypedecl);
473 var l_expression = new CCodeMemberAccess (new CCodeMemberAccess.pointer (obj_identifier, "parent_instance"), "g_class");
474 var sub_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, l_expression, new CCodeConstant ("NULL"));
475 var sub_true_stmt = new CCodeBlock ();
476 var sub_false_stmt = new CCodeBlock ();
478 var reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
479 var type_check = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
480 type_check.add_argument (new CCodeIdentifier ("object"));
481 reg_call.add_argument (type_check);
483 var type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("g_type_name"));
484 type_name_fct.add_argument (type_check);
486 var stored_type = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
487 stored_type.add_argument (new CCodeIdentifier ("value"));
488 reg_call.add_argument (stored_type);
490 var value_type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME"));
491 value_type_name_fct.add_argument (new CCodeConstant ("value"));
493 var true_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat"));
494 true_return.add_argument (new CCodeConstant ("\"invalid unclassed object pointer for value type `\""));
495 true_return.add_argument (value_type_name_fct);
496 true_return.add_argument (new CCodeConstant ("\"'\""));
497 true_return.add_argument (new CCodeConstant ("NULL"));
498 sub_true_stmt.add_statement (new CCodeReturnStatement (true_return));
500 var false_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat"));
501 false_return.add_argument (new CCodeConstant ("\"invalid object type `\""));
502 false_return.add_argument (type_name_fct);
503 false_return.add_argument (new CCodeConstant ("\"' for value type `\""));
504 false_return.add_argument (value_type_name_fct);
505 false_return.add_argument (new CCodeConstant ("\"'\""));
506 false_return.add_argument (new CCodeConstant ("NULL"));
507 sub_false_stmt.add_statement (new CCodeReturnStatement (false_return));
509 var sub_else_if_statement = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, reg_call), sub_false_stmt );
510 sub_else_if_statement.else_if = true;
511 var sub_if_statement = new CCodeIfStatement (sub_condition, sub_true_stmt, sub_else_if_statement);
512 true_stmt.add_statement (sub_if_statement);
514 var ref_call = new CCodeFunctionCall (new CCodeIdentifier (cl.get_ref_function ()));
515 ref_call.add_argument (new CCodeIdentifier ("object"));
517 var true_assignment = new CCodeExpressionStatement (new CCodeAssignment (vpointer, ref_call, CCodeAssignmentOperator.SIMPLE));
518 true_stmt.add_statement (true_assignment);
520 var else_assigment = new CCodeExpressionStatement (new CCodeAssignment (vpointer, new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE));
521 false_stmt.add_statement (else_assigment);
523 init_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL")));
524 source_type_member_definition.append (function);
527 private void add_g_param_spec_type_function (Class cl) {
528 var function_name = cl.get_lower_case_cname ("param_spec_");
530 var function = new CCodeFunction (function_name, "GParamSpec*");
531 function.add_parameter (new CCodeFormalParameter ("name", "const gchar*"));
532 function.add_parameter (new CCodeFormalParameter ("nick", "const gchar*"));
533 function.add_parameter (new CCodeFormalParameter ("blurb", "const gchar*"));
534 function.add_parameter (new CCodeFormalParameter ("object_type", "GType"));
535 function.add_parameter (new CCodeFormalParameter ("flags", "GParamFlags"));
537 cl.set_param_spec_function ( function_name );
539 if (cl.access == SymbolAccessibility.PRIVATE) {
540 function.modifiers = CCodeModifiers.STATIC;
541 source_type_member_declaration.append (function.copy ());
542 } else {
543 header_type_member_declaration.append (function.copy ());
546 var init_block = new CCodeBlock ();
547 function.block = init_block;
549 var ctypedecl = new CCodeDeclaration ("%sParamSpec%s*".printf (cl.parent_symbol.get_cprefix (), cl.name));
550 ctypedecl.add_declarator ( new CCodeVariableDeclarator ("spec"));
551 init_block.add_statement (ctypedecl);
553 var subccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_is_a"));
554 subccall.add_argument (new CCodeIdentifier ("object_type"));
555 subccall.add_argument (new CCodeIdentifier ( cl.get_type_id() ));
557 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail"));
558 ccall.add_argument (subccall);
559 ccall.add_argument (new CCodeIdentifier ("NULL"));
560 init_block.add_statement (new CCodeExpressionStatement (ccall));
562 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_internal"));
563 ccall.add_argument (new CCodeIdentifier ( "G_TYPE_PARAM_OBJECT" ));
564 ccall.add_argument (new CCodeIdentifier ("name"));
565 ccall.add_argument (new CCodeIdentifier ("nick"));
566 ccall.add_argument (new CCodeIdentifier ("blurb"));
567 ccall.add_argument (new CCodeIdentifier ("flags"));
569 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("spec"), ccall, CCodeAssignmentOperator.SIMPLE )));
571 ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_PARAM_SPEC"));
572 ccall.add_argument (new CCodeIdentifier ("spec"));
574 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "value_type"), new CCodeIdentifier ("object_type"), CCodeAssignmentOperator.SIMPLE )));
575 init_block.add_statement (new CCodeReturnStatement (ccall));
576 source_type_member_definition.append (function);
579 private void add_g_value_set_function (Class cl) {
580 var function = new CCodeFunction (cl.get_set_value_function (), "void");
581 function.add_parameter (new CCodeFormalParameter ("value", "GValue*"));
582 function.add_parameter (new CCodeFormalParameter ("v_object", "gpointer"));
584 if (cl.access == SymbolAccessibility.PRIVATE) {
585 function.modifiers = CCodeModifiers.STATIC;
586 source_type_member_declaration.append (function.copy ());
587 } else {
588 header_type_member_declaration.append (function.copy ());
591 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
593 var init_block = new CCodeBlock ();
594 function.block = init_block;
596 var ctypedecl = new CCodeDeclaration (cl.get_cname()+"*");
597 ctypedecl.add_declarator ( new CCodeVariableDeclarator ("old"));
598 init_block.add_statement (ctypedecl);
600 var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
601 ccall_typecheck.add_argument (new CCodeIdentifier ( "value" ));
602 ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() ));
604 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
605 ccall.add_argument (ccall_typecheck);
606 init_block.add_statement (new CCodeExpressionStatement (ccall));
608 init_block.add_statement(new CCodeExpressionStatement (new CCodeAssignment (new CCodeConstant ("old"), vpointer, CCodeAssignmentOperator.SIMPLE)));
610 var true_stmt = new CCodeBlock ();
611 var false_stmt = new CCodeBlock ();
612 var if_statement = new CCodeIfStatement (new CCodeIdentifier ("v_object"), true_stmt, false_stmt);
613 init_block.add_statement (if_statement);
616 ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
617 ccall_typecheck.add_argument (new CCodeIdentifier ( "v_object" ));
618 ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() ));
620 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
621 ccall.add_argument (ccall_typecheck);
622 true_stmt.add_statement (new CCodeExpressionStatement (ccall));
624 var ccall_typefrominstance = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
625 ccall_typefrominstance.add_argument (new CCodeIdentifier ( "v_object" ));
627 var ccall_gvaluetype = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
628 ccall_gvaluetype.add_argument (new CCodeIdentifier ( "value" ));
630 var ccall_typecompatible = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
631 ccall_typecompatible.add_argument (ccall_typefrominstance);
632 ccall_typecompatible.add_argument (ccall_gvaluetype);
634 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
635 ccall.add_argument (ccall_typecompatible);
636 true_stmt.add_statement (new CCodeExpressionStatement (ccall));
638 true_stmt.add_statement(new CCodeExpressionStatement (new CCodeAssignment (vpointer, new CCodeConstant ("v_object"), CCodeAssignmentOperator.SIMPLE)));
640 ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_ref_function ()));
641 ccall.add_argument (vpointer);
642 true_stmt.add_statement (new CCodeExpressionStatement (ccall));
644 false_stmt.add_statement(new CCodeExpressionStatement (new CCodeAssignment (vpointer, new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE)));
646 true_stmt = new CCodeBlock ();
647 if_statement = new CCodeIfStatement (new CCodeIdentifier ("old"), true_stmt);
648 init_block.add_statement (if_statement);
650 ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_unref_function ()));
651 ccall.add_argument (new CCodeIdentifier ("old"));
652 true_stmt.add_statement (new CCodeExpressionStatement (ccall));
653 source_type_member_definition.append (function);
656 private void add_g_value_get_function (Class cl) {
657 var function = new CCodeFunction (cl.get_get_value_function (), "gpointer");
658 function.add_parameter (new CCodeFormalParameter ("value", "const GValue*"));
660 if (cl.access == SymbolAccessibility.PRIVATE) {
661 function.modifiers = CCodeModifiers.STATIC;
662 source_type_member_declaration.append (function.copy ());
663 } else {
664 header_type_member_declaration.append (function.copy ());
667 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
669 var init_block = new CCodeBlock ();
670 function.block = init_block;
672 var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
673 ccall_typecheck.add_argument (new CCodeIdentifier ( "value" ));
674 ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() ));
676 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail"));
677 ccall.add_argument (ccall_typecheck);
678 ccall.add_argument (new CCodeIdentifier ( "NULL" ));
679 init_block.add_statement (new CCodeExpressionStatement (ccall));
681 init_block.add_statement (new CCodeReturnStatement ( vpointer ));
682 source_type_member_definition.append (function);
685 private void add_class_init_function (Class cl) {
686 var class_init = new CCodeFunction ("%s_class_init".printf (cl.get_lower_case_cname (null)), "void");
687 class_init.add_parameter (new CCodeFormalParameter ("klass", "%sClass *".printf (cl.get_cname ())));
688 class_init.modifiers = CCodeModifiers.STATIC;
690 var init_block = new CCodeBlock ();
691 class_init.block = init_block;
693 CCodeFunctionCall ccall;
695 /* save pointer to parent class */
696 var parent_decl = new CCodeDeclaration ("gpointer");
697 var parent_var_decl = new CCodeVariableDeclarator ("%s_parent_class".printf (cl.get_lower_case_cname (null)));
698 parent_var_decl.initializer = new CCodeConstant ("NULL");
699 parent_decl.add_declarator (parent_var_decl);
700 parent_decl.modifiers = CCodeModifiers.STATIC;
701 source_type_member_declaration.append (parent_decl);
702 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek_parent"));
703 ccall.add_argument (new CCodeIdentifier ("klass"));
704 var parent_assignment = new CCodeAssignment (new CCodeIdentifier ("%s_parent_class".printf (cl.get_lower_case_cname (null))), ccall);
705 init_block.add_statement (new CCodeExpressionStatement (parent_assignment));
708 if (!cl.is_compact && !cl.is_subtype_of (gobject_type) && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) {
709 // set finalize function
710 var fundamental_class = cl;
711 while (fundamental_class.base_class != null) {
712 fundamental_class = fundamental_class.base_class;
715 ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (fundamental_class.get_upper_case_cname (null))));
716 ccall.add_argument (new CCodeIdentifier ("klass"));
717 var finalize_assignment = new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "finalize"), new CCodeIdentifier (cl.get_lower_case_cprefix () + "finalize"));
718 init_block.add_statement (new CCodeExpressionStatement (finalize_assignment));
721 /* add struct for private fields */
722 if (cl.has_private_fields || cl.get_type_parameters ().size > 0) {
723 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_add_private"));
724 ccall.add_argument (new CCodeIdentifier ("klass"));
725 ccall.add_argument (new CCodeConstant ("sizeof (%sPrivate)".printf (cl.get_cname ())));
726 init_block.add_statement (new CCodeExpressionStatement (ccall));
729 if (cl.is_subtype_of (gobject_type)) {
730 /* set property handlers */
731 ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
732 ccall.add_argument (new CCodeIdentifier ("klass"));
733 if (class_has_readable_properties (cl) || cl.get_type_parameters ().size > 0) {
734 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "get_property"), new CCodeIdentifier ("%s_get_property".printf (cl.get_lower_case_cname (null))))));
736 if (class_has_writable_properties (cl) || cl.get_type_parameters ().size > 0) {
737 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "set_property"), new CCodeIdentifier ("%s_set_property".printf (cl.get_lower_case_cname (null))))));
740 /* set constructor */
741 if (cl.constructor != null) {
742 var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
743 ccast.add_argument (new CCodeIdentifier ("klass"));
744 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "constructor"), new CCodeIdentifier ("%s_constructor".printf (cl.get_lower_case_cname (null))))));
747 /* set finalize function */
748 if (cl.get_fields ().size > 0 || cl.destructor != null) {
749 var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
750 ccast.add_argument (new CCodeIdentifier ("klass"));
751 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "finalize"), new CCodeIdentifier ("%s_finalize".printf (cl.get_lower_case_cname (null))))));
755 /* connect overridden methods */
756 foreach (Method m in cl.get_methods ()) {
757 if (m.base_method == null) {
758 continue;
760 var base_type = m.base_method.parent_symbol;
762 var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (((Class) base_type).get_upper_case_cname (null))));
763 ccast.add_argument (new CCodeIdentifier ("klass"));
764 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, m.base_method.vfunc_name), new CCodeIdentifier (m.get_real_cname ()))));
767 /* connect overridden properties */
768 foreach (Property prop in cl.get_properties ()) {
769 if (prop.base_property == null) {
770 continue;
772 var base_type = prop.base_property.parent_symbol;
774 var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (((Class) base_type).get_upper_case_cname (null))));
775 ccast.add_argument (new CCodeIdentifier ("klass"));
777 if (prop.get_accessor != null) {
778 string cname = "%s_real_get_%s".printf (cl.get_lower_case_cname (null), prop.name);
779 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "get_%s".printf (prop.name)), new CCodeIdentifier (cname))));
781 if (prop.set_accessor != null) {
782 string cname = "%s_real_set_%s".printf (cl.get_lower_case_cname (null), prop.name);
783 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "set_%s".printf (prop.name)), new CCodeIdentifier (cname))));
787 /* initialize class fields */
788 var fields = cl.get_fields ();
789 foreach (Field field in fields) {
790 if (field.binding != MemberBinding.CLASS || field.initializer == null) {
791 continue;
793 CCodeExpression left = new CCodeMemberAccess (new CCodeIdentifier ("klass"),
794 field.get_cname (), true);
795 CCodeExpression right = (CCodeExpression)field.initializer.ccodenode;
796 CCodeAssignment assign = new CCodeAssignment (left, right);
797 init_block.add_statement (new CCodeExpressionStatement (assign));
800 if (cl.is_subtype_of (gobject_type)) {
801 /* create type, dup_func, and destroy_func properties for generic types */
802 foreach (TypeParameter type_param in cl.get_type_parameters ()) {
803 string func_name, enum_value;
804 CCodeConstant func_name_constant;
805 CCodeFunctionCall cinst, cspec;
807 func_name = "%s_type".printf (type_param.name.down ());
808 func_name_constant = new CCodeConstant ("\"%s-type\"".printf (type_param.name.down ()));
809 enum_value = "%s_%s".printf (cl.get_lower_case_cname (null), func_name).up ();
810 cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property"));
811 cinst.add_argument (ccall);
812 cinst.add_argument (new CCodeConstant (enum_value));
813 cspec = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_gtype"));
814 cspec.add_argument (func_name_constant);
815 cspec.add_argument (new CCodeConstant ("\"type\""));
816 cspec.add_argument (new CCodeConstant ("\"type\""));
817 cspec.add_argument (new CCodeIdentifier ("G_TYPE_NONE"));
818 cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY"));
819 cinst.add_argument (cspec);
820 init_block.add_statement (new CCodeExpressionStatement (cinst));
821 prop_enum.add_value (new CCodeEnumValue (enum_value));
823 instance_priv_struct.add_field ("GType", func_name);
826 func_name = "%s_dup_func".printf (type_param.name.down ());
827 func_name_constant = new CCodeConstant ("\"%s-dup-func\"".printf (type_param.name.down ()));
828 enum_value = "%s_%s".printf (cl.get_lower_case_cname (null), func_name).up ();
829 cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property"));
830 cinst.add_argument (ccall);
831 cinst.add_argument (new CCodeConstant (enum_value));
832 cspec = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_pointer"));
833 cspec.add_argument (func_name_constant);
834 cspec.add_argument (new CCodeConstant ("\"dup func\""));
835 cspec.add_argument (new CCodeConstant ("\"dup func\""));
836 cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY"));
837 cinst.add_argument (cspec);
838 init_block.add_statement (new CCodeExpressionStatement (cinst));
839 prop_enum.add_value (new CCodeEnumValue (enum_value));
841 instance_priv_struct.add_field ("GBoxedCopyFunc", func_name);
844 func_name = "%s_destroy_func".printf (type_param.name.down ());
845 func_name_constant = new CCodeConstant ("\"%s-destroy-func\"".printf (type_param.name.down ()));
846 enum_value = "%s_%s".printf (cl.get_lower_case_cname (null), func_name).up ();
847 cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property"));
848 cinst.add_argument (ccall);
849 cinst.add_argument (new CCodeConstant (enum_value));
850 cspec = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_pointer"));
851 cspec.add_argument (func_name_constant);
852 cspec.add_argument (new CCodeConstant ("\"destroy func\""));
853 cspec.add_argument (new CCodeConstant ("\"destroy func\""));
854 cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY"));
855 cinst.add_argument (cspec);
856 init_block.add_statement (new CCodeExpressionStatement (cinst));
857 prop_enum.add_value (new CCodeEnumValue (enum_value));
859 instance_priv_struct.add_field ("GDestroyNotify", func_name);
862 /* create properties */
863 var props = cl.get_properties ();
864 foreach (Property prop in props) {
865 // FIXME: omit real struct types for now since they cannot be expressed as gobject property yet
866 if (prop.property_type.is_real_struct_type ()) {
867 continue;
869 if (prop.access == SymbolAccessibility.PRIVATE) {
870 // don't register private properties
871 continue;
874 if (prop.overrides || prop.base_interface_property != null) {
875 var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_override_property"));
876 cinst.add_argument (ccall);
877 cinst.add_argument (new CCodeConstant (prop.get_upper_case_cname ()));
878 cinst.add_argument (prop.get_canonical_cconstant ());
880 init_block.add_statement (new CCodeExpressionStatement (cinst));
881 } else {
882 var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property"));
883 cinst.add_argument (ccall);
884 cinst.add_argument (new CCodeConstant (prop.get_upper_case_cname ()));
885 cinst.add_argument (head.get_param_spec (prop));
887 init_block.add_statement (new CCodeExpressionStatement (cinst));
890 } else if (!cl.is_compact) {
891 /* create type, dup_func, and destroy_func fields for generic types */
892 foreach (TypeParameter type_param in cl.get_type_parameters ()) {
893 string func_name;
895 func_name = "%s_type".printf (type_param.name.down ());
896 instance_priv_struct.add_field ("GType", func_name);
898 func_name = "%s_dup_func".printf (type_param.name.down ());
899 instance_priv_struct.add_field ("GBoxedCopyFunc", func_name);
901 func_name = "%s_destroy_func".printf (type_param.name.down ());
902 instance_priv_struct.add_field ("GDestroyNotify", func_name);
906 if (!cl.is_compact) {
907 /* create signals */
908 foreach (Signal sig in cl.get_signals ()) {
909 init_block.add_statement (new CCodeExpressionStatement (head.get_signal_creation (sig, cl)));
913 init_block.add_statement (head.register_dbus_info (cl));
914 init_block.add_statement (class_init_fragment);
916 source_type_member_definition.append (class_init);
919 private void add_interface_init_function (Class cl, Interface iface) {
920 var iface_init = new CCodeFunction ("%s_%s_interface_init".printf (cl.get_lower_case_cname (null), iface.get_lower_case_cname (null)), "void");
921 iface_init.add_parameter (new CCodeFormalParameter ("iface", "%s *".printf (iface.get_type_cname ())));
922 iface_init.modifiers = CCodeModifiers.STATIC;
924 var init_block = new CCodeBlock ();
925 iface_init.block = init_block;
927 CCodeFunctionCall ccall;
929 /* save pointer to parent vtable */
930 string parent_iface_var = "%s_%s_parent_iface".printf (cl.get_lower_case_cname (null), iface.get_lower_case_cname (null));
931 var parent_decl = new CCodeDeclaration (iface.get_type_cname () + "*");
932 var parent_var_decl = new CCodeVariableDeclarator (parent_iface_var);
933 parent_var_decl.initializer = new CCodeConstant ("NULL");
934 parent_decl.add_declarator (parent_var_decl);
935 parent_decl.modifiers = CCodeModifiers.STATIC;
936 source_type_member_declaration.append (parent_decl);
937 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_interface_peek_parent"));
938 ccall.add_argument (new CCodeIdentifier ("iface"));
939 var parent_assignment = new CCodeAssignment (new CCodeIdentifier (parent_iface_var), ccall);
940 init_block.add_statement (new CCodeExpressionStatement (parent_assignment));
942 foreach (Method m in cl.get_methods ()) {
943 if (m.base_interface_method == null) {
944 continue;
947 var base_type = m.base_interface_method.parent_symbol;
948 if (base_type != iface) {
949 continue;
952 var ciface = new CCodeIdentifier ("iface");
953 string cname = m.get_real_cname ();
954 if (m.is_abstract || m.is_virtual) {
955 // FIXME results in C compiler warning
956 cname = m.get_cname ();
958 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, m.base_interface_method.vfunc_name), new CCodeIdentifier (cname))));
961 // connect inherited implementations
962 foreach (Method m in iface.get_methods ()) {
963 if (m.is_abstract) {
964 Method cl_method = null;
965 var base_class = cl;
966 while (base_class != null && cl_method == null) {
967 cl_method = base_class.scope.lookup (m.name) as Method;
968 base_class = base_class.base_class;
970 if (base_class != null && cl_method.parent_symbol != cl) {
971 // method inherited from base class
973 var base_method = cl_method;
974 if (cl_method.base_method != null) {
975 base_method = cl_method.base_method;
976 } else if (cl_method.base_interface_method != null) {
977 base_method = cl_method.base_interface_method;
980 var ciface = new CCodeIdentifier ("iface");
981 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, m.vfunc_name), new CCodeIdentifier (base_method.get_cname ()))));
986 foreach (Property prop in cl.get_properties ()) {
987 if (prop.base_interface_property == null) {
988 continue;
991 var base_type = prop.base_interface_property.parent_symbol;
992 if (base_type != iface) {
993 continue;
996 var ciface = new CCodeIdentifier ("iface");
998 if (prop.get_accessor != null) {
999 string cname = "%s_real_get_%s".printf (cl.get_lower_case_cname (null), prop.name);
1000 if (prop.is_abstract || prop.is_virtual) {
1001 cname = "%s_get_%s".printf (cl.get_lower_case_cname (null), prop.name);
1003 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), new CCodeIdentifier (cname))));
1005 if (prop.set_accessor != null) {
1006 string cname = "%s_real_set_%s".printf (cl.get_lower_case_cname (null), prop.name);
1007 if (prop.is_abstract || prop.is_virtual) {
1008 cname = "%s_set_%s".printf (cl.get_lower_case_cname (null), prop.name);
1010 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), new CCodeIdentifier (cname))));
1014 foreach (Property prop in iface.get_properties ()) {
1015 if (!prop.is_abstract) {
1016 continue;
1019 Property cl_prop = null;
1020 var base_class = cl;
1021 while (base_class != null && cl_prop == null) {
1022 cl_prop = base_class.scope.lookup (prop.name) as Property;
1023 base_class = base_class.base_class;
1025 if (base_class != null && cl_prop.parent_symbol != cl) {
1026 // property inherited from base class
1028 var base_property = cl_prop;
1029 if (cl_prop.base_property != null) {
1030 base_property = cl_prop.base_property;
1031 } else if (cl_prop.base_interface_property != null) {
1032 base_property = cl_prop.base_interface_property;
1035 var ciface = new CCodeIdentifier ("iface");
1037 if (base_property.get_accessor != null) {
1038 string cname = base_property.get_accessor.get_cname ();
1039 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), new CCodeIdentifier (cname))));
1041 if (base_property.set_accessor != null) {
1042 string cname = base_property.set_accessor.get_cname ();
1043 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), new CCodeIdentifier (cname))));
1048 source_type_member_definition.append (iface_init);
1051 private void add_instance_init_function (Class cl) {
1052 var instance_init = new CCodeFunction ("%s_instance_init".printf (cl.get_lower_case_cname (null)), "void");
1053 instance_init.add_parameter (new CCodeFormalParameter ("self", "%s *".printf (cl.get_cname ())));
1054 instance_init.modifiers = CCodeModifiers.STATIC;
1056 if (cl.is_compact) {
1057 // Add declaration, since the instance_init function is explicitly called
1058 // by the creation methods
1059 source_type_member_declaration.append (instance_init.copy ());
1062 var init_block = new CCodeBlock ();
1063 instance_init.block = init_block;
1065 if (!cl.is_compact && (cl.has_private_fields || cl.get_type_parameters ().size > 0)) {
1066 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_PRIVATE".printf (cl.get_upper_case_cname (null))));
1067 ccall.add_argument (new CCodeIdentifier ("self"));
1068 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall)));
1071 init_block.add_statement (instance_init_fragment);
1073 source_type_member_definition.append (instance_init);
1076 private void add_finalize_function (Class cl) {
1077 var function = new CCodeFunction ("%s_finalize".printf (cl.get_lower_case_cname (null)), "void");
1078 function.modifiers = CCodeModifiers.STATIC;
1080 var fundamental_class = cl;
1081 while (fundamental_class.base_class != null) {
1082 fundamental_class = fundamental_class.base_class;
1085 function.add_parameter (new CCodeFormalParameter ("obj", fundamental_class.get_cname () + "*"));
1087 source_type_member_declaration.append (function.copy ());
1090 var cblock = new CCodeBlock ();
1092 CCodeFunctionCall ccall = new InstanceCast (new CCodeIdentifier ("obj"), cl);
1094 var cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ()));
1095 cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", ccall));
1097 cblock.add_statement (cdecl);
1099 if (cl.destructor != null) {
1100 cblock.add_statement (cl.destructor.ccodenode);
1103 cblock.add_statement (instance_finalize_fragment);
1105 // chain up to finalize function of the base class
1106 if (cl.base_class != null) {
1107 var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (fundamental_class.get_upper_case_cname ())));
1108 ccast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (cl.get_lower_case_cname (null))));
1109 ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize"));
1110 ccall.add_argument (new CCodeIdentifier ("obj"));
1111 cblock.add_statement (new CCodeExpressionStatement (ccall));
1115 function.block = cblock;
1117 source_type_member_definition.append (function);
1120 private bool class_has_readable_properties (Class cl) {
1121 foreach (Property prop in cl.get_properties ()) {
1122 if (prop.get_accessor != null) {
1123 return true;
1126 return false;
1129 private bool class_has_writable_properties (Class cl) {
1130 foreach (Property prop in cl.get_properties ()) {
1131 if (prop.set_accessor != null) {
1132 return true;
1135 return false;
1138 private void add_get_property_function (Class cl) {
1139 var get_prop = new CCodeFunction ("%s_get_property".printf (cl.get_lower_case_cname (null)), "void");
1140 get_prop.modifiers = CCodeModifiers.STATIC;
1141 get_prop.add_parameter (new CCodeFormalParameter ("object", "GObject *"));
1142 get_prop.add_parameter (new CCodeFormalParameter ("property_id", "guint"));
1143 get_prop.add_parameter (new CCodeFormalParameter ("value", "GValue *"));
1144 get_prop.add_parameter (new CCodeFormalParameter ("pspec", "GParamSpec *"));
1146 var block = new CCodeBlock ();
1148 CCodeFunctionCall ccall = new InstanceCast (new CCodeIdentifier ("object"), cl);
1149 var cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ()));
1150 cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", ccall));
1151 block.add_statement (cdecl);
1153 var cswitch = new CCodeSwitchStatement (new CCodeIdentifier ("property_id"));
1154 var props = cl.get_properties ();
1155 foreach (Property prop in props) {
1156 // FIXME: omit real struct types for now since they cannot be expressed as gobject property yet
1157 if (prop.get_accessor == null || prop.is_abstract || prop.property_type.is_real_struct_type ()) {
1158 continue;
1160 if (prop.access == SymbolAccessibility.PRIVATE) {
1161 // don't register private properties
1162 continue;
1165 string prefix = cl.get_lower_case_cname (null);
1166 CCodeExpression cself = new CCodeIdentifier ("self");
1167 if (prop.base_property != null) {
1168 var base_type = (Class) prop.base_property.parent_symbol;
1169 prefix = base_type.get_lower_case_cname (null);
1170 cself = transform_expression (cself, new ObjectType (cl), new ObjectType (base_type));
1171 } else if (prop.base_interface_property != null) {
1172 var base_type = (Interface) prop.base_interface_property.parent_symbol;
1173 prefix = base_type.get_lower_case_cname (null);
1174 cself = transform_expression (cself, new ObjectType (cl), new ObjectType (base_type));
1177 cswitch.add_statement (new CCodeCaseStatement (new CCodeIdentifier (prop.get_upper_case_cname ())));
1178 ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_get_%s".printf (prefix, prop.name)));
1179 ccall.add_argument (cself);
1180 var csetcall = new CCodeFunctionCall ();
1181 csetcall.call = head.get_value_setter_function (prop.property_type);
1182 csetcall.add_argument (new CCodeIdentifier ("value"));
1183 csetcall.add_argument (ccall);
1184 cswitch.add_statement (new CCodeExpressionStatement (csetcall));
1185 cswitch.add_statement (new CCodeBreakStatement ());
1187 cswitch.add_statement (new CCodeLabel ("default"));
1188 cswitch.add_statement (get_invalid_property_id_warn_statement ());
1189 cswitch.add_statement (new CCodeBreakStatement ());
1191 block.add_statement (cswitch);
1193 get_prop.block = block;
1195 source_type_member_definition.append (get_prop);
1198 private void add_set_property_function (Class cl) {
1199 var set_prop = new CCodeFunction ("%s_set_property".printf (cl.get_lower_case_cname (null)), "void");
1200 set_prop.modifiers = CCodeModifiers.STATIC;
1201 set_prop.add_parameter (new CCodeFormalParameter ("object", "GObject *"));
1202 set_prop.add_parameter (new CCodeFormalParameter ("property_id", "guint"));
1203 set_prop.add_parameter (new CCodeFormalParameter ("value", "const GValue *"));
1204 set_prop.add_parameter (new CCodeFormalParameter ("pspec", "GParamSpec *"));
1206 var block = new CCodeBlock ();
1208 CCodeFunctionCall ccall = new InstanceCast (new CCodeIdentifier ("object"), cl);
1209 var cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ()));
1210 cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", ccall));
1211 block.add_statement (cdecl);
1213 var cswitch = new CCodeSwitchStatement (new CCodeIdentifier ("property_id"));
1214 var props = cl.get_properties ();
1215 foreach (Property prop in props) {
1216 // FIXME: omit real struct types for now since they cannot be expressed as gobject property yet
1217 if (prop.set_accessor == null || prop.is_abstract || prop.property_type.is_real_struct_type ()) {
1218 continue;
1220 if (prop.access == SymbolAccessibility.PRIVATE) {
1221 // don't register private properties
1222 continue;
1225 string prefix = cl.get_lower_case_cname (null);
1226 CCodeExpression cself = new CCodeIdentifier ("self");
1227 if (prop.base_property != null) {
1228 var base_type = (Class) prop.base_property.parent_symbol;
1229 prefix = base_type.get_lower_case_cname (null);
1230 cself = transform_expression (cself, new ObjectType (cl), new ObjectType (base_type));
1231 } else if (prop.base_interface_property != null) {
1232 var base_type = (Interface) prop.base_interface_property.parent_symbol;
1233 prefix = base_type.get_lower_case_cname (null);
1234 cself = transform_expression (cself, new ObjectType (cl), new ObjectType (base_type));
1237 cswitch.add_statement (new CCodeCaseStatement (new CCodeIdentifier (prop.get_upper_case_cname ())));
1238 ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_set_%s".printf (prefix, prop.name)));
1239 ccall.add_argument (cself);
1240 var cgetcall = new CCodeFunctionCall ();
1241 if (prop.property_type.data_type != null) {
1242 cgetcall.call = new CCodeIdentifier (prop.property_type.data_type.get_get_value_function ());
1243 } else {
1244 cgetcall.call = new CCodeIdentifier ("g_value_get_pointer");
1246 cgetcall.add_argument (new CCodeIdentifier ("value"));
1247 ccall.add_argument (cgetcall);
1248 cswitch.add_statement (new CCodeExpressionStatement (ccall));
1249 cswitch.add_statement (new CCodeBreakStatement ());
1251 cswitch.add_statement (new CCodeLabel ("default"));
1252 cswitch.add_statement (get_invalid_property_id_warn_statement ());
1253 cswitch.add_statement (new CCodeBreakStatement ());
1255 block.add_statement (cswitch);
1257 /* type, dup func, and destroy func properties for generic types */
1258 foreach (TypeParameter type_param in cl.get_type_parameters ()) {
1259 string func_name, enum_value;
1260 CCodeMemberAccess cfield;
1261 CCodeFunctionCall cgetcall;
1263 func_name = "%s_type".printf (type_param.name.down ());
1264 enum_value = "%s_%s".printf (cl.get_lower_case_cname (null), func_name).up ();
1265 cswitch.add_statement (new CCodeCaseStatement (new CCodeIdentifier (enum_value)));
1266 cfield = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
1267 cgetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_gtype"));
1268 cgetcall.add_argument (new CCodeIdentifier ("value"));
1269 cswitch.add_statement (new CCodeExpressionStatement (new CCodeAssignment (cfield, cgetcall)));
1270 cswitch.add_statement (new CCodeBreakStatement ());
1272 func_name = "%s_dup_func".printf (type_param.name.down ());
1273 enum_value = "%s_%s".printf (cl.get_lower_case_cname (null), func_name).up ();
1274 cswitch.add_statement (new CCodeCaseStatement (new CCodeIdentifier (enum_value)));
1275 cfield = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
1276 cgetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_pointer"));
1277 cgetcall.add_argument (new CCodeIdentifier ("value"));
1278 cswitch.add_statement (new CCodeExpressionStatement (new CCodeAssignment (cfield, cgetcall)));
1279 cswitch.add_statement (new CCodeBreakStatement ());
1281 func_name = "%s_destroy_func".printf (type_param.name.down ());
1282 enum_value = "%s_%s".printf (cl.get_lower_case_cname (null), func_name).up ();
1283 cswitch.add_statement (new CCodeCaseStatement (new CCodeIdentifier (enum_value)));
1284 cfield = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
1285 cgetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_pointer"));
1286 cgetcall.add_argument (new CCodeIdentifier ("value"));
1287 cswitch.add_statement (new CCodeExpressionStatement (new CCodeAssignment (cfield, cgetcall)));
1288 cswitch.add_statement (new CCodeBreakStatement ());
1291 set_prop.block = block;
1293 source_type_member_definition.append (set_prop);
1296 private CCodeStatement get_invalid_property_id_warn_statement () {
1297 // warn on invalid property id
1298 var cwarn = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_WARN_INVALID_PROPERTY_ID"));
1299 cwarn.add_argument (new CCodeIdentifier ("object"));
1300 cwarn.add_argument (new CCodeIdentifier ("property_id"));
1301 cwarn.add_argument (new CCodeIdentifier ("pspec"));
1302 return new CCodeExpressionStatement (cwarn);
1305 public override CCodeFunctionCall get_param_spec (Property prop) {
1306 var cspec = new CCodeFunctionCall ();
1307 cspec.add_argument (prop.get_canonical_cconstant ());
1308 cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.nick)));
1309 cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.blurb)));
1312 if ((prop.property_type.data_type is Class && !(((Class) prop.property_type.data_type).is_compact)) || prop.property_type.data_type is Interface) {
1313 string param_spec_name = prop.property_type.data_type.get_param_spec_function ();
1314 if (param_spec_name == null) {
1315 cspec.call = new CCodeIdentifier ("g_param_spec_pointer");
1316 } else {
1317 cspec.call = new CCodeIdentifier ( param_spec_name );
1318 cspec.add_argument (new CCodeIdentifier (prop.property_type.data_type.get_type_id ()));
1320 } else if (prop.property_type.data_type == string_type.data_type) {
1321 cspec.call = new CCodeIdentifier ("g_param_spec_string");
1322 cspec.add_argument (new CCodeConstant ("NULL"));
1323 } else if (prop.property_type.data_type is Enum) {
1324 var e = prop.property_type.data_type as Enum;
1325 if (e.has_type_id) {
1326 if (e.is_flags) {
1327 cspec.call = new CCodeIdentifier ("g_param_spec_flags");
1328 } else {
1329 cspec.call = new CCodeIdentifier ("g_param_spec_enum");
1331 cspec.add_argument (new CCodeIdentifier (e.get_type_id ()));
1332 } else {
1333 if (e.is_flags) {
1334 cspec.call = new CCodeIdentifier ("g_param_spec_uint");
1335 cspec.add_argument (new CCodeConstant ("0"));
1336 cspec.add_argument (new CCodeConstant ("G_MAXUINT"));
1337 } else {
1338 cspec.call = new CCodeIdentifier ("g_param_spec_int");
1339 cspec.add_argument (new CCodeConstant ("G_MININT"));
1340 cspec.add_argument (new CCodeConstant ("G_MAXINT"));
1344 if (prop.default_expression != null) {
1345 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1346 } else {
1347 cspec.add_argument (new CCodeConstant (prop.property_type.data_type.get_default_value ()));
1349 } else if (prop.property_type.data_type is Struct) {
1350 var st = (Struct) prop.property_type.data_type;
1351 if (st.get_type_id () == "G_TYPE_INT") {
1352 cspec.call = new CCodeIdentifier ("g_param_spec_int");
1353 cspec.add_argument (new CCodeConstant ("G_MININT"));
1354 cspec.add_argument (new CCodeConstant ("G_MAXINT"));
1355 if (prop.default_expression != null) {
1356 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1357 } else {
1358 cspec.add_argument (new CCodeConstant ("0"));
1360 } else if (st.get_type_id () == "G_TYPE_UINT") {
1361 cspec.call = new CCodeIdentifier ("g_param_spec_uint");
1362 cspec.add_argument (new CCodeConstant ("0"));
1363 cspec.add_argument (new CCodeConstant ("G_MAXUINT"));
1364 if (prop.default_expression != null) {
1365 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1366 } else {
1367 cspec.add_argument (new CCodeConstant ("0U"));
1369 } else if (st.get_type_id () == "G_TYPE_INT64") {
1370 cspec.call = new CCodeIdentifier ("g_param_spec_int64");
1371 cspec.add_argument (new CCodeConstant ("G_MININT64"));
1372 cspec.add_argument (new CCodeConstant ("G_MAXINT64"));
1373 if (prop.default_expression != null) {
1374 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1375 } else {
1376 cspec.add_argument (new CCodeConstant ("0"));
1378 } else if (st.get_type_id () == "G_TYPE_UINT64") {
1379 cspec.call = new CCodeIdentifier ("g_param_spec_uint64");
1380 cspec.add_argument (new CCodeConstant ("0"));
1381 cspec.add_argument (new CCodeConstant ("G_MAXUINT64"));
1382 if (prop.default_expression != null) {
1383 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1384 } else {
1385 cspec.add_argument (new CCodeConstant ("0U"));
1387 } else if (st.get_type_id () == "G_TYPE_LONG") {
1388 cspec.call = new CCodeIdentifier ("g_param_spec_long");
1389 cspec.add_argument (new CCodeConstant ("G_MINLONG"));
1390 cspec.add_argument (new CCodeConstant ("G_MAXLONG"));
1391 if (prop.default_expression != null) {
1392 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1393 } else {
1394 cspec.add_argument (new CCodeConstant ("0L"));
1396 } else if (st.get_type_id () == "G_TYPE_ULONG") {
1397 cspec.call = new CCodeIdentifier ("g_param_spec_ulong");
1398 cspec.add_argument (new CCodeConstant ("0"));
1399 cspec.add_argument (new CCodeConstant ("G_MAXULONG"));
1400 if (prop.default_expression != null) {
1401 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1402 } else {
1403 cspec.add_argument (new CCodeConstant ("0UL"));
1405 } else if (st.get_type_id () == "G_TYPE_BOOLEAN") {
1406 cspec.call = new CCodeIdentifier ("g_param_spec_boolean");
1407 if (prop.default_expression != null) {
1408 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1409 } else {
1410 cspec.add_argument (new CCodeConstant ("FALSE"));
1412 } else if (st.get_type_id () == "G_TYPE_CHAR") {
1413 cspec.call = new CCodeIdentifier ("g_param_spec_char");
1414 cspec.add_argument (new CCodeConstant ("G_MININT8"));
1415 cspec.add_argument (new CCodeConstant ("G_MAXINT8"));
1416 if (prop.default_expression != null) {
1417 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1418 } else {
1419 cspec.add_argument (new CCodeConstant ("0"));
1421 } else if (st.get_type_id () == "G_TYPE_UCHAR") {
1422 cspec.call = new CCodeIdentifier ("g_param_spec_uchar");
1423 cspec.add_argument (new CCodeConstant ("0"));
1424 cspec.add_argument (new CCodeConstant ("G_MAXUINT8"));
1425 if (prop.default_expression != null) {
1426 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1427 } else {
1428 cspec.add_argument (new CCodeConstant ("0"));
1430 }else if (st.get_type_id () == "G_TYPE_FLOAT") {
1431 cspec.call = new CCodeIdentifier ("g_param_spec_float");
1432 cspec.add_argument (new CCodeConstant ("-G_MAXFLOAT"));
1433 cspec.add_argument (new CCodeConstant ("G_MAXFLOAT"));
1434 if (prop.default_expression != null) {
1435 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1436 } else {
1437 cspec.add_argument (new CCodeConstant ("0.0F"));
1439 } else if (st.get_type_id () == "G_TYPE_DOUBLE") {
1440 cspec.call = new CCodeIdentifier ("g_param_spec_double");
1441 cspec.add_argument (new CCodeConstant ("-G_MAXDOUBLE"));
1442 cspec.add_argument (new CCodeConstant ("G_MAXDOUBLE"));
1443 if (prop.default_expression != null) {
1444 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1445 } else {
1446 cspec.add_argument (new CCodeConstant ("0.0"));
1448 } else if (st.get_type_id () == "G_TYPE_GTYPE") {
1449 cspec.call = new CCodeIdentifier ("g_param_spec_gtype");
1450 if (prop.default_expression != null) {
1451 cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode);
1452 } else {
1453 cspec.add_argument (new CCodeConstant ("G_TYPE_NONE"));
1455 } else {
1456 cspec.call = new CCodeIdentifier ("g_param_spec_pointer");
1458 } else {
1459 cspec.call = new CCodeIdentifier ("g_param_spec_pointer");
1462 var pflags = "G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB";
1463 if (prop.get_accessor != null) {
1464 pflags = "%s%s".printf (pflags, " | G_PARAM_READABLE");
1466 if (prop.set_accessor != null) {
1467 pflags = "%s%s".printf (pflags, " | G_PARAM_WRITABLE");
1468 if (prop.set_accessor.construction) {
1469 if (prop.set_accessor.writable) {
1470 pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT");
1471 } else {
1472 pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT_ONLY");
1476 cspec.add_argument (new CCodeConstant (pflags));
1478 return cspec;
1481 public override CCodeExpression get_construct_property_assignment (CCodeConstant canonical_cconstant, DataType property_type, CCodeExpression value) {
1482 // this property is used as a construction parameter
1483 var cpointer = new CCodeIdentifier ("__params_it");
1485 var ccomma = new CCodeCommaExpression ();
1486 // set name in array for current parameter
1487 var cnamemember = new CCodeMemberAccess.pointer (cpointer, "name");
1488 var cnameassign = new CCodeAssignment (cnamemember, canonical_cconstant);
1489 ccomma.append_expression (cnameassign);
1491 var gvaluearg = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeMemberAccess.pointer (cpointer, "value"));
1493 // initialize GValue in array for current parameter
1494 var cvalueinit = new CCodeFunctionCall (new CCodeIdentifier ("g_value_init"));
1495 cvalueinit.add_argument (gvaluearg);
1496 cvalueinit.add_argument (new CCodeIdentifier (property_type.get_type_id ()));
1497 ccomma.append_expression (cvalueinit);
1499 // set GValue for current parameter
1500 var cvalueset = new CCodeFunctionCall (get_value_setter_function (property_type));
1501 cvalueset.add_argument (gvaluearg);
1502 cvalueset.add_argument (value);
1503 ccomma.append_expression (cvalueset);
1505 // move pointer to next parameter in array
1506 ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, cpointer));
1508 return ccomma;
1511 public override void visit_constructor (Constructor c) {
1512 current_method_inner_error = false;
1513 in_constructor = true;
1515 if (c.binding == MemberBinding.CLASS || c.binding == MemberBinding.STATIC) {
1516 in_static_or_class_ctor = true;
1518 c.accept_children (codegen);
1519 in_static_or_class_ctor = false;
1521 in_constructor = false;
1523 var cl = (Class) c.parent_symbol;
1525 if (c.binding == MemberBinding.INSTANCE) {
1526 function = new CCodeFunction ("%s_constructor".printf (cl.get_lower_case_cname (null)), "GObject *");
1527 function.modifiers = CCodeModifiers.STATIC;
1529 function.add_parameter (new CCodeFormalParameter ("type", "GType"));
1530 function.add_parameter (new CCodeFormalParameter ("n_construct_properties", "guint"));
1531 function.add_parameter (new CCodeFormalParameter ("construct_properties", "GObjectConstructParam *"));
1533 source_type_member_declaration.append (function.copy ());
1536 var cblock = new CCodeBlock ();
1537 var cdecl = new CCodeDeclaration ("GObject *");
1538 cdecl.add_declarator (new CCodeVariableDeclarator ("obj"));
1539 cblock.add_statement (cdecl);
1541 cdecl = new CCodeDeclaration ("%sClass *".printf (cl.get_cname ()));
1542 cdecl.add_declarator (new CCodeVariableDeclarator ("klass"));
1543 cblock.add_statement (cdecl);
1545 cdecl = new CCodeDeclaration ("GObjectClass *");
1546 cdecl.add_declarator (new CCodeVariableDeclarator ("parent_class"));
1547 cblock.add_statement (cdecl);
1550 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek"));
1551 ccall.add_argument (new CCodeIdentifier (cl.get_type_id ()));
1552 var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (cl.get_upper_case_cname (null))));
1553 ccast.add_argument (ccall);
1554 cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("klass"), ccast)));
1556 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek_parent"));
1557 ccall.add_argument (new CCodeIdentifier ("klass"));
1558 ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
1559 ccast.add_argument (ccall);
1560 cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_class"), ccast)));
1563 ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (new CCodeIdentifier ("parent_class"), "constructor"));
1564 ccall.add_argument (new CCodeIdentifier ("type"));
1565 ccall.add_argument (new CCodeIdentifier ("n_construct_properties"));
1566 ccall.add_argument (new CCodeIdentifier ("construct_properties"));
1567 cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("obj"), ccall)));
1570 ccall = new InstanceCast (new CCodeIdentifier ("obj"), cl);
1572 cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ()));
1573 cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", ccall));
1574 cblock.add_statement (cdecl);
1576 if (current_method_inner_error) {
1577 /* always separate error parameter and inner_error local variable
1578 * as error may be set to NULL but we're always interested in inner errors
1580 cdecl = new CCodeDeclaration ("GError *");
1581 cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("inner_error", new CCodeConstant ("NULL")));
1582 cblock.add_statement (cdecl);
1586 cblock.add_statement (c.body.ccodenode);
1588 cblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("obj")));
1590 function.block = cblock;
1592 if (c.source_reference.comment != null) {
1593 source_type_member_definition.append (new CCodeComment (c.source_reference.comment));
1595 source_type_member_definition.append (function);
1596 } else if (c.binding == MemberBinding.CLASS) {
1597 // class constructor
1599 var base_init = new CCodeFunction ("%s_base_init".printf (cl.get_lower_case_cname (null)), "void");
1600 base_init.add_parameter (new CCodeFormalParameter ("klass", "%sClass *".printf (cl.get_cname ())));
1601 base_init.modifiers = CCodeModifiers.STATIC;
1603 source_type_member_declaration.append (base_init.copy ());
1605 var block = (CCodeBlock) c.body.ccodenode;
1606 if (current_method_inner_error) {
1607 /* always separate error parameter and inner_error local variable
1608 * as error may be set to NULL but we're always interested in inner errors
1610 var cdecl = new CCodeDeclaration ("GError *");
1611 cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("inner_error", new CCodeConstant ("NULL")));
1612 block.prepend_statement (cdecl);
1615 base_init.block = block;
1617 source_type_member_definition.append (base_init);
1618 } else if (c.binding == MemberBinding.STATIC) {
1619 // static class constructor
1620 // add to class_init
1622 if (current_method_inner_error) {
1623 /* always separate error parameter and inner_error local variable
1624 * as error may be set to NULL but we're always interested in inner errors
1626 var cdecl = new CCodeDeclaration ("GError *");
1627 cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("inner_error", new CCodeConstant ("NULL")));
1628 class_init_fragment.append (cdecl);
1631 class_init_fragment.append (c.body.ccodenode);
1632 } else {
1633 Report.error (c.source_reference, "internal error: constructors must have instance, class, or static binding");
1637 public override string get_dynamic_property_getter_cname (DynamicProperty prop) {
1638 if (prop.dynamic_type.data_type == null
1639 || !prop.dynamic_type.data_type.is_subtype_of (gobject_type)) {
1640 return base.get_dynamic_property_getter_cname (prop);
1643 string getter_cname = "_dynamic_get_%s%d".printf (prop.name, dynamic_property_id++);
1645 var func = new CCodeFunction (getter_cname, prop.property_type.get_cname ());
1646 func.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.INLINE;
1648 func.add_parameter (new CCodeFormalParameter ("obj", prop.dynamic_type.get_cname ()));
1650 var block = new CCodeBlock ();
1651 generate_gobject_property_getter_wrapper (prop, block);
1653 // append to C source file
1654 source_type_member_declaration.append (func.copy ());
1656 func.block = block;
1657 source_type_member_definition.append (func);
1659 return getter_cname;
1662 public override string get_dynamic_property_setter_cname (DynamicProperty prop) {
1663 if (prop.dynamic_type.data_type == null
1664 || !prop.dynamic_type.data_type.is_subtype_of (gobject_type)) {
1665 return base.get_dynamic_property_setter_cname (prop);
1668 string setter_cname = "_dynamic_set_%s%d".printf (prop.name, dynamic_property_id++);
1670 var func = new CCodeFunction (setter_cname, "void");
1671 func.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.INLINE;
1673 func.add_parameter (new CCodeFormalParameter ("obj", prop.dynamic_type.get_cname ()));
1674 func.add_parameter (new CCodeFormalParameter ("value", prop.property_type.get_cname ()));
1676 var block = new CCodeBlock ();
1677 generate_gobject_property_setter_wrapper (prop, block);
1679 // append to C source file
1680 source_type_member_declaration.append (func.copy ());
1682 func.block = block;
1683 source_type_member_definition.append (func);
1685 return setter_cname;
1688 void generate_gobject_property_getter_wrapper (DynamicProperty node, CCodeBlock block) {
1689 var cdecl = new CCodeDeclaration (node.property_type.get_cname ());
1690 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
1691 block.add_statement (cdecl);
1693 var call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
1694 call.add_argument (new CCodeIdentifier ("obj"));
1695 call.add_argument (node.get_canonical_cconstant ());
1696 call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
1697 call.add_argument (new CCodeConstant ("NULL"));
1699 block.add_statement (new CCodeExpressionStatement (call));
1701 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
1704 void generate_gobject_property_setter_wrapper (DynamicProperty node, CCodeBlock block) {
1705 var call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_set"));
1706 call.add_argument (new CCodeIdentifier ("obj"));
1707 call.add_argument (node.get_canonical_cconstant ());
1708 call.add_argument (new CCodeIdentifier ("value"));
1709 call.add_argument (new CCodeConstant ("NULL"));
1711 block.add_statement (new CCodeExpressionStatement (call));
1714 public override string get_dynamic_signal_cname (DynamicSignal node) {
1715 return "dynamic_%s%d_".printf (node.name, signal_wrapper_id++);
1718 public override string get_dynamic_signal_connect_wrapper_name (DynamicSignal sig) {
1719 if (sig.dynamic_type.data_type == null
1720 || !sig.dynamic_type.data_type.is_subtype_of (gobject_type)) {
1721 return base.get_dynamic_signal_connect_wrapper_name (sig);
1724 string connect_wrapper_name = "_%sconnect".printf (get_dynamic_signal_cname (sig));
1725 var func = new CCodeFunction (connect_wrapper_name, "void");
1726 func.add_parameter (new CCodeFormalParameter ("obj", "gpointer"));
1727 func.add_parameter (new CCodeFormalParameter ("signal_name", "const char *"));
1728 func.add_parameter (new CCodeFormalParameter ("handler", "GCallback"));
1729 func.add_parameter (new CCodeFormalParameter ("data", "gpointer"));
1730 var block = new CCodeBlock ();
1731 generate_gobject_connect_wrapper (sig, block);
1733 // append to C source file
1734 source_type_member_declaration.append (func.copy ());
1736 func.block = block;
1737 source_type_member_definition.append (func);
1739 return connect_wrapper_name;
1742 void generate_gobject_connect_wrapper (DynamicSignal sig, CCodeBlock block) {
1743 var m = (Method) sig.handler.symbol_reference;
1745 sig.accept (codegen);
1747 string connect_func = "g_signal_connect_object";
1748 if (m.binding != MemberBinding.INSTANCE) {
1749 connect_func = "g_signal_connect";
1752 var call = new CCodeFunctionCall (new CCodeIdentifier (connect_func));
1753 call.add_argument (new CCodeIdentifier ("obj"));
1754 call.add_argument (new CCodeIdentifier ("signal_name"));
1755 call.add_argument (new CCodeIdentifier ("handler"));
1756 call.add_argument (new CCodeIdentifier ("data"));
1758 if (m.binding == MemberBinding.INSTANCE) {
1759 call.add_argument (new CCodeConstant ("0"));
1762 block.add_statement (new CCodeExpressionStatement (call));