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 (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
++) {
84 if (get_ccode_array_length_name (f
) != null) {
85 length_cname
= get_ccode_array_length_name (f
);
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
);
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) {
163 Report
.error (st
.source_reference
, "Name `%s' is too short for struct using GType".printf (get_ccode_name (st
)));
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
;
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
);
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"));
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
);
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
);
292 // error case, continue to avoid critical
296 store_field (f
, dest_struct
, value
);
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
);
322 void add_struct_destroy_function (Struct st
) {
323 cfile
.add_function (instance_finalize_context
.ccode
);