compiler: Prefix headers for set_cheader_override() if includedir is given
[vala-gnome.git] / codegen / valaccodestructmodule.vala
blob654894812f3f9d4fcac25a58c3fead15580b4ec8
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
20 * Author:
21 * Jürg Billeter <j@bitron.ch>
22 * Raffaele Sandrini <raffaele@sandrini.ch>
25 using GLib;
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))) {
30 return;
33 if (st.is_boolean_type () || st.is_integer_type () || st.is_floating_type ()) {
34 if (st.base_struct != null) {
35 generate_struct_declaration (st.base_struct, decl_space);
36 decl_space.add_type_declaration (new CCodeTypeDefinition (get_ccode_name (st.base_struct), new CCodeVariableDeclarator (get_ccode_name (st))));
37 } else {
38 string typename = null;
39 if (st.is_boolean_type ()) {
40 // typedef for boolean types
41 decl_space.add_include ("stdbool.h");
42 typename = "bool";
43 } else if (st.is_integer_type ()) {
44 // typedef for integral types
45 decl_space.add_include ("stdint.h");
46 typename = "%sint%d_t".printf (st.signed ? "" : "u", st.width);
47 } else if (st.is_floating_type ()) {
48 // typedef for floating types
49 typename = (st.width == 64 ? "double" : "float");
51 decl_space.add_type_declaration (new CCodeTypeDefinition (typename, new CCodeVariableDeclarator (get_ccode_name (st))));
53 return;
56 if (get_ccode_has_type_id (st)) {
57 decl_space.add_include ("glib-object.h");
58 decl_space.add_type_declaration (new CCodeNewline ());
59 var macro = "(%s_get_type ())".printf (get_ccode_lower_case_name (st, null));
60 decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (st), macro));
62 var type_fun = new StructRegisterFunction (st, context);
63 type_fun.init_from_type (false, true);
64 decl_space.add_type_member_declaration (type_fun.get_declaration ());
67 var instance_struct = new CCodeStruct ("_%s".printf (get_ccode_name (st)));
68 instance_struct.modifiers |= (st.version.deprecated ? CCodeModifiers.DEPRECATED : 0);
70 foreach (Field f in st.get_fields ()) {
71 if (f.binding == MemberBinding.INSTANCE) {
72 generate_type_declaration (f.variable_type, decl_space);
73 CCodeModifiers modifiers = (f.is_volatile ? CCodeModifiers.VOLATILE : 0) | (f.version.deprecated ? CCodeModifiers.DEPRECATED : 0);
74 instance_struct.add_field (get_ccode_name (f.variable_type), get_ccode_name (f), modifiers, get_ccode_declarator_suffix (f.variable_type));
75 if (f.variable_type is ArrayType && get_ccode_array_length (f)) {
76 // create fields to store array dimensions
77 var array_type = (ArrayType) f.variable_type;
79 if (!array_type.fixed_length) {
80 var len_type = int_type.copy ();
82 for (int dim = 1; dim <= array_type.rank; dim++) {
83 string length_cname;
84 if (get_ccode_array_length_name (f) != null) {
85 length_cname = get_ccode_array_length_name (f);
86 } else {
87 length_cname = get_array_length_cname (get_ccode_name (f), dim);
89 instance_struct.add_field (get_ccode_name (len_type), length_cname);
92 if (array_type.rank == 1 && f.is_internal_symbol ()) {
93 instance_struct.add_field (get_ccode_name (len_type), get_array_size_cname (get_ccode_name (f)));
96 } else if (f.variable_type is DelegateType) {
97 var delegate_type = (DelegateType) f.variable_type;
98 if (delegate_type.delegate_symbol.has_target) {
99 // create field to store delegate target
100 instance_struct.add_field ("gpointer", get_ccode_delegate_target_name (f));
101 if (delegate_type.is_disposable ()) {
102 instance_struct.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_ccode_name (f)));
109 if (st.base_struct == null) {
110 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (st)), new CCodeVariableDeclarator (get_ccode_name (st))));
112 decl_space.add_type_definition (instance_struct);
113 } else {
114 decl_space.add_type_declaration (new CCodeTypeDefinition (get_ccode_name (st.base_struct), new CCodeVariableDeclarator (get_ccode_name (st))));
117 var function = new CCodeFunction (get_ccode_dup_function (st), get_ccode_name (st) + "*");
118 if (st.is_private_symbol ()) {
119 function.modifiers = CCodeModifiers.STATIC;
120 } else if (context.hide_internal && st.is_internal_symbol ()) {
121 function.modifiers = CCodeModifiers.INTERNAL;
123 function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*"));
124 decl_space.add_function_declaration (function);
126 function = new CCodeFunction (get_ccode_free_function (st), "void");
127 if (st.is_private_symbol ()) {
128 function.modifiers = CCodeModifiers.STATIC;
129 } else if (context.hide_internal && st.is_internal_symbol ()) {
130 function.modifiers = CCodeModifiers.INTERNAL;
132 function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*"));
133 decl_space.add_function_declaration (function);
135 if (st.is_disposable ()) {
136 function = new CCodeFunction (get_ccode_copy_function (st), "void");
137 if (st.is_private_symbol ()) {
138 function.modifiers = CCodeModifiers.STATIC;
139 } else if (context.hide_internal && st.is_internal_symbol ()) {
140 function.modifiers = CCodeModifiers.INTERNAL;
142 function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*"));
143 function.add_parameter (new CCodeParameter ("dest", get_ccode_name (st) + "*"));
144 decl_space.add_function_declaration (function);
146 function = new CCodeFunction (get_ccode_destroy_function (st), "void");
147 if (st.is_private_symbol ()) {
148 function.modifiers = CCodeModifiers.STATIC;
149 } else if (context.hide_internal && st.is_internal_symbol ()) {
150 function.modifiers = CCodeModifiers.INTERNAL;
152 function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*"));
153 decl_space.add_function_declaration (function);
157 public override void visit_struct (Struct st) {
158 push_context (new EmitContext (st));
159 push_line (st.source_reference);
161 if (get_ccode_has_type_id (st) && get_ccode_name (st).length < 3) {
162 st.error = true;
163 Report.error (st.source_reference, "Name `%s' is too short for struct using GType".printf (get_ccode_name (st)));
164 return;
167 var old_instance_finalize_context = instance_finalize_context;
168 instance_finalize_context = new EmitContext ();
170 generate_struct_declaration (st, cfile);
172 if (!st.is_internal_symbol ()) {
173 generate_struct_declaration (st, header_file);
175 if (!st.is_private_symbol ()) {
176 generate_struct_declaration (st, internal_header_file);
179 if (!st.is_boolean_type () && !st.is_integer_type () && !st.is_floating_type ()) {
180 if (st.is_disposable ()) {
181 begin_struct_destroy_function (st);
185 st.accept_children (this);
187 if (!st.is_boolean_type () && !st.is_integer_type () && !st.is_floating_type ()) {
188 if (st.is_disposable ()) {
189 add_struct_copy_function (st);
190 add_struct_destroy_function (st);
193 add_struct_dup_function (st);
194 add_struct_free_function (st);
197 instance_finalize_context = old_instance_finalize_context;
199 pop_line ();
200 pop_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 var creation_call = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
216 creation_call.add_argument (new CCodeConstant (get_ccode_name (st)));
217 creation_call.add_argument (new CCodeConstant ("1"));
218 ccode.add_assignment (new CCodeIdentifier ("dup"), creation_call);
220 if (st.is_disposable ()) {
221 var copy_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_copy_function (st)));
222 copy_call.add_argument (new CCodeIdentifier ("self"));
223 copy_call.add_argument (new CCodeIdentifier ("dup"));
224 ccode.add_expression (copy_call);
225 } else {
226 cfile.add_include ("string.h");
228 var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
229 sizeof_call.add_argument (new CCodeConstant (get_ccode_name (st)));
231 var copy_call = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
232 copy_call.add_argument (new CCodeIdentifier ("dup"));
233 copy_call.add_argument (new CCodeIdentifier ("self"));
234 copy_call.add_argument (sizeof_call);
235 ccode.add_expression (copy_call);
238 ccode.add_return (new CCodeIdentifier ("dup"));
240 pop_function ();
242 cfile.add_function (function);
245 void add_struct_free_function (Struct st) {
246 var function = new CCodeFunction (get_ccode_free_function (st), "void");
247 if (st.is_private_symbol ()) {
248 function.modifiers = CCodeModifiers.STATIC;
249 } else if (context.hide_internal && st.is_internal_symbol ()) {
250 function.modifiers = CCodeModifiers.INTERNAL;
253 function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*"));
255 push_function (function);
257 if (st.is_disposable ()) {
258 var destroy_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_destroy_function (st)));
259 destroy_call.add_argument (new CCodeIdentifier ("self"));
260 ccode.add_expression (destroy_call);
263 var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
264 free_call.add_argument (new CCodeIdentifier ("self"));
265 ccode.add_expression (free_call);
267 pop_function ();
269 cfile.add_function (function);
272 void add_struct_copy_function (Struct st) {
273 var function = new CCodeFunction (get_ccode_copy_function (st), "void");
274 if (st.is_private_symbol ()) {
275 function.modifiers = CCodeModifiers.STATIC;
276 } else if (context.hide_internal && st.is_internal_symbol ()) {
277 function.modifiers = CCodeModifiers.INTERNAL;
280 function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*"));
281 function.add_parameter (new CCodeParameter ("dest", get_ccode_name (st) + "*"));
283 push_function (function);
285 var dest_struct = new GLibValue (get_data_type_for_symbol (st), new CCodeIdentifier ("(*dest)"), true);
286 foreach (var f in st.get_fields ()) {
287 if (f.binding == MemberBinding.INSTANCE) {
288 var value = load_field (f, load_this_parameter ((TypeSymbol) st));
289 if (requires_copy (f.variable_type)) {
290 value = copy_value (value, f);
291 if (value == null) {
292 // error case, continue to avoid critical
293 continue;
296 store_field (f, dest_struct, value);
300 pop_function ();
302 cfile.add_function (function);
305 void begin_struct_destroy_function (Struct st) {
306 push_context (instance_finalize_context);
308 var function = new CCodeFunction (get_ccode_destroy_function (st), "void");
309 if (st.is_private_symbol ()) {
310 function.modifiers = CCodeModifiers.STATIC;
311 } else if (context.hide_internal && st.is_internal_symbol ()) {
312 function.modifiers = CCodeModifiers.INTERNAL;
315 function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*"));
317 push_function (function);
319 pop_context ();
322 void add_struct_destroy_function (Struct st) {
323 cfile.add_function (instance_finalize_context.ccode);