~ubuntu-branches/ubuntu/raring/vala-0.16/raring

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