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
.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
))));
38 string typename
= null;
39 if (st
.is_boolean_type ()) {
40 // typedef for boolean types
41 decl_space
.add_include ("stdbool.h");
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
))));
56 if (context
.profile
== Profile
.GOBJECT
) {
57 if (get_ccode_has_type_id (st
)) {
58 decl_space
.add_include ("glib-object.h");
59 decl_space
.add_type_declaration (new
CCodeNewline ());
60 var macro
= "(%s_get_type ())".printf (get_ccode_lower_case_name (st
, null));
61 decl_space
.add_type_declaration (new
CCodeMacroReplacement (get_ccode_type_id (st
), macro
));
63 var type_fun
= new
StructRegisterFunction (st
);
64 type_fun
.init_from_type (context
, false, true);
65 decl_space
.add_type_member_declaration (type_fun
.get_declaration ());
69 var instance_struct
= new
CCodeStruct ("_%s".printf (get_ccode_name (st
)));
70 instance_struct
.modifiers
|= (st
.version
.deprecated ? CCodeModifiers
.DEPRECATED
: 0);
72 foreach (Field f
in st
.get_fields ()) {
73 if (f
.binding
== MemberBinding
.INSTANCE
) {
74 generate_type_declaration (f
.variable_type
, decl_space
);
75 CCodeModifiers modifiers
= (f
.is_volatile ? CCodeModifiers
.VOLATILE
: 0) | (f
.version
.deprecated ? CCodeModifiers
.DEPRECATED
: 0);
76 instance_struct
.add_field (get_ccode_name (f
.variable_type
), get_ccode_name (f
), modifiers
, get_ccode_declarator_suffix (f
.variable_type
));
77 if (f
.variable_type is ArrayType
&& get_ccode_array_length (f
)) {
78 // create fields to store array dimensions
79 var array_type
= (ArrayType
) f
.variable_type
;
81 if (!array_type
.fixed_length
) {
82 var len_type
= int_type
.copy ();
84 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
86 if (get_ccode_array_length_name (f
) != null) {
87 length_cname
= get_ccode_array_length_name (f
);
89 length_cname
= get_array_length_cname (get_ccode_name (f
), dim
);
91 instance_struct
.add_field (get_ccode_name (len_type
), length_cname
);
94 if (array_type
.rank
== 1 && f
.is_internal_symbol ()) {
95 instance_struct
.add_field (get_ccode_name (len_type
), get_array_size_cname (get_ccode_name (f
)));
98 } else if (f
.variable_type is DelegateType
&& get_ccode_delegate_target (f
)) {
99 var delegate_type
= (DelegateType
) f
.variable_type
;
100 if (delegate_type
.delegate_symbol
.has_target
) {
101 // create field to store delegate target
102 instance_struct
.add_field ("gpointer", get_ccode_delegate_target_name (f
));
103 if (delegate_type
.is_disposable ()) {
104 instance_struct
.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_ccode_name (f
)));
111 if (st
.base_struct
== null) {
112 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (st
)), new
CCodeVariableDeclarator (get_ccode_name (st
))));
114 decl_space
.add_type_definition (instance_struct
);
116 decl_space
.add_type_declaration (new
CCodeTypeDefinition (get_ccode_name (st
.base_struct
), new
CCodeVariableDeclarator (get_ccode_name (st
))));
119 var function
= new
CCodeFunction (get_ccode_dup_function (st
), get_ccode_name (st
) + "*");
120 if (st
.is_private_symbol ()) {
121 function
.modifiers
= CCodeModifiers
.STATIC
;
122 } else if (context
.hide_internal
&& st
.is_internal_symbol ()) {
123 function
.modifiers
= CCodeModifiers
.INTERNAL
;
125 function
.add_parameter (new
CCodeParameter ("self", "const " + get_ccode_name (st
) + "*"));
126 decl_space
.add_function_declaration (function
);
128 function
= new
CCodeFunction (get_ccode_free_function (st
), "void");
129 if (st
.is_private_symbol ()) {
130 function
.modifiers
= CCodeModifiers
.STATIC
;
131 } else if (context
.hide_internal
&& st
.is_internal_symbol ()) {
132 function
.modifiers
= CCodeModifiers
.INTERNAL
;
134 function
.add_parameter (new
CCodeParameter ("self", get_ccode_name (st
) + "*"));
135 decl_space
.add_function_declaration (function
);
137 if (st
.is_disposable ()) {
138 function
= new
CCodeFunction (get_ccode_copy_function (st
), "void");
139 if (st
.is_private_symbol ()) {
140 function
.modifiers
= CCodeModifiers
.STATIC
;
141 } else if (context
.hide_internal
&& st
.is_internal_symbol ()) {
142 function
.modifiers
= CCodeModifiers
.INTERNAL
;
144 function
.add_parameter (new
CCodeParameter ("self", "const " + get_ccode_name (st
) + "*"));
145 function
.add_parameter (new
CCodeParameter ("dest", get_ccode_name (st
) + "*"));
146 decl_space
.add_function_declaration (function
);
148 function
= new
CCodeFunction (get_ccode_destroy_function (st
), "void");
149 if (st
.is_private_symbol ()) {
150 function
.modifiers
= CCodeModifiers
.STATIC
;
151 } else if (context
.hide_internal
&& st
.is_internal_symbol ()) {
152 function
.modifiers
= CCodeModifiers
.INTERNAL
;
154 function
.add_parameter (new
CCodeParameter ("self", get_ccode_name (st
) + "*"));
155 decl_space
.add_function_declaration (function
);
159 public override void visit_struct (Struct st
) {
160 push_context (new
EmitContext (st
));
161 push_line (st
.source_reference
);
163 if (get_ccode_has_type_id (st
) && get_ccode_name (st
).length
< 3) {
165 Report
.error (st
.source_reference
, "Name `%s' is too short for struct using GType".printf (get_ccode_name (st
)));
169 var old_instance_finalize_context
= instance_finalize_context
;
170 instance_finalize_context
= new
EmitContext ();
172 generate_struct_declaration (st
, cfile
);
174 if (!st
.is_internal_symbol ()) {
175 generate_struct_declaration (st
, header_file
);
177 if (!st
.is_private_symbol ()) {
178 generate_struct_declaration (st
, internal_header_file
);
181 if (!st
.is_boolean_type () && !st
.is_integer_type () && !st
.is_floating_type ()) {
182 if (st
.is_disposable ()) {
183 begin_struct_destroy_function (st
);
187 st
.accept_children (this
);
189 if (!st
.is_boolean_type () && !st
.is_integer_type () && !st
.is_floating_type ()) {
190 if (st
.is_disposable ()) {
191 add_struct_copy_function (st
);
192 add_struct_destroy_function (st
);
195 add_struct_dup_function (st
);
196 add_struct_free_function (st
);
199 instance_finalize_context
= old_instance_finalize_context
;
205 void add_struct_dup_function (Struct st
) {
206 var function
= new
CCodeFunction (get_ccode_dup_function (st
), get_ccode_name (st
) + "*");
207 if (st
.access
== SymbolAccessibility
.PRIVATE
) {
208 function
.modifiers
= CCodeModifiers
.STATIC
;
211 function
.add_parameter (new
CCodeParameter ("self", "const " + get_ccode_name (st
) + "*"));
213 push_function (function
);
215 ccode
.add_declaration (get_ccode_name (st
) + "*", new
CCodeVariableDeclarator ("dup"));
217 if (context
.profile
== Profile
.GOBJECT
) {
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 var creation_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("calloc"));
224 creation_call
.add_argument (new
CCodeConstant ("1"));
225 creation_call
.add_argument (new
CCodeIdentifier ("sizeof (%s*)".printf (get_ccode_name (st
))));
226 ccode
.add_assignment (new
CCodeIdentifier ("dup"), creation_call
);
229 if (st
.is_disposable ()) {
230 var copy_call
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_copy_function (st
)));
231 copy_call
.add_argument (new
CCodeIdentifier ("self"));
232 copy_call
.add_argument (new
CCodeIdentifier ("dup"));
233 ccode
.add_expression (copy_call
);
235 cfile
.add_include ("string.h");
237 var sizeof_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("sizeof"));
238 sizeof_call
.add_argument (new
CCodeConstant (get_ccode_name (st
)));
240 var copy_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("memcpy"));
241 copy_call
.add_argument (new
CCodeIdentifier ("dup"));
242 copy_call
.add_argument (new
CCodeIdentifier ("self"));
243 copy_call
.add_argument (sizeof_call
);
244 ccode
.add_expression (copy_call
);
247 ccode
.add_return (new
CCodeIdentifier ("dup"));
251 cfile
.add_function (function
);
254 void add_struct_free_function (Struct st
) {
255 var function
= new
CCodeFunction (get_ccode_free_function (st
), "void");
256 if (st
.is_private_symbol ()) {
257 function
.modifiers
= CCodeModifiers
.STATIC
;
258 } else if (context
.hide_internal
&& st
.is_internal_symbol ()) {
259 function
.modifiers
= CCodeModifiers
.INTERNAL
;
262 function
.add_parameter (new
CCodeParameter ("self", get_ccode_name (st
) + "*"));
264 push_function (function
);
266 if (st
.is_disposable ()) {
267 var destroy_call
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_destroy_function (st
)));
268 destroy_call
.add_argument (new
CCodeIdentifier ("self"));
269 ccode
.add_expression (destroy_call
);
272 if (context
.profile
== Profile
.GOBJECT
) {
273 var free_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_free"));
274 free_call
.add_argument (new
CCodeIdentifier ("self"));
275 ccode
.add_expression (free_call
);
276 } else if (context
.profile
== Profile
.POSIX
) {
277 var free_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("free"));
278 free_call
.add_argument (new
CCodeIdentifier ("self"));
279 ccode
.add_expression (free_call
);
284 cfile
.add_function (function
);
287 void add_struct_copy_function (Struct st
) {
288 var function
= new
CCodeFunction (get_ccode_copy_function (st
), "void");
289 if (st
.is_private_symbol ()) {
290 function
.modifiers
= CCodeModifiers
.STATIC
;
291 } else if (context
.hide_internal
&& st
.is_internal_symbol ()) {
292 function
.modifiers
= CCodeModifiers
.INTERNAL
;
295 function
.add_parameter (new
CCodeParameter ("self", "const " + get_ccode_name (st
) + "*"));
296 function
.add_parameter (new
CCodeParameter ("dest", get_ccode_name (st
) + "*"));
298 push_function (function
);
300 var dest_struct
= new
GLibValue (get_data_type_for_symbol (st
), new
CCodeIdentifier ("(*dest)"), true);
301 foreach (var f
in st
.get_fields ()) {
302 if (f
.binding
== MemberBinding
.INSTANCE
) {
303 var value
= load_field (f
, load_this_parameter ((TypeSymbol
) st
));
304 if (get_ccode_delegate_target (f
) && requires_copy (f
.variable_type
)) {
305 value
= copy_value (value
, f
);
307 // error case, continue to avoid critical
311 store_field (f
, dest_struct
, value
);
317 cfile
.add_function (function
);
320 void begin_struct_destroy_function (Struct st
) {
321 push_context (instance_finalize_context
);
323 var function
= new
CCodeFunction (get_ccode_destroy_function (st
), "void");
324 if (st
.is_private_symbol ()) {
325 function
.modifiers
= CCodeModifiers
.STATIC
;
326 } else if (context
.hide_internal
&& st
.is_internal_symbol ()) {
327 function
.modifiers
= CCodeModifiers
.INTERNAL
;
330 function
.add_parameter (new
CCodeParameter ("self", get_ccode_name (st
) + "*"));
332 push_function (function
);
337 void add_struct_destroy_function (Struct st
) {
338 cfile
.add_function (instance_finalize_context
.ccode
);