gtk+-4.0: Update to 3.93.0+6aeae2c8
[vala-gnome.git] / codegen / valagtypemodule.vala
blobc282f2c3a53e98aa8111ceda060cb793e6329a8c
1 /* valagtypemodule.vala
3 * Copyright (C) 2006-2010 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>
26 public class Vala.GTypeModule : GErrorModule {
27 public override CCodeParameter generate_parameter (Parameter param, CCodeFile decl_space, Map<int,CCodeParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
28 if (!(param.variable_type is ObjectType)) {
29 return base.generate_parameter (param, decl_space, cparam_map, carg_map);
32 generate_type_declaration (param.variable_type, decl_space);
34 string ctypename = get_ccode_name (param.variable_type);
36 if (param.direction != ParameterDirection.IN) {
37 ctypename = "%s *".printf (ctypename);
40 var cparam = new CCodeParameter (get_variable_cname (param.name), ctypename);
41 if (param.format_arg) {
42 cparam.modifiers = CCodeModifiers.FORMAT_ARG;
45 cparam_map.set (get_param_pos (get_ccode_pos (param)), cparam);
46 if (carg_map != null) {
47 carg_map.set (get_param_pos (get_ccode_pos (param)), get_variable_cexpression (param.name));
50 return cparam;
53 public override void generate_class_declaration (Class cl, CCodeFile decl_space) {
54 if (add_symbol_declaration (decl_space, cl, get_ccode_name (cl))) {
55 return;
58 if (cl.base_class != null) {
59 // base class declaration
60 // necessary for ref and unref function declarations
61 generate_class_declaration (cl.base_class, decl_space);
64 bool is_gtypeinstance = !cl.is_compact;
65 bool is_fundamental = is_gtypeinstance && cl.base_class == null;
66 bool is_gsource = cl.base_class == gsource_type;
68 if (is_gtypeinstance) {
69 decl_space.add_type_declaration (new CCodeNewline ());
70 var macro = "(%s_get_type ())".printf (get_ccode_lower_case_name (cl, null));
71 decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (cl), macro));
73 macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (get_ccode_type_id (cl), get_ccode_name (cl));
74 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_upper_case_name (cl, null)), macro));
76 macro = "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %sClass))".printf (get_ccode_type_id (cl), get_ccode_name (cl));
77 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (get_ccode_upper_case_name (cl, null)), macro));
79 macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (get_ccode_type_id (cl));
80 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_check_function (cl)), macro));
82 macro = "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (get_ccode_type_id (cl));
83 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (get_ccode_type_check_function (cl)), macro));
85 macro = "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %sClass))".printf (get_ccode_type_id (cl), get_ccode_name (cl));
86 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_GET_CLASS(obj)".printf (get_ccode_upper_case_name (cl, null)), macro));
87 decl_space.add_type_declaration (new CCodeNewline ());
90 if (cl.is_compact && cl.base_class != null && !is_gsource) {
91 decl_space.add_type_declaration (new CCodeTypeDefinition (get_ccode_name (cl.base_class), new CCodeVariableDeclarator (get_ccode_name (cl))));
92 } else {
93 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (cl)), new CCodeVariableDeclarator (get_ccode_name (cl))));
96 if (is_fundamental) {
97 var ref_fun = new CCodeFunction ("%sref".printf (get_ccode_lower_case_prefix (cl)), "gpointer");
98 var unref_fun = new CCodeFunction ("%sunref".printf (get_ccode_lower_case_prefix (cl)), "void");
99 if (cl.is_private_symbol ()) {
100 ref_fun.modifiers = CCodeModifiers.STATIC;
101 unref_fun.modifiers = CCodeModifiers.STATIC;
102 } else if (context.hide_internal && cl.is_internal_symbol ()) {
103 ref_fun.modifiers = CCodeModifiers.INTERNAL;
104 unref_fun.modifiers = CCodeModifiers.INTERNAL;
107 ref_fun.add_parameter (new CCodeParameter ("instance", "gpointer"));
108 unref_fun.add_parameter (new CCodeParameter ("instance", "gpointer"));
110 decl_space.add_function_declaration (ref_fun);
111 decl_space.add_function_declaration (unref_fun);
113 // GParamSpec and GValue functions
114 string function_name = get_ccode_lower_case_name (cl, "param_spec_");
116 var function = new CCodeFunction (function_name, "GParamSpec*");
117 function.add_parameter (new CCodeParameter ("name", "const gchar*"));
118 function.add_parameter (new CCodeParameter ("nick", "const gchar*"));
119 function.add_parameter (new CCodeParameter ("blurb", "const gchar*"));
120 function.add_parameter (new CCodeParameter ("object_type", "GType"));
121 function.add_parameter (new CCodeParameter ("flags", "GParamFlags"));
123 if (cl.is_private_symbol ()) {
124 // avoid C warning as this function is not always used
125 function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
126 } else if (context.hide_internal && cl.is_internal_symbol ()) {
127 function.modifiers = CCodeModifiers.INTERNAL;
130 decl_space.add_function_declaration (function);
132 function = new CCodeFunction (get_ccode_set_value_function (cl), "void");
133 function.add_parameter (new CCodeParameter ("value", "GValue*"));
134 function.add_parameter (new CCodeParameter ("v_object", "gpointer"));
136 if (cl.is_private_symbol ()) {
137 // avoid C warning as this function is not always used
138 function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
139 } else if (context.hide_internal && cl.is_internal_symbol ()) {
140 // avoid C warning as this function is not always used
141 function.modifiers = CCodeModifiers.INTERNAL | CCodeModifiers.UNUSED;
144 decl_space.add_function_declaration (function);
146 function = new CCodeFunction (get_ccode_take_value_function (cl), "void");
147 function.add_parameter (new CCodeParameter ("value", "GValue*"));
148 function.add_parameter (new CCodeParameter ("v_object", "gpointer"));
150 if (cl.is_private_symbol ()) {
151 // avoid C warning as this function is not always used
152 function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
153 } else if (context.hide_internal && cl.is_internal_symbol ()) {
154 function.modifiers = CCodeModifiers.INTERNAL;
157 decl_space.add_function_declaration (function);
159 function = new CCodeFunction (get_ccode_get_value_function (cl), "gpointer");
160 function.add_parameter (new CCodeParameter ("value", "const GValue*"));
162 if (cl.is_private_symbol ()) {
163 // avoid C warning as this function is not always used
164 function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
165 } else if (context.hide_internal && cl.is_internal_symbol ()) {
166 // avoid C warning as this function is not always used
167 function.modifiers = CCodeModifiers.INTERNAL | CCodeModifiers.UNUSED;
170 decl_space.add_function_declaration (function);
171 } else if (!is_gtypeinstance && !is_gsource) {
172 if (cl.base_class == null) {
173 var function = new CCodeFunction ("%sfree".printf (get_ccode_lower_case_prefix (cl)), "void");
174 if (cl.is_private_symbol ()) {
175 function.modifiers = CCodeModifiers.STATIC;
176 } else if (context.hide_internal && cl.is_internal_symbol ()) {
177 function.modifiers = CCodeModifiers.INTERNAL;
180 function.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl))));
182 decl_space.add_function_declaration (function);
186 if (is_gtypeinstance) {
187 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%sClass".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("%sClass".printf (get_ccode_name (cl)))));
189 var type_fun = new ClassRegisterFunction (cl);
190 type_fun.init_from_type (context, in_plugin, true);
191 decl_space.add_type_member_declaration (type_fun.get_declaration ());
195 public override void generate_class_struct_declaration (Class cl, CCodeFile decl_space) {
196 if (add_symbol_declaration (decl_space, cl, "struct _%s".printf (get_ccode_name (cl)))) {
197 return;
200 if (cl.base_class != null) {
201 // base class declaration
202 generate_class_struct_declaration (cl.base_class, decl_space);
204 foreach (DataType base_type in cl.get_base_types ()) {
205 var iface = base_type.data_type as Interface;
206 if (iface != null) {
207 generate_interface_declaration (iface, decl_space);
211 generate_class_declaration (cl, decl_space);
213 bool is_gtypeinstance = !cl.is_compact;
214 bool is_fundamental = is_gtypeinstance && cl.base_class == null;
215 bool is_gsource = cl.base_class == gsource_type;
217 var instance_struct = new CCodeStruct ("_%s".printf (get_ccode_name (cl)));
218 var type_struct = new CCodeStruct ("_%sClass".printf (get_ccode_name (cl)));
220 if (cl.base_class != null) {
221 instance_struct.add_field (get_ccode_name (cl.base_class), "parent_instance");
222 } else if (is_fundamental) {
223 decl_space.add_include ("glib-object.h");
224 instance_struct.add_field ("GTypeInstance", "parent_instance");
225 instance_struct.add_field ("volatile int", "ref_count");
228 if (cl.is_compact && cl.base_class == null && cl.get_fields ().size == 0) {
229 // add dummy member, C doesn't allow empty structs
230 instance_struct.add_field ("int", "dummy");
233 if (is_gtypeinstance) {
234 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %sPrivate".printf (instance_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (get_ccode_name (cl)))));
236 instance_struct.add_field ("%sPrivate *".printf (get_ccode_name (cl)), "priv");
237 if (is_fundamental) {
238 type_struct.add_field ("GTypeClass", "parent_class");
239 } else {
240 type_struct.add_field ("%sClass".printf (get_ccode_name (cl.base_class)), "parent_class");
243 if (is_fundamental) {
244 type_struct.add_field ("void", "(*finalize) (%s *self)".printf (get_ccode_name (cl)));
248 foreach (Method m in cl.get_methods ()) {
249 generate_virtual_method_declaration (m, decl_space, type_struct);
252 foreach (Signal sig in cl.get_signals ()) {
253 if (sig.default_handler != null) {
254 generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
258 foreach (Property prop in cl.get_properties ()) {
259 if (!prop.is_abstract && !prop.is_virtual) {
260 continue;
262 generate_type_declaration (prop.property_type, decl_space);
264 var t = (ObjectTypeSymbol) prop.parent_symbol;
266 var this_type = new ObjectType (t);
267 var cselfparam = new CCodeParameter ("self", get_ccode_name (this_type));
269 if (prop.get_accessor != null) {
270 var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name));
271 vdeclarator.add_parameter (cselfparam);
272 string creturn_type;
273 if (prop.property_type.is_real_non_null_struct_type ()) {
274 var cvalueparam = new CCodeParameter ("result", "%s *".printf (get_ccode_name (prop.get_accessor.value_type)));
275 vdeclarator.add_parameter (cvalueparam);
276 creturn_type = "void";
277 } else {
278 creturn_type = get_ccode_name (prop.get_accessor.value_type);
281 var array_type = prop.property_type as ArrayType;
282 if (array_type != null) {
283 for (int dim = 1; dim <= array_type.rank; dim++) {
284 vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("result", dim), "int*"));
286 } else if ((prop.property_type is DelegateType) && ((DelegateType) prop.property_type).delegate_symbol.has_target) {
287 vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_cname ("result"), "gpointer*"));
290 var vdecl = new CCodeDeclaration (creturn_type);
291 vdecl.add_declarator (vdeclarator);
292 type_struct.add_declaration (vdecl);
294 if (prop.set_accessor != null) {
295 CCodeParameter cvalueparam;
296 if (prop.property_type.is_real_non_null_struct_type ()) {
297 cvalueparam = new CCodeParameter ("value", "%s *".printf (get_ccode_name (prop.set_accessor.value_type)));
298 } else {
299 cvalueparam = new CCodeParameter ("value", get_ccode_name (prop.set_accessor.value_type));
302 var vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name));
303 vdeclarator.add_parameter (cselfparam);
304 vdeclarator.add_parameter (cvalueparam);
306 var array_type = prop.property_type as ArrayType;
307 if (array_type != null) {
308 for (int dim = 1; dim <= array_type.rank; dim++) {
309 vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("value", dim), "int"));
311 } else if ((prop.property_type is DelegateType) && ((DelegateType) prop.property_type).delegate_symbol.has_target) {
312 vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_cname ("value"), "gpointer"));
315 var vdecl = new CCodeDeclaration ("void");
316 vdecl.add_declarator (vdeclarator);
317 type_struct.add_declaration (vdecl);
321 foreach (Field f in cl.get_fields ()) {
322 if (f.access != SymbolAccessibility.PRIVATE) {
323 CCodeModifiers modifiers = (f.is_volatile ? CCodeModifiers.VOLATILE : 0) | (f.version.deprecated ? CCodeModifiers.DEPRECATED : 0);
324 if (f.binding == MemberBinding.INSTANCE) {
325 generate_type_declaration (f.variable_type, decl_space);
327 instance_struct.add_field (get_ccode_name (f.variable_type), get_ccode_name (f), modifiers, get_ccode_declarator_suffix (f.variable_type));
328 if (f.variable_type is ArrayType && get_ccode_array_length (f)) {
329 // create fields to store array dimensions
330 var array_type = (ArrayType) f.variable_type;
332 if (!array_type.fixed_length) {
333 var len_type = int_type.copy ();
335 for (int dim = 1; dim <= array_type.rank; dim++) {
336 string length_cname;
337 if (get_ccode_array_length_name (f) != null) {
338 length_cname = get_ccode_array_length_name (f);
339 } else {
340 length_cname = get_array_length_cname (get_ccode_name (f), dim);
342 instance_struct.add_field (get_ccode_name (len_type), length_cname);
345 if (array_type.rank == 1 && f.is_internal_symbol ()) {
346 instance_struct.add_field (get_ccode_name (len_type), get_array_size_cname (get_ccode_name (f)));
349 } else if (f.variable_type is DelegateType) {
350 var delegate_type = (DelegateType) f.variable_type;
351 if (delegate_type.delegate_symbol.has_target) {
352 // create field to store delegate target
353 instance_struct.add_field ("gpointer", get_ccode_delegate_target_name (f));
354 if (delegate_type.is_disposable ()) {
355 instance_struct.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_ccode_name (f)));
359 } else if (f.binding == MemberBinding.CLASS) {
360 type_struct.add_field (get_ccode_name (f.variable_type), get_ccode_name (f), modifiers);
365 if (!cl.is_compact || cl.base_class == null || is_gsource) {
366 // derived compact classes do not have a struct
367 decl_space.add_type_definition (instance_struct);
370 if (is_gtypeinstance) {
371 decl_space.add_type_definition (type_struct);
375 public virtual void generate_virtual_method_declaration (Method m, CCodeFile decl_space, CCodeStruct type_struct) {
376 if (!m.is_abstract && !m.is_virtual) {
377 return;
380 var creturn_type = m.return_type;
381 if (m.return_type.is_real_non_null_struct_type ()) {
382 // structs are returned via out parameter
383 creturn_type = new VoidType ();
386 // add vfunc field to the type struct
387 var vdeclarator = new CCodeFunctionDeclarator (get_ccode_vfunc_name (m));
388 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
390 if (m.printf_format) {
391 vdeclarator.modifiers |= CCodeModifiers.PRINTF;
392 } else if (m.scanf_format) {
393 vdeclarator.modifiers |= CCodeModifiers.SCANF;
396 if (m.version.deprecated) {
397 vdeclarator.modifiers |= CCodeModifiers.DEPRECATED;
400 generate_cparameters (m, decl_space, cparam_map, new CCodeFunction ("fake"), vdeclarator);
402 var vdecl = new CCodeDeclaration (get_ccode_name (creturn_type));
403 vdecl.add_declarator (vdeclarator);
404 type_struct.add_declaration (vdecl);
407 void generate_class_private_declaration (Class cl, CCodeFile decl_space) {
408 if (decl_space.add_declaration ("%sPrivate".printf (get_ccode_name (cl)))) {
409 return;
412 bool is_gtypeinstance = !cl.is_compact;
413 bool has_class_locks = false;
415 var instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (get_ccode_name (cl)));
416 var type_priv_struct = new CCodeStruct ("_%sClassPrivate".printf (get_ccode_name (cl)));
418 if (is_gtypeinstance) {
419 /* create type, dup_func, and destroy_func fields for generic types */
420 foreach (TypeParameter type_param in cl.get_type_parameters ()) {
421 string func_name;
423 func_name = "%s_type".printf (type_param.name.down ());
424 instance_priv_struct.add_field ("GType", func_name);
426 func_name = "%s_dup_func".printf (type_param.name.down ());
427 instance_priv_struct.add_field ("GBoxedCopyFunc", func_name);
429 func_name = "%s_destroy_func".printf (type_param.name.down ());
430 instance_priv_struct.add_field ("GDestroyNotify", func_name);
434 foreach (Field f in cl.get_fields ()) {
435 CCodeModifiers modifiers = (f.is_volatile ? CCodeModifiers.VOLATILE : 0) | (f.version.deprecated ? CCodeModifiers.DEPRECATED : 0);
436 if (f.binding == MemberBinding.INSTANCE) {
437 if (f.access == SymbolAccessibility.PRIVATE) {
438 generate_type_declaration (f.variable_type, decl_space);
440 instance_priv_struct.add_field (get_ccode_name (f.variable_type), get_ccode_name (f), modifiers, get_ccode_declarator_suffix (f.variable_type));
441 if (f.variable_type is ArrayType && get_ccode_array_length (f)) {
442 // create fields to store array dimensions
443 var array_type = (ArrayType) f.variable_type;
444 var len_type = int_type.copy ();
446 if (!array_type.fixed_length) {
447 for (int dim = 1; dim <= array_type.rank; dim++) {
448 string length_cname;
449 if (get_ccode_array_length_name (f) != null) {
450 length_cname = get_ccode_array_length_name (f);
451 } else {
452 length_cname = get_array_length_cname (get_ccode_name (f), dim);
454 instance_priv_struct.add_field (get_ccode_name (len_type), length_cname);
457 if (array_type.rank == 1 && f.is_internal_symbol ()) {
458 instance_priv_struct.add_field (get_ccode_name (len_type), get_array_size_cname (get_ccode_name (f)));
461 } else if (f.variable_type is DelegateType) {
462 var delegate_type = (DelegateType) f.variable_type;
463 if (delegate_type.delegate_symbol.has_target) {
464 // create field to store delegate target
465 instance_priv_struct.add_field ("gpointer", get_ccode_delegate_target_name (f));
466 if (delegate_type.is_disposable ()) {
467 instance_priv_struct.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_ccode_name (f)));
473 if (f.get_lock_used ()) {
474 cl.has_private_fields = true;
475 // add field for mutex
476 instance_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (f)));
478 } else if (f.binding == MemberBinding.CLASS) {
479 if (f.access == SymbolAccessibility.PRIVATE) {
480 type_priv_struct.add_field (get_ccode_name (f.variable_type), get_ccode_name (f), modifiers);
483 if (f.get_lock_used ()) {
484 has_class_locks = true;
485 // add field for mutex
486 type_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (f)));
491 foreach (Property prop in cl.get_properties ()) {
492 if (prop.binding == MemberBinding.INSTANCE) {
493 if (prop.get_lock_used ()) {
494 cl.has_private_fields = true;
495 // add field for mutex
496 instance_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (prop.name));
498 } else if (prop.binding == MemberBinding.CLASS) {
499 if (prop.get_lock_used ()) {
500 has_class_locks = true;
501 // add field for mutex
502 type_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (prop.name));
507 if (is_gtypeinstance) {
508 if (cl.has_class_private_fields || has_class_locks) {
509 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_priv_struct.name), new CCodeVariableDeclarator ("%sClassPrivate".printf (get_ccode_name (cl)))));
512 /* only add the *Private struct if it is not empty, i.e. we actually have private data */
513 if (cl.has_private_fields || cl.get_type_parameters ().size > 0) {
514 decl_space.add_type_definition (instance_priv_struct);
515 var macro = "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (get_ccode_type_id (cl), get_ccode_name (cl));
516 decl_space.add_type_member_declaration (new CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (get_ccode_upper_case_name (cl, null)), macro));
519 if (cl.has_class_private_fields || has_class_locks) {
520 decl_space.add_type_member_declaration (type_priv_struct);
522 string macro = "(G_TYPE_CLASS_GET_PRIVATE (klass, %s, %sClassPrivate))".printf (get_ccode_type_id (cl), get_ccode_name (cl));
523 decl_space.add_type_member_declaration (new CCodeMacroReplacement ("%s_GET_CLASS_PRIVATE(klass)".printf (get_ccode_upper_case_name (cl, null)), macro));
525 } else {
526 if (cl.has_private_fields) {
527 Report.error (cl.source_reference, "Private fields not supported in compact classes");
532 public override void visit_class (Class cl) {
533 push_context (new EmitContext (cl));
534 push_line (cl.source_reference);
536 var old_param_spec_struct = param_spec_struct;
537 var old_prop_enum = prop_enum;
538 var old_signal_enum = signal_enum;
539 var old_class_init_context = class_init_context;
540 var old_base_init_context = base_init_context;
541 var old_class_finalize_context = class_finalize_context;
542 var old_base_finalize_context = base_finalize_context;
543 var old_instance_init_context = instance_init_context;
544 var old_instance_finalize_context = instance_finalize_context;
546 bool is_gtypeinstance = !cl.is_compact;
547 bool is_fundamental = is_gtypeinstance && cl.base_class == null;
549 if (get_ccode_name (cl).length < 3) {
550 cl.error = true;
551 Report.error (cl.source_reference, "Class name `%s' is too short".printf (get_ccode_name (cl)));
552 return;
555 prop_enum = new CCodeEnum ();
556 prop_enum.add_value (new CCodeEnumValue ("%s_0_PROPERTY".printf (get_ccode_upper_case_name (cl, null))));
557 signal_enum = new CCodeEnum ();
558 class_init_context = new EmitContext (cl);
559 base_init_context = new EmitContext (cl);
560 class_finalize_context = new EmitContext (cl);
561 base_finalize_context = new EmitContext (cl);
562 instance_init_context = new EmitContext (cl);
563 instance_finalize_context = new EmitContext (cl);
565 generate_class_struct_declaration (cl, cfile);
566 generate_class_private_declaration (cl, cfile);
568 var last_prop = "%s_NUM_PROPERTIES".printf (get_ccode_upper_case_name (cl));
569 if (is_gtypeinstance) {
570 cfile.add_type_declaration (prop_enum);
572 var prop_array_decl = new CCodeDeclaration ("GParamSpec*");
573 prop_array_decl.modifiers |= CCodeModifiers.STATIC;
574 prop_array_decl.add_declarator (new CCodeVariableDeclarator ("%s_properties".printf (get_ccode_lower_case_name (cl)), null, new CCodeDeclaratorSuffix.with_array (new CCodeIdentifier (last_prop))));
575 cfile.add_type_declaration (prop_array_decl);
578 if (!cl.is_internal_symbol ()) {
579 generate_class_struct_declaration (cl, header_file);
581 if (!cl.is_private_symbol ()) {
582 generate_class_struct_declaration (cl, internal_header_file);
585 if (is_gtypeinstance) {
586 begin_base_init_function (cl);
587 begin_class_init_function (cl);
588 begin_instance_init_function (cl);
590 begin_base_finalize_function (cl);
591 begin_class_finalize_function (cl);
592 begin_finalize_function (cl);
593 } else {
594 if (cl.base_class == null || cl.base_class == gsource_type) {
595 begin_instance_init_function (cl);
596 begin_finalize_function (cl);
600 cl.accept_children (this);
602 if (is_gtypeinstance) {
603 if (is_fundamental) {
604 param_spec_struct = new CCodeStruct ( "_%sParamSpec%s".printf(get_ccode_prefix (cl.parent_symbol), cl.name));
605 param_spec_struct.add_field ("GParamSpec", "parent_instance");
606 cfile.add_type_definition (param_spec_struct);
608 cfile.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (param_spec_struct.name), new CCodeVariableDeclarator ( "%sParamSpec%s".printf(get_ccode_prefix (cl.parent_symbol), cl.name))));
611 gvaluecollector_h_needed = true;
613 add_type_value_table_init_function (cl);
614 add_type_value_table_free_function (cl);
615 add_type_value_table_copy_function (cl);
616 add_type_value_table_peek_pointer_function (cl);
617 add_type_value_table_collect_value_function (cl);
618 add_type_value_table_lcopy_value_function (cl);
619 add_g_param_spec_type_function (cl);
620 add_g_value_get_function (cl);
621 add_g_value_set_function (cl);
622 add_g_value_take_function (cl);
624 var ref_count = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count"), new CCodeConstant ("1"));
625 push_context (instance_init_context);
626 ccode.add_expression (ref_count);
627 pop_context ();
630 prop_enum.add_value (new CCodeEnumValue (last_prop));
632 if (cl.get_signals ().size > 0) {
633 var last_signal = "%s_NUM_SIGNALS".printf (get_ccode_upper_case_name (cl));
634 signal_enum.add_value (new CCodeEnumValue (last_signal));
635 cfile.add_type_declaration (signal_enum);
637 var signal_array_decl = new CCodeDeclaration ("guint");
638 signal_array_decl.modifiers |= CCodeModifiers.STATIC;
639 signal_array_decl.add_declarator (new CCodeVariableDeclarator ("%s_signals".printf (get_ccode_lower_case_name (cl)), new CCodeConstant ("{0}"), new CCodeDeclaratorSuffix.with_array (new CCodeIdentifier (last_signal))));
640 cfile.add_type_declaration (signal_array_decl);
644 if (cl.class_constructor != null) {
645 add_base_init_function (cl);
647 add_class_init_function (cl);
649 if (cl.class_destructor != null) {
650 add_base_finalize_function (cl);
653 if (cl.static_destructor != null) {
654 add_class_finalize_function (cl);
657 foreach (DataType base_type in cl.get_base_types ()) {
658 if (base_type.data_type is Interface) {
659 add_interface_init_function (cl, (Interface) base_type.data_type);
663 add_instance_init_function (cl);
665 if (!cl.is_compact && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) {
666 add_finalize_function (cl);
669 if (cl.comment != null) {
670 cfile.add_type_member_definition (new CCodeComment (cl.comment.content));
673 var type_fun = new ClassRegisterFunction (cl);
674 type_fun.init_from_type (context, in_plugin, false);
675 cfile.add_type_member_declaration (type_fun.get_source_declaration ());
676 cfile.add_type_member_definition (type_fun.get_definition ());
678 if (is_fundamental) {
679 var ref_count = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count");
681 // ref function
682 var ref_fun = new CCodeFunction ("%sref".printf (get_ccode_lower_case_prefix (cl)), "gpointer");
683 ref_fun.add_parameter (new CCodeParameter ("instance", "gpointer"));
684 if (cl.is_private_symbol ()) {
685 ref_fun.modifiers = CCodeModifiers.STATIC;
686 } else if (context.hide_internal && cl.is_internal_symbol ()) {
687 ref_fun.modifiers = CCodeModifiers.INTERNAL;
689 push_function (ref_fun);
691 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self", new CCodeIdentifier ("instance")));
692 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_inc"));
693 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ref_count));
694 ccode.add_expression (ccall);
695 ccode.add_return (new CCodeIdentifier ("instance"));
697 pop_function ();
698 cfile.add_function (ref_fun);
700 // unref function
701 var unref_fun = new CCodeFunction ("%sunref".printf (get_ccode_lower_case_prefix (cl)), "void");
702 unref_fun.add_parameter (new CCodeParameter ("instance", "gpointer"));
703 if (cl.is_private_symbol ()) {
704 unref_fun.modifiers = CCodeModifiers.STATIC;
705 } else if (context.hide_internal && cl.is_internal_symbol ()) {
706 unref_fun.modifiers = CCodeModifiers.INTERNAL;
708 push_function (unref_fun);
710 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self", new CCodeIdentifier ("instance")));
711 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_dec_and_test"));
712 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ref_count));
713 ccode.open_if (ccall);
715 var get_class = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS".printf (get_ccode_upper_case_name (cl, null))));
716 get_class.add_argument (new CCodeIdentifier ("self"));
718 // finalize class
719 var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS".printf (get_ccode_upper_case_name (cl, null))));
720 ccast.add_argument (new CCodeIdentifier ("self"));
721 ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize"));
722 ccall.add_argument (new CCodeIdentifier ("self"));
723 ccode.add_expression (ccall);
725 // free type instance
726 var free = new CCodeFunctionCall (new CCodeIdentifier ("g_type_free_instance"));
727 free.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GTypeInstance *"));
728 ccode.add_expression (free);
730 ccode.close ();
731 pop_function ();
732 cfile.add_function (unref_fun);
734 } else {
735 if (cl.base_class == null || cl.base_class == gsource_type) {
736 // derived compact classes do not have fields
737 add_instance_init_function (cl);
738 add_finalize_function (cl);
742 param_spec_struct = old_param_spec_struct;
743 prop_enum = old_prop_enum;
744 signal_enum = old_signal_enum;
745 class_init_context = old_class_init_context;
746 base_init_context = old_base_init_context;
747 class_finalize_context = old_class_finalize_context;
748 base_finalize_context = old_base_finalize_context;
749 instance_init_context = old_instance_init_context;
750 instance_finalize_context = old_instance_finalize_context;
752 pop_line ();
753 pop_context ();
756 private void add_type_value_table_init_function (Class cl) {
757 var function = new CCodeFunction ("%s_init".printf (get_ccode_lower_case_name (cl, "value_")), "void");
758 function.add_parameter (new CCodeParameter ("value", "GValue*"));
759 function.modifiers = CCodeModifiers.STATIC;
761 push_function (function);
762 ccode.add_assignment (new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer"), new CCodeConstant ("NULL"));
763 pop_function ();
764 cfile.add_function (function);
767 private void add_type_value_table_free_function (Class cl) {
768 var function = new CCodeFunction ("%s_free_value".printf (get_ccode_lower_case_name (cl, "value_")), "void");
769 function.add_parameter (new CCodeParameter ("value", "GValue*"));
770 function.modifiers = CCodeModifiers.STATIC;
772 push_function (function);
774 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
775 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%sunref".printf (get_ccode_lower_case_prefix (cl))));
776 ccall.add_argument (vpointer);
778 ccode.open_if (vpointer);
779 ccode.add_expression (ccall);
780 ccode.close ();
782 pop_function ();
783 cfile.add_function (function);
786 private void add_type_value_table_copy_function (Class cl) {
787 var function = new CCodeFunction ("%s_copy_value".printf (get_ccode_lower_case_name (cl, "value_")), "void");
788 function.add_parameter (new CCodeParameter ("src_value", "const GValue*"));
789 function.add_parameter (new CCodeParameter ("dest_value", "GValue*"));
790 function.modifiers = CCodeModifiers.STATIC;
792 push_function (function);
794 var dest_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dest_value"), "data[0]"), "v_pointer");
795 var src_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("src_value"), "data[0]"), "v_pointer");
797 var ref_ccall = new CCodeFunctionCall (new CCodeIdentifier ("%sref".printf (get_ccode_lower_case_prefix (cl))));
798 ref_ccall.add_argument ( src_vpointer );
800 ccode.open_if (src_vpointer);
801 ccode.add_assignment (dest_vpointer, ref_ccall);
802 ccode.add_else ();
803 ccode.add_assignment (dest_vpointer, new CCodeConstant ("NULL"));
804 ccode.close ();
806 pop_function ();
807 cfile.add_function (function);
810 private void add_type_value_table_peek_pointer_function (Class cl) {
811 var function = new CCodeFunction ("%s_peek_pointer".printf (get_ccode_lower_case_name (cl, "value_")), "gpointer");
812 function.add_parameter (new CCodeParameter ("value", "const GValue*"));
813 function.modifiers = CCodeModifiers.STATIC;
815 push_function (function);
817 var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
818 ccode.add_return (vpointer);
820 pop_function ();
821 cfile.add_function (function);
824 private void add_type_value_table_lcopy_value_function ( Class cl ) {
825 var function = new CCodeFunction ("%s_lcopy_value".printf (get_ccode_lower_case_name (cl, "value_")), "gchar*");
826 function.add_parameter (new CCodeParameter ("value", "const GValue*"));
827 function.add_parameter (new CCodeParameter ("n_collect_values", "guint"));
828 function.add_parameter (new CCodeParameter ("collect_values", "GTypeCValue*"));
829 function.add_parameter (new CCodeParameter ("collect_flags", "guint"));
830 function.modifiers = CCodeModifiers.STATIC;
832 var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
833 var object_p_ptr = new CCodeIdentifier ("*object_p");
834 var null_ = new CCodeConstant ("NULL");
836 push_function (function);
838 ccode.add_declaration ("%s **".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("object_p", new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"), "v_pointer")));
840 var value_type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME"));
841 value_type_name_fct.add_argument (new CCodeConstant ("value"));
843 var assert_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("object_p"));
844 ccode.open_if (assert_condition);
845 var assert_printf = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup_printf"));
846 assert_printf.add_argument (new CCodeConstant ("\"value location for `%s' passed as NULL\""));
847 assert_printf.add_argument (value_type_name_fct);
848 ccode.add_return (assert_printf);
849 ccode.close ();
851 var main_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, vpointer);
852 var main_else_if_condition = new CCodeBinaryExpression (CCodeBinaryOperator.BITWISE_AND, new CCodeIdentifier ("collect_flags"), new CCodeIdentifier ("G_VALUE_NOCOPY_CONTENTS"));
853 var ref_fct = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl)));
854 ref_fct.add_argument (vpointer);
855 ccode.open_if (main_condition);
856 ccode.add_assignment (object_p_ptr, null_);
857 ccode.else_if (main_else_if_condition);
858 ccode.add_assignment (object_p_ptr, vpointer);
859 ccode.add_else ();
860 ccode.add_assignment (object_p_ptr, ref_fct);
861 ccode.close ();
863 ccode.add_return (null_);
864 pop_function ();
865 cfile.add_function (function);
868 private void add_type_value_table_collect_value_function (Class cl) {
869 var function = new CCodeFunction ("%s_collect_value".printf (get_ccode_lower_case_name (cl, "value_")), "gchar*");
870 function.add_parameter (new CCodeParameter ("value", "GValue*"));
871 function.add_parameter (new CCodeParameter ("n_collect_values", "guint"));
872 function.add_parameter (new CCodeParameter ("collect_values", "GTypeCValue*"));
873 function.add_parameter (new CCodeParameter ("collect_flags", "guint"));
874 function.modifiers = CCodeModifiers.STATIC;
876 var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
878 push_function (function);
880 var collect_vpointer = new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"), "v_pointer");
882 ccode.open_if (collect_vpointer);
883 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("object", collect_vpointer));
884 var obj_identifier = new CCodeIdentifier ("object");
885 var l_expression = new CCodeMemberAccess (new CCodeMemberAccess.pointer (obj_identifier, "parent_instance"), "g_class");
886 var sub_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, l_expression, new CCodeConstant ("NULL"));
887 var value_type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME"));
888 value_type_name_fct.add_argument (new CCodeConstant ("value"));
890 ccode.open_if (sub_condition);
891 var true_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat"));
892 true_return.add_argument (new CCodeConstant ("\"invalid unclassed object pointer for value type `\""));
893 true_return.add_argument (value_type_name_fct);
894 true_return.add_argument (new CCodeConstant ("\"'\""));
895 true_return.add_argument (new CCodeConstant ("NULL"));
896 ccode.add_return (true_return);
898 var reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
899 var type_check = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
900 type_check.add_argument (new CCodeIdentifier ("object"));
901 reg_call.add_argument (type_check);
902 var stored_type = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
903 stored_type.add_argument (new CCodeIdentifier ("value"));
904 reg_call.add_argument (stored_type);
906 ccode.else_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, reg_call));
907 var false_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat"));
908 var type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("g_type_name"));
909 type_name_fct.add_argument (type_check);
910 false_return.add_argument (new CCodeConstant ("\"invalid object type `\""));
911 false_return.add_argument (type_name_fct);
912 false_return.add_argument (new CCodeConstant ("\"' for value type `\""));
913 false_return.add_argument (value_type_name_fct);
914 false_return.add_argument (new CCodeConstant ("\"'\""));
915 false_return.add_argument (new CCodeConstant ("NULL"));
916 ccode.add_return (false_return);
918 ccode.close ();
920 var ref_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl)));
921 ref_call.add_argument (new CCodeIdentifier ("object"));
922 ccode.add_assignment (vpointer, ref_call);
924 ccode.add_else ();
925 ccode.add_assignment (vpointer, new CCodeConstant ("NULL"));
927 ccode.close ();
929 ccode.add_return (new CCodeConstant ("NULL"));
931 pop_function ();
932 cfile.add_function (function);
935 private void add_g_param_spec_type_function (Class cl) {
936 string function_name = get_ccode_lower_case_name (cl, "param_spec_");
938 var function = new CCodeFunction (function_name, "GParamSpec*");
939 function.add_parameter (new CCodeParameter ("name", "const gchar*"));
940 function.add_parameter (new CCodeParameter ("nick", "const gchar*"));
941 function.add_parameter (new CCodeParameter ("blurb", "const gchar*"));
942 function.add_parameter (new CCodeParameter ("object_type", "GType"));
943 function.add_parameter (new CCodeParameter ("flags", "GParamFlags"));
945 if (cl.is_private_symbol ()) {
946 function.modifiers = CCodeModifiers.STATIC;
947 } else if (context.hide_internal && cl.is_internal_symbol ()) {
948 function.modifiers = CCodeModifiers.INTERNAL;
951 push_function (function);
953 ccode.add_declaration ("%sParamSpec%s*".printf (get_ccode_prefix (cl.parent_symbol), cl.name), new CCodeVariableDeclarator ("spec"));
955 var subccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_is_a"));
956 subccall.add_argument (new CCodeIdentifier ("object_type"));
957 subccall.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
959 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail"));
960 ccall.add_argument (subccall);
961 ccall.add_argument (new CCodeIdentifier ("NULL"));
962 ccode.add_expression (ccall);
964 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_internal"));
965 ccall.add_argument (new CCodeIdentifier ( "G_TYPE_PARAM_OBJECT" ));
966 ccall.add_argument (new CCodeIdentifier ("name"));
967 ccall.add_argument (new CCodeIdentifier ("nick"));
968 ccall.add_argument (new CCodeIdentifier ("blurb"));
969 ccall.add_argument (new CCodeIdentifier ("flags"));
971 ccode.add_assignment (new CCodeIdentifier ("spec"), ccall);
973 ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_PARAM_SPEC"));
974 ccall.add_argument (new CCodeIdentifier ("spec"));
976 ccode.add_assignment (new CCodeMemberAccess.pointer (ccall, "value_type"), new CCodeIdentifier ("object_type"));
977 ccode.add_return (ccall);
979 pop_function ();
980 cfile.add_function (function);
983 private void add_g_value_set_function (Class cl) {
984 var function = new CCodeFunction (get_ccode_set_value_function (cl), "void");
985 function.add_parameter (new CCodeParameter ("value", "GValue*"));
986 function.add_parameter (new CCodeParameter ("v_object", "gpointer"));
988 if (cl.is_private_symbol ()) {
989 function.modifiers = CCodeModifiers.STATIC;
990 } else if (context.hide_internal && cl.is_internal_symbol ()) {
991 function.modifiers = CCodeModifiers.INTERNAL;
994 var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
996 push_function (function);
998 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("old"));
1000 var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1001 ccall_typecheck.add_argument (new CCodeIdentifier ( "value" ));
1002 ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
1004 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1005 ccall.add_argument (ccall_typecheck);
1006 ccode.add_expression (ccall);
1008 ccode.add_assignment (new CCodeConstant ("old"), vpointer);
1010 ccode.open_if (new CCodeIdentifier ("v_object"));
1011 ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
1012 ccall_typecheck.add_argument (new CCodeIdentifier ( "v_object" ));
1013 ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
1015 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1016 ccall.add_argument (ccall_typecheck);
1017 ccode.add_expression (ccall);
1019 var ccall_typefrominstance = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
1020 ccall_typefrominstance.add_argument (new CCodeIdentifier ( "v_object" ));
1022 var ccall_gvaluetype = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
1023 ccall_gvaluetype.add_argument (new CCodeIdentifier ( "value" ));
1025 var ccall_typecompatible = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
1026 ccall_typecompatible.add_argument (ccall_typefrominstance);
1027 ccall_typecompatible.add_argument (ccall_gvaluetype);
1029 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1030 ccall.add_argument (ccall_typecompatible);
1031 ccode.add_expression (ccall);
1033 ccode.add_assignment (vpointer, new CCodeConstant ("v_object"));
1035 ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl)));
1036 ccall.add_argument (vpointer);
1037 ccode.add_expression (ccall);
1039 ccode.add_else ();
1040 ccode.add_assignment (vpointer, new CCodeConstant ("NULL"));
1041 ccode.close ();
1043 ccode.open_if (new CCodeIdentifier ("old"));
1044 ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (cl)));
1045 ccall.add_argument (new CCodeIdentifier ("old"));
1046 ccode.add_expression (ccall);
1047 ccode.close ();
1049 pop_function ();
1050 cfile.add_function (function);
1053 private void add_g_value_take_function (Class cl) {
1054 var function = new CCodeFunction (get_ccode_take_value_function (cl), "void");
1055 function.add_parameter (new CCodeParameter ("value", "GValue*"));
1056 function.add_parameter (new CCodeParameter ("v_object", "gpointer"));
1058 if (cl.is_private_symbol ()) {
1059 function.modifiers = CCodeModifiers.STATIC;
1060 } else if (context.hide_internal && cl.is_internal_symbol ()) {
1061 function.modifiers = CCodeModifiers.INTERNAL;
1064 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
1066 push_function (function);
1068 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("old"));
1070 var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1071 ccall_typecheck.add_argument (new CCodeIdentifier ( "value" ));
1072 ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
1074 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1075 ccall.add_argument (ccall_typecheck);
1076 ccode.add_expression (ccall);
1078 ccode.add_assignment (new CCodeConstant ("old"), vpointer);
1080 ccode.open_if (new CCodeIdentifier ("v_object"));
1082 ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
1083 ccall_typecheck.add_argument (new CCodeIdentifier ( "v_object" ));
1084 ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
1086 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1087 ccall.add_argument (ccall_typecheck);
1088 ccode.add_expression (ccall);
1090 var ccall_typefrominstance = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
1091 ccall_typefrominstance.add_argument (new CCodeIdentifier ( "v_object" ));
1093 var ccall_gvaluetype = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
1094 ccall_gvaluetype.add_argument (new CCodeIdentifier ( "value" ));
1096 var ccall_typecompatible = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
1097 ccall_typecompatible.add_argument (ccall_typefrominstance);
1098 ccall_typecompatible.add_argument (ccall_gvaluetype);
1100 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1101 ccall.add_argument (ccall_typecompatible);
1102 ccode.add_expression (ccall);
1104 ccode.add_assignment (vpointer, new CCodeConstant ("v_object"));
1106 ccode.add_else ();
1107 ccode.add_assignment (vpointer, new CCodeConstant ("NULL"));
1108 ccode.close ();
1110 ccode.open_if (new CCodeIdentifier ("old"));
1111 ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (cl)));
1112 ccall.add_argument (new CCodeIdentifier ("old"));
1113 ccode.add_expression (ccall);
1114 ccode.close ();
1116 pop_function ();
1117 cfile.add_function (function);
1120 private void add_g_value_get_function (Class cl) {
1121 var function = new CCodeFunction (get_ccode_get_value_function (cl), "gpointer");
1122 function.add_parameter (new CCodeParameter ("value", "const GValue*"));
1124 if (cl.is_private_symbol ()) {
1125 function.modifiers = CCodeModifiers.STATIC;
1126 } else if (context.hide_internal && cl.is_internal_symbol ()) {
1127 function.modifiers = CCodeModifiers.INTERNAL;
1130 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
1132 push_function (function);
1134 var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1135 ccall_typecheck.add_argument (new CCodeIdentifier ("value"));
1136 ccall_typecheck.add_argument (new CCodeIdentifier (get_ccode_type_id (cl)));
1138 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail"));
1139 ccall.add_argument (ccall_typecheck);
1140 ccall.add_argument (new CCodeIdentifier ("NULL"));
1141 ccode.add_expression (ccall);
1143 ccode.add_return (vpointer);
1145 pop_function ();
1146 cfile.add_function (function);
1149 private void begin_base_init_function (Class cl) {
1150 push_context (base_init_context);
1152 var base_init = new CCodeFunction ("%s_base_init".printf (get_ccode_lower_case_name (cl, null)), "void");
1153 base_init.add_parameter (new CCodeParameter ("klass", "%sClass *".printf (get_ccode_name (cl))));
1154 base_init.modifiers = CCodeModifiers.STATIC;
1156 push_function (base_init);
1158 pop_context ();
1161 private void add_base_init_function (Class cl) {
1162 cfile.add_function (base_init_context.ccode);
1165 public virtual void generate_class_init (Class cl) {
1168 public virtual void end_instance_init (Class cl) {
1171 private void begin_class_init_function (Class cl) {
1172 push_context (class_init_context);
1174 var func = new CCodeFunction ("%s_class_init".printf (get_ccode_lower_case_name (cl, null)));
1175 func.add_parameter (new CCodeParameter ("klass", "%sClass *".printf (get_ccode_name (cl))));
1176 func.modifiers = CCodeModifiers.STATIC;
1178 CCodeFunctionCall ccall;
1180 /* save pointer to parent class */
1181 var parent_decl = new CCodeDeclaration ("gpointer");
1182 var parent_var_decl = new CCodeVariableDeclarator ("%s_parent_class".printf (get_ccode_lower_case_name (cl, null)));
1183 parent_var_decl.initializer = new CCodeConstant ("NULL");
1184 parent_decl.add_declarator (parent_var_decl);
1185 parent_decl.modifiers = CCodeModifiers.STATIC;
1186 cfile.add_type_member_declaration (parent_decl);
1188 push_function (func);
1190 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek_parent"));
1191 ccall.add_argument (new CCodeIdentifier ("klass"));
1192 var parent_assignment = new CCodeAssignment (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (cl, null))), ccall);
1193 ccode.add_expression (parent_assignment);
1196 if (!cl.is_compact && !cl.is_subtype_of (gobject_type) && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) {
1197 // set finalize function
1198 var fundamental_class = cl;
1199 while (fundamental_class.base_class != null) {
1200 fundamental_class = fundamental_class.base_class;
1203 var ccast = new CCodeCastExpression (new CCodeIdentifier ("klass"), "%sClass *".printf (get_ccode_name (fundamental_class)));
1204 var finalize_assignment = new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "finalize"), new CCodeIdentifier ("%sfinalize".printf (get_ccode_lower_case_prefix (cl))));
1205 ccode.add_expression (finalize_assignment);
1208 /* add struct for private fields */
1209 if (cl.has_private_fields || cl.get_type_parameters ().size > 0) {
1210 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_add_private"));
1211 ccall.add_argument (new CCodeIdentifier ("klass"));
1212 ccall.add_argument (new CCodeConstant ("sizeof (%sPrivate)".printf (get_ccode_name (cl))));
1213 ccode.add_expression (ccall);
1216 /* connect overridden methods */
1217 foreach (Method m in cl.get_methods ()) {
1218 if (m.base_method == null) {
1219 continue;
1221 var base_type = (ObjectTypeSymbol) m.base_method.parent_symbol;
1223 // there is currently no default handler for abstract async methods
1224 if (!m.is_abstract || !m.coroutine) {
1225 CCodeExpression cfunc = new CCodeIdentifier (get_ccode_real_name (m));
1226 cfunc = cast_method_pointer (m.base_method, cfunc, base_type, (m.coroutine ? 1 : 3));
1227 var ccast = new CCodeCastExpression (new CCodeIdentifier ("klass"), "%sClass *".printf (get_ccode_name (base_type)));
1228 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_vfunc_name (m.base_method)), cfunc);
1230 if (m.coroutine) {
1231 cfunc = new CCodeIdentifier (get_ccode_finish_real_name (m));
1232 cfunc = cast_method_pointer (m.base_method, cfunc, base_type, 2);
1233 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_finish_vfunc_name (m.base_method)), cfunc);
1238 /* connect default signal handlers */
1239 foreach (Signal sig in cl.get_signals ()) {
1240 if (sig.default_handler == null) {
1241 continue;
1243 var ccast = new CCodeCastExpression (new CCodeIdentifier ("klass"), "%sClass *".printf (get_ccode_name (cl)));
1244 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_vfunc_name (sig.default_handler)), new CCodeIdentifier (get_ccode_real_name (sig.default_handler)));
1247 /* connect overridden properties */
1248 foreach (Property prop in cl.get_properties ()) {
1249 if (prop.base_property == null) {
1250 continue;
1252 var base_type = prop.base_property.parent_symbol;
1254 var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (get_ccode_upper_case_name (base_type))));
1255 ccast.add_argument (new CCodeIdentifier ("klass"));
1257 if (!get_ccode_no_accessor_method (prop.base_property) && !get_ccode_concrete_accessor (prop.base_property)) {
1258 if (prop.get_accessor != null) {
1259 string cname = get_ccode_real_name (prop.get_accessor);
1260 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "get_%s".printf (prop.name)), new CCodeIdentifier (cname));
1262 if (prop.set_accessor != null) {
1263 string cname = get_ccode_real_name (prop.set_accessor);
1264 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "set_%s".printf (prop.name)), new CCodeIdentifier (cname));
1269 generate_class_init (cl);
1271 if (!cl.is_compact) {
1272 /* create signals */
1273 foreach (Signal sig in cl.get_signals ()) {
1274 if (sig.comment != null) {
1275 ccode.add_statement (new CCodeComment (sig.comment.content));
1277 ccode.add_expression (get_signal_creation (sig, cl));
1281 pop_context ();
1284 private void add_class_init_function (Class cl) {
1285 cfile.add_function (class_init_context.ccode);
1288 private void add_generic_accessor_function (string base_name, string return_type, CCodeExpression? expression, TypeParameter p, Class cl, Interface iface) {
1289 string name = "%s_%s_%s".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface), base_name);
1291 var function = new CCodeFunction (name, return_type);
1292 function.modifiers = CCodeModifiers.STATIC;
1293 var this_type = get_data_type_for_symbol (cl);
1294 function.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
1295 push_function (function);
1296 ccode.add_return (expression);
1297 pop_function ();
1298 cfile.add_function (function);
1300 CCodeExpression cfunc = new CCodeIdentifier (function.name);
1301 string cast = "%s (*)".printf (return_type);
1302 string cast_args = "%s *".printf (get_ccode_name (iface));
1303 cast = "%s (%s)".printf (cast, cast_args);
1304 cfunc = new CCodeCastExpression (cfunc, cast);
1305 var ciface = new CCodeIdentifier ("iface");
1306 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, base_name), cfunc);
1309 private void add_interface_init_function (Class cl, Interface iface) {
1310 var iface_init = new CCodeFunction ("%s_%s_interface_init".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface)), "void");
1311 iface_init.add_parameter (new CCodeParameter ("iface", "%s *".printf (get_ccode_type_name (iface))));
1312 iface_init.modifiers = CCodeModifiers.STATIC;
1314 push_function (iface_init);
1316 CCodeFunctionCall ccall;
1318 /* save pointer to parent vtable */
1319 string parent_iface_var = "%s_%s_parent_iface".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface));
1320 var parent_decl = new CCodeDeclaration ("%s *".printf (get_ccode_type_name (iface)));
1321 var parent_var_decl = new CCodeVariableDeclarator (parent_iface_var);
1322 parent_var_decl.initializer = new CCodeConstant ("NULL");
1323 parent_decl.add_declarator (parent_var_decl);
1324 parent_decl.modifiers = CCodeModifiers.STATIC;
1325 cfile.add_type_member_declaration (parent_decl);
1326 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_interface_peek_parent"));
1327 ccall.add_argument (new CCodeIdentifier ("iface"));
1328 ccode.add_assignment (new CCodeIdentifier (parent_iface_var), ccall);
1330 foreach (Method m in cl.get_methods ()) {
1331 if (m.base_interface_method == null) {
1332 continue;
1335 var base_type = m.base_interface_method.parent_symbol;
1336 if (base_type != iface) {
1337 continue;
1340 var ciface = new CCodeIdentifier ("iface");
1341 CCodeExpression cfunc;
1342 if (m.is_abstract || m.is_virtual) {
1343 cfunc = new CCodeIdentifier (get_ccode_name (m));
1344 } else {
1345 cfunc = new CCodeIdentifier (get_ccode_real_name (m));
1347 cfunc = cast_method_pointer (m.base_interface_method, cfunc, iface, (m.coroutine ? 1 : 3));
1348 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (m.base_interface_method)), cfunc);
1350 if (m.coroutine) {
1351 if (m.is_abstract || m.is_virtual) {
1352 cfunc = new CCodeIdentifier (get_ccode_finish_name (m));
1353 } else {
1354 cfunc = new CCodeIdentifier (get_ccode_finish_real_name (m));
1356 cfunc = cast_method_pointer (m.base_interface_method, cfunc, iface, 2);
1357 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_finish_vfunc_name (m.base_interface_method)), cfunc);
1361 if (iface.get_attribute ("GenericAccessors") != null) {
1362 foreach (TypeParameter p in iface.get_type_parameters ()) {
1363 GenericType p_type = new GenericType (p);
1364 DataType p_data_type = p_type.get_actual_type (get_data_type_for_symbol (cl), null, cl);
1366 add_generic_accessor_function ("get_%s_type".printf (p.name.down ()),
1367 "GType",
1368 get_type_id_expression (p_data_type),
1369 p, cl, iface);
1371 add_generic_accessor_function ("get_%s_dup_func".printf (p.name.down ()),
1372 "GBoxedCopyFunc",
1373 get_dup_func_expression (p_data_type, null),
1374 p, cl, iface);
1376 add_generic_accessor_function ("get_%s_destroy_func".printf (p.name.down ()),
1377 "GDestroyNotify",
1378 get_destroy_func_expression (p_data_type),
1379 p, cl, iface);
1383 // connect inherited implementations
1384 foreach (Method m in iface.get_methods ()) {
1385 if (m.is_abstract) {
1386 Method cl_method = null;
1387 var base_class = cl;
1388 while (base_class != null && cl_method == null) {
1389 cl_method = base_class.scope.lookup (m.name) as Method;
1390 base_class = base_class.base_class;
1392 if (base_class != null && cl_method.parent_symbol != cl) {
1393 // method inherited from base class
1395 var base_method = cl_method;
1396 if (cl_method.base_method != null) {
1397 base_method = cl_method.base_method;
1398 } else if (cl_method.base_interface_method != null) {
1399 base_method = cl_method.base_interface_method;
1402 generate_method_declaration (base_method, cfile);
1404 CCodeExpression cfunc = new CCodeIdentifier (get_ccode_name (base_method));
1405 cfunc = cast_method_pointer (base_method, cfunc, iface);
1406 var ciface = new CCodeIdentifier ("iface");
1407 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (m)), cfunc);
1412 foreach (Property prop in cl.get_properties ()) {
1413 if (prop.base_interface_property == null) {
1414 continue;
1417 var base_type = (ObjectTypeSymbol) prop.base_interface_property.parent_symbol;
1418 if (base_type != iface) {
1419 continue;
1422 var ciface = new CCodeIdentifier ("iface");
1424 if (!get_ccode_no_accessor_method (prop.base_interface_property) && !get_ccode_concrete_accessor (prop.base_interface_property)) {
1425 if (prop.get_accessor != null) {
1426 string cname = get_ccode_real_name (prop.get_accessor);
1427 if (prop.is_abstract || prop.is_virtual) {
1428 cname = get_ccode_name (prop.get_accessor);
1431 CCodeExpression cfunc = new CCodeIdentifier (cname);
1432 if (prop.is_abstract || prop.is_virtual) {
1433 cfunc = cast_property_accessor_pointer (prop.get_accessor, cfunc, base_type);
1435 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), cfunc);
1437 if (prop.set_accessor != null) {
1438 string cname = get_ccode_real_name (prop.set_accessor);
1439 if (prop.is_abstract || prop.is_virtual) {
1440 cname = get_ccode_name (prop.set_accessor);
1443 CCodeExpression cfunc = new CCodeIdentifier (cname);
1444 if (prop.is_abstract || prop.is_virtual) {
1445 cfunc = cast_property_accessor_pointer (prop.set_accessor, cfunc, base_type);
1447 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), cfunc);
1452 foreach (Property prop in iface.get_properties ()) {
1453 if (!prop.is_abstract) {
1454 continue;
1457 Property cl_prop = null;
1458 var base_class = cl;
1459 while (base_class != null && cl_prop == null) {
1460 cl_prop = base_class.scope.lookup (prop.name) as Property;
1461 base_class = base_class.base_class;
1463 if (base_class != null && cl_prop.parent_symbol != cl) {
1464 // property inherited from base class
1466 var base_property = cl_prop;
1467 if (cl_prop.base_property != null) {
1468 base_property = cl_prop.base_property;
1469 } else if (cl_prop.base_interface_property != null) {
1470 base_property = cl_prop.base_interface_property;
1473 var ciface = new CCodeIdentifier ("iface");
1475 if (base_property.get_accessor != null && prop.get_accessor != null) {
1476 generate_property_accessor_declaration (base_property.get_accessor, cfile);
1478 string cname = get_ccode_name (base_property.get_accessor);
1479 CCodeExpression cfunc = new CCodeIdentifier (cname);
1480 cfunc = cast_property_accessor_pointer (prop.get_accessor, cfunc, iface);
1481 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), cfunc);
1483 if (base_property.set_accessor != null && prop.set_accessor != null) {
1484 generate_property_accessor_declaration (base_property.set_accessor, cfile);
1486 string cname = get_ccode_name (base_property.set_accessor);
1487 CCodeExpression cfunc = new CCodeIdentifier (cname);
1488 cfunc = cast_property_accessor_pointer (prop.set_accessor, cfunc, iface);
1489 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), cfunc);
1494 pop_function ();
1495 cfile.add_function (iface_init);
1498 CCodeExpression cast_property_accessor_pointer (PropertyAccessor acc, CCodeExpression cfunc, ObjectTypeSymbol base_type) {
1499 string cast;
1500 if (acc.readable && acc.value_type.is_real_non_null_struct_type ()) {
1501 cast = "void (*) (%s *, %s *)".printf (get_ccode_name (base_type), get_ccode_name (acc.value_type));
1502 } else if (acc.readable) {
1503 cast = "%s (*) (%s *)".printf (get_ccode_name (acc.value_type), get_ccode_name (base_type));
1504 } else if (acc.value_type.is_real_non_null_struct_type ()) {
1505 cast = "void (*) (%s *, %s *)".printf (get_ccode_name (base_type), get_ccode_name (acc.value_type));
1506 } else {
1507 cast = "void (*) (%s *, %s)".printf (get_ccode_name (base_type), get_ccode_name (acc.value_type));
1509 return new CCodeCastExpression (cfunc, cast);
1512 CCodeExpression cast_method_pointer (Method m, CCodeExpression cfunc, ObjectTypeSymbol base_type, int direction = 3) {
1513 // Cast the function pointer to match the interface
1514 string cast;
1515 if (direction == 1 || m.return_type.is_real_non_null_struct_type ()) {
1516 cast = "void (*)";
1517 } else {
1518 cast = "%s (*)".printf (get_ccode_name (m.return_type));
1520 string cast_args = "%s *".printf (get_ccode_name (base_type));
1522 var vdeclarator = new CCodeFunctionDeclarator (get_ccode_vfunc_name (m));
1523 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
1525 generate_cparameters (m, cfile, cparam_map, new CCodeFunction ("fake"), vdeclarator, null, null, direction);
1527 // append C arguments in the right order
1528 int last_pos = -1;
1529 int min_pos;
1530 while (true) {
1531 min_pos = -1;
1532 foreach (int pos in cparam_map.get_keys ()) {
1533 if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
1534 min_pos = pos;
1537 if (last_pos != -1) { // Skip the 1st parameter
1538 if (min_pos == -1) {
1539 break;
1542 var tmp = cparam_map.get (min_pos);
1543 if (tmp.ellipsis) {
1544 cast_args = "%s, ...".printf (cast_args);
1545 } else {
1546 cast_args = "%s, %s".printf (cast_args, tmp.type_name);
1549 last_pos = min_pos;
1551 cast = "%s (%s)".printf (cast, cast_args);
1552 return new CCodeCastExpression (cfunc, cast);
1555 private void begin_instance_init_function (Class cl) {
1556 push_context (instance_init_context);
1558 var func = new CCodeFunction ("%s_instance_init".printf (get_ccode_lower_case_name (cl, null)));
1559 func.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl))));
1560 func.modifiers = CCodeModifiers.STATIC;
1562 push_function (func);
1564 if (cl.is_compact) {
1565 // Add declaration, since the instance_init function is explicitly called
1566 // by the creation methods
1567 cfile.add_function_declaration (func);
1570 if (!cl.is_compact && (cl.has_private_fields || cl.get_type_parameters ().size > 0)) {
1571 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_PRIVATE".printf (get_ccode_upper_case_name (cl, null))));
1572 ccall.add_argument (new CCodeIdentifier ("self"));
1573 func.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall);
1576 pop_context ();
1579 private void add_instance_init_function (Class cl) {
1580 push_context (instance_init_context);
1581 end_instance_init (cl);
1582 pop_context ();
1584 cfile.add_function (instance_init_context.ccode);
1587 private void begin_class_finalize_function (Class cl) {
1588 push_context (class_finalize_context);
1590 var function = new CCodeFunction ("%s_class_finalize".printf (get_ccode_lower_case_name (cl, null)), "void");
1591 function.modifiers = CCodeModifiers.STATIC;
1593 function.add_parameter (new CCodeParameter ("klass", "%sClass *".printf (get_ccode_name (cl))));
1595 push_function (function);
1597 if (cl.static_destructor != null) {
1598 cl.static_destructor.body.emit (this);
1601 pop_context ();
1604 private void add_class_finalize_function (Class cl) {
1605 cfile.add_function_declaration (class_finalize_context.ccode);
1606 cfile.add_function (class_finalize_context.ccode);
1609 private void begin_base_finalize_function (Class cl) {
1610 push_context (base_finalize_context);
1612 var function = new CCodeFunction ("%s_base_finalize".printf (get_ccode_lower_case_name (cl, null)), "void");
1613 function.modifiers = CCodeModifiers.STATIC;
1615 function.add_parameter (new CCodeParameter ("klass", "%sClass *".printf (get_ccode_name (cl))));
1617 push_function (function);
1619 if (cl.class_destructor != null) {
1620 cl.class_destructor.body.emit (this);
1623 pop_context ();
1626 private void add_base_finalize_function (Class cl) {
1627 push_context (base_finalize_context);
1629 cfile.add_function_declaration (ccode);
1630 cfile.add_function (ccode);
1632 pop_context ();
1635 private void begin_finalize_function (Class cl) {
1636 push_context (instance_finalize_context);
1638 bool is_gsource = cl.base_class == gsource_type;
1640 if (!cl.is_compact || is_gsource) {
1641 var fundamental_class = cl;
1642 while (fundamental_class.base_class != null) {
1643 fundamental_class = fundamental_class.base_class;
1646 var func = new CCodeFunction ("%s_finalize".printf (get_ccode_lower_case_name (cl, null)));
1647 func.add_parameter (new CCodeParameter ("obj", "%s *".printf (get_ccode_name (fundamental_class))));
1648 func.modifiers = CCodeModifiers.STATIC;
1650 push_function (func);
1652 if (is_gsource) {
1653 cfile.add_function_declaration (func);
1656 CCodeExpression ccast;
1657 if (!cl.is_compact) {
1658 ccast = generate_instance_cast (new CCodeIdentifier ("obj"), cl);
1659 } else {
1660 ccast = new CCodeCastExpression (new CCodeIdentifier ("obj"), "%s *".printf (get_ccode_name (cl)));
1663 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self"));
1664 ccode.add_assignment (new CCodeIdentifier ("self"), ccast);
1666 if (!cl.is_compact && cl.base_class == null) {
1667 // non-gobject class
1668 var call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_handlers_destroy"));
1669 call.add_argument (new CCodeIdentifier ("self"));
1670 ccode.add_expression (call);
1672 } else {
1673 var function = new CCodeFunction ("%sfree".printf (get_ccode_lower_case_prefix (cl)), "void");
1674 if (cl.is_private_symbol ()) {
1675 function.modifiers = CCodeModifiers.STATIC;
1676 } else if (context.hide_internal && cl.is_internal_symbol ()) {
1677 function.modifiers = CCodeModifiers.INTERNAL;
1680 function.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl))));
1682 push_function (function);
1685 if (cl.destructor != null) {
1686 cl.destructor.body.emit (this);
1688 if (current_method_inner_error) {
1689 ccode.add_declaration ("GError *", new CCodeVariableDeclarator.zero ("_inner_error_", new CCodeConstant ("NULL")));
1692 if (current_method_return) {
1693 // support return statements in destructors
1694 ccode.add_label ("_return");
1698 pop_context ();
1701 private void add_finalize_function (Class cl) {
1702 if (!cl.is_compact) {
1703 var fundamental_class = cl;
1704 while (fundamental_class.base_class != null) {
1705 fundamental_class = fundamental_class.base_class;
1708 // chain up to finalize function of the base class
1709 if (cl.base_class != null) {
1710 var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (get_ccode_upper_case_name (fundamental_class))));
1711 ccast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (cl, null))));
1712 var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize"));
1713 ccall.add_argument (new CCodeIdentifier ("obj"));
1714 push_context (instance_finalize_context);
1715 ccode.add_expression (ccall);
1716 pop_context ();
1719 cfile.add_function_declaration (instance_finalize_context.ccode);
1720 } else if (cl.base_class == null) {
1721 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
1722 ccall.add_argument (new CCodeIdentifier (get_ccode_name (cl)));
1723 ccall.add_argument (new CCodeIdentifier ("self"));
1724 push_context (instance_finalize_context);
1725 ccode.add_expression (ccall);
1726 pop_context ();
1729 cfile.add_function (instance_finalize_context.ccode);
1732 public override CCodeExpression get_param_spec_cexpression (Property prop) {
1733 var cl = (TypeSymbol) prop.parent_symbol;
1734 var prop_array = new CCodeIdentifier ("%s_properties".printf (get_ccode_lower_case_name (cl)));
1735 var prop_enum_value = new CCodeIdentifier ("%s_PROPERTY".printf (get_ccode_upper_case_name (prop)));
1737 return new CCodeElementAccess (prop_array, prop_enum_value);
1740 public override CCodeExpression get_param_spec (Property prop) {
1741 var cspec = new CCodeFunctionCall ();
1742 cspec.add_argument (get_property_canonical_cconstant (prop));
1743 cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.nick)));
1744 cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.blurb)));
1747 if (prop.property_type.data_type is Class || prop.property_type.data_type is Interface) {
1748 string param_spec_name = get_ccode_param_spec_function (prop.property_type.data_type);
1749 cspec.call = new CCodeIdentifier (param_spec_name);
1750 if (param_spec_name == "g_param_spec_string") {
1751 cspec.add_argument (new CCodeConstant ("NULL"));
1752 } else if (param_spec_name == "g_param_spec_variant") {
1753 cspec.add_argument (new CCodeConstant ("G_VARIANT_TYPE_ANY"));
1754 cspec.add_argument (new CCodeConstant ("NULL"));
1755 } else if (get_ccode_type_id (prop.property_type.data_type) != "G_TYPE_POINTER") {
1756 cspec.add_argument (new CCodeIdentifier (get_ccode_type_id (prop.property_type.data_type)));
1758 } else if (prop.property_type.data_type is Enum) {
1759 var e = prop.property_type.data_type as Enum;
1760 if (get_ccode_has_type_id (e)) {
1761 if (e.is_flags) {
1762 cspec.call = new CCodeIdentifier ("g_param_spec_flags");
1763 } else {
1764 cspec.call = new CCodeIdentifier ("g_param_spec_enum");
1766 cspec.add_argument (new CCodeIdentifier (get_ccode_type_id (e)));
1767 } else {
1768 if (e.is_flags) {
1769 cspec.call = new CCodeIdentifier ("g_param_spec_uint");
1770 cspec.add_argument (new CCodeConstant ("0"));
1771 cspec.add_argument (new CCodeConstant ("G_MAXUINT"));
1772 } else {
1773 cspec.call = new CCodeIdentifier ("g_param_spec_int");
1774 cspec.add_argument (new CCodeConstant ("G_MININT"));
1775 cspec.add_argument (new CCodeConstant ("G_MAXINT"));
1779 if (prop.initializer != null) {
1780 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1781 } else {
1782 cspec.add_argument (new CCodeConstant (get_ccode_default_value (prop.property_type.data_type)));
1784 } else if (prop.property_type.data_type is Struct) {
1785 var st = (Struct) prop.property_type.data_type;
1786 var type_id = get_ccode_type_id (st);
1787 if (type_id == "G_TYPE_INT") {
1788 cspec.call = new CCodeIdentifier ("g_param_spec_int");
1789 cspec.add_argument (new CCodeConstant ("G_MININT"));
1790 cspec.add_argument (new CCodeConstant ("G_MAXINT"));
1791 if (prop.initializer != null) {
1792 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1793 } else {
1794 cspec.add_argument (new CCodeConstant ("0"));
1796 } else if (type_id == "G_TYPE_UINT") {
1797 cspec.call = new CCodeIdentifier ("g_param_spec_uint");
1798 cspec.add_argument (new CCodeConstant ("0"));
1799 cspec.add_argument (new CCodeConstant ("G_MAXUINT"));
1800 if (prop.initializer != null) {
1801 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1802 } else {
1803 cspec.add_argument (new CCodeConstant ("0U"));
1805 } else if (type_id == "G_TYPE_INT64") {
1806 cspec.call = new CCodeIdentifier ("g_param_spec_int64");
1807 cspec.add_argument (new CCodeConstant ("G_MININT64"));
1808 cspec.add_argument (new CCodeConstant ("G_MAXINT64"));
1809 if (prop.initializer != null) {
1810 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1811 } else {
1812 cspec.add_argument (new CCodeConstant ("0"));
1814 } else if (type_id == "G_TYPE_UINT64") {
1815 cspec.call = new CCodeIdentifier ("g_param_spec_uint64");
1816 cspec.add_argument (new CCodeConstant ("0"));
1817 cspec.add_argument (new CCodeConstant ("G_MAXUINT64"));
1818 if (prop.initializer != null) {
1819 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1820 } else {
1821 cspec.add_argument (new CCodeConstant ("0U"));
1823 } else if (type_id == "G_TYPE_LONG") {
1824 cspec.call = new CCodeIdentifier ("g_param_spec_long");
1825 cspec.add_argument (new CCodeConstant ("G_MINLONG"));
1826 cspec.add_argument (new CCodeConstant ("G_MAXLONG"));
1827 if (prop.initializer != null) {
1828 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1829 } else {
1830 cspec.add_argument (new CCodeConstant ("0L"));
1832 } else if (type_id == "G_TYPE_ULONG") {
1833 cspec.call = new CCodeIdentifier ("g_param_spec_ulong");
1834 cspec.add_argument (new CCodeConstant ("0"));
1835 cspec.add_argument (new CCodeConstant ("G_MAXULONG"));
1836 if (prop.initializer != null) {
1837 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1838 } else {
1839 cspec.add_argument (new CCodeConstant ("0UL"));
1841 } else if (type_id == "G_TYPE_BOOLEAN") {
1842 cspec.call = new CCodeIdentifier ("g_param_spec_boolean");
1843 if (prop.initializer != null) {
1844 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1845 } else {
1846 cspec.add_argument (new CCodeConstant ("FALSE"));
1848 } else if (type_id == "G_TYPE_CHAR") {
1849 cspec.call = new CCodeIdentifier ("g_param_spec_char");
1850 cspec.add_argument (new CCodeConstant ("G_MININT8"));
1851 cspec.add_argument (new CCodeConstant ("G_MAXINT8"));
1852 if (prop.initializer != null) {
1853 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1854 } else {
1855 cspec.add_argument (new CCodeConstant ("0"));
1857 } else if (type_id == "G_TYPE_UCHAR") {
1858 cspec.call = new CCodeIdentifier ("g_param_spec_uchar");
1859 cspec.add_argument (new CCodeConstant ("0"));
1860 cspec.add_argument (new CCodeConstant ("G_MAXUINT8"));
1861 if (prop.initializer != null) {
1862 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1863 } else {
1864 cspec.add_argument (new CCodeConstant ("0"));
1866 } else if (type_id == "G_TYPE_FLOAT") {
1867 cspec.call = new CCodeIdentifier ("g_param_spec_float");
1868 cspec.add_argument (new CCodeConstant ("-G_MAXFLOAT"));
1869 cspec.add_argument (new CCodeConstant ("G_MAXFLOAT"));
1870 if (prop.initializer != null) {
1871 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1872 } else {
1873 cspec.add_argument (new CCodeConstant ("0.0F"));
1875 } else if (type_id == "G_TYPE_DOUBLE") {
1876 cspec.call = new CCodeIdentifier ("g_param_spec_double");
1877 cspec.add_argument (new CCodeConstant ("-G_MAXDOUBLE"));
1878 cspec.add_argument (new CCodeConstant ("G_MAXDOUBLE"));
1879 if (prop.initializer != null) {
1880 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1881 } else {
1882 cspec.add_argument (new CCodeConstant ("0.0"));
1884 } else if (type_id == "G_TYPE_GTYPE") {
1885 cspec.call = new CCodeIdentifier ("g_param_spec_gtype");
1886 if (prop.initializer != null) {
1887 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1888 } else {
1889 cspec.add_argument (new CCodeConstant ("G_TYPE_NONE"));
1891 } else {
1892 cspec.call = new CCodeIdentifier ("g_param_spec_boxed");
1893 cspec.add_argument (new CCodeIdentifier (type_id));
1895 } else if (prop.property_type is ArrayType && ((ArrayType)prop.property_type).element_type.data_type == string_type.data_type) {
1896 cspec.call = new CCodeIdentifier ("g_param_spec_boxed");
1897 cspec.add_argument (new CCodeIdentifier ("G_TYPE_STRV"));
1898 } else {
1899 cspec.call = new CCodeIdentifier ("g_param_spec_pointer");
1902 var pflags = "G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB";
1903 if (prop.get_accessor != null && prop.get_accessor.access != SymbolAccessibility.PRIVATE) {
1904 pflags = "%s%s".printf (pflags, " | G_PARAM_READABLE");
1906 if (prop.set_accessor != null && prop.set_accessor.access != SymbolAccessibility.PRIVATE) {
1907 pflags = "%s%s".printf (pflags, " | G_PARAM_WRITABLE");
1908 if (prop.set_accessor.construction) {
1909 if (prop.set_accessor.writable) {
1910 pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT");
1911 } else {
1912 pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT_ONLY");
1916 if (prop.version.deprecated) {
1917 pflags = "%s%s".printf (pflags, " | G_PARAM_DEPRECATED");
1919 cspec.add_argument (new CCodeConstant (pflags));
1921 if (prop.parent_symbol is Interface) {
1922 return cspec;
1923 } else {
1924 return new CCodeAssignment (get_param_spec_cexpression (prop), cspec);
1928 public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) {
1929 if (add_symbol_declaration (decl_space, iface, get_ccode_name (iface))) {
1930 return;
1933 foreach (DataType prerequisite in iface.get_prerequisites ()) {
1934 var prereq_cl = prerequisite.data_type as Class;
1935 var prereq_iface = prerequisite.data_type as Interface;
1936 if (prereq_cl != null) {
1937 generate_class_declaration (prereq_cl, decl_space);
1938 } else if (prereq_iface != null) {
1939 generate_interface_declaration (prereq_iface, decl_space);
1943 var type_struct = new CCodeStruct ("_%s".printf (get_ccode_type_name (iface)));
1945 decl_space.add_type_declaration (new CCodeNewline ());
1946 var macro = "(%s_get_type ())".printf (get_ccode_lower_case_name (iface, null));
1947 decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (iface), macro));
1949 macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (get_ccode_type_id (iface), get_ccode_name (iface));
1950 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_upper_case_name (iface, null)), macro));
1952 macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (get_ccode_type_id (iface));
1953 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_check_function (iface)), macro));
1955 macro = "(G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, %s))".printf (get_ccode_type_id (iface), get_ccode_type_name (iface));
1956 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_GET_INTERFACE(obj)".printf (get_ccode_upper_case_name (iface, null)), macro));
1957 decl_space.add_type_declaration (new CCodeNewline ());
1959 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (iface)), new CCodeVariableDeclarator (get_ccode_name (iface))));
1960 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_struct.name), new CCodeVariableDeclarator (get_ccode_type_name (iface))));
1962 type_struct.add_field ("GTypeInterface", "parent_iface");
1964 if (iface.get_attribute ("GenericAccessors") != null) {
1965 foreach (TypeParameter p in iface.get_type_parameters ()) {
1966 string method_name = "get_%s_type".printf (p.name.down ());
1967 var vdeclarator = new CCodeFunctionDeclarator (method_name);
1968 var this_type = get_data_type_for_symbol (iface);
1969 vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
1971 var vdecl = new CCodeDeclaration ("GType");
1972 vdecl.add_declarator (vdeclarator);
1973 type_struct.add_declaration (vdecl);
1975 method_name = "get_%s_dup_func".printf (p.name.down ());
1976 vdeclarator = new CCodeFunctionDeclarator (method_name);
1977 this_type = get_data_type_for_symbol (iface);
1978 vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
1980 vdecl = new CCodeDeclaration ("GBoxedCopyFunc");
1981 vdecl.add_declarator (vdeclarator);
1982 type_struct.add_declaration (vdecl);
1984 method_name = "get_%s_destroy_func".printf (p.name.down ());
1985 vdeclarator = new CCodeFunctionDeclarator (method_name);
1986 this_type = get_data_type_for_symbol (iface);
1987 vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
1989 vdecl = new CCodeDeclaration ("GDestroyNotify");
1990 vdecl.add_declarator (vdeclarator);
1991 type_struct.add_declaration (vdecl);
1995 foreach (Symbol sym in iface.get_virtuals ()) {
1996 Method m;
1997 Signal sig;
1998 Property prop;
1999 if ((m = sym as Method) != null) {
2000 generate_virtual_method_declaration (m, decl_space, type_struct);
2001 } else if ((sig = sym as Signal) != null) {
2002 if (sig.default_handler != null) {
2003 generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
2005 } else if ((prop = sym as Property) != null) {
2006 generate_type_declaration (prop.property_type, decl_space);
2008 var t = (ObjectTypeSymbol) prop.parent_symbol;
2010 bool returns_real_struct = prop.property_type.is_real_non_null_struct_type ();
2012 var this_type = new ObjectType (t);
2013 var cselfparam = new CCodeParameter ("self", get_ccode_name (this_type));
2015 if (prop.get_accessor != null) {
2016 var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name));
2017 vdeclarator.add_parameter (cselfparam);
2018 string creturn_type;
2019 if (returns_real_struct) {
2020 var cvalueparam = new CCodeParameter ("value", "%s *".printf (get_ccode_name (prop.get_accessor.value_type)));
2021 vdeclarator.add_parameter (cvalueparam);
2022 creturn_type = "void";
2023 } else {
2024 creturn_type = get_ccode_name (prop.get_accessor.value_type);
2027 var array_type = prop.property_type as ArrayType;
2028 if (array_type != null) {
2029 for (int dim = 1; dim <= array_type.rank; dim++) {
2030 vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("result", dim), "int*"));
2034 var vdecl = new CCodeDeclaration (creturn_type);
2035 vdecl.add_declarator (vdeclarator);
2036 type_struct.add_declaration (vdecl);
2038 if (prop.set_accessor != null) {
2039 var vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name));
2040 vdeclarator.add_parameter (cselfparam);
2041 if (returns_real_struct) {
2042 var cvalueparam = new CCodeParameter ("value", "%s *".printf (get_ccode_name (prop.set_accessor.value_type)));
2043 vdeclarator.add_parameter (cvalueparam);
2044 } else {
2045 var cvalueparam = new CCodeParameter ("value", get_ccode_name (prop.set_accessor.value_type));
2046 vdeclarator.add_parameter (cvalueparam);
2049 var array_type = prop.property_type as ArrayType;
2050 if (array_type != null) {
2051 for (int dim = 1; dim <= array_type.rank; dim++) {
2052 vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("value", dim), "int"));
2056 var vdecl = new CCodeDeclaration ("void");
2057 vdecl.add_declarator (vdeclarator);
2058 type_struct.add_declaration (vdecl);
2060 } else {
2061 assert_not_reached ();
2065 decl_space.add_type_definition (type_struct);
2067 var type_fun = new InterfaceRegisterFunction (iface);
2068 type_fun.init_from_type (context, in_plugin, true);
2069 decl_space.add_type_member_declaration (type_fun.get_declaration ());
2072 public override void visit_interface (Interface iface) {
2073 push_context (new EmitContext (iface));
2074 push_line (iface.source_reference);
2076 var old_signal_enum = signal_enum;
2078 if (get_ccode_name (iface).length < 3) {
2079 iface.error = true;
2080 Report.error (iface.source_reference, "Interface name `%s' is too short".printf (get_ccode_name (iface)));
2081 return;
2084 signal_enum = new CCodeEnum ();
2086 generate_interface_declaration (iface, cfile);
2087 if (!iface.is_internal_symbol ()) {
2088 generate_interface_declaration (iface, header_file);
2090 if (!iface.is_private_symbol ()) {
2091 generate_interface_declaration (iface, internal_header_file);
2094 iface.accept_children (this);
2096 if (iface.get_signals ().size > 0) {
2097 var last_signal = "%s_NUM_SIGNALS".printf (get_ccode_upper_case_name (iface));
2098 signal_enum.add_value (new CCodeEnumValue (last_signal));
2099 cfile.add_type_declaration (signal_enum);
2101 var signal_array_decl = new CCodeDeclaration ("guint");
2102 signal_array_decl.modifiers |= CCodeModifiers.STATIC;
2103 signal_array_decl.add_declarator (new CCodeVariableDeclarator ("%s_signals".printf (get_ccode_lower_case_name (iface)), new CCodeConstant ("{0}"), new CCodeDeclaratorSuffix.with_array (new CCodeIdentifier (last_signal))));
2104 cfile.add_type_declaration (signal_array_decl);
2107 add_interface_base_init_function (iface);
2109 if (iface.comment != null) {
2110 cfile.add_type_member_definition (new CCodeComment (iface.comment.content));
2113 var type_fun = new InterfaceRegisterFunction (iface);
2114 type_fun.init_from_type (context, in_plugin, false);
2115 cfile.add_type_member_declaration (type_fun.get_source_declaration ());
2116 cfile.add_type_member_definition (type_fun.get_definition ());
2118 signal_enum = old_signal_enum;
2120 pop_line ();
2121 pop_context ();
2124 private void add_interface_base_init_function (Interface iface) {
2125 push_context (new EmitContext (iface));
2127 var base_init = new CCodeFunction ("%s_base_init".printf (get_ccode_lower_case_name (iface, null)), "void");
2128 base_init.add_parameter (new CCodeParameter ("iface", "%sIface *".printf (get_ccode_name (iface))));
2129 base_init.modifiers = CCodeModifiers.STATIC;
2131 push_function (base_init);
2133 /* make sure not to run the initialization code twice */
2134 ccode.add_declaration (get_ccode_name (bool_type), new CCodeVariableDeclarator ("initialized", new CCodeConstant ("FALSE")), CCodeModifiers.STATIC);
2135 ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("initialized")));
2137 ccode.add_assignment (new CCodeIdentifier ("initialized"), new CCodeConstant ("TRUE"));
2139 if (iface.is_subtype_of (gobject_type)) {
2140 /* create properties */
2141 var props = iface.get_properties ();
2142 foreach (Property prop in props) {
2143 if (prop.is_abstract) {
2144 if (!is_gobject_property (prop)) {
2145 continue;
2148 if (prop.comment != null) {
2149 ccode.add_statement (new CCodeComment (prop.comment.content));
2152 var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_interface_install_property"));
2153 cinst.add_argument (new CCodeIdentifier ("iface"));
2154 cinst.add_argument (get_param_spec (prop));
2156 ccode.add_expression (cinst);
2161 var ciface = new CCodeIdentifier ("iface");
2163 /* connect default signal handlers */
2164 foreach (Signal sig in iface.get_signals ()) {
2165 if (sig.default_handler == null) {
2166 continue;
2168 var cname = get_ccode_real_name (sig.default_handler);
2169 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (sig.default_handler)), new CCodeIdentifier (cname));
2172 /* create signals */
2173 foreach (Signal sig in iface.get_signals ()) {
2174 if (sig.comment != null) {
2175 ccode.add_statement (new CCodeComment (sig.comment.content));
2177 ccode.add_expression (get_signal_creation (sig, iface));
2180 // connect default implementations
2181 foreach (Method m in iface.get_methods ()) {
2182 if (m.is_virtual) {
2183 var cname = get_ccode_real_name (m);
2184 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (m)), new CCodeIdentifier (cname));
2185 if (m.coroutine) {
2186 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_finish_vfunc_name (m)), new CCodeIdentifier (get_ccode_finish_real_name (m)));
2191 foreach (Property prop in iface.get_properties ()) {
2192 if (prop.is_virtual) {
2193 if (prop.get_accessor != null) {
2194 string cname = get_ccode_real_name (prop.get_accessor);
2195 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), new CCodeIdentifier (cname));
2197 if (prop.set_accessor != null) {
2198 string cname = get_ccode_real_name (prop.set_accessor);
2199 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), new CCodeIdentifier (cname));
2204 ccode.close ();
2206 pop_context ();
2208 cfile.add_function (base_init);
2211 public override void visit_struct (Struct st) {
2212 base.visit_struct (st);
2214 if (get_ccode_has_type_id (st)) {
2215 push_line (st.source_reference);
2216 var type_fun = new StructRegisterFunction (st);
2217 type_fun.init_from_type (context, false, false);
2218 cfile.add_type_member_definition (type_fun.get_definition ());
2219 pop_line ();
2223 public override void visit_enum (Enum en) {
2224 base.visit_enum (en);
2226 if (get_ccode_has_type_id (en)) {
2227 push_line (en.source_reference);
2228 var type_fun = new EnumRegisterFunction (en);
2229 type_fun.init_from_type (context, false, false);
2230 cfile.add_type_member_definition (type_fun.get_definition ());
2231 pop_line ();
2235 public override void visit_method_call (MethodCall expr) {
2236 var ma = expr.call as MemberAccess;
2237 var mtype = expr.call.value_type as MethodType;
2238 if (mtype == null || ma == null || ma.inner == null ||
2239 !(ma.inner.value_type is EnumValueType) || !get_ccode_has_type_id (ma.inner.value_type.data_type) ||
2240 mtype.method_symbol != ((EnumValueType) ma.inner.value_type).get_to_string_method ()) {
2241 base.visit_method_call (expr);
2242 return;
2244 // to_string() on a gtype enum
2246 bool is_flags = ((Enum) ((EnumValueType) ma.inner.value_type).type_symbol).is_flags;
2248 push_line (expr.source_reference);
2249 var temp_var = get_temp_variable (new CType (is_flags ? "GFlagsValue*" : "GEnumValue*"), false, expr, false);
2250 emit_temp_var (temp_var);
2252 var class_ref = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_ref"));
2253 class_ref.add_argument (new CCodeIdentifier (get_ccode_type_id (ma.inner.value_type)));
2254 var get_value = new CCodeFunctionCall (new CCodeIdentifier (is_flags ? "g_flags_get_first_value" : "g_enum_get_value"));
2255 get_value.add_argument (class_ref);
2256 get_value.add_argument ((CCodeExpression) get_ccodenode (((MemberAccess) expr.call).inner));
2258 ccode.add_assignment (get_variable_cexpression (temp_var.name), get_value);
2259 var is_null_value = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_variable_cexpression (temp_var.name), new CCodeIdentifier ("NULL"));
2260 set_cvalue (expr, new CCodeConditionalExpression (is_null_value, new CCodeMemberAccess.pointer (get_variable_cexpression (temp_var.name), "value_name"), new CCodeIdentifier ("NULL")));
2261 pop_line ();
2264 public override void visit_property (Property prop) {
2265 var cl = current_type_symbol as Class;
2266 var st = current_type_symbol as Struct;
2268 var base_prop = prop;
2269 if (prop.base_property != null) {
2270 base_prop = prop.base_property;
2271 } else if (prop.base_interface_property != null) {
2272 base_prop = prop.base_interface_property;
2275 if (base_prop.get_attribute ("NoAccessorMethod") == null &&
2276 prop.name == "type" && ((cl != null && !cl.is_compact) || (st != null && get_ccode_has_type_id (st)))) {
2277 Report.error (prop.source_reference, "Property 'type' not allowed");
2278 return;
2280 base.visit_property (prop);
2283 public override void create_type_check_statement (CodeNode method_node, DataType ret_type, TypeSymbol t, bool non_null, string var_name) {
2284 var ccheck = new CCodeFunctionCall ();
2286 if (!context.assert) {
2287 return;
2288 } else if (context.checking && ((t is Class && !((Class) t).is_compact) || t is Interface)) {
2289 var ctype_check = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_check_function (t)));
2290 ctype_check.add_argument (new CCodeIdentifier (var_name));
2292 CCodeExpression cexpr = ctype_check;
2293 if (!non_null) {
2294 var cnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier (var_name), new CCodeConstant ("NULL"));
2296 cexpr = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cnull, ctype_check);
2298 ccheck.add_argument (cexpr);
2299 } else if (!non_null || (t is Struct && ((Struct) t).is_simple_type ())) {
2300 return;
2301 } else if (t == glist_type || t == gslist_type) {
2302 // NULL is empty list
2303 return;
2304 } else {
2305 var cnonnull = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (var_name), new CCodeConstant ("NULL"));
2306 ccheck.add_argument (cnonnull);
2309 var cm = method_node as CreationMethod;
2310 if (cm != null && cm.parent_symbol is ObjectTypeSymbol) {
2311 ccheck.call = new CCodeIdentifier ("g_return_val_if_fail");
2312 ccheck.add_argument (new CCodeConstant ("NULL"));
2313 } else if (ret_type is VoidType) {
2314 /* void function */
2315 ccheck.call = new CCodeIdentifier ("g_return_if_fail");
2316 } else {
2317 ccheck.call = new CCodeIdentifier ("g_return_val_if_fail");
2319 var cdefault = default_value_for_type (ret_type, false);
2320 if (cdefault != null) {
2321 ccheck.add_argument (cdefault);
2322 } else if (ret_type.data_type is Struct && !((Struct) ret_type.data_type).is_simple_type ()) {
2323 ccheck.add_argument (new CCodeIdentifier ("result"));
2324 } else {
2325 return;
2329 ccode.add_expression (ccheck);