1 /* valaccodestructmodule.vala
3 * Copyright (C) 2006-2009 Jürg Billeter
4 * Copyright (C) 2006-2008 Raffaele Sandrini
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * Jürg Billeter <j@bitron.ch>
22 * Raffaele Sandrini <raffaele@sandrini.ch>
27 public abstract class Vala.CCodeStructModule : CCodeBaseModule {
28 public override void generate_struct_declaration (Struct st, CCodeFile decl_space) {
29 if (add_symbol_declaration (decl_space, st, get_ccode_name (st))) {
33 if (st.base_struct != null) {
34 generate_struct_declaration (st.base_struct, decl_space);
35 } else if (!st.external_package) {
36 // custom simple type structs cannot have a type id which depends on head-allocation
37 if (st.get_attribute ("SimpleType") != null && !st.has_attribute_argument ("CCode", "type_id")) {
38 st.set_attribute_bool ("CCode", "has_type_id", false);
42 if (st.is_boolean_type () || st.is_integer_type () || st.is_floating_type ()) {
44 // See GTypeModule.visit_struct()
45 if (st.base_struct != null) {
46 typename = get_ccode_name (st.base_struct);
47 } else if (st.is_boolean_type ()) {
48 // typedef for boolean types
49 decl_space.add_include ("stdbool.h");
51 } else if (st.is_integer_type ()) {
52 // typedef for integral types
53 decl_space.add_include ("stdint.h");
54 typename = "%sint%d_t".printf (st.signed ? "" : "u", st.width);
55 } else if (st.is_floating_type ()) {
56 // typedef for floating types
57 typename = (st.width == 64 ? "double" : "float");
59 assert_not_reached ();
61 decl_space.add_type_declaration (new CCodeTypeDefinition (typename, new CCodeVariableDeclarator (get_ccode_name (st))));
65 if (context.profile == Profile.GOBJECT) {
66 if (get_ccode_has_type_id (st)) {
67 decl_space.add_include ("glib-object.h");
68 decl_space.add_type_declaration (new CCodeNewline ());
69 var macro = "(%s_get_type ())".printf (get_ccode_lower_case_name (st, null));
70 decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (st), macro));
72 var type_fun = new StructRegisterFunction (st);
73 type_fun.init_from_type (context, false, true);
74 decl_space.add_type_member_declaration (type_fun.get_declaration ());
76 requires_vala_extern = true;
80 if (st.base_struct == null) {
81 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (st)), new CCodeVariableDeclarator (get_ccode_name (st))));
83 decl_space.add_type_declaration (new CCodeTypeDefinition (get_ccode_name (st.base_struct), new CCodeVariableDeclarator (get_ccode_name (st))));
86 var instance_struct = new CCodeStruct ("_%s".printf (get_ccode_name (st)));
88 if (st.version.deprecated) {
89 if (context.profile == Profile.GOBJECT) {
90 decl_space.add_include ("glib.h");
92 instance_struct.modifiers |= CCodeModifiers.DEPRECATED;
95 foreach (Field f in st.get_fields ()) {
96 if (f.binding == MemberBinding.INSTANCE) {
97 append_field (instance_struct, f, decl_space);
101 if (st.base_struct == null) {
102 decl_space.add_type_definition (instance_struct);
105 if (st.is_simple_type ()) {
109 var function = new CCodeFunction (get_ccode_dup_function (st), get_ccode_name (st) + "*");
110 if (st.is_private_symbol ()) {
111 function.modifiers = CCodeModifiers.STATIC;
112 } else if (context.hide_internal && st.is_internal_symbol ()) {
113 function.modifiers = CCodeModifiers.INTERNAL;
115 function.modifiers |= CCodeModifiers.EXTERN;
116 requires_vala_extern = true;
118 function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*"));
119 decl_space.add_function_declaration (function);
121 function = new CCodeFunction (get_ccode_free_function (st), "void");
122 if (st.is_private_symbol ()) {
123 function.modifiers = CCodeModifiers.STATIC;
124 } else if (context.hide_internal && st.is_internal_symbol ()) {
125 function.modifiers = CCodeModifiers.INTERNAL;
127 function.modifiers = CCodeModifiers.EXTERN;
128 requires_vala_extern = true;
130 function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*"));
131 decl_space.add_function_declaration (function);
133 if (st.is_disposable ()) {
134 function = new CCodeFunction (get_ccode_copy_function (st), "void");
135 if (st.is_private_symbol ()) {
136 function.modifiers = CCodeModifiers.STATIC;
137 } else if (context.hide_internal && st.is_internal_symbol ()) {
138 function.modifiers = CCodeModifiers.INTERNAL;
140 function.modifiers = CCodeModifiers.EXTERN;
141 requires_vala_extern = true;
143 function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*"));
144 function.add_parameter (new CCodeParameter ("dest", get_ccode_name (st) + "*"));
145 decl_space.add_function_declaration (function);
147 function = new CCodeFunction (get_ccode_destroy_function (st), "void");
148 if (st.is_private_symbol ()) {
149 function.modifiers = CCodeModifiers.STATIC;
150 } else if (context.hide_internal && st.is_internal_symbol ()) {
151 function.modifiers = CCodeModifiers.INTERNAL;
153 function.modifiers = CCodeModifiers.EXTERN;
154 requires_vala_extern = true;
156 function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*"));
157 decl_space.add_function_declaration (function);
161 public override void visit_struct (Struct st) {
162 push_context (new EmitContext (st));
163 push_line (st.source_reference);
165 var old_instance_finalize_context = instance_finalize_context;
166 instance_finalize_context = new EmitContext ();
168 generate_struct_declaration (st, cfile);
170 if (!st.is_internal_symbol ()) {
171 generate_struct_declaration (st, header_file);
173 if (!st.is_private_symbol ()) {
174 generate_struct_declaration (st, internal_header_file);
177 if (!st.is_boolean_type () && !st.is_integer_type () && !st.is_floating_type ()) {
178 if (st.is_disposable ()) {
179 begin_struct_destroy_function (st);
183 st.accept_children (this);
185 if (!st.is_boolean_type () && !st.is_integer_type () && !st.is_floating_type ()) {
186 if (st.is_disposable ()) {
187 add_struct_copy_function (st);
188 add_struct_destroy_function (st);
191 if (!st.is_simple_type ()) {
192 add_struct_dup_function (st);
193 add_struct_free_function (st);
197 instance_finalize_context = old_instance_finalize_context;
203 void add_struct_dup_function (Struct st) {
204 var function = new CCodeFunction (get_ccode_dup_function (st), get_ccode_name (st) + "*");
205 if (st.access == SymbolAccessibility.PRIVATE) {
206 function.modifiers = CCodeModifiers.STATIC;
209 function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*"));
211 push_function (function);
213 ccode.add_declaration (get_ccode_name (st) + "*", new CCodeVariableDeclarator ("dup"));
215 if (context.profile == Profile.GOBJECT) {
216 // g_new0 needs glib.h
217 cfile.add_include ("glib.h");
218 var creation_call = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
219 creation_call.add_argument (new CCodeConstant (get_ccode_name (st)));
220 creation_call.add_argument (new CCodeConstant ("1"));
221 ccode.add_assignment (new CCodeIdentifier ("dup"), creation_call);
222 } else if (context.profile == Profile.POSIX) {
223 // calloc needs stdlib.h
224 cfile.add_include ("stdlib.h");
226 var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
227 sizeof_call.add_argument (new CCodeConstant (get_ccode_name (st)));
229 var creation_call = new CCodeFunctionCall (new CCodeIdentifier ("calloc"));
230 creation_call.add_argument (new CCodeConstant ("1"));
231 creation_call.add_argument (sizeof_call);
232 ccode.add_assignment (new CCodeIdentifier ("dup"), creation_call);
235 if (st.is_disposable ()) {
236 var copy_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_copy_function (st)));
237 copy_call.add_argument (new CCodeIdentifier ("self"));
238 copy_call.add_argument (new CCodeIdentifier ("dup"));
239 ccode.add_expression (copy_call);
241 cfile.add_include ("string.h");
243 var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
244 sizeof_call.add_argument (new CCodeConstant (get_ccode_name (st)));
246 var copy_call = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
247 copy_call.add_argument (new CCodeIdentifier ("dup"));
248 copy_call.add_argument (new CCodeIdentifier ("self"));
249 copy_call.add_argument (sizeof_call);
250 ccode.add_expression (copy_call);
253 ccode.add_return (new CCodeIdentifier ("dup"));
257 cfile.add_function (function);
260 void add_struct_free_function (Struct st) {
261 var function = new CCodeFunction (get_ccode_free_function (st), "void");
262 if (st.is_private_symbol ()) {
263 function.modifiers = CCodeModifiers.STATIC;
264 } else if (context.hide_internal && st.is_internal_symbol ()) {
265 function.modifiers = CCodeModifiers.INTERNAL;
268 function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*"));
270 push_function (function);
272 if (st.is_disposable ()) {
273 var destroy_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_destroy_function (st)));
274 destroy_call.add_argument (new CCodeIdentifier ("self"));
275 ccode.add_expression (destroy_call);
278 if (context.profile == Profile.GOBJECT) {
279 // g_free needs glib.h
280 cfile.add_include ("glib.h");
281 var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
282 free_call.add_argument (new CCodeIdentifier ("self"));
283 ccode.add_expression (free_call);
284 } else if (context.profile == Profile.POSIX) {
285 // free needs stdlib.h
286 cfile.add_include ("stdlib.h");
287 var free_call = new CCodeFunctionCall (new CCodeIdentifier ("free"));
288 free_call.add_argument (new CCodeIdentifier ("self"));
289 ccode.add_expression (free_call);
294 cfile.add_function (function);
297 void add_struct_copy_function (Struct st) {
298 var function = new CCodeFunction (get_ccode_copy_function (st), "void");
299 if (st.is_private_symbol ()) {
300 function.modifiers = CCodeModifiers.STATIC;
301 } else if (context.hide_internal && st.is_internal_symbol ()) {
302 function.modifiers = CCodeModifiers.INTERNAL;
305 function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*"));
306 function.add_parameter (new CCodeParameter ("dest", get_ccode_name (st) + "*"));
308 push_function (function);
310 var dest_struct = new GLibValue (SemanticAnalyzer.get_data_type_for_symbol (st), new CCodeIdentifier ("(*dest)"), true);
311 unowned Struct sym = st;
312 while (sym.base_struct != null) {
313 sym = sym.base_struct;
315 foreach (var f in sym.get_fields ()) {
316 if (f.binding == MemberBinding.INSTANCE) {
317 var value = load_field (f, load_this_parameter ((TypeSymbol) st));
318 if ((!(f.variable_type is DelegateType) || get_ccode_delegate_target (f)) && requires_copy (f.variable_type)) {
319 value = copy_value (value, f);
321 // error case, continue to avoid critical
325 store_field (f, dest_struct, value);
331 cfile.add_function (function);
334 void begin_struct_destroy_function (Struct st) {
335 push_context (instance_finalize_context);
337 var function = new CCodeFunction (get_ccode_destroy_function (st), "void");
338 if (st.is_private_symbol ()) {
339 function.modifiers = CCodeModifiers.STATIC;
340 } else if (context.hide_internal && st.is_internal_symbol ()) {
341 function.modifiers = CCodeModifiers.INTERNAL;
344 function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*"));
346 push_function (function);
351 void add_struct_destroy_function (Struct st) {
352 unowned Struct sym = st;
353 while (sym.base_struct != null) {
354 sym = sym.base_struct;
357 push_context (instance_finalize_context);
359 var destroy_func = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_destroy_function (sym)));
360 destroy_func.add_argument (new CCodeIdentifier ("self"));
361 ccode.add_expression (destroy_func);
366 cfile.add_function (instance_finalize_context.ccode);