Line data Source code
1 : /* valagtypemodule.vala
2 : *
3 : * Copyright (C) 2006-2010 Jürg Billeter
4 : * Copyright (C) 2006-2008 Raffaele Sandrini
5 : *
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.
10 :
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.
15 :
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
19 : *
20 : * Author:
21 : * Jürg Billeter <j@bitron.ch>
22 : * Raffaele Sandrini <raffaele@sandrini.ch>
23 : */
24 :
25 :
26 2914 : public class Vala.GTypeModule : GErrorModule {
27 10510 : public override CCodeParameter generate_parameter (Parameter param, CCodeFile decl_space, Map<int,CCodeParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
28 10510 : if (!(param.variable_type is ObjectType)) {
29 4122 : return base.generate_parameter (param, decl_space, cparam_map, carg_map);
30 : }
31 :
32 6388 : generate_type_declaration (param.variable_type, decl_space);
33 :
34 6388 : string? ctypename = get_ccode_type (param);
35 6388 : if (ctypename == null) {
36 6382 : ctypename = get_ccode_name (param.variable_type);
37 :
38 6382 : if (param.direction != ParameterDirection.IN) {
39 172 : ctypename = "%s*".printf (ctypename);
40 : }
41 : }
42 :
43 6388 : var cparam = new CCodeParameter (get_ccode_name (param), ctypename);
44 6388 : if (param.format_arg) {
45 32 : cparam.modifiers = CCodeModifiers.FORMAT_ARG;
46 : }
47 :
48 6388 : cparam_map.set (get_param_pos (get_ccode_pos (param)), cparam);
49 6388 : if (carg_map != null) {
50 2390 : carg_map.set (get_param_pos (get_ccode_pos (param)), get_parameter_cexpression (param));
51 : }
52 :
53 6388 : return cparam;
54 : }
55 :
56 75210 : public override void generate_class_declaration (Class cl, CCodeFile decl_space) {
57 73585 : if (add_symbol_declaration (decl_space, cl, get_ccode_name (cl))) {
58 : return;
59 : }
60 :
61 1631 : if (cl.base_class != null) {
62 : // base class declaration
63 : // necessary for ref and unref function declarations
64 989 : generate_class_declaration (cl.base_class, decl_space);
65 : }
66 :
67 1631 : bool final_not_public = (cl.is_opaque || cl.is_sealed) && context.header_filename != null && decl_space.file_type != CCodeFileType.PUBLIC_HEADER;
68 1631 : bool is_gtypeinstance = !cl.is_compact;
69 1631 : bool is_fundamental = is_gtypeinstance && cl.base_class == null;
70 1631 : bool is_gsource = cl.is_subtype_of (gsource_type);
71 :
72 1631 : if (final_not_public) {
73 : // nothing to do
74 3148 : } else if (is_gtypeinstance) {
75 1523 : decl_space.add_include ("glib-object.h");
76 :
77 1523 : decl_space.add_type_declaration (new CCodeNewline ());
78 :
79 1523 : var macro = "(%s_get_type ())".printf (get_ccode_lower_case_name (cl, null));
80 1523 : decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (cl), macro));
81 :
82 1523 : macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (get_ccode_type_id (cl), get_ccode_name (cl));
83 1523 : decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_cast_function (cl)), macro));
84 :
85 1523 : macro = "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %s))".printf (get_ccode_type_id (cl), get_ccode_type_name (cl));
86 1523 : decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(klass)".printf (get_ccode_class_type_function (cl)), macro));
87 :
88 1523 : macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (get_ccode_type_id (cl));
89 1523 : decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_check_function (cl)), macro));
90 :
91 1523 : macro = "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (get_ccode_type_id (cl));
92 1523 : decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(klass)".printf (get_ccode_class_type_check_function (cl)), macro));
93 :
94 1523 : macro = "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %s))".printf (get_ccode_type_id (cl), get_ccode_type_name (cl));
95 1523 : decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_get_function (cl)), macro));
96 1523 : decl_space.add_type_declaration (new CCodeNewline ());
97 : }
98 :
99 1631 : if (!(!cl.is_compact || cl.base_class == null || compact_class_has_instance_struct_member (cl))) {
100 26 : decl_space.add_type_declaration (new CCodeTypeDefinition (get_ccode_name (cl.base_class), new CCodeVariableDeclarator (get_ccode_name (cl))));
101 : } else {
102 1605 : decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (cl)), new CCodeVariableDeclarator (get_ccode_name (cl))));
103 : }
104 :
105 1631 : if (final_not_public) {
106 : // nothing to do
107 2191 : } else if (is_fundamental) {
108 566 : var ref_fun = new CCodeFunction (get_ccode_ref_function (cl), "gpointer");
109 566 : var unref_fun = new CCodeFunction (get_ccode_unref_function (cl), "void");
110 566 : if (cl.is_private_symbol ()) {
111 7 : ref_fun.modifiers = CCodeModifiers.STATIC;
112 7 : unref_fun.modifiers = CCodeModifiers.STATIC;
113 559 : } else if (context.hide_internal && cl.is_internal_symbol ()) {
114 6 : ref_fun.modifiers = CCodeModifiers.INTERNAL;
115 6 : unref_fun.modifiers = CCodeModifiers.INTERNAL;
116 : } else {
117 553 : ref_fun.modifiers = CCodeModifiers.EXTERN;
118 553 : unref_fun.modifiers = CCodeModifiers.EXTERN;
119 553 : requires_vala_extern = true;
120 : }
121 :
122 566 : ref_fun.add_parameter (new CCodeParameter ("instance", "gpointer"));
123 566 : unref_fun.add_parameter (new CCodeParameter ("instance", "gpointer"));
124 :
125 566 : decl_space.add_function_declaration (ref_fun);
126 566 : decl_space.add_function_declaration (unref_fun);
127 :
128 : // GParamSpec and GValue functions
129 566 : var function = new CCodeFunction (get_ccode_param_spec_function (cl), "GParamSpec*");
130 566 : function.add_parameter (new CCodeParameter ("name", "const gchar*"));
131 566 : function.add_parameter (new CCodeParameter ("nick", "const gchar*"));
132 566 : function.add_parameter (new CCodeParameter ("blurb", "const gchar*"));
133 566 : function.add_parameter (new CCodeParameter ("object_type", "GType"));
134 566 : function.add_parameter (new CCodeParameter ("flags", "GParamFlags"));
135 :
136 566 : if (cl.is_private_symbol ()) {
137 : // avoid C warning as this function is not always used
138 7 : function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
139 559 : } else if (context.hide_internal && cl.is_internal_symbol ()) {
140 6 : function.modifiers = CCodeModifiers.INTERNAL;
141 : } else {
142 553 : function.modifiers = CCodeModifiers.EXTERN;
143 553 : requires_vala_extern = true;
144 : }
145 :
146 566 : decl_space.add_function_declaration (function);
147 :
148 566 : function = new CCodeFunction (get_ccode_set_value_function (cl), "void");
149 566 : function.add_parameter (new CCodeParameter ("value", "GValue*"));
150 566 : function.add_parameter (new CCodeParameter ("v_object", "gpointer"));
151 :
152 566 : if (cl.is_private_symbol ()) {
153 : // avoid C warning as this function is not always used
154 7 : function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
155 559 : } else if (context.hide_internal && cl.is_internal_symbol ()) {
156 : // avoid C warning as this function is not always used
157 6 : function.modifiers = CCodeModifiers.INTERNAL | CCodeModifiers.UNUSED;
158 : } else {
159 553 : function.modifiers = CCodeModifiers.EXTERN;
160 553 : requires_vala_extern = true;
161 : }
162 :
163 566 : decl_space.add_function_declaration (function);
164 :
165 566 : function = new CCodeFunction (get_ccode_take_value_function (cl), "void");
166 566 : function.add_parameter (new CCodeParameter ("value", "GValue*"));
167 566 : function.add_parameter (new CCodeParameter ("v_object", "gpointer"));
168 :
169 566 : if (cl.is_private_symbol ()) {
170 : // avoid C warning as this function is not always used
171 7 : function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
172 559 : } else if (context.hide_internal && cl.is_internal_symbol ()) {
173 6 : function.modifiers = CCodeModifiers.INTERNAL;
174 : } else {
175 553 : function.modifiers = CCodeModifiers.EXTERN;
176 553 : requires_vala_extern = true;
177 : }
178 :
179 566 : decl_space.add_function_declaration (function);
180 :
181 566 : function = new CCodeFunction (get_ccode_get_value_function (cl), "gpointer");
182 566 : function.add_parameter (new CCodeParameter ("value", "const GValue*"));
183 :
184 566 : if (cl.is_private_symbol ()) {
185 : // avoid C warning as this function is not always used
186 7 : function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
187 559 : } else if (context.hide_internal && cl.is_internal_symbol ()) {
188 : // avoid C warning as this function is not always used
189 6 : function.modifiers = CCodeModifiers.INTERNAL | CCodeModifiers.UNUSED;
190 : } else {
191 553 : function.modifiers = CCodeModifiers.EXTERN;
192 553 : requires_vala_extern = true;
193 : }
194 :
195 566 : decl_space.add_function_declaration (function);
196 1059 : } else if (!is_gtypeinstance && !is_gsource) {
197 170 : if (cl.base_class == null) {
198 74 : var function = new CCodeFunction (get_ccode_free_function (cl), "void");
199 74 : if (cl.is_private_symbol ()) {
200 0 : function.modifiers = CCodeModifiers.STATIC;
201 74 : } else if (context.hide_internal && cl.is_internal_symbol ()) {
202 0 : function.modifiers = CCodeModifiers.INTERNAL;
203 : } else {
204 74 : function.modifiers = CCodeModifiers.EXTERN;
205 74 : requires_vala_extern = true;
206 : }
207 :
208 74 : function.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl))));
209 :
210 74 : decl_space.add_function_declaration (function);
211 : }
212 : }
213 :
214 3160 : if (is_gtypeinstance) {
215 1529 : decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_type_name (cl)), new CCodeVariableDeclarator (get_ccode_type_name (cl))));
216 :
217 1529 : var type_fun = new ClassRegisterFunction (cl);
218 1529 : type_fun.init_from_type (context, in_plugin, true);
219 1529 : if (!final_not_public) {
220 1523 : decl_space.add_type_member_declaration (type_fun.get_declaration ());
221 : }
222 :
223 1529 : requires_vala_extern = true;
224 : }
225 :
226 1631 : if (final_not_public) {
227 : // nothing to do
228 : return;
229 : }
230 :
231 45712 : var base_class = cl;
232 3099 : while (base_class.base_class != null) {
233 2948 : base_class = base_class.base_class;
234 : }
235 : // Custom unref-methods need to be emitted before G_DEFINE_AUTOPTR_CLEANUP_FUNC,
236 : // so we guard against that special case and handle it in generate_method_declaration.
237 1625 : generate_autoptr_cleanup (cl, base_class, decl_space);
238 : }
239 :
240 1802 : void generate_autoptr_cleanup (ObjectTypeSymbol sym, Class cl, CCodeFile decl_space) {
241 3570 : if (!(cl.is_compact && is_reference_counting (cl))
242 1786 : && (context.header_filename == null|| decl_space.file_type == CCodeFileType.PUBLIC_HEADER
243 18 : || (decl_space.file_type == CCodeFileType.INTERNAL_HEADER && cl.is_internal_symbol ()))) {
244 : string autoptr_cleanup_func;
245 1768 : if (is_reference_counting (cl)) {
246 1682 : autoptr_cleanup_func = get_ccode_unref_function (cl);
247 : } else {
248 86 : autoptr_cleanup_func = get_ccode_free_function (cl);
249 : }
250 1768 : if (autoptr_cleanup_func == null || autoptr_cleanup_func == "") {
251 0 : Report.error (cl.source_reference, "internal error: autoptr_cleanup_func not available");
252 : }
253 1768 : decl_space.add_type_member_declaration (new CCodeIdentifier ("G_DEFINE_AUTOPTR_CLEANUP_FUNC (%s, %s)".printf (get_ccode_name (sym), autoptr_cleanup_func)));
254 1768 : decl_space.add_type_member_declaration (new CCodeNewline ());
255 : }
256 : }
257 :
258 7099 : public override void generate_class_struct_declaration (Class cl, CCodeFile decl_space) {
259 5497 : if (add_symbol_declaration (decl_space, cl, "struct _%s".printf (get_ccode_name (cl)))) {
260 : return;
261 : }
262 :
263 1602 : if (cl.base_class != null) {
264 : // base class declaration
265 969 : generate_class_struct_declaration (cl.base_class, decl_space);
266 : }
267 3962 : foreach (DataType base_type in cl.get_base_types ()) {
268 1180 : unowned Interface? iface = base_type.type_symbol as Interface;
269 1180 : if (iface != null) {
270 211 : generate_interface_declaration (iface, decl_space);
271 : }
272 : }
273 :
274 1602 : generate_class_declaration (cl, decl_space);
275 :
276 1602 : bool is_gtypeinstance = !cl.is_compact;
277 1602 : bool is_fundamental = is_gtypeinstance && cl.base_class == null;
278 :
279 1602 : var instance_struct = new CCodeStruct ("_%s".printf (get_ccode_name (cl)));
280 1602 : var type_struct = new CCodeStruct ("_%s".printf (get_ccode_type_name (cl)));
281 :
282 1602 : if (cl.base_class != null) {
283 969 : instance_struct.add_field (get_ccode_name (cl.base_class), "parent_instance");
284 633 : } else if (is_fundamental) {
285 561 : instance_struct.add_field ("GTypeInstance", "parent_instance");
286 561 : instance_struct.add_field ("volatile int", "ref_count");
287 : }
288 :
289 1602 : if (is_gtypeinstance) {
290 1502 : decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %sPrivate".printf (instance_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (get_ccode_name (cl)))));
291 :
292 1502 : if (!context.abi_stability) {
293 1300 : instance_struct.add_field ("%sPrivate *".printf (get_ccode_name (cl)), "priv");
294 : }
295 1502 : if (is_fundamental) {
296 561 : type_struct.add_field ("GTypeClass", "parent_class");
297 : } else {
298 941 : type_struct.add_field (get_ccode_type_name (cl.base_class), "parent_class");
299 : }
300 :
301 1502 : if (is_fundamental) {
302 561 : type_struct.add_field ("void", "(*finalize) (%s *self)".printf (get_ccode_name (cl)));
303 : }
304 : }
305 :
306 1602 : if (context.abi_stability) {
307 8204 : foreach (Symbol s in cl.get_members ()) {
308 6580 : if (s is Method) {
309 2579 : var m = (Method) s;
310 2579 : generate_struct_method_declaration (cl, m, instance_struct, type_struct, decl_space);
311 1422 : } else if (s is Signal) {
312 0 : var sig = (Signal) s;
313 0 : if (sig.default_handler != null) {
314 0 : if (sig.is_virtual) {
315 0 : generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
316 : } else {
317 0 : generate_method_declaration (sig.default_handler, cfile);
318 : }
319 : }
320 1627 : } else if (s is Property) {
321 205 : var prop = (Property) s;
322 205 : generate_struct_property_declaration (cl, prop, instance_struct, type_struct, decl_space);
323 1217 : } else if (s is Field) {
324 1217 : if (s.access != SymbolAccessibility.PRIVATE || cl.is_opaque) {
325 318 : generate_struct_field_declaration ((Field) s, instance_struct, type_struct, decl_space);
326 : }
327 : } else {
328 0 : Report.error (s.source_reference, "internal: Unsupported symbol");
329 : }
330 : }
331 : } else {
332 6802 : foreach (Method m in cl.get_methods ()) {
333 2701 : generate_struct_method_declaration (cl, m, instance_struct, type_struct, decl_space);
334 : }
335 :
336 1744 : foreach (Signal sig in cl.get_signals ()) {
337 172 : if (sig.default_handler != null) {
338 25 : if (sig.is_virtual) {
339 21 : generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
340 : } else {
341 4 : generate_method_declaration (sig.default_handler, cfile);
342 : }
343 : }
344 : }
345 :
346 2608 : foreach (Property prop in cl.get_properties ()) {
347 604 : generate_struct_property_declaration (cl, prop, instance_struct, type_struct, decl_space);
348 : }
349 :
350 3556 : foreach (Field f in cl.get_fields ()) {
351 1078 : if (f.access != SymbolAccessibility.PRIVATE || cl.is_opaque) {
352 443 : generate_struct_field_declaration (f, instance_struct, type_struct, decl_space);
353 : }
354 : }
355 : }
356 :
357 1602 : if (cl.is_compact && cl.base_class == null && !compact_class_has_instance_struct_member (cl)) {
358 : // add dummy member, C doesn't allow empty structs
359 22 : instance_struct.add_field ("int", "dummy");
360 : }
361 :
362 1602 : if (!cl.is_compact || cl.base_class == null || compact_class_has_instance_struct_member (cl)) {
363 1576 : decl_space.add_type_definition (instance_struct);
364 : }
365 :
366 1602 : if (is_gtypeinstance) {
367 1502 : if (context.abi_stability) {
368 202 : instance_struct.add_field ("%sPrivate *".printf (get_ccode_name (cl)), "priv");
369 : }
370 1502 : decl_space.add_type_definition (type_struct);
371 : }
372 : }
373 :
374 128 : bool compact_class_has_instance_struct_member (Class cl) {
375 128 : assert (cl.is_compact);
376 436 : foreach (Symbol s in cl.get_members ()) {
377 208 : if (s is Method) {
378 142 : unowned Method m = (Method) s;
379 142 : if (m.is_abstract || m.is_virtual) {
380 0 : return true;
381 : }
382 66 : } else if (s is Property) {
383 12 : unowned Property prop = (Property) s;
384 12 : if (prop.is_abstract || prop.is_virtual) {
385 0 : return true;
386 : }
387 54 : } else if (s is Field) {
388 54 : if (s.access != SymbolAccessibility.PRIVATE || cl.is_opaque) {
389 54 : unowned Field f = (Field) s;
390 54 : if (f.binding == MemberBinding.INSTANCE) {
391 54 : return true;
392 : }
393 : }
394 : } else {
395 0 : Report.error (s.source_reference, "internal: Unsupported symbol");
396 : }
397 : }
398 128 : return false;
399 : }
400 :
401 5536 : void generate_struct_method_declaration (ObjectTypeSymbol type_sym, Method m, CCodeStruct instance_struct, CCodeStruct type_struct, CCodeFile decl_space) {
402 5536 : unowned Class? cl = type_sym as Class;
403 5536 : if (type_sym is Interface || (cl != null && !cl.is_compact)) {
404 5359 : generate_virtual_method_declaration (m, decl_space, type_struct);
405 177 : } else if (cl != null && cl.is_compact && cl.base_class == null) {
406 118 : generate_virtual_method_declaration (m, decl_space, instance_struct);
407 : }
408 : }
409 :
410 987 : void generate_struct_property_declaration (ObjectTypeSymbol type_sym, Property prop, CCodeStruct instance_struct, CCodeStruct type_struct, CCodeFile decl_space) {
411 869 : if (!prop.is_abstract && !prop.is_virtual) {
412 : return;
413 : }
414 118 : generate_type_declaration (prop.property_type, decl_space);
415 :
416 118 : unowned ObjectTypeSymbol t = (ObjectTypeSymbol) prop.parent_symbol;
417 118 : unowned Class? cl = type_sym as Class;
418 :
419 118 : var this_type = new ObjectType (t);
420 118 : var cselfparam = new CCodeParameter ("self", get_ccode_name (this_type));
421 :
422 236 : if (prop.get_accessor != null) {
423 118 : var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name));
424 118 : vdeclarator.add_parameter (cselfparam);
425 118 : var creturn_type = get_callable_creturn_type (prop.get_accessor.get_method ());
426 128 : if (prop.property_type.is_real_non_null_struct_type ()) {
427 10 : var cvalueparam = new CCodeParameter ("result", "%s *".printf (get_ccode_name (prop.get_accessor.value_type)));
428 10 : vdeclarator.add_parameter (cvalueparam);
429 : }
430 :
431 118 : var array_type = prop.property_type as ArrayType;
432 127 : if (array_type != null && get_ccode_array_length (prop)) {
433 9 : var length_ctype = get_ccode_array_length_type (prop) + "*";
434 18 : for (int dim = 1; dim <= array_type.rank; dim++) {
435 9 : vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("result", dim), length_ctype));
436 : }
437 109 : } else if ((prop.property_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) prop.property_type).delegate_symbol.has_target) {
438 13 : vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_cname ("result"), "gpointer*"));
439 : }
440 :
441 118 : var vdecl = new CCodeDeclaration (get_ccode_name (creturn_type));
442 118 : vdecl.add_declarator (vdeclarator);
443 118 : type_struct.add_declaration (vdecl);
444 :
445 118 : if (cl != null && cl.is_compact && cl.base_class == null) {
446 4 : instance_struct.add_declaration (vdecl);
447 : }
448 : }
449 220 : if (prop.set_accessor != null) {
450 : CCodeParameter cvalueparam;
451 102 : if (prop.property_type.is_real_non_null_struct_type ()) {
452 10 : cvalueparam = new CCodeParameter ("value", "%s *".printf (get_ccode_name (prop.set_accessor.value_type)));
453 : } else {
454 92 : cvalueparam = new CCodeParameter ("value", get_ccode_name (prop.set_accessor.value_type));
455 : }
456 :
457 102 : var vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name));
458 102 : vdeclarator.add_parameter (cselfparam);
459 102 : vdeclarator.add_parameter (cvalueparam);
460 :
461 102 : var array_type = prop.property_type as ArrayType;
462 111 : if (array_type != null && get_ccode_array_length (prop)) {
463 9 : var length_ctype = get_ccode_array_length_type (prop);
464 18 : for (int dim = 1; dim <= array_type.rank; dim++) {
465 9 : vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("value", dim), length_ctype));
466 : }
467 93 : } else if ((prop.property_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) prop.property_type).delegate_symbol.has_target) {
468 13 : vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_cname ("value"), "gpointer"));
469 13 : if (prop.set_accessor.value_type.value_owned) {
470 8 : vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_destroy_notify_cname ("value"), get_ccode_name (delegate_target_destroy_type)));
471 : }
472 : }
473 :
474 102 : var vdecl = new CCodeDeclaration ("void");
475 102 : vdecl.add_declarator (vdeclarator);
476 102 : type_struct.add_declaration (vdecl);
477 :
478 102 : if (cl != null && cl.is_compact && cl.base_class == null) {
479 4 : instance_struct.add_declaration (vdecl);
480 : }
481 : }
482 : }
483 :
484 1644 : void generate_struct_field_declaration (Field f, CCodeStruct instance_struct, CCodeStruct type_struct, CCodeFile decl_space) {
485 1644 : if (f.binding == MemberBinding.INSTANCE) {
486 1387 : append_field (instance_struct, f, decl_space);
487 257 : } else if (f.binding == MemberBinding.CLASS) {
488 25 : append_field (type_struct, f, decl_space);
489 : }
490 : }
491 :
492 28276 : public override bool generate_method_declaration (Method m, CCodeFile decl_space) {
493 28276 : if (base.generate_method_declaration (m, decl_space)) {
494 : // Custom unref-methods need to be emitted before G_DEFINE_AUTOPTR_CLEANUP_FUNC,
495 : // in addition to the non-ref-countable case in generate_class_declaration.
496 7310 : unowned Class? cl = m.parent_symbol as Class;
497 3561 : if (cl != null && cl.is_compact && get_ccode_unref_function (cl) == get_ccode_name (m)
498 6 : && (context.header_filename == null || decl_space.file_type == CCodeFileType.PUBLIC_HEADER
499 0 : || (decl_space.file_type == CCodeFileType.INTERNAL_HEADER && cl.is_internal_symbol()))) {
500 6 : decl_space.add_type_member_declaration (new CCodeIdentifier ("G_DEFINE_AUTOPTR_CLEANUP_FUNC (%s, %s)".printf (get_ccode_name (cl), get_ccode_name (m))));
501 6 : decl_space.add_type_member_declaration (new CCodeNewline ());
502 : }
503 :
504 7310 : return true;
505 : }
506 :
507 28276 : return false;
508 : }
509 :
510 11248 : public virtual void generate_virtual_method_declaration (Method m, CCodeFile decl_space, CCodeStruct type_struct) {
511 5286 : if (!m.is_abstract && !m.is_virtual) {
512 : return;
513 : }
514 :
515 462 : var creturn_type = get_callable_creturn_type (m);
516 :
517 : // add vfunc field to the type struct
518 462 : var vdeclarator = new CCodeFunctionDeclarator (get_ccode_vfunc_name (m));
519 462 : var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
520 :
521 462 : if (m.printf_format) {
522 4 : vdeclarator.modifiers |= CCodeModifiers.PRINTF;
523 458 : } else if (m.scanf_format) {
524 2 : vdeclarator.modifiers |= CCodeModifiers.SCANF;
525 : }
526 :
527 462 : if (m.version.deprecated) {
528 6 : vdeclarator.modifiers |= CCodeModifiers.DEPRECATED;
529 : }
530 :
531 462 : generate_cparameters (m, decl_space, cparam_map, new CCodeFunction ("fake"), vdeclarator);
532 :
533 462 : var vdecl = new CCodeDeclaration (get_ccode_name (creturn_type));
534 462 : vdecl.add_declarator (vdeclarator);
535 462 : type_struct.add_declaration (vdecl);
536 : }
537 :
538 1556 : void generate_class_private_declaration (Class cl, CCodeFile decl_space) {
539 779 : if (cl.is_opaque || decl_space.add_declaration ("%sPrivate".printf (get_ccode_name (cl)))) {
540 2 : return;
541 : }
542 :
543 777 : bool is_gtypeinstance = !cl.is_compact;
544 777 : bool has_class_locks = false;
545 :
546 777 : var instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (get_ccode_name (cl)));
547 777 : var type_priv_struct = new CCodeStruct ("_%sPrivate".printf (get_ccode_type_name (cl)));
548 :
549 777 : if (is_gtypeinstance) {
550 : /* create type, dup_func, and destroy_func fields for generic types */
551 842 : foreach (TypeParameter type_param in cl.get_type_parameters ()) {
552 54 : instance_priv_struct.add_field ("GType", get_ccode_type_id (type_param));
553 54 : instance_priv_struct.add_field ("GBoxedCopyFunc", get_ccode_copy_function (type_param));
554 54 : instance_priv_struct.add_field ("GDestroyNotify", get_ccode_destroy_function (type_param));
555 : }
556 : }
557 :
558 3319 : foreach (Field f in cl.get_fields ()) {
559 1271 : if (f.access == SymbolAccessibility.PRIVATE) {
560 883 : generate_struct_field_declaration (f, instance_priv_struct, type_priv_struct, decl_space);
561 : }
562 1271 : if (f.lock_used) {
563 22 : if (f.binding == MemberBinding.INSTANCE) {
564 9 : cl.has_private_fields = true;
565 : // add field for mutex
566 9 : instance_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (f)));
567 13 : } else if (f.binding == MemberBinding.CLASS) {
568 7 : has_class_locks = true;
569 : // add field for mutex
570 7 : type_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (f)));
571 : }
572 : }
573 : }
574 :
575 1705 : foreach (Property prop in cl.get_properties ()) {
576 464 : if (prop.binding == MemberBinding.INSTANCE) {
577 460 : if (prop.lock_used) {
578 3 : cl.has_private_fields = true;
579 : // add field for mutex
580 3 : instance_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (prop)));
581 : }
582 4 : } else if (prop.binding == MemberBinding.CLASS) {
583 0 : if (prop.lock_used) {
584 0 : has_class_locks = true;
585 : // add field for mutex
586 0 : type_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (prop)));
587 : }
588 : }
589 : }
590 :
591 777 : if (is_gtypeinstance) {
592 734 : if (cl.has_class_private_fields || has_class_locks) {
593 5 : decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_priv_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (get_ccode_type_name (cl)))));
594 : }
595 :
596 : /* only add the *Private struct if it is not empty, i.e. we actually have private data */
597 1017 : if (cl.has_private_fields || cl.has_type_parameters ()) {
598 283 : decl_space.add_type_definition (instance_priv_struct);
599 :
600 283 : var parent_decl = new CCodeDeclaration ("gint");
601 283 : var parent_var_decl = new CCodeVariableDeclarator ("%s_private_offset".printf (get_ccode_name (cl)));
602 283 : parent_decl.add_declarator (parent_var_decl);
603 283 : parent_decl.modifiers = CCodeModifiers.STATIC;
604 283 : cfile.add_type_member_declaration (parent_decl);
605 :
606 283 : var function = new CCodeFunction ("%s_get_instance_private".printf (get_ccode_lower_case_name (cl, null)), "gpointer");
607 283 : function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.INLINE;
608 283 : function.add_parameter (new CCodeParameter ("self", "%s*".printf (get_ccode_name (cl))));
609 :
610 283 : push_function (function);
611 :
612 283 : function.block = new CCodeBlock ();
613 283 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_STRUCT_MEMBER_P"));
614 283 : ccall.add_argument (new CCodeIdentifier ("self"));
615 283 : ccall.add_argument (new CCodeIdentifier ("%s_private_offset".printf (get_ccode_name (cl))));
616 283 : function.block.add_statement (new CCodeReturnStatement (ccall));
617 :
618 283 : pop_function ();
619 283 : cfile.add_function (function);
620 : }
621 :
622 734 : if (cl.has_class_private_fields || has_class_locks) {
623 5 : decl_space.add_type_definition (type_priv_struct);
624 :
625 5 : string macro = "(G_TYPE_CLASS_GET_PRIVATE (klass, %s, %sPrivate))".printf (get_ccode_type_id (cl), get_ccode_type_name (cl));
626 5 : decl_space.add_type_member_declaration (new CCodeMacroReplacement ("%s(klass)".printf (get_ccode_class_get_private_function (cl)), macro));
627 : }
628 : }
629 : }
630 :
631 1559 : public override void visit_class (Class cl) {
632 780 : push_context (new EmitContext (cl));
633 780 : push_line (cl.source_reference);
634 :
635 5333 : var old_param_spec_struct = param_spec_struct;
636 780 : var old_prop_enum = prop_enum;
637 780 : var old_signal_enum = signal_enum;
638 6234 : var old_class_init_context = class_init_context;
639 780 : var old_base_init_context = base_init_context;
640 780 : var old_class_finalize_context = class_finalize_context;
641 780 : var old_base_finalize_context = base_finalize_context;
642 780 : var old_instance_init_context = instance_init_context;
643 780 : var old_instance_finalize_context = instance_finalize_context;
644 :
645 780 : bool is_gtypeinstance = !cl.is_compact;
646 780 : bool is_gobject = is_gtypeinstance && cl.is_subtype_of (gobject_type);
647 735 : bool is_fundamental = is_gtypeinstance && cl.base_class == null;
648 :
649 780 : if (get_ccode_name (cl).length < 3) {
650 1 : cl.error = true;
651 1 : Report.error (cl.source_reference, "Class name `%s' is too short", get_ccode_name (cl));
652 1 : return;
653 : }
654 :
655 779 : prop_enum = new CCodeEnum ();
656 779 : prop_enum.add_value (new CCodeEnumValue ("%s_0_PROPERTY".printf (get_ccode_upper_case_name (cl, null))));
657 779 : signal_enum = new CCodeEnum ();
658 779 : class_init_context = new EmitContext (cl);
659 779 : base_init_context = new EmitContext (cl);
660 779 : class_finalize_context = new EmitContext (cl);
661 779 : base_finalize_context = new EmitContext (cl);
662 779 : instance_init_context = new EmitContext (cl);
663 779 : instance_finalize_context = new EmitContext (cl);
664 :
665 779 : generate_class_struct_declaration (cl, cfile);
666 779 : generate_class_private_declaration (cl, cfile);
667 :
668 779 : var last_prop = "%s_NUM_PROPERTIES".printf (get_ccode_upper_case_name (cl));
669 1204 : if (is_gobject) {
670 425 : cfile.add_type_declaration (prop_enum);
671 :
672 425 : var prop_array_decl = new CCodeDeclaration ("GParamSpec*");
673 425 : prop_array_decl.modifiers |= CCodeModifiers.STATIC;
674 425 : 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))));
675 425 : cfile.add_type_declaration (prop_array_decl);
676 : }
677 :
678 779 : if (!cl.is_internal_symbol () || cl.is_sealed) {
679 277 : if (!cl.is_opaque && !cl.is_sealed) {
680 269 : generate_class_struct_declaration (cl, header_file);
681 : } else {
682 8 : generate_class_declaration (cl, header_file);
683 : }
684 : }
685 779 : if (!cl.is_private_symbol () || cl.is_sealed) {
686 766 : generate_class_struct_declaration (cl, internal_header_file);
687 : }
688 :
689 779 : if (is_gtypeinstance) {
690 734 : begin_base_init_function (cl);
691 734 : begin_class_init_function (cl);
692 734 : begin_instance_init_function (cl);
693 :
694 734 : begin_base_finalize_function (cl);
695 734 : begin_class_finalize_function (cl);
696 734 : begin_finalize_function (cl);
697 : } else {
698 45 : if (cl.is_compact || cl.base_class == null || cl.is_subtype_of (gsource_type)) {
699 45 : begin_instance_init_function (cl);
700 45 : begin_finalize_function (cl);
701 : }
702 : }
703 :
704 779 : cl.accept_children (this);
705 :
706 1513 : if (is_gtypeinstance) {
707 990 : if (is_fundamental) {
708 256 : param_spec_struct = new CCodeStruct ( "_%sParamSpec%s".printf(get_ccode_prefix (cl.parent_symbol), cl.name));
709 256 : param_spec_struct.add_field ("GParamSpec", "parent_instance");
710 256 : cfile.add_type_definition (param_spec_struct);
711 :
712 256 : 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))));
713 :
714 256 : add_type_value_table_init_function (cl);
715 256 : add_type_value_table_free_function (cl);
716 256 : add_type_value_table_copy_function (cl);
717 256 : add_type_value_table_peek_pointer_function (cl);
718 256 : add_type_value_table_collect_value_function (cl);
719 256 : add_type_value_table_lcopy_value_function (cl);
720 256 : add_g_param_spec_type_function (cl);
721 256 : add_g_value_get_function (cl);
722 256 : add_g_value_set_function (cl);
723 256 : add_g_value_take_function (cl);
724 :
725 256 : var ref_count = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count"), new CCodeConstant ("1"));
726 256 : push_context (instance_init_context);
727 256 : ccode.add_expression (ref_count);
728 256 : pop_context ();
729 : }
730 :
731 734 : if (is_gobject) {
732 425 : prop_enum.add_value (new CCodeEnumValue (last_prop));
733 : }
734 :
735 779 : if (cl.get_signals ().size > 0) {
736 45 : var last_signal = "%s_NUM_SIGNALS".printf (get_ccode_upper_case_name (cl));
737 45 : signal_enum.add_value (new CCodeEnumValue (last_signal));
738 45 : cfile.add_type_declaration (signal_enum);
739 :
740 45 : var signal_array_decl = new CCodeDeclaration ("guint");
741 45 : signal_array_decl.modifiers |= CCodeModifiers.STATIC;
742 45 : 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))));
743 45 : cfile.add_type_declaration (signal_array_decl);
744 : }
745 :
746 :
747 734 : if (cl.class_constructor != null) {
748 7 : add_base_init_function (cl);
749 : }
750 734 : add_class_init_function (cl);
751 :
752 734 : if (cl.class_destructor != null) {
753 3 : add_base_finalize_function (cl);
754 : }
755 :
756 734 : if (cl.static_destructor != null) {
757 1 : add_class_finalize_function (cl);
758 : }
759 :
760 1938 : foreach (DataType base_type in cl.get_base_types ()) {
761 602 : if (base_type.type_symbol is Interface) {
762 124 : add_interface_init_function (cl, (Interface) base_type.type_symbol);
763 : }
764 : }
765 :
766 734 : add_instance_init_function (cl);
767 :
768 734 : if (!cl.is_compact && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) {
769 480 : add_finalize_function (cl);
770 : }
771 :
772 734 : if (cl.comment != null) {
773 41 : cfile.add_type_member_definition (new CCodeComment (cl.comment.content));
774 : }
775 :
776 734 : var type_fun = new ClassRegisterFunction (cl);
777 734 : type_fun.init_from_type (context, in_plugin, false);
778 734 : cfile.add_type_member_declaration (type_fun.get_source_declaration ());
779 734 : cfile.add_type_member_definition (type_fun.get_definition ());
780 :
781 990 : if (is_fundamental) {
782 256 : var ref_count = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count");
783 :
784 : // ref function
785 256 : var ref_fun = new CCodeFunction (get_ccode_ref_function (cl), "gpointer");
786 256 : ref_fun.add_parameter (new CCodeParameter ("instance", "gpointer"));
787 256 : if (cl.is_private_symbol ()) {
788 7 : ref_fun.modifiers = CCodeModifiers.STATIC;
789 249 : } else if (context.hide_internal && cl.is_internal_symbol ()) {
790 3 : ref_fun.modifiers = CCodeModifiers.INTERNAL;
791 : }
792 256 : push_function (ref_fun);
793 :
794 256 : ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self", new CCodeIdentifier ("instance")));
795 256 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_inc"));
796 256 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ref_count));
797 256 : ccode.add_expression (ccall);
798 256 : ccode.add_return (new CCodeIdentifier ("instance"));
799 :
800 256 : pop_function ();
801 256 : cfile.add_function (ref_fun);
802 :
803 : // unref function
804 256 : var unref_fun = new CCodeFunction (get_ccode_unref_function (cl), "void");
805 256 : unref_fun.add_parameter (new CCodeParameter ("instance", "gpointer"));
806 256 : if (cl.is_private_symbol ()) {
807 7 : unref_fun.modifiers = CCodeModifiers.STATIC;
808 249 : } else if (context.hide_internal && cl.is_internal_symbol ()) {
809 3 : unref_fun.modifiers = CCodeModifiers.INTERNAL;
810 : }
811 256 : push_function (unref_fun);
812 :
813 256 : ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self", new CCodeIdentifier ("instance")));
814 256 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_dec_and_test"));
815 256 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ref_count));
816 256 : ccode.open_if (ccall);
817 :
818 256 : var get_class = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_get_function (cl)));
819 256 : get_class.add_argument (new CCodeIdentifier ("self"));
820 :
821 : // finalize class
822 256 : var ccast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_get_function (cl)));
823 256 : ccast.add_argument (new CCodeIdentifier ("self"));
824 256 : ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize"));
825 256 : ccall.add_argument (new CCodeIdentifier ("self"));
826 256 : ccode.add_expression (ccall);
827 :
828 : // free type instance
829 256 : var free = new CCodeFunctionCall (new CCodeIdentifier ("g_type_free_instance"));
830 256 : free.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GTypeInstance *"));
831 256 : ccode.add_expression (free);
832 :
833 256 : ccode.close ();
834 256 : pop_function ();
835 256 : cfile.add_function (unref_fun);
836 : }
837 : } else {
838 45 : if (cl.is_compact || cl.base_class == null || cl.is_subtype_of (gsource_type)) {
839 45 : add_instance_init_function (cl);
840 45 : add_finalize_function (cl);
841 : }
842 : }
843 :
844 779 : param_spec_struct = old_param_spec_struct;
845 792 : prop_enum = old_prop_enum;
846 794 : signal_enum = old_signal_enum;
847 792 : class_init_context = old_class_init_context;
848 792 : base_init_context = old_base_init_context;
849 792 : class_finalize_context = old_class_finalize_context;
850 792 : base_finalize_context = old_base_finalize_context;
851 792 : instance_init_context = old_instance_init_context;
852 792 : instance_finalize_context = old_instance_finalize_context;
853 :
854 779 : pop_line ();
855 779 : pop_context ();
856 : }
857 :
858 512 : private void add_type_value_table_init_function (Class cl) {
859 256 : var function = new CCodeFunction ("%s_init".printf (get_ccode_lower_case_name (cl, "value_")), "void");
860 256 : function.add_parameter (new CCodeParameter ("value", "GValue*"));
861 256 : function.modifiers = CCodeModifiers.STATIC;
862 :
863 256 : push_function (function);
864 256 : ccode.add_assignment (new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer"), new CCodeConstant ("NULL"));
865 256 : pop_function ();
866 256 : cfile.add_function (function);
867 : }
868 :
869 512 : private void add_type_value_table_free_function (Class cl) {
870 256 : var function = new CCodeFunction ("%s_free_value".printf (get_ccode_lower_case_name (cl, "value_")), "void");
871 256 : function.add_parameter (new CCodeParameter ("value", "GValue*"));
872 256 : function.modifiers = CCodeModifiers.STATIC;
873 :
874 256 : push_function (function);
875 :
876 256 : var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
877 256 : var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (cl)));
878 256 : ccall.add_argument (vpointer);
879 :
880 256 : ccode.open_if (vpointer);
881 256 : ccode.add_expression (ccall);
882 256 : ccode.close ();
883 :
884 256 : pop_function ();
885 256 : cfile.add_function (function);
886 : }
887 :
888 512 : private void add_type_value_table_copy_function (Class cl) {
889 256 : var function = new CCodeFunction ("%s_copy_value".printf (get_ccode_lower_case_name (cl, "value_")), "void");
890 256 : function.add_parameter (new CCodeParameter ("src_value", "const GValue*"));
891 256 : function.add_parameter (new CCodeParameter ("dest_value", "GValue*"));
892 256 : function.modifiers = CCodeModifiers.STATIC;
893 :
894 256 : push_function (function);
895 :
896 256 : var dest_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dest_value"), "data[0]"), "v_pointer");
897 256 : var src_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("src_value"), "data[0]"), "v_pointer");
898 :
899 256 : var ref_ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl)));
900 256 : ref_ccall.add_argument ( src_vpointer );
901 :
902 256 : ccode.open_if (src_vpointer);
903 256 : ccode.add_assignment (dest_vpointer, ref_ccall);
904 256 : ccode.add_else ();
905 256 : ccode.add_assignment (dest_vpointer, new CCodeConstant ("NULL"));
906 256 : ccode.close ();
907 :
908 256 : pop_function ();
909 256 : cfile.add_function (function);
910 : }
911 :
912 512 : private void add_type_value_table_peek_pointer_function (Class cl) {
913 256 : var function = new CCodeFunction ("%s_peek_pointer".printf (get_ccode_lower_case_name (cl, "value_")), "gpointer");
914 256 : function.add_parameter (new CCodeParameter ("value", "const GValue*"));
915 256 : function.modifiers = CCodeModifiers.STATIC;
916 :
917 256 : push_function (function);
918 :
919 256 : var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
920 256 : ccode.add_return (vpointer);
921 :
922 256 : pop_function ();
923 256 : cfile.add_function (function);
924 : }
925 :
926 512 : private void add_type_value_table_lcopy_value_function ( Class cl ) {
927 : // Required for GTypeCValue
928 256 : cfile.add_include ("gobject/gvaluecollector.h");
929 :
930 256 : var function = new CCodeFunction ("%s_lcopy_value".printf (get_ccode_lower_case_name (cl, "value_")), "gchar*");
931 256 : function.add_parameter (new CCodeParameter ("value", "const GValue*"));
932 256 : function.add_parameter (new CCodeParameter ("n_collect_values", "guint"));
933 256 : function.add_parameter (new CCodeParameter ("collect_values", "GTypeCValue*"));
934 256 : function.add_parameter (new CCodeParameter ("collect_flags", "guint"));
935 256 : function.modifiers = CCodeModifiers.STATIC;
936 :
937 256 : var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
938 256 : var object_p_ptr = new CCodeIdentifier ("*object_p");
939 256 : var null_ = new CCodeConstant ("NULL");
940 :
941 256 : push_function (function);
942 :
943 256 : ccode.add_declaration ("%s **".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("object_p", new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"), "v_pointer")));
944 :
945 256 : var value_type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME"));
946 256 : value_type_name_fct.add_argument (new CCodeConstant ("value"));
947 :
948 256 : var assert_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("object_p"));
949 256 : ccode.open_if (assert_condition);
950 256 : var assert_printf = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup_printf"));
951 256 : assert_printf.add_argument (new CCodeConstant ("\"value location for `%s' passed as NULL\""));
952 256 : assert_printf.add_argument (value_type_name_fct);
953 256 : ccode.add_return (assert_printf);
954 256 : ccode.close ();
955 :
956 256 : var main_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, vpointer);
957 256 : var main_else_if_condition = new CCodeBinaryExpression (CCodeBinaryOperator.BITWISE_AND, new CCodeIdentifier ("collect_flags"), new CCodeIdentifier ("G_VALUE_NOCOPY_CONTENTS"));
958 256 : var ref_fct = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl)));
959 256 : ref_fct.add_argument (vpointer);
960 256 : ccode.open_if (main_condition);
961 256 : ccode.add_assignment (object_p_ptr, null_);
962 256 : ccode.else_if (main_else_if_condition);
963 256 : ccode.add_assignment (object_p_ptr, vpointer);
964 256 : ccode.add_else ();
965 256 : ccode.add_assignment (object_p_ptr, ref_fct);
966 256 : ccode.close ();
967 :
968 256 : ccode.add_return (null_);
969 256 : pop_function ();
970 256 : cfile.add_function (function);
971 : }
972 :
973 512 : private void add_type_value_table_collect_value_function (Class cl) {
974 : // Required for GTypeCValue
975 256 : cfile.add_include ("gobject/gvaluecollector.h");
976 :
977 256 : var function = new CCodeFunction ("%s_collect_value".printf (get_ccode_lower_case_name (cl, "value_")), "gchar*");
978 256 : function.add_parameter (new CCodeParameter ("value", "GValue*"));
979 256 : function.add_parameter (new CCodeParameter ("n_collect_values", "guint"));
980 256 : function.add_parameter (new CCodeParameter ("collect_values", "GTypeCValue*"));
981 256 : function.add_parameter (new CCodeParameter ("collect_flags", "guint"));
982 256 : function.modifiers = CCodeModifiers.STATIC;
983 :
984 256 : var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
985 :
986 256 : push_function (function);
987 :
988 256 : var collect_vpointer = new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"), "v_pointer");
989 :
990 256 : ccode.open_if (collect_vpointer);
991 256 : ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("object", collect_vpointer));
992 256 : var obj_identifier = new CCodeIdentifier ("object");
993 256 : var l_expression = new CCodeMemberAccess (new CCodeMemberAccess.pointer (obj_identifier, "parent_instance"), "g_class");
994 256 : var sub_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, l_expression, new CCodeConstant ("NULL"));
995 256 : var value_type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME"));
996 256 : value_type_name_fct.add_argument (new CCodeConstant ("value"));
997 :
998 256 : ccode.open_if (sub_condition);
999 256 : var true_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat"));
1000 256 : true_return.add_argument (new CCodeConstant ("\"invalid unclassed object pointer for value type `\""));
1001 256 : true_return.add_argument (value_type_name_fct);
1002 256 : true_return.add_argument (new CCodeConstant ("\"'\""));
1003 256 : true_return.add_argument (new CCodeConstant ("NULL"));
1004 256 : ccode.add_return (true_return);
1005 :
1006 256 : var reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
1007 256 : var type_check = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
1008 256 : type_check.add_argument (new CCodeIdentifier ("object"));
1009 256 : reg_call.add_argument (type_check);
1010 256 : var stored_type = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
1011 256 : stored_type.add_argument (new CCodeIdentifier ("value"));
1012 256 : reg_call.add_argument (stored_type);
1013 :
1014 256 : ccode.else_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, reg_call));
1015 256 : var false_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat"));
1016 256 : var type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("g_type_name"));
1017 256 : type_name_fct.add_argument (type_check);
1018 256 : false_return.add_argument (new CCodeConstant ("\"invalid object type `\""));
1019 256 : false_return.add_argument (type_name_fct);
1020 256 : false_return.add_argument (new CCodeConstant ("\"' for value type `\""));
1021 256 : false_return.add_argument (value_type_name_fct);
1022 256 : false_return.add_argument (new CCodeConstant ("\"'\""));
1023 256 : false_return.add_argument (new CCodeConstant ("NULL"));
1024 256 : ccode.add_return (false_return);
1025 :
1026 256 : ccode.close ();
1027 :
1028 256 : var ref_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl)));
1029 256 : ref_call.add_argument (new CCodeIdentifier ("object"));
1030 256 : ccode.add_assignment (vpointer, ref_call);
1031 :
1032 256 : ccode.add_else ();
1033 256 : ccode.add_assignment (vpointer, new CCodeConstant ("NULL"));
1034 :
1035 256 : ccode.close ();
1036 :
1037 256 : ccode.add_return (new CCodeConstant ("NULL"));
1038 :
1039 256 : pop_function ();
1040 256 : cfile.add_function (function);
1041 : }
1042 :
1043 512 : private void add_g_param_spec_type_function (Class cl) {
1044 256 : var function = new CCodeFunction (get_ccode_param_spec_function (cl), "GParamSpec*");
1045 256 : function.add_parameter (new CCodeParameter ("name", "const gchar*"));
1046 256 : function.add_parameter (new CCodeParameter ("nick", "const gchar*"));
1047 256 : function.add_parameter (new CCodeParameter ("blurb", "const gchar*"));
1048 256 : function.add_parameter (new CCodeParameter ("object_type", "GType"));
1049 256 : function.add_parameter (new CCodeParameter ("flags", "GParamFlags"));
1050 :
1051 256 : if (cl.is_private_symbol ()) {
1052 7 : function.modifiers = CCodeModifiers.STATIC;
1053 249 : } else if (context.hide_internal && cl.is_internal_symbol ()) {
1054 3 : function.modifiers = CCodeModifiers.INTERNAL;
1055 : }
1056 :
1057 256 : push_function (function);
1058 :
1059 256 : ccode.add_declaration ("%sParamSpec%s*".printf (get_ccode_prefix (cl.parent_symbol), cl.name), new CCodeVariableDeclarator ("spec"));
1060 :
1061 256 : var subccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_is_a"));
1062 256 : subccall.add_argument (new CCodeIdentifier ("object_type"));
1063 256 : subccall.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
1064 :
1065 256 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail"));
1066 256 : ccall.add_argument (subccall);
1067 256 : ccall.add_argument (new CCodeConstant ("NULL"));
1068 256 : ccode.add_expression (ccall);
1069 :
1070 256 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_internal"));
1071 256 : ccall.add_argument (new CCodeIdentifier ( "G_TYPE_PARAM_OBJECT" ));
1072 256 : ccall.add_argument (new CCodeIdentifier ("name"));
1073 256 : ccall.add_argument (new CCodeIdentifier ("nick"));
1074 256 : ccall.add_argument (new CCodeIdentifier ("blurb"));
1075 256 : ccall.add_argument (new CCodeIdentifier ("flags"));
1076 :
1077 256 : ccode.add_assignment (new CCodeIdentifier ("spec"), ccall);
1078 :
1079 256 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_PARAM_SPEC"));
1080 256 : ccall.add_argument (new CCodeIdentifier ("spec"));
1081 :
1082 256 : ccode.add_assignment (new CCodeMemberAccess.pointer (ccall, "value_type"), new CCodeIdentifier ("object_type"));
1083 256 : ccode.add_return (ccall);
1084 :
1085 256 : pop_function ();
1086 256 : cfile.add_function (function);
1087 : }
1088 :
1089 512 : private void add_g_value_set_function (Class cl) {
1090 256 : var function = new CCodeFunction (get_ccode_set_value_function (cl), "void");
1091 256 : function.add_parameter (new CCodeParameter ("value", "GValue*"));
1092 256 : function.add_parameter (new CCodeParameter ("v_object", "gpointer"));
1093 :
1094 256 : if (cl.is_private_symbol ()) {
1095 7 : function.modifiers = CCodeModifiers.STATIC;
1096 249 : } else if (context.hide_internal && cl.is_internal_symbol ()) {
1097 3 : function.modifiers = CCodeModifiers.INTERNAL;
1098 : }
1099 :
1100 256 : var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
1101 :
1102 256 : push_function (function);
1103 :
1104 256 : ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("old"));
1105 :
1106 256 : var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1107 256 : ccall_typecheck.add_argument (new CCodeIdentifier ( "value" ));
1108 256 : ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
1109 :
1110 256 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1111 256 : ccall.add_argument (ccall_typecheck);
1112 256 : ccode.add_expression (ccall);
1113 :
1114 256 : ccode.add_assignment (new CCodeConstant ("old"), vpointer);
1115 :
1116 256 : ccode.open_if (new CCodeIdentifier ("v_object"));
1117 256 : ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
1118 256 : ccall_typecheck.add_argument (new CCodeIdentifier ( "v_object" ));
1119 256 : ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
1120 :
1121 256 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1122 256 : ccall.add_argument (ccall_typecheck);
1123 256 : ccode.add_expression (ccall);
1124 :
1125 256 : var ccall_typefrominstance = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
1126 256 : ccall_typefrominstance.add_argument (new CCodeIdentifier ( "v_object" ));
1127 :
1128 256 : var ccall_gvaluetype = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
1129 256 : ccall_gvaluetype.add_argument (new CCodeIdentifier ( "value" ));
1130 :
1131 256 : var ccall_typecompatible = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
1132 256 : ccall_typecompatible.add_argument (ccall_typefrominstance);
1133 256 : ccall_typecompatible.add_argument (ccall_gvaluetype);
1134 :
1135 256 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1136 256 : ccall.add_argument (ccall_typecompatible);
1137 256 : ccode.add_expression (ccall);
1138 :
1139 256 : ccode.add_assignment (vpointer, new CCodeConstant ("v_object"));
1140 :
1141 256 : ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl)));
1142 256 : ccall.add_argument (vpointer);
1143 256 : ccode.add_expression (ccall);
1144 :
1145 256 : ccode.add_else ();
1146 256 : ccode.add_assignment (vpointer, new CCodeConstant ("NULL"));
1147 256 : ccode.close ();
1148 :
1149 256 : ccode.open_if (new CCodeIdentifier ("old"));
1150 256 : ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (cl)));
1151 256 : ccall.add_argument (new CCodeIdentifier ("old"));
1152 256 : ccode.add_expression (ccall);
1153 256 : ccode.close ();
1154 :
1155 256 : pop_function ();
1156 256 : cfile.add_function (function);
1157 : }
1158 :
1159 512 : private void add_g_value_take_function (Class cl) {
1160 256 : var function = new CCodeFunction (get_ccode_take_value_function (cl), "void");
1161 256 : function.add_parameter (new CCodeParameter ("value", "GValue*"));
1162 256 : function.add_parameter (new CCodeParameter ("v_object", "gpointer"));
1163 :
1164 256 : if (cl.is_private_symbol ()) {
1165 7 : function.modifiers = CCodeModifiers.STATIC;
1166 249 : } else if (context.hide_internal && cl.is_internal_symbol ()) {
1167 3 : function.modifiers = CCodeModifiers.INTERNAL;
1168 : }
1169 :
1170 256 : var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
1171 :
1172 256 : push_function (function);
1173 :
1174 256 : ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("old"));
1175 :
1176 256 : var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1177 256 : ccall_typecheck.add_argument (new CCodeIdentifier ( "value" ));
1178 256 : ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
1179 :
1180 256 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1181 256 : ccall.add_argument (ccall_typecheck);
1182 256 : ccode.add_expression (ccall);
1183 :
1184 256 : ccode.add_assignment (new CCodeConstant ("old"), vpointer);
1185 :
1186 256 : ccode.open_if (new CCodeIdentifier ("v_object"));
1187 :
1188 256 : ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
1189 256 : ccall_typecheck.add_argument (new CCodeIdentifier ( "v_object" ));
1190 256 : ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
1191 :
1192 256 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1193 256 : ccall.add_argument (ccall_typecheck);
1194 256 : ccode.add_expression (ccall);
1195 :
1196 256 : var ccall_typefrominstance = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
1197 256 : ccall_typefrominstance.add_argument (new CCodeIdentifier ( "v_object" ));
1198 :
1199 256 : var ccall_gvaluetype = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
1200 256 : ccall_gvaluetype.add_argument (new CCodeIdentifier ( "value" ));
1201 :
1202 256 : var ccall_typecompatible = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
1203 256 : ccall_typecompatible.add_argument (ccall_typefrominstance);
1204 256 : ccall_typecompatible.add_argument (ccall_gvaluetype);
1205 :
1206 256 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1207 256 : ccall.add_argument (ccall_typecompatible);
1208 256 : ccode.add_expression (ccall);
1209 :
1210 256 : ccode.add_assignment (vpointer, new CCodeConstant ("v_object"));
1211 :
1212 256 : ccode.add_else ();
1213 256 : ccode.add_assignment (vpointer, new CCodeConstant ("NULL"));
1214 256 : ccode.close ();
1215 :
1216 256 : ccode.open_if (new CCodeIdentifier ("old"));
1217 256 : ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (cl)));
1218 256 : ccall.add_argument (new CCodeIdentifier ("old"));
1219 256 : ccode.add_expression (ccall);
1220 256 : ccode.close ();
1221 :
1222 256 : pop_function ();
1223 256 : cfile.add_function (function);
1224 : }
1225 :
1226 512 : private void add_g_value_get_function (Class cl) {
1227 256 : var function = new CCodeFunction (get_ccode_get_value_function (cl), "gpointer");
1228 256 : function.add_parameter (new CCodeParameter ("value", "const GValue*"));
1229 :
1230 256 : if (cl.is_private_symbol ()) {
1231 7 : function.modifiers = CCodeModifiers.STATIC;
1232 249 : } else if (context.hide_internal && cl.is_internal_symbol ()) {
1233 3 : function.modifiers = CCodeModifiers.INTERNAL;
1234 : }
1235 :
1236 256 : var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
1237 :
1238 256 : push_function (function);
1239 :
1240 256 : var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1241 256 : ccall_typecheck.add_argument (new CCodeIdentifier ("value"));
1242 256 : ccall_typecheck.add_argument (new CCodeIdentifier (get_ccode_type_id (cl)));
1243 :
1244 256 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail"));
1245 256 : ccall.add_argument (ccall_typecheck);
1246 256 : ccall.add_argument (new CCodeConstant ("NULL"));
1247 256 : ccode.add_expression (ccall);
1248 :
1249 256 : ccode.add_return (vpointer);
1250 :
1251 256 : pop_function ();
1252 256 : cfile.add_function (function);
1253 : }
1254 :
1255 1468 : private void begin_base_init_function (Class cl) {
1256 734 : push_context (base_init_context);
1257 :
1258 734 : var base_init = new CCodeFunction ("%s_base_init".printf (get_ccode_lower_case_name (cl, null)), "void");
1259 734 : base_init.add_parameter (new CCodeParameter ("klass", "%s *".printf (get_ccode_type_name (cl))));
1260 734 : base_init.modifiers = CCodeModifiers.STATIC;
1261 :
1262 734 : push_function (base_init);
1263 :
1264 734 : pop_context ();
1265 : }
1266 :
1267 7 : private void add_base_init_function (Class cl) {
1268 7 : cfile.add_function (base_init_context.ccode);
1269 : }
1270 :
1271 734 : public virtual void generate_class_init (Class cl) {
1272 : }
1273 :
1274 779 : public virtual void end_instance_init (Class cl) {
1275 : }
1276 :
1277 1468 : private void begin_class_init_function (Class cl) {
1278 734 : push_context (class_init_context);
1279 :
1280 734 : var func = new CCodeFunction ("%s_class_init".printf (get_ccode_lower_case_name (cl, null)));
1281 734 : func.add_parameter (new CCodeParameter ("klass", "%s *".printf (get_ccode_type_name (cl))));
1282 734 : func.add_parameter (new CCodeParameter ("klass_data", "gpointer"));
1283 734 : func.modifiers = CCodeModifiers.STATIC;
1284 :
1285 : CCodeFunctionCall ccall;
1286 :
1287 : /* save pointer to parent class */
1288 734 : var parent_decl = new CCodeDeclaration ("gpointer");
1289 734 : var parent_var_decl = new CCodeVariableDeclarator ("%s_parent_class".printf (get_ccode_lower_case_name (cl, null)));
1290 734 : parent_var_decl.initializer = new CCodeConstant ("NULL");
1291 734 : parent_decl.add_declarator (parent_var_decl);
1292 734 : parent_decl.modifiers = CCodeModifiers.STATIC;
1293 734 : cfile.add_type_member_declaration (parent_decl);
1294 :
1295 734 : push_function (func);
1296 :
1297 734 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek_parent"));
1298 734 : ccall.add_argument (new CCodeIdentifier ("klass"));
1299 734 : var parent_assignment = new CCodeAssignment (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (cl, null))), ccall);
1300 734 : ccode.add_expression (parent_assignment);
1301 :
1302 :
1303 1009 : if (!cl.is_compact && !cl.is_subtype_of (gobject_type) && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) {
1304 : // set finalize function
1305 275 : var fundamental_class = cl;
1306 296 : while (fundamental_class.base_class != null) {
1307 42 : fundamental_class = fundamental_class.base_class;
1308 : }
1309 :
1310 275 : var ccast = new CCodeCastExpression (new CCodeIdentifier ("klass"), "%s *".printf (get_ccode_type_name (fundamental_class)));
1311 275 : var finalize_assignment = new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "finalize"), new CCodeIdentifier ("%sfinalize".printf (get_ccode_lower_case_prefix (cl))));
1312 275 : ccode.add_expression (finalize_assignment);
1313 : }
1314 :
1315 : /* add struct for private fields */
1316 734 : if (cl.has_private_fields || cl.has_type_parameters ()) {
1317 283 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_adjust_private_offset"));
1318 283 : ccall.add_argument (new CCodeIdentifier ("klass"));
1319 283 : ccall.add_argument (new CCodeIdentifier ("&%s_private_offset".printf (get_ccode_name (cl))));
1320 283 : ccode.add_expression (ccall);
1321 : }
1322 :
1323 : /* connect overridden methods */
1324 4272 : foreach (Method m in cl.get_methods ()) {
1325 2756 : if (m.base_method == null) {
1326 1974 : continue;
1327 : }
1328 782 : var base_type = (ObjectTypeSymbol) m.base_method.parent_symbol;
1329 :
1330 : // there is currently no default handler for abstract async methods
1331 1556 : if (!m.is_abstract || !m.coroutine) {
1332 774 : generate_method_declaration (m.base_method, cfile);
1333 :
1334 774 : CCodeExpression cfunc = new CCodeIdentifier (get_ccode_real_name (m));
1335 774 : cfunc = cast_method_pointer (m.base_method, cfunc, base_type, (m.coroutine ? 1 : 3));
1336 774 : var ccast = new CCodeCastExpression (new CCodeIdentifier ("klass"), "%s *".printf (get_ccode_type_name (base_type)));
1337 774 : ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_vfunc_name (m.base_method)), cfunc);
1338 :
1339 774 : if (m.coroutine) {
1340 19 : cfunc = new CCodeIdentifier (get_ccode_finish_real_name (m));
1341 19 : cfunc = cast_method_pointer (m.base_method, cfunc, base_type, 2);
1342 19 : ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_finish_vfunc_name (m.base_method)), cfunc);
1343 : }
1344 : }
1345 : }
1346 :
1347 : /* connect default signal handlers */
1348 820 : foreach (Signal sig in cl.get_signals ()) {
1349 78 : if (sig.default_handler == null || !sig.is_virtual) {
1350 70 : continue;
1351 : }
1352 :
1353 8 : var ccast = new CCodeCastExpression (new CCodeIdentifier ("klass"), "%s *".printf (get_ccode_type_name (cl)));
1354 8 : ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_vfunc_name (sig.default_handler)), new CCodeIdentifier (get_ccode_real_name (sig.default_handler)));
1355 : }
1356 :
1357 : /* connect overridden properties */
1358 1241 : foreach (Property prop in cl.get_properties ()) {
1359 459 : if (prop.base_property == null) {
1360 411 : continue;
1361 : }
1362 48 : var base_type = (Class) prop.base_property.parent_symbol;
1363 :
1364 48 : var ccast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function (base_type)));
1365 48 : ccast.add_argument (new CCodeIdentifier ("klass"));
1366 :
1367 48 : if (!get_ccode_no_accessor_method (prop.base_property) && !get_ccode_concrete_accessor (prop.base_property)) {
1368 96 : if (prop.get_accessor != null) {
1369 48 : generate_property_accessor_declaration (prop.base_property.get_accessor, cfile);
1370 :
1371 48 : CCodeExpression cfunc = new CCodeIdentifier (get_ccode_real_name (prop.get_accessor));
1372 48 : cfunc = cast_method_pointer (prop.base_property.get_accessor.get_method (), cfunc, base_type);
1373 48 : ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "get_%s".printf (prop.name)), cfunc);
1374 : }
1375 73 : if (prop.set_accessor != null) {
1376 25 : generate_property_accessor_declaration (prop.base_property.set_accessor, cfile);
1377 :
1378 25 : CCodeExpression cfunc = new CCodeIdentifier (get_ccode_real_name (prop.set_accessor));
1379 25 : cfunc = cast_method_pointer (prop.base_property.set_accessor.get_method (), cfunc, base_type);
1380 25 : ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "set_%s".printf (prop.name)), cfunc);
1381 : }
1382 : }
1383 : }
1384 :
1385 734 : generate_class_init (cl);
1386 :
1387 734 : if (!cl.is_compact) {
1388 : /* create signals */
1389 890 : foreach (Signal sig in cl.get_signals ()) {
1390 78 : if (sig.comment != null) {
1391 0 : ccode.add_statement (new CCodeComment (sig.comment.content));
1392 : }
1393 78 : ccode.add_expression (get_signal_creation (sig, cl));
1394 : }
1395 : }
1396 :
1397 734 : pop_context ();
1398 : }
1399 :
1400 734 : private void add_class_init_function (Class cl) {
1401 734 : cfile.add_function (class_init_context.ccode);
1402 : }
1403 :
1404 12 : private void add_generic_accessor_function (string base_name, string return_type, CCodeExpression? expression, TypeParameter p, Class cl, Interface iface) {
1405 6 : string name = "%s_%s_%s".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface), base_name);
1406 :
1407 6 : var function = new CCodeFunction (name, return_type);
1408 6 : function.modifiers = CCodeModifiers.STATIC;
1409 6 : var this_type = SemanticAnalyzer.get_data_type_for_symbol (cl);
1410 6 : function.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
1411 6 : push_function (function);
1412 6 : ccode.add_return (new CCodeCastExpression (expression, return_type));
1413 6 : pop_function ();
1414 6 : cfile.add_function (function);
1415 :
1416 6 : CCodeExpression cfunc = new CCodeIdentifier (function.name);
1417 6 : string cast = "%s (*)".printf (return_type);
1418 6 : string cast_args = "%s *".printf (get_ccode_name (iface));
1419 6 : cast = "%s (%s)".printf (cast, cast_args);
1420 6 : cfunc = new CCodeCastExpression (cfunc, cast);
1421 6 : var ciface = new CCodeIdentifier ("iface");
1422 6 : ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, base_name), cfunc);
1423 : }
1424 :
1425 248 : private void add_interface_init_function (Class cl, Interface iface) {
1426 124 : var iface_init = new CCodeFunction ("%s_%s_interface_init".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface)), "void");
1427 124 : iface_init.add_parameter (new CCodeParameter ("iface", "%s *".printf (get_ccode_type_name (iface))));
1428 124 : iface_init.add_parameter (new CCodeParameter ("iface_data", "gpointer"));
1429 124 : iface_init.modifiers = CCodeModifiers.STATIC;
1430 :
1431 124 : push_function (iface_init);
1432 :
1433 : CCodeFunctionCall ccall;
1434 :
1435 : /* save pointer to parent vtable */
1436 124 : string parent_iface_var = "%s_%s_parent_iface".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface));
1437 124 : var parent_decl = new CCodeDeclaration ("%s *".printf (get_ccode_type_name (iface)));
1438 124 : var parent_var_decl = new CCodeVariableDeclarator (parent_iface_var);
1439 124 : parent_var_decl.initializer = new CCodeConstant ("NULL");
1440 124 : parent_decl.add_declarator (parent_var_decl);
1441 124 : parent_decl.modifiers = CCodeModifiers.STATIC;
1442 124 : cfile.add_type_member_declaration (parent_decl);
1443 124 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_interface_peek_parent"));
1444 124 : ccall.add_argument (new CCodeIdentifier ("iface"));
1445 124 : ccode.add_assignment (new CCodeIdentifier (parent_iface_var), ccall);
1446 :
1447 904 : foreach (Method m in cl.get_methods ()) {
1448 685 : if (m.base_interface_method == null) {
1449 565 : continue;
1450 : }
1451 :
1452 120 : var base_type = m.base_interface_method.parent_symbol;
1453 120 : if (base_type != iface) {
1454 25 : continue;
1455 : }
1456 :
1457 95 : generate_method_declaration (m.base_interface_method, cfile);
1458 :
1459 95 : var ciface = new CCodeIdentifier ("iface");
1460 : CCodeExpression cfunc;
1461 95 : if (m.is_abstract || m.is_virtual) {
1462 19 : cfunc = new CCodeIdentifier (get_ccode_name (m));
1463 : } else {
1464 76 : cfunc = new CCodeIdentifier (get_ccode_real_name (m));
1465 : }
1466 95 : cfunc = cast_method_pointer (m.base_interface_method, cfunc, iface, (m.coroutine ? 1 : 3));
1467 95 : ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (m.base_interface_method)), cfunc);
1468 :
1469 95 : if (m.coroutine) {
1470 7 : if (m.is_abstract || m.is_virtual) {
1471 2 : cfunc = new CCodeIdentifier (get_ccode_finish_name (m));
1472 : } else {
1473 5 : cfunc = new CCodeIdentifier (get_ccode_finish_real_name (m));
1474 : }
1475 7 : cfunc = cast_method_pointer (m.base_interface_method, cfunc, iface, 2);
1476 7 : ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_finish_vfunc_name (m.base_interface_method)), cfunc);
1477 : }
1478 : }
1479 :
1480 124 : if (iface.has_attribute ("GenericAccessors")) {
1481 6 : foreach (TypeParameter p in iface.get_type_parameters ()) {
1482 2 : GenericType p_type = new GenericType (p);
1483 2 : DataType p_data_type = p_type.get_actual_type (SemanticAnalyzer.get_data_type_for_symbol (cl), null, cl);
1484 :
1485 2 : add_generic_accessor_function ("get_%s".printf (get_ccode_type_id (p)),
1486 : "GType",
1487 : get_type_id_expression (p_data_type),
1488 : p, cl, iface);
1489 :
1490 2 : add_generic_accessor_function ("get_%s".printf (get_ccode_copy_function (p)),
1491 : "GBoxedCopyFunc",
1492 : get_dup_func_expression (p_data_type, p_data_type.source_reference),
1493 : p, cl, iface);
1494 :
1495 2 : add_generic_accessor_function ("get_%s".printf (get_ccode_destroy_function (p)),
1496 : "GDestroyNotify",
1497 : get_destroy_func_expression (p_data_type),
1498 : p, cl, iface);
1499 : }
1500 : }
1501 :
1502 : // connect inherited implementations
1503 251 : var it = cl.get_implicit_implementations ().map_iterator ();
1504 130 : while (it.next ()) {
1505 3 : Method m = it.get_key ();
1506 5 : if (m.parent_symbol == iface) {
1507 2 : Method base_method = it.get_value ();
1508 :
1509 2 : generate_method_declaration (base_method, cfile);
1510 :
1511 2 : CCodeExpression cfunc = new CCodeIdentifier (get_ccode_name (base_method));
1512 2 : cfunc = cast_method_pointer (m, cfunc, iface);
1513 2 : var ciface = new CCodeIdentifier ("iface");
1514 2 : ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (m)), cfunc);
1515 : }
1516 : }
1517 :
1518 279 : foreach (Property prop in cl.get_properties ()) {
1519 120 : if (prop.base_interface_property == null) {
1520 79 : continue;
1521 : }
1522 :
1523 41 : var base_type = (ObjectTypeSymbol) prop.base_interface_property.parent_symbol;
1524 41 : if (base_type != iface) {
1525 6 : continue;
1526 : }
1527 :
1528 35 : var ciface = new CCodeIdentifier ("iface");
1529 :
1530 35 : if (!get_ccode_no_accessor_method (prop.base_interface_property) && !get_ccode_concrete_accessor (prop.base_interface_property)) {
1531 70 : if (prop.get_accessor != null) {
1532 35 : generate_property_accessor_declaration (prop.base_interface_property.get_accessor, cfile);
1533 :
1534 35 : string cname = get_ccode_real_name (prop.get_accessor);
1535 35 : if (prop.is_abstract || prop.is_virtual) {
1536 3 : cname = get_ccode_name (prop.get_accessor);
1537 : }
1538 :
1539 35 : CCodeExpression cfunc = new CCodeIdentifier (cname);
1540 35 : if (prop.is_abstract || prop.is_virtual) {
1541 3 : cfunc = cast_method_pointer (prop.base_interface_property.get_accessor.get_method (), cfunc, base_type);
1542 : }
1543 35 : ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), cfunc);
1544 : }
1545 65 : if (prop.set_accessor != null) {
1546 30 : generate_property_accessor_declaration (prop.base_interface_property.set_accessor, cfile);
1547 :
1548 30 : string cname = get_ccode_real_name (prop.set_accessor);
1549 30 : if (prop.is_abstract || prop.is_virtual) {
1550 2 : cname = get_ccode_name (prop.set_accessor);
1551 : }
1552 :
1553 30 : CCodeExpression cfunc = new CCodeIdentifier (cname);
1554 30 : if (prop.is_abstract || prop.is_virtual) {
1555 2 : cfunc = cast_method_pointer (prop.base_interface_property.set_accessor.get_method (), cfunc, base_type);
1556 : }
1557 30 : ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), cfunc);
1558 : }
1559 : }
1560 : }
1561 :
1562 193 : foreach (Property prop in iface.get_properties ()) {
1563 36 : if (!prop.is_abstract) {
1564 2 : continue;
1565 : }
1566 :
1567 34 : Property cl_prop = null;
1568 34 : var base_class = cl;
1569 69 : while (base_class != null && cl_prop == null) {
1570 35 : cl_prop = base_class.scope.lookup (prop.name) as Property;
1571 64 : base_class = base_class.base_class;
1572 : }
1573 34 : if (base_class != null && cl_prop.parent_symbol != cl) {
1574 : // property inherited from base class
1575 :
1576 1 : var base_property = cl_prop;
1577 1 : if (cl_prop.base_property != null) {
1578 0 : base_property = cl_prop.base_property;
1579 1 : } else if (cl_prop.base_interface_property != null) {
1580 2 : base_property = cl_prop.base_interface_property;
1581 : }
1582 :
1583 : // Our base class provides this interface implementation
1584 1 : if (prop == base_property) {
1585 1 : continue;
1586 : }
1587 :
1588 0 : var ciface = new CCodeIdentifier ("iface");
1589 :
1590 0 : if (base_property.get_accessor != null && prop.get_accessor != null) {
1591 0 : generate_property_accessor_declaration (base_property.get_accessor, cfile);
1592 :
1593 0 : string cname = get_ccode_name (base_property.get_accessor);
1594 0 : CCodeExpression cfunc = new CCodeIdentifier (cname);
1595 0 : cfunc = cast_method_pointer (base_property.get_accessor.get_method (), cfunc, iface);
1596 0 : ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), cfunc);
1597 : }
1598 0 : if (base_property.set_accessor != null && prop.set_accessor != null) {
1599 0 : generate_property_accessor_declaration (base_property.set_accessor, cfile);
1600 :
1601 0 : string cname = get_ccode_name (base_property.set_accessor);
1602 0 : CCodeExpression cfunc = new CCodeIdentifier (cname);
1603 0 : cfunc = cast_method_pointer (base_property.set_accessor.get_method (), cfunc, iface);
1604 0 : ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), cfunc);
1605 : }
1606 : }
1607 : }
1608 :
1609 124 : pop_function ();
1610 124 : cfile.add_function (iface_init);
1611 : }
1612 :
1613 988 : CCodeExpression cast_method_pointer (Method m, CCodeExpression cfunc, ObjectTypeSymbol base_type, int direction = 3) {
1614 : // Cast the function pointer to match the interface
1615 : string cast;
1616 988 : if (direction == 1 || m.return_type.is_real_non_null_struct_type ()) {
1617 31 : cast = "void (*)";
1618 : } else {
1619 957 : cast = "%s (*)".printf (get_ccode_name (m.return_type));
1620 : }
1621 :
1622 988 : var vdeclarator = new CCodeFunctionDeclarator (get_ccode_vfunc_name (m));
1623 988 : var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
1624 :
1625 988 : generate_cparameters (m, cfile, cparam_map, new CCodeFunction ("fake"), vdeclarator, null, null, direction);
1626 :
1627 : // append C arguments in the right order
1628 988 : int last_pos = -1;
1629 : int min_pos;
1630 988 : string cast_args = "";
1631 5138 : while (true) {
1632 3063 : min_pos = -1;
1633 13556 : foreach (int pos in cparam_map.get_keys ()) {
1634 7430 : if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
1635 2602 : min_pos = pos;
1636 : }
1637 : }
1638 3063 : if (min_pos == -1) {
1639 : break;
1640 : }
1641 2075 : if (last_pos != -1) {
1642 1087 : cast_args = "%s, ".printf (cast_args);
1643 : }
1644 2075 : var cparam = cparam_map.get (min_pos);
1645 2075 : if (cparam.ellipsis) {
1646 0 : cast_args = "%s...".printf (cast_args);
1647 : } else {
1648 2075 : cast_args = "%s%s".printf (cast_args, cparam.type_name);
1649 : }
1650 2075 : last_pos = min_pos;
1651 : }
1652 988 : cast = "%s (%s)".printf (cast, cast_args);
1653 988 : return new CCodeCastExpression (cfunc, cast);
1654 : }
1655 :
1656 1558 : private void begin_instance_init_function (Class cl) {
1657 779 : push_context (instance_init_context);
1658 :
1659 779 : var func = new CCodeFunction ("%s_instance_init".printf (get_ccode_lower_case_name (cl, null)));
1660 779 : func.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl))));
1661 779 : if (!cl.is_compact) {
1662 734 : func.add_parameter (new CCodeParameter ("klass", "gpointer"));
1663 : }
1664 779 : func.modifiers = CCodeModifiers.STATIC;
1665 :
1666 779 : push_function (func);
1667 :
1668 779 : bool is_gsource = cl.is_subtype_of (gsource_type);
1669 :
1670 779 : if (cl.is_compact) {
1671 : // Add declaration, since the instance_init function is explicitly called
1672 : // by the creation methods
1673 45 : cfile.add_function_declaration (func);
1674 :
1675 : // connect overridden methods
1676 130 : foreach (Method m in cl.get_methods ()) {
1677 78 : if (m.base_method == null || is_gsource) {
1678 71 : continue;
1679 : }
1680 7 : var base_type = (ObjectTypeSymbol) m.base_method.parent_symbol;
1681 :
1682 : // there is currently no default handler for abstract async methods
1683 14 : if (!m.is_abstract || !m.coroutine) {
1684 7 : generate_method_declaration (m.base_method, cfile);
1685 :
1686 7 : CCodeExpression cfunc = new CCodeIdentifier (get_ccode_real_name (m));
1687 7 : cfunc = cast_method_pointer (m.base_method, cfunc, base_type, (m.coroutine ? 1 : 3));
1688 7 : var ccast = new CCodeCastExpression (new CCodeIdentifier ("self"), "%s *".printf (get_ccode_name (base_type)));
1689 7 : func.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_vfunc_name (m.base_method)), cfunc);
1690 :
1691 7 : if (m.coroutine) {
1692 0 : cfunc = new CCodeIdentifier (get_ccode_finish_real_name (m));
1693 0 : cfunc = cast_method_pointer (m.base_method, cfunc, base_type, 2);
1694 0 : ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_finish_vfunc_name (m.base_method)), cfunc);
1695 : }
1696 : }
1697 : }
1698 :
1699 : // connect overridden properties
1700 54 : foreach (Property prop in cl.get_properties ()) {
1701 6 : if (prop.base_property == null || is_gsource) {
1702 3 : continue;
1703 : }
1704 3 : var base_type = (ObjectTypeSymbol) prop.base_property.parent_symbol;
1705 :
1706 3 : var ccast = new CCodeCastExpression (new CCodeIdentifier ("self"), "%s *".printf (get_ccode_name (base_type)));
1707 :
1708 3 : if (!get_ccode_no_accessor_method (prop.base_property) && !get_ccode_concrete_accessor (prop.base_property)) {
1709 6 : if (prop.get_accessor != null) {
1710 3 : generate_property_accessor_declaration (prop.base_property.get_accessor, cfile);
1711 :
1712 3 : CCodeExpression cfunc = new CCodeIdentifier (get_ccode_real_name (prop.get_accessor));
1713 3 : cfunc = cast_method_pointer (prop.base_property.get_accessor.get_method (), cfunc, base_type);
1714 3 : ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "get_%s".printf (prop.name)), cfunc);
1715 : }
1716 6 : if (prop.set_accessor != null) {
1717 3 : generate_property_accessor_declaration (prop.base_property.set_accessor, cfile);
1718 :
1719 3 : CCodeExpression cfunc = new CCodeIdentifier (get_ccode_real_name (prop.set_accessor));
1720 3 : cfunc = cast_method_pointer (prop.base_property.set_accessor.get_method (), cfunc, base_type);
1721 3 : ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "set_%s".printf (prop.name)), cfunc);
1722 : }
1723 : }
1724 : }
1725 : }
1726 :
1727 1062 : if (!cl.is_compact && (cl.has_private_fields || cl.has_type_parameters ())) {
1728 283 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_get_instance_private".printf (get_ccode_lower_case_name (cl, null))));
1729 283 : ccall.add_argument (new CCodeIdentifier ("self"));
1730 283 : func.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall);
1731 : }
1732 :
1733 779 : pop_context ();
1734 : }
1735 :
1736 779 : private void add_instance_init_function (Class cl) {
1737 779 : push_context (instance_init_context);
1738 779 : end_instance_init (cl);
1739 779 : pop_context ();
1740 :
1741 779 : cfile.add_function (instance_init_context.ccode);
1742 : }
1743 :
1744 1468 : private void begin_class_finalize_function (Class cl) {
1745 734 : push_context (class_finalize_context);
1746 :
1747 734 : var function = new CCodeFunction ("%s_class_finalize".printf (get_ccode_lower_case_name (cl, null)), "void");
1748 734 : function.modifiers = CCodeModifiers.STATIC;
1749 :
1750 734 : function.add_parameter (new CCodeParameter ("klass", "%s *".printf (get_ccode_type_name (cl))));
1751 :
1752 734 : push_function (function);
1753 :
1754 734 : if (cl.static_destructor != null) {
1755 1 : cl.static_destructor.body.emit (this);
1756 :
1757 1 : if (current_method_inner_error) {
1758 0 : ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL")));
1759 : }
1760 :
1761 1 : if (current_method_return) {
1762 : // support return statements in destructors
1763 0 : ccode.add_label ("_return");
1764 0 : ccode.add_statement (new CCodeEmptyStatement ());
1765 : }
1766 : }
1767 :
1768 734 : pop_context ();
1769 : }
1770 :
1771 1 : private void add_class_finalize_function (Class cl) {
1772 1 : cfile.add_function_declaration (class_finalize_context.ccode);
1773 1 : cfile.add_function (class_finalize_context.ccode);
1774 : }
1775 :
1776 1468 : private void begin_base_finalize_function (Class cl) {
1777 734 : push_context (base_finalize_context);
1778 :
1779 734 : var function = new CCodeFunction ("%s_base_finalize".printf (get_ccode_lower_case_name (cl, null)), "void");
1780 734 : function.modifiers = CCodeModifiers.STATIC;
1781 :
1782 734 : function.add_parameter (new CCodeParameter ("klass", "%s *".printf (get_ccode_type_name (cl))));
1783 734 : function.add_parameter (new CCodeParameter ("klass_data", "gpointer"));
1784 :
1785 734 : push_function (function);
1786 :
1787 734 : if (cl.class_destructor != null) {
1788 3 : cl.class_destructor.body.emit (this);
1789 :
1790 3 : if (current_method_inner_error) {
1791 1 : ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL")));
1792 : }
1793 :
1794 3 : if (current_method_return) {
1795 : // support return statements in destructors
1796 1 : ccode.add_label ("_return");
1797 1 : ccode.add_statement (new CCodeEmptyStatement ());
1798 : }
1799 : }
1800 :
1801 734 : pop_context ();
1802 : }
1803 :
1804 3 : private void add_base_finalize_function (Class cl) {
1805 3 : push_context (base_finalize_context);
1806 :
1807 3 : cfile.add_function_declaration (ccode);
1808 3 : cfile.add_function (ccode);
1809 :
1810 3 : pop_context ();
1811 : }
1812 :
1813 779 : private void begin_finalize_function (Class cl) {
1814 779 : push_context (instance_finalize_context);
1815 :
1816 779 : bool is_gsource = cl.is_subtype_of (gsource_type);
1817 :
1818 1516 : if (!cl.is_compact || is_gsource) {
1819 737 : var fundamental_class = cl;
1820 1484 : while (fundamental_class.base_class != null) {
1821 1494 : fundamental_class = fundamental_class.base_class;
1822 : }
1823 :
1824 737 : var func = new CCodeFunction ("%sfinalize".printf (get_ccode_lower_case_prefix (cl)));
1825 737 : func.add_parameter (new CCodeParameter ("obj", "%s *".printf (get_ccode_name (fundamental_class))));
1826 737 : func.modifiers = CCodeModifiers.STATIC;
1827 :
1828 737 : push_function (func);
1829 :
1830 737 : if (is_gsource) {
1831 3 : cfile.add_function_declaration (func);
1832 : }
1833 :
1834 : CCodeExpression ccast;
1835 737 : if (!cl.is_compact) {
1836 734 : ccast = generate_instance_cast (new CCodeIdentifier ("obj"), cl);
1837 : } else {
1838 3 : ccast = new CCodeCastExpression (new CCodeIdentifier ("obj"), "%s *".printf (get_ccode_name (cl)));
1839 : }
1840 :
1841 737 : ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self"));
1842 737 : ccode.add_assignment (new CCodeIdentifier ("self"), ccast);
1843 :
1844 993 : if (!cl.is_compact && cl.base_class == null) {
1845 : // non-gobject class
1846 256 : var call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_handlers_destroy"));
1847 256 : call.add_argument (new CCodeIdentifier ("self"));
1848 256 : ccode.add_expression (call);
1849 : }
1850 74 : } else if (cl.base_class == null) {
1851 32 : var function = new CCodeFunction (get_ccode_free_function (cl), "void");
1852 32 : if (cl.is_private_symbol ()) {
1853 0 : function.modifiers = CCodeModifiers.STATIC;
1854 32 : } else if (context.hide_internal && cl.is_internal_symbol ()) {
1855 0 : function.modifiers = CCodeModifiers.INTERNAL;
1856 : }
1857 :
1858 32 : function.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl))));
1859 :
1860 32 : push_function (function);
1861 : }
1862 :
1863 779 : if (cl.destructor != null) {
1864 13 : cl.destructor.body.emit (this);
1865 :
1866 13 : if (current_method_inner_error) {
1867 1 : ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL")));
1868 : }
1869 :
1870 13 : if (current_method_return) {
1871 : // support return statements in destructors
1872 1 : ccode.add_label ("_return");
1873 : }
1874 : }
1875 :
1876 779 : pop_context ();
1877 : }
1878 :
1879 525 : private void add_finalize_function (Class cl) {
1880 1005 : if (!cl.is_compact) {
1881 480 : var fundamental_class = cl;
1882 868 : while (fundamental_class.base_class != null) {
1883 776 : fundamental_class = fundamental_class.base_class;
1884 : }
1885 :
1886 : // chain up to finalize function of the base class
1887 704 : if (cl.base_class != null) {
1888 224 : var ccast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function (fundamental_class)));
1889 224 : ccast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (cl, null))));
1890 224 : var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize"));
1891 224 : ccall.add_argument (new CCodeIdentifier ("obj"));
1892 224 : push_context (instance_finalize_context);
1893 224 : ccode.add_expression (ccall);
1894 224 : pop_context ();
1895 : }
1896 :
1897 480 : cfile.add_function_declaration (instance_finalize_context.ccode);
1898 480 : cfile.add_function (instance_finalize_context.ccode);
1899 77 : } else if (cl.base_class == null) {
1900 : // g_slice_free needs glib.h
1901 32 : cfile.add_include ("glib.h");
1902 32 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
1903 32 : ccall.add_argument (new CCodeIdentifier (get_ccode_name (cl)));
1904 32 : ccall.add_argument (new CCodeIdentifier ("self"));
1905 32 : push_context (instance_finalize_context);
1906 32 : ccode.add_expression (ccall);
1907 32 : pop_context ();
1908 :
1909 32 : cfile.add_function (instance_finalize_context.ccode);
1910 13 : } else if (cl.is_subtype_of (gsource_type)) {
1911 3 : cfile.add_function (instance_finalize_context.ccode);
1912 : }
1913 : }
1914 :
1915 632 : public override CCodeExpression get_param_spec_cexpression (Property prop) {
1916 632 : var cl = (TypeSymbol) prop.parent_symbol;
1917 632 : var prop_array = new CCodeIdentifier ("%s_properties".printf (get_ccode_lower_case_name (cl)));
1918 632 : var prop_enum_value = new CCodeIdentifier ("%s_PROPERTY".printf (get_ccode_upper_case_name (prop)));
1919 :
1920 632 : return new CCodeElementAccess (prop_array, prop_enum_value);
1921 : }
1922 :
1923 371 : public override CCodeExpression get_param_spec (Property prop) {
1924 371 : var cspec = new CCodeFunctionCall ();
1925 371 : cspec.add_argument (get_property_canonical_cconstant (prop));
1926 371 : cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.nick)));
1927 371 : cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.blurb)));
1928 :
1929 371 : unowned TypeSymbol? type_symbol = prop.property_type.type_symbol;
1930 519 : if (type_symbol is Class || type_symbol is Interface) {
1931 148 : string param_spec_name = get_ccode_param_spec_function (type_symbol);
1932 148 : cspec.call = new CCodeIdentifier (param_spec_name);
1933 148 : if (param_spec_name == "g_param_spec_string") {
1934 80 : cspec.add_argument (new CCodeConstant ("NULL"));
1935 68 : } else if (param_spec_name == "g_param_spec_variant") {
1936 3 : cspec.add_argument (new CCodeConstant ("G_VARIANT_TYPE_ANY"));
1937 3 : cspec.add_argument (new CCodeConstant ("NULL"));
1938 65 : } else if (param_spec_name == "gtk_param_spec_expression") {
1939 : // No additional parameter required
1940 65 : } else if (get_ccode_type_id (type_symbol) != "G_TYPE_POINTER") {
1941 64 : cspec.add_argument (new CCodeIdentifier (get_ccode_type_id (type_symbol)));
1942 : }
1943 223 : } else if (type_symbol is Enum) {
1944 39 : unowned Enum e = (Enum) type_symbol;
1945 39 : if (get_ccode_has_type_id (e)) {
1946 37 : if (e.is_flags) {
1947 3 : cspec.call = new CCodeIdentifier ("g_param_spec_flags");
1948 : } else {
1949 34 : cspec.call = new CCodeIdentifier ("g_param_spec_enum");
1950 : }
1951 37 : cspec.add_argument (new CCodeIdentifier (get_ccode_type_id (e)));
1952 : } else {
1953 2 : if (e.is_flags) {
1954 1 : cspec.call = new CCodeIdentifier ("g_param_spec_uint");
1955 1 : cspec.add_argument (new CCodeConstant ("0"));
1956 1 : cspec.add_argument (new CCodeConstant ("G_MAXUINT"));
1957 : } else {
1958 1 : cspec.call = new CCodeIdentifier ("g_param_spec_int");
1959 1 : cspec.add_argument (new CCodeConstant ("G_MININT"));
1960 1 : cspec.add_argument (new CCodeConstant ("G_MAXINT"));
1961 : }
1962 : }
1963 :
1964 39 : if (prop.initializer != null) {
1965 2 : cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1966 : } else {
1967 37 : cspec.add_argument (new CCodeConstant (get_ccode_default_value (type_symbol)));
1968 : }
1969 184 : } else if (type_symbol is ErrorDomain) {
1970 2 : cspec.call = new CCodeIdentifier ("g_param_spec_boxed");
1971 2 : cspec.add_argument (new CCodeIdentifier ("G_TYPE_ERROR"));
1972 344 : } else if (type_symbol is Struct) {
1973 162 : unowned Struct st = (Struct) type_symbol;
1974 162 : var type_id = get_ccode_type_id (st);
1975 162 : if (type_id == "G_TYPE_INT") {
1976 50 : cspec.call = new CCodeIdentifier ("g_param_spec_int");
1977 50 : cspec.add_argument (new CCodeConstant ("G_MININT"));
1978 50 : cspec.add_argument (new CCodeConstant ("G_MAXINT"));
1979 50 : if (prop.initializer != null) {
1980 6 : cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1981 : } else {
1982 44 : cspec.add_argument (new CCodeConstant ("0"));
1983 : }
1984 112 : } else if (type_id == "G_TYPE_UINT") {
1985 4 : cspec.call = new CCodeIdentifier ("g_param_spec_uint");
1986 4 : cspec.add_argument (new CCodeConstant ("0"));
1987 4 : cspec.add_argument (new CCodeConstant ("G_MAXUINT"));
1988 4 : if (prop.initializer != null) {
1989 1 : cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1990 : } else {
1991 3 : cspec.add_argument (new CCodeConstant ("0U"));
1992 : }
1993 108 : } else if (type_id == "G_TYPE_INT64") {
1994 3 : cspec.call = new CCodeIdentifier ("g_param_spec_int64");
1995 3 : cspec.add_argument (new CCodeConstant ("G_MININT64"));
1996 3 : cspec.add_argument (new CCodeConstant ("G_MAXINT64"));
1997 3 : if (prop.initializer != null) {
1998 1 : cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1999 : } else {
2000 2 : cspec.add_argument (new CCodeConstant ("0"));
2001 : }
2002 105 : } else if (type_id == "G_TYPE_UINT64") {
2003 3 : cspec.call = new CCodeIdentifier ("g_param_spec_uint64");
2004 3 : cspec.add_argument (new CCodeConstant ("0"));
2005 3 : cspec.add_argument (new CCodeConstant ("G_MAXUINT64"));
2006 3 : if (prop.initializer != null) {
2007 1 : cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2008 : } else {
2009 2 : cspec.add_argument (new CCodeConstant ("0U"));
2010 : }
2011 102 : } else if (type_id == "G_TYPE_LONG") {
2012 3 : cspec.call = new CCodeIdentifier ("g_param_spec_long");
2013 3 : cspec.add_argument (new CCodeConstant ("G_MINLONG"));
2014 3 : cspec.add_argument (new CCodeConstant ("G_MAXLONG"));
2015 3 : if (prop.initializer != null) {
2016 1 : cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2017 : } else {
2018 2 : cspec.add_argument (new CCodeConstant ("0L"));
2019 : }
2020 99 : } else if (type_id == "G_TYPE_ULONG") {
2021 3 : cspec.call = new CCodeIdentifier ("g_param_spec_ulong");
2022 3 : cspec.add_argument (new CCodeConstant ("0"));
2023 3 : cspec.add_argument (new CCodeConstant ("G_MAXULONG"));
2024 3 : if (prop.initializer != null) {
2025 1 : cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2026 : } else {
2027 2 : cspec.add_argument (new CCodeConstant ("0UL"));
2028 : }
2029 96 : } else if (type_id == "G_TYPE_BOOLEAN") {
2030 57 : cspec.call = new CCodeIdentifier ("g_param_spec_boolean");
2031 57 : if (prop.initializer != null) {
2032 4 : cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2033 : } else {
2034 53 : cspec.add_argument (new CCodeConstant ("FALSE"));
2035 : }
2036 39 : } else if (type_id == "G_TYPE_CHAR") {
2037 3 : cspec.call = new CCodeIdentifier ("g_param_spec_char");
2038 3 : cspec.add_argument (new CCodeConstant ("G_MININT8"));
2039 3 : cspec.add_argument (new CCodeConstant ("G_MAXINT8"));
2040 3 : if (prop.initializer != null) {
2041 1 : cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2042 : } else {
2043 2 : cspec.add_argument (new CCodeConstant ("0"));
2044 : }
2045 36 : } else if (type_id == "G_TYPE_UCHAR") {
2046 3 : cspec.call = new CCodeIdentifier ("g_param_spec_uchar");
2047 3 : cspec.add_argument (new CCodeConstant ("0"));
2048 3 : cspec.add_argument (new CCodeConstant ("G_MAXUINT8"));
2049 3 : if (prop.initializer != null) {
2050 1 : cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2051 : } else {
2052 2 : cspec.add_argument (new CCodeConstant ("0"));
2053 : }
2054 33 : } else if (type_id == "G_TYPE_FLOAT") {
2055 3 : cspec.call = new CCodeIdentifier ("g_param_spec_float");
2056 3 : cspec.add_argument (new CCodeConstant ("-G_MAXFLOAT"));
2057 3 : cspec.add_argument (new CCodeConstant ("G_MAXFLOAT"));
2058 3 : if (prop.initializer != null) {
2059 1 : cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2060 : } else {
2061 2 : cspec.add_argument (new CCodeConstant ("0.0F"));
2062 : }
2063 30 : } else if (type_id == "G_TYPE_DOUBLE") {
2064 3 : cspec.call = new CCodeIdentifier ("g_param_spec_double");
2065 3 : cspec.add_argument (new CCodeConstant ("-G_MAXDOUBLE"));
2066 3 : cspec.add_argument (new CCodeConstant ("G_MAXDOUBLE"));
2067 3 : if (prop.initializer != null) {
2068 1 : cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2069 : } else {
2070 2 : cspec.add_argument (new CCodeConstant ("0.0"));
2071 : }
2072 27 : } else if (type_id == "G_TYPE_GTYPE") {
2073 5 : cspec.call = new CCodeIdentifier ("g_param_spec_gtype");
2074 5 : if (prop.initializer != null) {
2075 1 : cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2076 : } else {
2077 4 : cspec.add_argument (new CCodeConstant ("G_TYPE_NONE"));
2078 : }
2079 : } else {
2080 22 : cspec.call = new CCodeIdentifier ("g_param_spec_boxed");
2081 22 : cspec.add_argument (new CCodeIdentifier (type_id));
2082 : }
2083 20 : } else if (prop.property_type is ArrayType && ((ArrayType)prop.property_type).element_type.type_symbol == string_type.type_symbol) {
2084 10 : cspec.call = new CCodeIdentifier ("g_param_spec_boxed");
2085 10 : cspec.add_argument (new CCodeIdentifier ("G_TYPE_STRV"));
2086 : } else {
2087 10 : cspec.call = new CCodeIdentifier ("g_param_spec_pointer");
2088 : }
2089 :
2090 371 : var pflags = "G_PARAM_STATIC_STRINGS";
2091 371 : if (prop.get_accessor != null && prop.get_accessor.access != SymbolAccessibility.PRIVATE) {
2092 368 : pflags = "%s%s".printf (pflags, " | G_PARAM_READABLE");
2093 : }
2094 371 : if (prop.set_accessor != null && prop.set_accessor.access != SymbolAccessibility.PRIVATE) {
2095 237 : pflags = "%s%s".printf (pflags, " | G_PARAM_WRITABLE");
2096 237 : if (prop.set_accessor.construction) {
2097 16 : if (prop.set_accessor.writable) {
2098 6 : pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT");
2099 : } else {
2100 10 : pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT_ONLY");
2101 : }
2102 : }
2103 : }
2104 371 : if (!prop.notify) {
2105 1 : pflags = "%s%s".printf (pflags, " | G_PARAM_EXPLICIT_NOTIFY");
2106 : }
2107 371 : if (prop.version.deprecated) {
2108 1 : pflags = "%s%s".printf (pflags, " | G_PARAM_DEPRECATED");
2109 : }
2110 371 : cspec.add_argument (new CCodeConstant (pflags));
2111 :
2112 371 : if (prop.parent_symbol is Interface) {
2113 15 : return cspec;
2114 : } else {
2115 356 : return new CCodeAssignment (get_param_spec_cexpression (prop), cspec);
2116 : }
2117 : }
2118 :
2119 4716 : public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) {
2120 4474 : if (add_symbol_declaration (decl_space, iface, get_ccode_name (iface))) {
2121 : return;
2122 : }
2123 :
2124 242 : decl_space.add_include ("glib-object.h");
2125 :
2126 242 : var instance_struct = new CCodeStruct ("_%s".printf (get_ccode_name (iface)));
2127 242 : var type_struct = new CCodeStruct ("_%s".printf (get_ccode_type_name (iface)));
2128 :
2129 242 : decl_space.add_type_declaration (new CCodeNewline ());
2130 242 : var macro = "(%s_get_type ())".printf (get_ccode_lower_case_name (iface, null));
2131 242 : decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (iface), macro));
2132 :
2133 242 : macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (get_ccode_type_id (iface), get_ccode_name (iface));
2134 242 : decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_cast_function (iface)), macro));
2135 :
2136 242 : macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (get_ccode_type_id (iface));
2137 242 : decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_check_function (iface)), macro));
2138 :
2139 242 : macro = "(G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, %s))".printf (get_ccode_type_id (iface), get_ccode_type_name (iface));
2140 242 : decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_get_function (iface)), macro));
2141 242 : decl_space.add_type_declaration (new CCodeNewline ());
2142 :
2143 242 : decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (iface)), new CCodeVariableDeclarator (get_ccode_name (iface))));
2144 242 : decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_struct.name), new CCodeVariableDeclarator (get_ccode_type_name (iface))));
2145 :
2146 242 : unowned Class? prereq_cl = null;
2147 610 : foreach (DataType prerequisite in iface.get_prerequisites ()) {
2148 184 : prereq_cl = prerequisite.type_symbol as Class;
2149 184 : unowned Interface? prereq_iface = prerequisite.type_symbol as Interface;
2150 184 : if (prereq_cl != null) {
2151 179 : generate_class_declaration (prereq_cl, decl_space);
2152 5 : } else if (prereq_iface != null) {
2153 5 : generate_interface_declaration (prereq_iface, decl_space);
2154 : }
2155 : }
2156 :
2157 242 : type_struct.add_field ("GTypeInterface", "parent_iface");
2158 :
2159 242 : if (iface.has_attribute ("GenericAccessors")) {
2160 12 : foreach (TypeParameter p in iface.get_type_parameters ()) {
2161 4 : var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (get_ccode_type_id (p)));
2162 4 : var this_type = SemanticAnalyzer.get_data_type_for_symbol (iface);
2163 4 : vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
2164 :
2165 4 : var vdecl = new CCodeDeclaration ("GType");
2166 4 : vdecl.add_declarator (vdeclarator);
2167 4 : type_struct.add_declaration (vdecl);
2168 :
2169 4 : vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (get_ccode_copy_function (p)));
2170 4 : this_type = SemanticAnalyzer.get_data_type_for_symbol (iface);
2171 4 : vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
2172 :
2173 4 : vdecl = new CCodeDeclaration ("GBoxedCopyFunc");
2174 4 : vdecl.add_declarator (vdeclarator);
2175 4 : type_struct.add_declaration (vdecl);
2176 :
2177 4 : vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (get_ccode_destroy_function (p)));
2178 4 : this_type = SemanticAnalyzer.get_data_type_for_symbol (iface);
2179 4 : vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
2180 :
2181 4 : vdecl = new CCodeDeclaration ("GDestroyNotify");
2182 4 : vdecl.add_declarator (vdeclarator);
2183 4 : type_struct.add_declaration (vdecl);
2184 : }
2185 : }
2186 :
2187 938 : foreach (Symbol sym in iface.get_virtuals ()) {
2188 : Method m;
2189 : Signal sig;
2190 : Property prop;
2191 574 : if ((m = sym as Method) != null) {
2192 256 : generate_struct_method_declaration (iface, m, instance_struct, type_struct, decl_space);
2193 64 : } else if ((sig = sym as Signal) != null) {
2194 2 : if (sig.default_handler != null) {
2195 2 : if (sig.is_virtual) {
2196 2 : generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
2197 : } else {
2198 0 : generate_method_declaration (sig.default_handler, cfile);
2199 : }
2200 : }
2201 120 : } else if ((prop = sym as Property) != null) {
2202 60 : generate_struct_property_declaration (iface, prop, instance_struct, type_struct, decl_space);
2203 : } else {
2204 0 : Report.error (sym.source_reference, "internal: Unsupported symbol");
2205 : }
2206 : }
2207 :
2208 242 : decl_space.add_type_definition (type_struct);
2209 :
2210 242 : var type_fun = new InterfaceRegisterFunction (iface);
2211 242 : type_fun.init_from_type (context, in_plugin, true);
2212 242 : decl_space.add_type_member_declaration (type_fun.get_declaration ());
2213 :
2214 242 : requires_vala_extern = true;
2215 :
2216 419 : if (prereq_cl != null) {
2217 177 : var base_class = prereq_cl;
2218 188 : while (base_class.base_class != null) {
2219 22 : base_class = base_class.base_class;
2220 : }
2221 : // Custom unref-methods need to be emitted before G_DEFINE_AUTOPTR_CLEANUP_FUNC,
2222 : // so we guard against that special case and handle it in generate_method_declaration.
2223 177 : generate_autoptr_cleanup (iface, base_class, decl_space);
2224 : }
2225 : }
2226 :
2227 235 : public override void visit_interface (Interface iface) {
2228 118 : push_context (new EmitContext (iface));
2229 118 : push_line (iface.source_reference);
2230 :
2231 118 : var old_signal_enum = signal_enum;
2232 :
2233 118 : if (get_ccode_name (iface).length < 3) {
2234 1 : iface.error = true;
2235 1 : Report.error (iface.source_reference, "Interface name `%s' is too short", get_ccode_name (iface));
2236 1 : return;
2237 : }
2238 :
2239 117 : signal_enum = new CCodeEnum ();
2240 :
2241 117 : generate_interface_declaration (iface, cfile);
2242 117 : if (!iface.is_internal_symbol ()) {
2243 32 : generate_interface_declaration (iface, header_file);
2244 : }
2245 117 : if (!iface.is_private_symbol ()) {
2246 115 : generate_interface_declaration (iface, internal_header_file);
2247 : }
2248 :
2249 117 : iface.accept_children (this);
2250 :
2251 124 : if (iface.get_signals ().size > 0) {
2252 7 : var last_signal = "%s_NUM_SIGNALS".printf (get_ccode_upper_case_name (iface));
2253 7 : signal_enum.add_value (new CCodeEnumValue (last_signal));
2254 7 : cfile.add_type_declaration (signal_enum);
2255 :
2256 7 : var signal_array_decl = new CCodeDeclaration ("guint");
2257 7 : signal_array_decl.modifiers |= CCodeModifiers.STATIC;
2258 7 : 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))));
2259 7 : cfile.add_type_declaration (signal_array_decl);
2260 : }
2261 :
2262 117 : add_interface_default_init_function (iface);
2263 :
2264 117 : if (iface.comment != null) {
2265 3 : cfile.add_type_member_definition (new CCodeComment (iface.comment.content));
2266 : }
2267 :
2268 117 : var type_fun = new InterfaceRegisterFunction (iface);
2269 117 : type_fun.init_from_type (context, in_plugin, false);
2270 117 : cfile.add_type_member_declaration (type_fun.get_source_declaration ());
2271 117 : cfile.add_type_member_definition (type_fun.get_definition ());
2272 :
2273 121 : signal_enum = old_signal_enum;
2274 :
2275 117 : pop_line ();
2276 117 : pop_context ();
2277 : }
2278 :
2279 234 : private void add_interface_default_init_function (Interface iface) {
2280 117 : push_context (new EmitContext (iface));
2281 :
2282 117 : var default_init = new CCodeFunction ("%s_default_init".printf (get_ccode_lower_case_name (iface, null)), "void");
2283 117 : default_init.add_parameter (new CCodeParameter ("iface", "%s *".printf (get_ccode_type_name (iface))));
2284 117 : default_init.add_parameter (new CCodeParameter ("iface_data", "gpointer"));
2285 117 : default_init.modifiers = CCodeModifiers.STATIC;
2286 :
2287 117 : push_function (default_init);
2288 :
2289 201 : if (iface.is_subtype_of (gobject_type)) {
2290 : /* create properties */
2291 84 : var props = iface.get_properties ();
2292 122 : foreach (Property prop in props) {
2293 37 : if (prop.is_abstract) {
2294 21 : if (!context.analyzer.is_gobject_property (prop)) {
2295 6 : continue;
2296 : }
2297 :
2298 15 : if (prop.comment != null) {
2299 3 : ccode.add_statement (new CCodeComment (prop.comment.content));
2300 : }
2301 :
2302 15 : var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_interface_install_property"));
2303 15 : cinst.add_argument (new CCodeIdentifier ("iface"));
2304 15 : cinst.add_argument (get_param_spec (prop));
2305 :
2306 15 : ccode.add_expression (cinst);
2307 : }
2308 : }
2309 : }
2310 :
2311 117 : var ciface = new CCodeIdentifier ("iface");
2312 :
2313 : /* connect default signal handlers */
2314 127 : foreach (Signal sig in iface.get_signals ()) {
2315 9 : if (sig.default_handler == null || !sig.is_virtual) {
2316 8 : continue;
2317 : }
2318 1 : var cname = get_ccode_real_name (sig.default_handler);
2319 1 : ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (sig.default_handler)), new CCodeIdentifier (cname));
2320 : }
2321 :
2322 : /* create signals */
2323 135 : foreach (Signal sig in iface.get_signals ()) {
2324 9 : if (sig.comment != null) {
2325 0 : ccode.add_statement (new CCodeComment (sig.comment.content));
2326 : }
2327 9 : ccode.add_expression (get_signal_creation (sig, iface));
2328 : }
2329 :
2330 : // connect default implementations
2331 393 : foreach (Method m in iface.get_methods ()) {
2332 155 : if (m.is_virtual) {
2333 17 : var cname = get_ccode_real_name (m);
2334 17 : ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (m)), new CCodeIdentifier (cname));
2335 17 : if (m.coroutine) {
2336 6 : ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_finish_vfunc_name (m)), new CCodeIdentifier (get_ccode_finish_real_name (m)));
2337 : }
2338 : }
2339 : }
2340 :
2341 177 : foreach (Property prop in iface.get_properties ()) {
2342 30 : if (prop.is_virtual) {
2343 2 : if (prop.get_accessor != null) {
2344 2 : string cname = get_ccode_real_name (prop.get_accessor);
2345 2 : ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), new CCodeIdentifier (cname));
2346 : }
2347 2 : if (prop.set_accessor != null) {
2348 2 : string cname = get_ccode_real_name (prop.set_accessor);
2349 2 : ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), new CCodeIdentifier (cname));
2350 : }
2351 : }
2352 : }
2353 :
2354 117 : pop_context ();
2355 :
2356 117 : cfile.add_function (default_init);
2357 : }
2358 :
2359 185 : public override void visit_struct (Struct st) {
2360 : // custom simple type structs cannot have a type id which depends on head-allocation
2361 185 : if (st.has_attribute ("SimpleType") && !st.has_attribute_argument ("CCode", "type_id")) {
2362 16 : st.set_attribute_bool ("CCode", "has_type_id", false);
2363 : }
2364 :
2365 185 : base.visit_struct (st);
2366 :
2367 185 : if (st.is_boolean_type () || st.is_integer_type () || st.is_floating_type ()) {
2368 : // Skip GType handling for these struct types,
2369 : // like in CCodeStructModule.generate_struct_declaration()
2370 26 : return;
2371 : }
2372 :
2373 297 : if (get_ccode_has_type_id (st)) {
2374 139 : if (get_ccode_name (st).length < 3) {
2375 1 : st.error = true;
2376 1 : Report.error (st.source_reference, "Struct name `%s' is too short", get_ccode_name (st));
2377 1 : return;
2378 : }
2379 :
2380 138 : push_line (st.source_reference);
2381 138 : var type_fun = new StructRegisterFunction (st);
2382 138 : type_fun.init_from_type (context, false, false);
2383 138 : cfile.add_type_member_definition (type_fun.get_definition ());
2384 138 : pop_line ();
2385 : }
2386 : }
2387 :
2388 80 : public override void visit_enum (Enum en) {
2389 80 : base.visit_enum (en);
2390 :
2391 148 : if (get_ccode_has_type_id (en)) {
2392 69 : if (get_ccode_name (en).length < 3) {
2393 1 : en.error = true;
2394 1 : Report.error (en.source_reference, "Enum name `%s' is too short", get_ccode_name (en));
2395 1 : return;
2396 : }
2397 :
2398 68 : push_line (en.source_reference);
2399 68 : var type_fun = new EnumRegisterFunction (en);
2400 68 : type_fun.init_from_type (context, false, false);
2401 68 : cfile.add_type_member_definition (type_fun.get_definition ());
2402 68 : pop_line ();
2403 : }
2404 : }
2405 :
2406 39 : public override void visit_error_domain (ErrorDomain edomain) {
2407 39 : base.visit_error_domain (edomain);
2408 :
2409 77 : if (get_ccode_has_type_id (edomain)) {
2410 38 : push_line (edomain.source_reference);
2411 38 : var type_fun = new ErrorDomainRegisterFunction (edomain);
2412 38 : type_fun.init_from_type (context, false, false);
2413 38 : cfile.add_type_member_definition (type_fun.get_definition ());
2414 38 : pop_line ();
2415 : }
2416 : }
2417 :
2418 17453 : public override void visit_method_call (MethodCall expr) {
2419 17445 : var ma = expr.call as MemberAccess;
2420 17445 : var mtype = expr.call.value_type as MethodType;
2421 16672 : if (mtype == null || ma == null || ma.inner == null ||
2422 15790 : !(ma.inner.value_type is EnumValueType) || !get_ccode_has_type_id (ma.inner.value_type.type_symbol) ||
2423 39 : mtype.method_symbol != ((EnumValueType) ma.inner.value_type).get_to_string_method ()) {
2424 17437 : base.visit_method_call (expr);
2425 17437 : return;
2426 : }
2427 : // to_string() on a gtype enum
2428 :
2429 8 : bool is_flags = ((Enum) ((EnumValueType) ma.inner.value_type).type_symbol).is_flags;
2430 :
2431 8 : push_line (expr.source_reference);
2432 8 : var to_string = new CCodeFunctionCall (new CCodeIdentifier ((is_flags ? "g_flags_to_string" : "g_enum_to_string")));
2433 8 : to_string.add_argument (new CCodeIdentifier (get_ccode_type_id (ma.inner.value_type)));
2434 8 : to_string.add_argument ((CCodeExpression) get_ccodenode (((MemberAccess) expr.call).inner));
2435 8 : expr.value_type.value_owned = true;
2436 8 : set_cvalue (expr, to_string);
2437 8 : pop_line ();
2438 : }
2439 :
2440 1020 : public override void visit_property (Property prop) {
2441 510 : var cl = current_type_symbol as Class;
2442 510 : var st = current_type_symbol as Struct;
2443 :
2444 510 : var base_prop = prop;
2445 510 : if (prop.base_property != null) {
2446 102 : base_prop = prop.base_property;
2447 459 : } else if (prop.base_interface_property != null) {
2448 126 : base_prop = prop.base_interface_property;
2449 : }
2450 :
2451 510 : if (!base_prop.has_attribute ("NoAccessorMethod") &&
2452 507 : prop.name == "type" && ((cl != null && !cl.is_compact) || (st != null && get_ccode_has_type_id (st)))) {
2453 0 : Report.error (prop.source_reference, "Property 'type' not allowed");
2454 0 : return;
2455 : }
2456 510 : base.visit_property (prop);
2457 : }
2458 :
2459 8639 : public override void create_type_check_statement (CodeNode method_node, DataType ret_type, TypeSymbol t, bool non_null, string var_name) {
2460 4435 : var ccheck = new CCodeFunctionCall ();
2461 :
2462 4435 : if (!context.assert) {
2463 0 : return;
2464 5405 : } else if (context.checking && ((t is Class && !((Class) t).is_compact) || t is Interface)) {
2465 970 : if (!get_ccode_has_type_id (t)) {
2466 0 : return;
2467 : }
2468 :
2469 : CCodeFunctionCall ctype_check;
2470 970 : if (t.external_package) {
2471 77 : ctype_check = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
2472 77 : ctype_check.add_argument (new CCodeIdentifier (var_name));
2473 77 : ctype_check.add_argument (new CCodeIdentifier (get_ccode_type_id (t)));
2474 : } else {
2475 893 : ctype_check = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_check_function (t)));
2476 893 : ctype_check.add_argument (new CCodeIdentifier (var_name));
2477 : }
2478 :
2479 970 : CCodeExpression cexpr = ctype_check;
2480 1005 : if (!non_null) {
2481 35 : var cnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier (var_name), new CCodeConstant ("NULL"));
2482 :
2483 35 : cexpr = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cnull, ctype_check);
2484 : }
2485 970 : ccheck.add_argument (cexpr);
2486 3465 : } else if (!non_null || (t is Struct && ((Struct) t).is_simple_type ())) {
2487 220 : return;
2488 6480 : } else if (t == glist_type || t == gslist_type) {
2489 : // NULL is empty list
2490 10 : return;
2491 : } else {
2492 3235 : var cnonnull = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (var_name), new CCodeConstant ("NULL"));
2493 3235 : ccheck.add_argument (cnonnull);
2494 : }
2495 :
2496 : // g_return_* needs glib.h
2497 4205 : cfile.add_include ("glib.h");
2498 :
2499 4205 : var cm = method_node as CreationMethod;
2500 209 : if (cm != null && !cm.coroutine && cm.parent_symbol is ObjectTypeSymbol) {
2501 202 : ccheck.call = new CCodeIdentifier ("g_return_val_if_fail");
2502 202 : ccheck.add_argument (new CCodeConstant ("NULL"));
2503 5808 : } else if (ret_type is VoidType) {
2504 : /* void function */
2505 2197 : ccheck.call = new CCodeIdentifier ("g_return_if_fail");
2506 : } else {
2507 1806 : ccheck.call = new CCodeIdentifier ("g_return_val_if_fail");
2508 :
2509 1806 : var cdefault = default_value_for_type (ret_type, false);
2510 1806 : if (cdefault != null) {
2511 1805 : ccheck.add_argument (cdefault);
2512 1 : } else if (ret_type.type_symbol is Struct && !((Struct) ret_type.type_symbol).is_simple_type ()) {
2513 0 : ccheck.add_argument (new CCodeIdentifier ("result"));
2514 : } else {
2515 1 : return;
2516 : }
2517 : }
2518 :
2519 4204 : ccode.add_expression (ccheck);
2520 : }
2521 :
2522 1692 : public override void visit_cast_expression (CastExpression expr) {
2523 1692 : unowned ObjectTypeSymbol? type_symbol = expr.type_reference.type_symbol as ObjectTypeSymbol;
2524 :
2525 1087 : if (type_symbol == null || (type_symbol is Class && ((Class) type_symbol).is_compact)) {
2526 859 : base.visit_cast_expression (expr);
2527 859 : return;
2528 : }
2529 :
2530 833 : generate_type_declaration (expr.type_reference, cfile);
2531 :
2532 : // checked cast for strict subtypes of GTypeInstance
2533 1064 : if (expr.is_silent_cast) {
2534 231 : TargetValue to_cast = expr.inner.target_value;
2535 : CCodeExpression cexpr;
2536 231 : if (!get_lvalue (to_cast)) {
2537 61 : to_cast = store_temp_value (to_cast, expr);
2538 : }
2539 231 : cexpr = get_cvalue_ (to_cast);
2540 231 : var ccheck = create_type_check (cexpr, expr.type_reference);
2541 231 : var ccast = new CCodeCastExpression (cexpr, get_ccode_name (expr.type_reference));
2542 231 : var cnull = new CCodeConstant ("NULL");
2543 231 : var cast_value = new GLibValue (expr.value_type, new CCodeConditionalExpression (ccheck, ccast, cnull));
2544 378 : if (requires_destroy (expr.inner.value_type)) {
2545 147 : var casted = store_temp_value (cast_value, expr);
2546 147 : ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, get_cvalue_ (casted), new CCodeConstant ("NULL")));
2547 147 : ccode.add_expression (destroy_value (to_cast));
2548 147 : ccode.close ();
2549 147 : expr.target_value = ((GLibValue) casted).copy ();
2550 : } else {
2551 84 : expr.target_value = cast_value;
2552 : }
2553 : } else {
2554 602 : set_cvalue (expr, generate_instance_cast (get_cvalue (expr.inner), expr.type_reference.type_symbol));
2555 : }
2556 : }
2557 : }
|