1
by Sebastien Bacher
Import upstream version 0.15.0 |
1 |
/* valaccodestructmodule.vala
|
2 |
*
|
|
3 |
* Copyright (C) 2006-2009 Jürg Billeter
|
|
4 |
* Copyright (C) 2006-2008 Raffaele Sandrini
|
|
5 |
*
|
|
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.
|
|
10 |
||
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.
|
|
15 |
||
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
|
|
19 |
*
|
|
20 |
* Author:
|
|
21 |
* Jürg Billeter <j@bitron.ch>
|
|
22 |
* Raffaele Sandrini <raffaele@sandrini.ch>
|
|
23 |
*/
|
|
24 |
||
25 |
using GLib; |
|
26 |
||
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; |
|
31 |
}
|
|
32 |
||
33 |
if (st.is_boolean_type ()) { |
|
34 |
// typedef for boolean types
|
|
35 |
decl_space.add_include ("stdbool.h"); |
|
36 |
return; |
|
37 |
} else if (st.is_integer_type ()) { |
|
38 |
// typedef for integral types
|
|
39 |
decl_space.add_include ("stdint.h"); |
|
40 |
return; |
|
41 |
}
|
|
42 |
||
43 |
if (context.profile == Profile.GOBJECT) { |
|
44 |
if (get_ccode_has_type_id (st)) { |
|
45 |
decl_space.add_type_declaration (new CCodeNewline ()); |
|
46 |
var macro = "(%s_get_type ())".printf (get_ccode_lower_case_name (st, null)); |
|
47 |
decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (st), macro)); |
|
48 |
||
49 |
var type_fun = new StructRegisterFunction (st, context); |
|
50 |
type_fun.init_from_type (false, true); |
|
51 |
decl_space.add_type_member_declaration (type_fun.get_declaration ()); |
|
52 |
}
|
|
53 |
}
|
|
54 |
||
55 |
var instance_struct = new CCodeStruct ("_%s".printf (get_ccode_name (st))); |
|
56 |
instance_struct.deprecated = st.deprecated; |
|
57 |
||
58 |
foreach (Field f in st.get_fields ()) { |
|
59 |
string field_ctype = get_ccode_name (f.variable_type); |
|
60 |
if (f.is_volatile) { |
|
61 |
field_ctype = "volatile " + field_ctype; |
|
62 |
}
|
|
63 |
||
64 |
if (f.binding == MemberBinding.INSTANCE) { |
|
65 |
generate_type_declaration (f.variable_type, decl_space); |
|
66 |
||
67 |
instance_struct.add_field (field_ctype, get_ccode_name (f) + get_ccode_declarator_suffix (f.variable_type), f.deprecated ? " G_GNUC_DEPRECATED" : null); |
|
68 |
if (f.variable_type is ArrayType && get_ccode_array_length (f)) { |
|
69 |
// create fields to store array dimensions
|
|
70 |
var array_type = (ArrayType) f.variable_type; |
|
71 |
||
72 |
if (!array_type.fixed_length) { |
|
73 |
var len_type = int_type.copy (); |
|
74 |
||
75 |
for (int dim = 1; dim <= array_type.rank; dim++) { |
|
76 |
string length_cname; |
|
77 |
if (get_ccode_array_length_name (f) != null) { |
|
78 |
length_cname = get_ccode_array_length_name (f); |
|
79 |
} else { |
|
80 |
length_cname = get_array_length_cname (f.name, dim); |
|
81 |
}
|
|
82 |
instance_struct.add_field (get_ccode_name (len_type), length_cname); |
|
83 |
}
|
|
84 |
||
85 |
if (array_type.rank == 1 && f.is_internal_symbol ()) { |
|
86 |
instance_struct.add_field (get_ccode_name (len_type), get_array_size_cname (f.name)); |
|
87 |
}
|
|
88 |
}
|
|
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)); |
|
96 |
}
|
|
97 |
}
|
|
98 |
}
|
|
99 |
}
|
|
100 |
}
|
|
101 |
||
102 |
if (st.base_struct == null) { |
|
103 |
decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (st)), new CCodeVariableDeclarator (get_ccode_name (st)))); |
|
104 |
||
105 |
decl_space.add_type_definition (instance_struct); |
|
106 |
} else { |
|
107 |
decl_space.add_type_declaration (new CCodeTypeDefinition (get_ccode_name (st.base_struct), new CCodeVariableDeclarator (get_ccode_name (st)))); |
|
108 |
}
|
|
109 |
||
110 |
var function = new CCodeFunction (get_ccode_dup_function (st), get_ccode_name (st) + "*"); |
|
111 |
if (st.is_private_symbol ()) { |
|
112 |
function.modifiers = CCodeModifiers.STATIC; |
|
113 |
}
|
|
114 |
function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*")); |
|
115 |
decl_space.add_function_declaration (function); |
|
116 |
||
117 |
function = new CCodeFunction (get_ccode_free_function (st), "void"); |
|
118 |
if (st.is_private_symbol ()) { |
|
119 |
function.modifiers = CCodeModifiers.STATIC; |
|
120 |
}
|
|
121 |
function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*")); |
|
122 |
decl_space.add_function_declaration (function); |
|
123 |
||
124 |
if (st.is_disposable ()) { |
|
125 |
function = new CCodeFunction (get_ccode_copy_function (st), "void"); |
|
126 |
if (st.is_private_symbol ()) { |
|
127 |
function.modifiers = CCodeModifiers.STATIC; |
|
128 |
}
|
|
129 |
function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*")); |
|
130 |
function.add_parameter (new CCodeParameter ("dest", get_ccode_name (st) + "*")); |
|
131 |
decl_space.add_function_declaration (function); |
|
132 |
||
133 |
function = new CCodeFunction (get_ccode_destroy_function (st), "void"); |
|
134 |
if (st.is_private_symbol ()) { |
|
135 |
function.modifiers = CCodeModifiers.STATIC; |
|
136 |
}
|
|
137 |
function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*")); |
|
138 |
decl_space.add_function_declaration (function); |
|
139 |
}
|
|
140 |
}
|
|
141 |
||
142 |
public override void visit_struct (Struct st) { |
|
143 |
push_context (new EmitContext (st)); |
|
144 |
push_line (st.source_reference); |
|
145 |
||
146 |
var old_instance_finalize_context = instance_finalize_context; |
|
147 |
instance_finalize_context = new EmitContext (); |
|
148 |
||
149 |
generate_struct_declaration (st, cfile); |
|
150 |
||
151 |
if (!st.is_internal_symbol ()) { |
|
152 |
generate_struct_declaration (st, header_file); |
|
153 |
}
|
|
154 |
if (!st.is_private_symbol ()) { |
|
155 |
generate_struct_declaration (st, internal_header_file); |
|
156 |
}
|
|
157 |
||
1.1.1
by Sebastien Bacher
Import upstream version 0.15.1 |
158 |
if (!st.is_boolean_type () && !st.is_integer_type () && !st.is_floating_type ()) { |
1
by Sebastien Bacher
Import upstream version 0.15.0 |
159 |
if (st.is_disposable ()) { |
160 |
begin_struct_destroy_function (st); |
|
161 |
}
|
|
162 |
}
|
|
163 |
||
164 |
st.accept_children (this); |
|
165 |
||
1.1.1
by Sebastien Bacher
Import upstream version 0.15.1 |
166 |
if (!st.is_boolean_type () && !st.is_integer_type () && !st.is_floating_type ()) { |
1
by Sebastien Bacher
Import upstream version 0.15.0 |
167 |
if (st.is_disposable ()) { |
168 |
add_struct_copy_function (st); |
|
169 |
add_struct_destroy_function (st); |
|
170 |
}
|
|
171 |
||
172 |
add_struct_dup_function (st); |
|
173 |
add_struct_free_function (st); |
|
174 |
}
|
|
175 |
||
176 |
instance_finalize_context = old_instance_finalize_context; |
|
177 |
||
178 |
pop_line (); |
|
179 |
pop_context (); |
|
180 |
}
|
|
181 |
||
182 |
void add_struct_dup_function (Struct st) { |
|
183 |
var function = new CCodeFunction (get_ccode_dup_function (st), get_ccode_name (st) + "*"); |
|
184 |
if (st.access == SymbolAccessibility.PRIVATE) { |
|
185 |
function.modifiers = CCodeModifiers.STATIC; |
|
186 |
}
|
|
187 |
||
188 |
function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*")); |
|
189 |
||
190 |
push_function (function); |
|
191 |
||
192 |
ccode.add_declaration (get_ccode_name (st) + "*", new CCodeVariableDeclarator ("dup")); |
|
193 |
||
1.1.1
by Sebastien Bacher
Import upstream version 0.15.1 |
194 |
if (context.profile == Profile.GOBJECT) { |
195 |
var creation_call = new CCodeFunctionCall (new CCodeIdentifier ("g_new0")); |
|
196 |
creation_call.add_argument (new CCodeConstant (get_ccode_name (st))); |
|
197 |
creation_call.add_argument (new CCodeConstant ("1")); |
|
198 |
ccode.add_assignment (new CCodeIdentifier ("dup"), creation_call); |
|
199 |
} else if (context.profile == Profile.POSIX) { |
|
200 |
var creation_call = new CCodeFunctionCall (new CCodeIdentifier ("calloc")); |
|
201 |
creation_call.add_argument (new CCodeConstant ("1")); |
|
202 |
creation_call.add_argument (new CCodeIdentifier ("sizeof (%s*)".printf (get_ccode_name (st)))); |
|
203 |
ccode.add_assignment (new CCodeIdentifier ("dup"), creation_call); |
|
204 |
}
|
|
1
by Sebastien Bacher
Import upstream version 0.15.0 |
205 |
|
206 |
if (st.is_disposable ()) { |
|
207 |
var copy_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_copy_function (st))); |
|
208 |
copy_call.add_argument (new CCodeIdentifier ("self")); |
|
209 |
copy_call.add_argument (new CCodeIdentifier ("dup")); |
|
210 |
ccode.add_expression (copy_call); |
|
211 |
} else { |
|
212 |
cfile.add_include ("string.h"); |
|
213 |
||
214 |
var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); |
|
215 |
sizeof_call.add_argument (new CCodeConstant (get_ccode_name (st))); |
|
216 |
||
217 |
var copy_call = new CCodeFunctionCall (new CCodeIdentifier ("memcpy")); |
|
218 |
copy_call.add_argument (new CCodeIdentifier ("dup")); |
|
219 |
copy_call.add_argument (new CCodeIdentifier ("self")); |
|
220 |
copy_call.add_argument (sizeof_call); |
|
221 |
ccode.add_expression (copy_call); |
|
222 |
}
|
|
223 |
||
224 |
ccode.add_return (new CCodeIdentifier ("dup")); |
|
225 |
||
226 |
pop_function (); |
|
227 |
||
228 |
cfile.add_function (function); |
|
229 |
}
|
|
230 |
||
231 |
void add_struct_free_function (Struct st) { |
|
232 |
var function = new CCodeFunction (get_ccode_free_function (st), "void"); |
|
233 |
if (st.access == SymbolAccessibility.PRIVATE) { |
|
234 |
function.modifiers = CCodeModifiers.STATIC; |
|
235 |
}
|
|
236 |
||
237 |
function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*")); |
|
238 |
||
239 |
push_function (function); |
|
240 |
||
241 |
if (st.is_disposable ()) { |
|
242 |
var destroy_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_destroy_function (st))); |
|
243 |
destroy_call.add_argument (new CCodeIdentifier ("self")); |
|
244 |
ccode.add_expression (destroy_call); |
|
245 |
}
|
|
246 |
||
1.1.1
by Sebastien Bacher
Import upstream version 0.15.1 |
247 |
if (context.profile == Profile.GOBJECT) { |
248 |
var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free")); |
|
249 |
free_call.add_argument (new CCodeIdentifier ("self")); |
|
250 |
ccode.add_expression (free_call); |
|
251 |
} else if (context.profile == Profile.POSIX) { |
|
252 |
var free_call = new CCodeFunctionCall (new CCodeIdentifier ("free")); |
|
253 |
free_call.add_argument (new CCodeIdentifier ("self")); |
|
254 |
ccode.add_expression (free_call); |
|
255 |
}
|
|
1
by Sebastien Bacher
Import upstream version 0.15.0 |
256 |
|
257 |
pop_function (); |
|
258 |
||
259 |
cfile.add_function (function); |
|
260 |
}
|
|
261 |
||
262 |
void add_struct_copy_function (Struct st) { |
|
263 |
var function = new CCodeFunction (get_ccode_copy_function (st), "void"); |
|
264 |
if (st.access == SymbolAccessibility.PRIVATE) { |
|
265 |
function.modifiers = CCodeModifiers.STATIC; |
|
266 |
}
|
|
267 |
||
268 |
function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*")); |
|
269 |
function.add_parameter (new CCodeParameter ("dest", get_ccode_name (st) + "*")); |
|
270 |
||
271 |
push_function (function); |
|
272 |
||
273 |
var dest_struct = new GLibValue (get_data_type_for_symbol (st), new CCodeIdentifier ("(*dest)"), true); |
|
274 |
foreach (var f in st.get_fields ()) { |
|
275 |
if (f.binding == MemberBinding.INSTANCE) { |
|
276 |
var value = load_field (f, load_this_parameter ((TypeSymbol) st)); |
|
277 |
if (requires_copy (f.variable_type)) { |
|
278 |
value = copy_value (value, f); |
|
279 |
if (value == null) { |
|
280 |
// error case, continue to avoid critical
|
|
281 |
continue; |
|
282 |
}
|
|
283 |
}
|
|
284 |
store_field (f, dest_struct, value); |
|
285 |
}
|
|
286 |
}
|
|
287 |
||
288 |
pop_function (); |
|
289 |
||
290 |
cfile.add_function (function); |
|
291 |
}
|
|
292 |
||
293 |
void begin_struct_destroy_function (Struct st) { |
|
294 |
push_context (instance_finalize_context); |
|
295 |
||
296 |
var function = new CCodeFunction (get_ccode_destroy_function (st), "void"); |
|
297 |
if (st.access == SymbolAccessibility.PRIVATE) { |
|
298 |
function.modifiers = CCodeModifiers.STATIC; |
|
299 |
}
|
|
300 |
||
301 |
function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*")); |
|
302 |
||
303 |
push_function (function); |
|
304 |
||
305 |
pop_context (); |
|
306 |
}
|
|
307 |
||
308 |
void add_struct_destroy_function (Struct st) { |
|
309 |
cfile.add_function (instance_finalize_context.ccode); |
|
310 |
}
|
|
311 |
}
|
|
312 |