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
, st
.get_cname ())) {
33 if (st
.is_boolean_type ()) {
34 // typedef for boolean types
35 decl_space
.add_include ("stdbool.h");
36 st
.set_cname ("bool");
38 } else if (st
.is_integer_type ()) {
39 // typedef for integral types
40 decl_space
.add_include ("stdint.h");
41 st
.set_cname ("%sint%d_t".printf (st
.signed ?
"" : "u", st
.width
));
43 } else if (st
.is_floating_type ()) {
44 // typedef for floating types
45 st
.set_cname (st
.width
== 64 ?
"double" : "float");
49 if (context
.profile
== Profile
.GOBJECT
) {
51 decl_space
.add_type_declaration (new
CCodeNewline ());
52 var macro
= "(%s_get_type ())".printf (st
.get_lower_case_cname (null));
53 decl_space
.add_type_declaration (new
CCodeMacroReplacement (st
.get_type_id (), macro
));
55 var type_fun
= new
StructRegisterFunction (st
, context
);
56 type_fun
.init_from_type (false, true);
57 decl_space
.add_type_member_declaration (type_fun
.get_declaration ());
61 var instance_struct
= new
CCodeStruct ("_%s".printf (st
.get_cname ()));
62 instance_struct
.deprecated
= st
.deprecated
;
64 foreach (Field f
in st
.get_fields ()) {
65 string field_ctype
= f
.variable_type
.get_cname ();
67 field_ctype
= "volatile " + field_ctype
;
70 if (f
.binding
== MemberBinding
.INSTANCE
) {
71 generate_type_declaration (f
.variable_type
, decl_space
);
73 instance_struct
.add_field (field_ctype
, f
.get_cname () + f
.variable_type
.get_cdeclarator_suffix (), f
.deprecated ?
" G_GNUC_DEPRECATED" : null);
74 if (f
.variable_type is ArrayType
&& !f
.no_array_length
) {
75 // create fields to store array dimensions
76 var array_type
= (ArrayType
) f
.variable_type
;
78 if (!array_type
.fixed_length
) {
79 var len_type
= int_type
.copy ();
81 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
82 instance_struct
.add_field (len_type
.get_cname (), get_array_length_cname (f
.name
, dim
));
85 if (array_type
.rank
== 1 && f
.is_internal_symbol ()) {
86 instance_struct
.add_field (len_type
.get_cname (), get_array_size_cname (f
.name
));
89 } else if (f
.variable_type is DelegateType
) {
90 var delegate_type
= (DelegateType
) f
.variable_type
;
91 if (delegate_type
.delegate_symbol
.has_target
) {
92 // create field to store delegate target
93 instance_struct
.add_field ("gpointer", get_delegate_target_cname (f
.name
));
94 if (delegate_type
.value_owned
) {
95 instance_struct
.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (f
.name
));
102 if (st
.base_struct
== null) {
103 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct _%s".printf (st
.get_cname ()), new
CCodeVariableDeclarator (st
.get_cname ())));
105 decl_space
.add_type_definition (instance_struct
);
107 decl_space
.add_type_declaration (new
CCodeTypeDefinition (st
.base_struct
.get_cname (), new
CCodeVariableDeclarator (st
.get_cname ())));
110 var function
= new
CCodeFunction (st
.get_dup_function (), st
.get_cname () + "*");
111 if (st
.is_private_symbol ()) {
112 function
.modifiers
= CCodeModifiers
.STATIC
;
114 function
.add_parameter (new
CCodeParameter ("self", "const " + st
.get_cname () + "*"));
115 decl_space
.add_function_declaration (function
);
117 function
= new
CCodeFunction (st
.get_free_function (), "void");
118 if (st
.is_private_symbol ()) {
119 function
.modifiers
= CCodeModifiers
.STATIC
;
121 function
.add_parameter (new
CCodeParameter ("self", st
.get_cname () + "*"));
122 decl_space
.add_function_declaration (function
);
124 if (st
.is_disposable ()) {
125 function
= new
CCodeFunction (st
.get_copy_function (), "void");
126 if (st
.is_private_symbol ()) {
127 function
.modifiers
= CCodeModifiers
.STATIC
;
129 function
.add_parameter (new
CCodeParameter ("self", "const " + st
.get_cname () + "*"));
130 function
.add_parameter (new
CCodeParameter ("dest", st
.get_cname () + "*"));
131 decl_space
.add_function_declaration (function
);
133 function
= new
CCodeFunction (st
.get_destroy_function (), "void");
134 if (st
.is_private_symbol ()) {
135 function
.modifiers
= CCodeModifiers
.STATIC
;
137 function
.add_parameter (new
CCodeParameter ("self", st
.get_cname () + "*"));
138 decl_space
.add_function_declaration (function
);
142 public override void visit_struct (Struct st
) {
143 push_context (new
EmitContext (st
));
145 var old_instance_finalize_context
= instance_finalize_context
;
146 instance_finalize_context
= new
EmitContext ();
148 generate_struct_declaration (st
, cfile
);
150 if (!st
.is_internal_symbol ()) {
151 generate_struct_declaration (st
, header_file
);
153 if (!st
.is_private_symbol ()) {
154 generate_struct_declaration (st
, internal_header_file
);
157 if (context
.profile
== Profile
.GOBJECT
&& !st
.is_boolean_type () && !st
.is_integer_type () && !st
.is_floating_type ()) {
158 if (st
.is_disposable ()) {
159 begin_struct_destroy_function (st
);
163 st
.accept_children (this
);
165 if (context
.profile
== Profile
.GOBJECT
&& !st
.is_boolean_type () && !st
.is_integer_type () && !st
.is_floating_type ()) {
166 if (st
.is_disposable ()) {
167 add_struct_copy_function (st
);
168 add_struct_destroy_function (st
);
171 add_struct_dup_function (st
);
172 add_struct_free_function (st
);
175 instance_finalize_context
= old_instance_finalize_context
;
180 void add_struct_dup_function (Struct st
) {
181 var function
= new
CCodeFunction (st
.get_dup_function (), st
.get_cname () + "*");
182 if (st
.access
== SymbolAccessibility
.PRIVATE
) {
183 function
.modifiers
= CCodeModifiers
.STATIC
;
186 function
.add_parameter (new
CCodeParameter ("self", "const " + st
.get_cname () + "*"));
188 var cblock
= new
CCodeBlock ();
190 var cdecl
= new
CCodeDeclaration (st
.get_cname () + "*");
191 cdecl
.add_declarator (new
CCodeVariableDeclarator ("dup"));
192 cblock
.add_statement (cdecl
);
194 var creation_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_new0"));
195 creation_call
.add_argument (new
CCodeConstant (st
.get_cname ()));
196 creation_call
.add_argument (new
CCodeConstant ("1"));
197 cblock
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("dup"), creation_call
)));
199 if (st
.is_disposable ()) {
200 var copy_call
= new
CCodeFunctionCall (new
CCodeIdentifier (st
.get_copy_function ()));
201 copy_call
.add_argument (new
CCodeIdentifier ("self"));
202 copy_call
.add_argument (new
CCodeIdentifier ("dup"));
203 cblock
.add_statement (new
CCodeExpressionStatement (copy_call
));
205 cfile
.add_include ("string.h");
207 var sizeof_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("sizeof"));
208 sizeof_call
.add_argument (new
CCodeConstant (st
.get_cname ()));
210 var copy_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("memcpy"));
211 copy_call
.add_argument (new
CCodeIdentifier ("dup"));
212 copy_call
.add_argument (new
CCodeIdentifier ("self"));
213 copy_call
.add_argument (sizeof_call
);
214 cblock
.add_statement (new
CCodeExpressionStatement (copy_call
));
217 cblock
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("dup")));
219 function
.block
= cblock
;
221 cfile
.add_function (function
);
224 void add_struct_free_function (Struct st
) {
225 var function
= new
CCodeFunction (st
.get_free_function (), "void");
226 if (st
.access
== SymbolAccessibility
.PRIVATE
) {
227 function
.modifiers
= CCodeModifiers
.STATIC
;
230 function
.add_parameter (new
CCodeParameter ("self", st
.get_cname () + "*"));
232 var cblock
= new
CCodeBlock ();
234 if (st
.is_disposable ()) {
235 var destroy_call
= new
CCodeFunctionCall (new
CCodeIdentifier (st
.get_destroy_function ()));
236 destroy_call
.add_argument (new
CCodeIdentifier ("self"));
237 cblock
.add_statement (new
CCodeExpressionStatement (destroy_call
));
240 var free_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_free"));
241 free_call
.add_argument (new
CCodeIdentifier ("self"));
242 cblock
.add_statement (new
CCodeExpressionStatement (free_call
));
244 function
.block
= cblock
;
246 cfile
.add_function (function
);
249 void add_struct_copy_function (Struct st
) {
250 var function
= new
CCodeFunction (st
.get_copy_function (), "void");
251 if (st
.access
== SymbolAccessibility
.PRIVATE
) {
252 function
.modifiers
= CCodeModifiers
.STATIC
;
255 function
.add_parameter (new
CCodeParameter ("self", "const " + st
.get_cname () + "*"));
256 function
.add_parameter (new
CCodeParameter ("dest", st
.get_cname () + "*"));
258 push_function (function
);
260 foreach (var f
in st
.get_fields ()) {
261 if (f
.binding
== MemberBinding
.INSTANCE
) {
262 CCodeExpression copy
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), f
.name
);
263 if (requires_copy (f
.variable_type
)) {
264 var this_access
= new MemberAccess
.simple ("this");
265 this_access
.value_type
= get_data_type_for_symbol ((TypeSymbol
) f
.parent_symbol
);
266 set_cvalue (this_access
, new
CCodeIdentifier ("(*self)"));
267 var ma
= new
MemberAccess (this_access
, f
.name
);
268 ma
.symbol_reference
= f
;
269 ma
.value_type
= f
.variable_type
.copy ();
270 visit_member_access (ma
);
271 copy
= get_ref_cexpression (f
.variable_type
, copy
, ma
, f
);
273 // error case, continue to avoid critical
277 var dest
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("dest"), f
.name
);
279 var array_type
= f
.variable_type as ArrayType
;
280 if (array_type
!= null && array_type
.fixed_length
) {
281 // fixed-length (stack-allocated) arrays
282 cfile
.add_include ("string.h");
284 var sizeof_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("sizeof"));
285 sizeof_call
.add_argument (new
CCodeIdentifier (array_type
.element_type
.get_cname ()));
286 var size
= new
CCodeBinaryExpression (CCodeBinaryOperator
.MUL
, new
CCodeConstant ("%d".printf (array_type
.length
)), sizeof_call
);
288 var array_copy_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("memcpy"));
289 array_copy_call
.add_argument (dest
);
290 array_copy_call
.add_argument (copy
);
291 array_copy_call
.add_argument (size
);
292 ccode
.add_expression (array_copy_call
);
294 ccode
.add_assignment (dest
, copy
);
296 if (array_type
!= null) {
297 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
298 var len_src
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), get_array_length_cname (f
.name
, dim
));
299 var len_dest
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("dest"), get_array_length_cname (f
.name
, dim
));
300 ccode
.add_assignment (len_dest
, len_src
);
309 cfile
.add_function (function
);
312 void begin_struct_destroy_function (Struct st
) {
313 push_context (instance_finalize_context
);
315 var function
= new
CCodeFunction (st
.get_destroy_function (), "void");
316 if (st
.access
== SymbolAccessibility
.PRIVATE
) {
317 function
.modifiers
= CCodeModifiers
.STATIC
;
320 function
.add_parameter (new
CCodeParameter ("self", st
.get_cname () + "*"));
322 push_function (function
);
327 void add_struct_destroy_function (Struct st
) {
328 cfile
.add_function (instance_finalize_context
.ccode
);