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 class Vala
.CCodeStructModule
: CCodeBaseModule
{
28 public override void generate_struct_declaration (Struct st
, CCodeDeclarationSpace decl_space
) {
29 if (decl_space
.add_symbol_declaration (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);
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
CCodeFormalParameter ("self", "const " + st
.get_cname () + "*"));
115 decl_space
.add_type_member_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
CCodeFormalParameter ("self", st
.get_cname () + "*"));
122 decl_space
.add_type_member_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
CCodeFormalParameter ("self", "const " + st
.get_cname () + "*"));
130 function
.add_parameter (new
CCodeFormalParameter ("dest", st
.get_cname () + "*"));
131 decl_space
.add_type_member_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
CCodeFormalParameter ("self", st
.get_cname () + "*"));
138 decl_space
.add_type_member_declaration (function
);
142 public override void visit_struct (Struct st
) {
143 push_context (new
EmitContext (st
));
145 var old_instance_finalize_fragment
= instance_finalize_fragment
;
146 instance_finalize_fragment
= new
CCodeFragment ();
148 generate_struct_declaration (st
, source_declarations
);
150 if (!st
.is_internal_symbol ()) {
151 generate_struct_declaration (st
, header_declarations
);
153 if (!st
.is_private_symbol ()) {
154 generate_struct_declaration (st
, internal_header_declarations
);
157 st
.accept_children (this
);
159 if (context
.profile
== Profile
.GOBJECT
&& !st
.is_boolean_type () && !st
.is_integer_type () && !st
.is_floating_type ()) {
160 if (st
.is_disposable ()) {
161 add_struct_copy_function (st
);
162 add_struct_destroy_function (st
);
165 add_struct_dup_function (st
);
166 add_struct_free_function (st
);
169 instance_finalize_fragment
= old_instance_finalize_fragment
;
174 void add_struct_dup_function (Struct st
) {
175 var function
= new
CCodeFunction (st
.get_dup_function (), st
.get_cname () + "*");
176 if (st
.access
== SymbolAccessibility
.PRIVATE
) {
177 function
.modifiers
= CCodeModifiers
.STATIC
;
180 function
.add_parameter (new
CCodeFormalParameter ("self", "const " + st
.get_cname () + "*"));
182 var cblock
= new
CCodeBlock ();
184 var cdecl
= new
CCodeDeclaration (st
.get_cname () + "*");
185 cdecl
.add_declarator (new
CCodeVariableDeclarator ("dup"));
186 cblock
.add_statement (cdecl
);
188 var creation_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_new0"));
189 creation_call
.add_argument (new
CCodeConstant (st
.get_cname ()));
190 creation_call
.add_argument (new
CCodeConstant ("1"));
191 cblock
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("dup"), creation_call
)));
193 if (st
.is_disposable ()) {
194 var copy_call
= new
CCodeFunctionCall (new
CCodeIdentifier (st
.get_copy_function ()));
195 copy_call
.add_argument (new
CCodeIdentifier ("self"));
196 copy_call
.add_argument (new
CCodeIdentifier ("dup"));
197 cblock
.add_statement (new
CCodeExpressionStatement (copy_call
));
199 source_declarations
.add_include ("string.h");
201 var sizeof_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("sizeof"));
202 sizeof_call
.add_argument (new
CCodeConstant (st
.get_cname ()));
204 var copy_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("memcpy"));
205 copy_call
.add_argument (new
CCodeIdentifier ("dup"));
206 copy_call
.add_argument (new
CCodeIdentifier ("self"));
207 copy_call
.add_argument (sizeof_call
);
208 cblock
.add_statement (new
CCodeExpressionStatement (copy_call
));
211 cblock
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("dup")));
213 function
.block
= cblock
;
215 source_type_member_definition
.append (function
);
218 void add_struct_free_function (Struct st
) {
219 var function
= new
CCodeFunction (st
.get_free_function (), "void");
220 if (st
.access
== SymbolAccessibility
.PRIVATE
) {
221 function
.modifiers
= CCodeModifiers
.STATIC
;
224 function
.add_parameter (new
CCodeFormalParameter ("self", st
.get_cname () + "*"));
226 var cblock
= new
CCodeBlock ();
228 if (st
.is_disposable ()) {
229 var destroy_call
= new
CCodeFunctionCall (new
CCodeIdentifier (st
.get_destroy_function ()));
230 destroy_call
.add_argument (new
CCodeIdentifier ("self"));
231 cblock
.add_statement (new
CCodeExpressionStatement (destroy_call
));
234 var free_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_free"));
235 free_call
.add_argument (new
CCodeIdentifier ("self"));
236 cblock
.add_statement (new
CCodeExpressionStatement (free_call
));
238 function
.block
= cblock
;
240 source_type_member_definition
.append (function
);
243 void add_struct_copy_function (Struct st
) {
244 var function
= new
CCodeFunction (st
.get_copy_function (), "void");
245 if (st
.access
== SymbolAccessibility
.PRIVATE
) {
246 function
.modifiers
= CCodeModifiers
.STATIC
;
249 function
.add_parameter (new
CCodeFormalParameter ("self", "const " + st
.get_cname () + "*"));
250 function
.add_parameter (new
CCodeFormalParameter ("dest", st
.get_cname () + "*"));
252 var cblock
= new
CCodeBlock ();
253 var cfrag
= new
CCodeFragment ();
254 cblock
.add_statement (cfrag
);
256 foreach (var f
in st
.get_fields ()) {
257 if (f
.binding
== MemberBinding
.INSTANCE
) {
258 CCodeExpression copy
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), f
.name
);
259 if (requires_copy (f
.variable_type
)) {
260 var this_access
= new MemberAccess
.simple ("this");
261 this_access
.value_type
= get_data_type_for_symbol ((TypeSymbol
) f
.parent_symbol
);
262 this_access
.ccodenode
= new
CCodeIdentifier ("(*self)");
263 var ma
= new
MemberAccess (this_access
, f
.name
);
264 ma
.symbol_reference
= f
;
265 copy
= get_ref_cexpression (f
.variable_type
, copy
, ma
, f
);
267 var dest
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("dest"), f
.name
);
269 var array_type
= f
.variable_type as ArrayType
;
270 if (array_type
!= null && array_type
.fixed_length
) {
271 // fixed-length (stack-allocated) arrays
272 source_declarations
.add_include ("string.h");
274 var sizeof_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("sizeof"));
275 sizeof_call
.add_argument (new
CCodeIdentifier (array_type
.element_type
.get_cname ()));
276 var size
= new
CCodeBinaryExpression (CCodeBinaryOperator
.MUL
, new
CCodeConstant ("%d".printf (array_type
.length
)), sizeof_call
);
278 var array_copy_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("memcpy"));
279 array_copy_call
.add_argument (dest
);
280 array_copy_call
.add_argument (copy
);
281 array_copy_call
.add_argument (size
);
282 cblock
.add_statement (new
CCodeExpressionStatement (array_copy_call
));
284 cblock
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (dest
, copy
)));
286 if (array_type
!= null) {
287 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
288 var len_src
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), get_array_length_cname (f
.name
, dim
));
289 var len_dest
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("dest"), get_array_length_cname (f
.name
, dim
));
290 cblock
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (len_dest
, len_src
)));
297 append_temp_decl (cfrag
, temp_vars
);
300 function
.block
= cblock
;
302 source_type_member_definition
.append (function
);
305 void add_struct_destroy_function (Struct st
) {
306 var function
= new
CCodeFunction (st
.get_destroy_function (), "void");
307 if (st
.access
== SymbolAccessibility
.PRIVATE
) {
308 function
.modifiers
= CCodeModifiers
.STATIC
;
311 function
.add_parameter (new
CCodeFormalParameter ("self", st
.get_cname () + "*"));
313 var cblock
= new
CCodeBlock ();
315 cblock
.add_statement (instance_finalize_fragment
);
317 function
.block
= cblock
;
319 source_type_member_definition
.append (function
);