Line data Source code
1 : /* valaccodearraymodule.vala
2 : *
3 : * Copyright (C) 2006-2010 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 :
26 4395 : public class Vala.CCodeArrayModule : CCodeMethodCallModule {
27 1465 : int next_array_dup_id = 0;
28 1465 : int next_array_add_id = 0;
29 :
30 656 : void append_initializer_list (CCodeExpression name_cnode, InitializerList initializer_list, int rank, ref int i) {
31 3856 : foreach (Expression e in initializer_list.get_initializers ()) {
32 1600 : if (rank > 1) {
33 50 : append_initializer_list (name_cnode, (InitializerList) e, rank - 1, ref i);
34 : } else {
35 1550 : ccode.add_assignment (new CCodeElementAccess (name_cnode, new CCodeConstant (i.to_string ())), get_cvalue (e));
36 1550 : i++;
37 : }
38 : }
39 : }
40 :
41 1390 : public override void visit_array_creation_expression (ArrayCreationExpression expr) {
42 12748 : var array_type = expr.target_type as ArrayType;
43 686 : if (array_type != null && array_type.fixed_length) {
44 : // no heap allocation for fixed-length arrays
45 :
46 27 : var temp_var = get_temp_variable (array_type, true, expr);
47 27 : temp_var.init = true;
48 27 : var name_cnode = get_variable_cexpression (temp_var.name);
49 27 : int i = 0;
50 :
51 27 : emit_temp_var (temp_var);
52 :
53 27 : append_initializer_list (name_cnode, expr.initializer_list, expr.rank, ref i);
54 :
55 27 : set_cvalue (expr, name_cnode);
56 :
57 27 : return;
58 : }
59 :
60 : CCodeFunctionCall gnew;
61 668 : if (context.profile == Profile.POSIX) {
62 27 : cfile.add_include ("stdlib.h");
63 27 : gnew = new CCodeFunctionCall (new CCodeIdentifier ("calloc"));
64 : } else {
65 641 : gnew = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
66 641 : gnew.add_argument (new CCodeIdentifier (get_ccode_name (expr.element_type)));
67 : }
68 :
69 668 : bool first = true;
70 668 : CCodeExpression cexpr = null;
71 :
72 : // iterate over each dimension
73 2046 : foreach (Expression size in expr.get_sizes ()) {
74 7216 : CCodeExpression csize = get_cvalue (size);
75 689 : append_array_length (expr, csize);
76 :
77 689 : if (first) {
78 1336 : cexpr = csize;
79 : first = false;
80 : } else {
81 21 : cexpr = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, cexpr, csize);
82 : }
83 : }
84 :
85 : // add extra item to have array NULL-terminated for all reference types
86 668 : if (expr.element_type.type_symbol != null && expr.element_type.type_symbol.is_reference_type ()) {
87 472 : cexpr = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, cexpr, new CCodeConstant ("1"));
88 : }
89 :
90 668 : gnew.add_argument (cexpr);
91 :
92 695 : if (context.profile == Profile.POSIX) {
93 27 : var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
94 27 : csizeof.add_argument (new CCodeIdentifier (get_ccode_name (expr.element_type)));
95 27 : gnew.add_argument (csizeof);
96 : }
97 :
98 668 : var temp_var = get_temp_variable (expr.value_type, true, expr);
99 668 : var name_cnode = get_variable_cexpression (temp_var.name);
100 668 : int i = 0;
101 :
102 668 : emit_temp_var (temp_var);
103 :
104 668 : ccode.add_assignment (name_cnode, gnew);
105 :
106 668 : if (expr.initializer_list != null) {
107 579 : append_initializer_list (name_cnode, expr.initializer_list, expr.rank, ref i);
108 : }
109 :
110 668 : set_cvalue (expr, name_cnode);
111 : }
112 :
113 10237 : public override string get_array_length_cname (string array_cname, int dim) {
114 10237 : return "%s_length%d".printf (array_cname, dim);
115 : }
116 :
117 2058 : public override string get_variable_array_length_cname (Variable variable, int dim) {
118 2058 : string? length_cname = get_ccode_array_length_name (variable);
119 2058 : if (length_cname == null) {
120 2026 : length_cname = get_array_length_cname (get_ccode_name (variable), dim);
121 : }
122 4116 : return (!) length_cname;
123 : }
124 :
125 1438 : public override CCodeExpression get_array_length_cexpression (Expression array_expr, int dim = -1) {
126 1438 : return get_array_length_cvalue (array_expr.target_value, dim);
127 : }
128 :
129 8278 : public override CCodeExpression get_array_length_cvalue (TargetValue value, int dim = -1) {
130 8278 : var array_type = value.value_type as ArrayType;
131 :
132 8278 : if (array_type != null && array_type.fixed_length) {
133 34 : return get_ccodenode (array_type.length);
134 : }
135 :
136 : // dim == -1 => total size over all dimensions
137 8244 : if (dim == -1) {
138 1211 : if (array_type != null && array_type.rank > 1) {
139 18 : CCodeExpression cexpr = get_array_length_cvalue (value, 1);
140 47 : for (dim = 2; dim <= array_type.rank; dim++) {
141 29 : cexpr = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, cexpr, get_array_length_cvalue (value, dim));
142 : }
143 18 : return cexpr;
144 : } else {
145 : dim = 1;
146 : }
147 : }
148 :
149 9588 : List<CCodeExpression> size = ((GLibValue) value).array_length_cvalues;
150 8226 : if (size == null || size.size < dim) {
151 0 : Report.error (array_type.source_reference, "internal: invalid array_length for given dimension");
152 0 : return new CCodeInvalidExpression ();
153 : }
154 8226 : return size[dim - 1];
155 : }
156 :
157 5354 : public override string get_array_size_cname (string array_cname) {
158 5354 : return "_%s_size_".printf (array_cname);
159 : }
160 :
161 2724 : public override void visit_element_access (ElementAccess expr) {
162 1362 : List<Expression> indices = expr.get_indices ();
163 1362 : int rank = indices.size;
164 :
165 1362 : var ccontainer = get_cvalue (expr.container);
166 2724 : var cindex = get_cvalue (indices[0]);
167 1411 : if (expr.container.symbol_reference is ArrayLengthField) {
168 : /* Figure if cindex is a constant expression and calculate dim...*/
169 49 : var lit = indices[0] as IntegerLiteral;
170 49 : var memberaccess = expr.container as MemberAccess;
171 49 : if (lit != null && memberaccess != null) {
172 49 : int dim = int.parse (lit.value);
173 49 : set_cvalue (expr, get_array_length_cexpression (memberaccess.inner, dim + 1));
174 : } else {
175 0 : Report.error (expr.source_reference, "internal error: only integer literals supported as index");
176 : }
177 1329 : } else if (expr.container.symbol_reference is Constant && rank > 1) {
178 : // access to element in a multi-dimensional array constant
179 16 : var cindices = new ArrayList<CCodeExpression> ();
180 16 : cindices.add (cindex);
181 32 : for (int i = 1; i < rank; i++) {
182 16 : cindices.add (get_cvalue (indices[i]));
183 : }
184 16 : set_cvalue (expr, new CCodeElementAccess.with_indices (ccontainer, cindices));
185 : } else {
186 : // access to element in an array
187 1399 : for (int i = 1; i < rank; i++) {
188 51 : var cmul = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, cindex, get_array_length_cexpression (expr.container, i + 1));
189 51 : cindex = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, cmul, get_cvalue (indices[i]));
190 51 : if (expr.container.is_constant ()) {
191 0 : ccontainer = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, ccontainer);
192 : }
193 : }
194 1297 : set_cvalue (expr, new CCodeElementAccess (ccontainer, cindex));
195 : }
196 :
197 1362 : expr.target_value.value_type = expr.value_type.copy ();
198 1362 : if (!expr.lvalue) {
199 1262 : expr.target_value = store_temp_value (expr.target_value, expr);
200 : }
201 1362 : ((GLibValue) expr.target_value).lvalue = true;
202 : }
203 :
204 52 : public override void visit_slice_expression (SliceExpression expr) {
205 26 : var ccontainer = get_cvalue (expr.container);
206 26 : var cstart = get_cvalue (expr.start);
207 26 : var cstop = get_cvalue (expr.stop);
208 :
209 26 : var cstartpointer = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, ccontainer, cstart);
210 26 : var splicelen = new CCodeBinaryExpression (CCodeBinaryOperator.MINUS, cstop, cstart);
211 :
212 26 : set_cvalue (expr, cstartpointer);
213 26 : ((GLibValue) expr.target_value).non_null = get_non_null (expr.container.target_value);
214 : // Make sure no previous length values are preserved
215 26 : set_array_length (expr, splicelen);
216 : }
217 :
218 18 : void append_struct_array_free_loop (Struct st) {
219 9 : var cforinit = new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0"));
220 9 : var cforcond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeIdentifier ("array_length"));
221 9 : var cforiter = new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("i"), new CCodeConstant ("1")));
222 9 : ccode.open_for (cforinit, cforcond, cforiter);
223 :
224 9 : var cptrarray = new CCodeIdentifier ("array");
225 9 : var cea = new CCodeElementAccess (cptrarray, new CCodeIdentifier ("i"));
226 :
227 9 : var cfreecall = new CCodeFunctionCall (get_destroy_func_expression (new StructValueType (st)));
228 9 : cfreecall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cea));
229 9 : ccode.add_expression (cfreecall);
230 :
231 9 : ccode.close ();
232 : }
233 :
234 14 : public override string? append_struct_array_free (Struct st) {
235 14 : string cname = "_vala_%s_array_free".printf (get_ccode_name (st));
236 :
237 14 : if (cfile.add_declaration (cname)) {
238 14 : return cname;
239 : }
240 :
241 7 : generate_type_declaration (ssize_t_type, cfile);
242 :
243 7 : var fun = new CCodeFunction (cname, "void");
244 7 : fun.modifiers = CCodeModifiers.STATIC;
245 7 : fun.add_parameter (new CCodeParameter ("array", "%s *".printf (get_ccode_name (st))));
246 7 : fun.add_parameter (new CCodeParameter ("array_length", get_ccode_name (ssize_t_type)));
247 :
248 7 : push_function (fun);
249 :
250 7 : var ccondarr = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("array"), new CCodeConstant ("NULL"));
251 7 : ccode.open_if (ccondarr);
252 :
253 7 : ccode.add_declaration (get_ccode_name (ssize_t_type), new CCodeVariableDeclarator ("i"));
254 7 : append_struct_array_free_loop (st);
255 :
256 7 : ccode.close ();
257 :
258 : CCodeFunctionCall carrfree;
259 7 : if (context.profile == Profile.POSIX) {
260 1 : cfile.add_include ("stdlib.h");
261 1 : carrfree = new CCodeFunctionCall (new CCodeIdentifier ("free"));
262 : } else {
263 6 : carrfree = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
264 : }
265 7 : carrfree.add_argument (new CCodeIdentifier ("array"));
266 7 : ccode.add_expression (carrfree);
267 :
268 7 : pop_function ();
269 :
270 7 : cfile.add_function_declaration (fun);
271 7 : cfile.add_function (fun);
272 :
273 7 : return cname;
274 : }
275 :
276 2 : public override string? append_struct_array_destroy (Struct st) {
277 2 : string cname = "_vala_%s_array_destroy".printf (get_ccode_name (st));
278 :
279 2 : if (cfile.add_declaration (cname)) {
280 2 : return cname;
281 : }
282 :
283 2 : generate_type_declaration (ssize_t_type, cfile);
284 :
285 2 : var fun = new CCodeFunction (cname, "void");
286 2 : fun.modifiers = CCodeModifiers.STATIC;
287 2 : fun.add_parameter (new CCodeParameter ("array", "%s *".printf (get_ccode_name (st))));
288 2 : fun.add_parameter (new CCodeParameter ("array_length", get_ccode_name (ssize_t_type)));
289 :
290 2 : push_function (fun);
291 :
292 2 : var ccondarr = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("array"), new CCodeConstant ("NULL"));
293 2 : ccode.open_if (ccondarr);
294 :
295 2 : ccode.add_declaration (get_ccode_name (ssize_t_type), new CCodeVariableDeclarator ("i"));
296 2 : append_struct_array_free_loop (st);
297 :
298 2 : ccode.close ();
299 :
300 2 : pop_function ();
301 :
302 2 : cfile.add_function_declaration (fun);
303 2 : cfile.add_function (fun);
304 :
305 2 : return cname;
306 : }
307 :
308 292 : void append_vala_array_free_loop () {
309 146 : var cforinit = new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0"));
310 146 : var cforcond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeIdentifier ("array_length"));
311 146 : var cforiter = new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("i"), new CCodeConstant ("1")));
312 146 : ccode.open_for (cforinit, cforcond, cforiter);
313 :
314 146 : var cptrarray = new CCodeCastExpression (new CCodeIdentifier ("array"), "%s*".printf (get_ccode_name (pointer_type)));
315 146 : var cea = new CCodeElementAccess (cptrarray, new CCodeIdentifier ("i"));
316 :
317 146 : var cfreecond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, cea, new CCodeConstant ("NULL"));
318 146 : ccode.open_if (cfreecond);
319 :
320 146 : var cfreecall = new CCodeFunctionCall (new CCodeIdentifier ("destroy_func"));
321 146 : cfreecall.add_argument (cea);
322 146 : ccode.add_expression (cfreecall);
323 :
324 146 : ccode.close ();
325 : }
326 :
327 146 : public override void append_vala_array_free () {
328 : // _vala_array_destroy only frees elements but not the array itself
329 146 : generate_type_declaration (delegate_target_destroy_type, cfile);
330 146 : generate_type_declaration (ssize_t_type, cfile);
331 :
332 146 : var fun = new CCodeFunction ("_vala_array_destroy", "void");
333 146 : fun.modifiers = CCodeModifiers.STATIC;
334 146 : fun.add_parameter (new CCodeParameter ("array", get_ccode_name (pointer_type)));
335 146 : fun.add_parameter (new CCodeParameter ("array_length", get_ccode_name (ssize_t_type)));
336 146 : fun.add_parameter (new CCodeParameter ("destroy_func", get_ccode_name (delegate_target_destroy_type)));
337 :
338 146 : push_function (fun);
339 :
340 146 : var ccondarr = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("array"), new CCodeConstant ("NULL"));
341 146 : var ccondfunc = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("destroy_func"), new CCodeConstant ("NULL"));
342 146 : ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccondarr, ccondfunc));
343 :
344 146 : ccode.add_declaration (get_ccode_name (ssize_t_type), new CCodeVariableDeclarator ("i"));
345 146 : append_vala_array_free_loop ();
346 :
347 146 : ccode.close ();
348 :
349 146 : pop_function ();
350 :
351 146 : cfile.add_function_declaration (fun);
352 146 : cfile.add_function (fun);
353 :
354 : // _vala_array_free frees elements and array
355 :
356 146 : fun = new CCodeFunction ("_vala_array_free", "void");
357 146 : fun.modifiers = CCodeModifiers.STATIC;
358 146 : fun.add_parameter (new CCodeParameter ("array", get_ccode_name (pointer_type)));
359 146 : fun.add_parameter (new CCodeParameter ("array_length", get_ccode_name (ssize_t_type)));
360 146 : fun.add_parameter (new CCodeParameter ("destroy_func", get_ccode_name (delegate_target_destroy_type)));
361 :
362 146 : push_function (fun);
363 :
364 : // call _vala_array_destroy to free the array elements
365 146 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_destroy"));
366 146 : ccall.add_argument (new CCodeIdentifier ("array"));
367 146 : ccall.add_argument (new CCodeIdentifier ("array_length"));
368 146 : ccall.add_argument (new CCodeIdentifier ("destroy_func"));
369 146 : ccode.add_expression (ccall);
370 :
371 : CCodeFunctionCall carrfree;
372 146 : if (context.profile == Profile.POSIX) {
373 2 : cfile.add_include ("stdlib.h");
374 2 : carrfree = new CCodeFunctionCall (new CCodeIdentifier ("free"));
375 : } else {
376 144 : carrfree = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
377 : }
378 146 : carrfree.add_argument (new CCodeIdentifier ("array"));
379 146 : ccode.add_expression (carrfree);
380 :
381 146 : pop_function ();
382 :
383 146 : cfile.add_function_declaration (fun);
384 146 : cfile.add_function (fun);
385 : }
386 :
387 2 : public override void append_vala_array_move () {
388 2 : cfile.add_include ("string.h");
389 2 : generate_type_declaration (ssize_t_type, cfile);
390 :
391 : // assumes that overwritten array elements are null before invocation
392 : // FIXME will leak memory if that's not the case
393 2 : var fun = new CCodeFunction ("_vala_array_move", "void");
394 2 : fun.modifiers = CCodeModifiers.STATIC;
395 2 : fun.add_parameter (new CCodeParameter ("array", get_ccode_name (pointer_type)));
396 2 : fun.add_parameter (new CCodeParameter ("element_size", get_ccode_name (size_t_type)));
397 2 : fun.add_parameter (new CCodeParameter ("src", get_ccode_name (ssize_t_type)));
398 2 : fun.add_parameter (new CCodeParameter ("dest", get_ccode_name (ssize_t_type)));
399 2 : fun.add_parameter (new CCodeParameter ("length", get_ccode_name (ssize_t_type)));
400 :
401 2 : push_function (fun);
402 :
403 2 : var array = new CCodeCastExpression (new CCodeIdentifier ("array"), "char*");
404 2 : var element_size = new CCodeIdentifier ("element_size");
405 2 : var length = new CCodeIdentifier ("length");
406 2 : var src = new CCodeIdentifier ("src");
407 2 : var src_end = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, src, length);
408 2 : var dest = new CCodeIdentifier ("dest");
409 2 : var dest_end = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, dest, length);
410 2 : var src_address = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, array, new CCodeBinaryExpression (CCodeBinaryOperator.MUL, src, element_size));
411 2 : var dest_address = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, array, new CCodeBinaryExpression (CCodeBinaryOperator.MUL, dest, element_size));
412 2 : var dest_end_address = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, array, new CCodeBinaryExpression (CCodeBinaryOperator.MUL, dest_end, element_size));
413 :
414 2 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("memmove"));
415 2 : ccall.add_argument (dest_address);
416 2 : ccall.add_argument (src_address);
417 2 : ccall.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, length, element_size));
418 2 : ccode.add_expression (ccall);
419 :
420 2 : ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.AND, new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, src, dest), new CCodeBinaryExpression (CCodeBinaryOperator.GREATER_THAN, src_end, dest)));
421 :
422 2 : var czero1 = new CCodeFunctionCall (new CCodeIdentifier ("memset"));
423 2 : czero1.add_argument (src_address);
424 2 : czero1.add_argument (new CCodeConstant ("0"));
425 2 : czero1.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeBinaryExpression (CCodeBinaryOperator.MINUS, dest, src), element_size));
426 2 : ccode.add_expression (czero1);
427 :
428 2 : ccode.else_if (new CCodeBinaryExpression (CCodeBinaryOperator.AND, new CCodeBinaryExpression (CCodeBinaryOperator.GREATER_THAN, src, dest), new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, src, dest_end)));
429 :
430 2 : var czero2 = new CCodeFunctionCall (new CCodeIdentifier ("memset"));
431 2 : czero2.add_argument (dest_end_address);
432 2 : czero2.add_argument (new CCodeConstant ("0"));
433 2 : czero2.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeBinaryExpression (CCodeBinaryOperator.MINUS, src, dest), element_size));
434 2 : ccode.add_expression (czero2);
435 :
436 2 : ccode.else_if (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, src, dest));
437 :
438 2 : var czero3 = new CCodeFunctionCall (new CCodeIdentifier ("memset"));
439 2 : czero3.add_argument (src_address);
440 2 : czero3.add_argument (new CCodeConstant ("0"));
441 2 : czero3.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, length, element_size));
442 2 : ccode.add_expression (czero3);
443 :
444 2 : ccode.close ();
445 :
446 2 : pop_function ();
447 :
448 2 : cfile.add_function_declaration (fun);
449 2 : cfile.add_function (fun);
450 : }
451 :
452 35 : public override void append_vala_array_length () {
453 35 : generate_type_declaration (ssize_t_type, cfile);
454 :
455 35 : var fun = new CCodeFunction ("_vala_array_length", get_ccode_name (ssize_t_type));
456 35 : fun.modifiers = CCodeModifiers.STATIC;
457 35 : fun.add_parameter (new CCodeParameter ("array", get_ccode_name (pointer_type)));
458 :
459 35 : push_function (fun);
460 :
461 35 : ccode.add_declaration (get_ccode_name (ssize_t_type), new CCodeVariableDeclarator ("length", new CCodeConstant ("0")));
462 :
463 : // return 0 if the array is NULL
464 : // avoids an extra NULL check on the caller side
465 35 : var array_check = new CCodeIdentifier ("array");
466 35 : ccode.open_if (array_check);
467 :
468 35 : var array_element_check = new CCodeElementAccess (new CCodeCastExpression (new CCodeIdentifier ("array"), "%s*".printf (get_ccode_name (pointer_type))), new CCodeConstant ("length"));
469 35 : ccode.open_while (array_element_check);
470 35 : ccode.add_expression (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("length")));
471 35 : ccode.close ();
472 :
473 35 : ccode.close ();
474 :
475 35 : ccode.add_return (new CCodeIdentifier ("length"));
476 :
477 35 : pop_function ();
478 :
479 35 : cfile.add_function_declaration (fun);
480 35 : cfile.add_function (fun);
481 : }
482 :
483 3031 : public override TargetValue? copy_value (TargetValue value, CodeNode node) {
484 3031 : var type = value.value_type;
485 3031 : var cexpr = get_cvalue_ (value);
486 :
487 3031 : if (type is ArrayType) {
488 130 : var array_type = (ArrayType) type;
489 :
490 130 : if (!array_type.fixed_length) {
491 129 : return base.copy_value (value, node);
492 : }
493 :
494 1 : var temp_value = create_temp_value (type, false, node);
495 :
496 1 : var copy_call = new CCodeFunctionCall (new CCodeIdentifier (generate_array_copy_wrapper (array_type)));
497 1 : copy_call.add_argument (cexpr);
498 1 : copy_call.add_argument (get_cvalue_ (temp_value));
499 1 : ccode.add_expression (copy_call);
500 :
501 1 : return temp_value;
502 : } else {
503 2901 : return base.copy_value (value, node);
504 : }
505 : }
506 :
507 3310 : public override CCodeExpression? get_dup_func_expression (DataType type, SourceReference? source_reference, bool is_chainup) {
508 3310 : if (type is ArrayType) {
509 130 : var array_type = (ArrayType) type;
510 : // fixed length arrays use different code
511 : // generated by overridden get_ref_cexpression method
512 130 : assert (!array_type.fixed_length);
513 130 : return new CCodeIdentifier (generate_array_dup_wrapper (array_type));
514 : } else {
515 3180 : return base.get_dup_func_expression (type, source_reference, is_chainup);
516 : }
517 : }
518 :
519 12765 : public override CCodeExpression destroy_value (TargetValue value, bool is_macro_definition = false) {
520 12765 : unowned ArrayType? array_type = value.value_type as ArrayType;
521 :
522 12765 : if (array_type != null && array_type.fixed_length) {
523 17 : unowned Struct? st = array_type.element_type.type_symbol as Struct;
524 2 : if (st != null && !array_type.element_type.nullable) {
525 2 : var ccall = new CCodeFunctionCall (new CCodeIdentifier (append_struct_array_destroy (st)));
526 2 : ccall.add_argument (get_cvalue_ (value));
527 2 : ccall.add_argument (get_ccodenode (array_type.length));
528 2 : return ccall;
529 : }
530 :
531 15 : requires_array_free = true;
532 15 : generate_type_declaration (delegate_target_destroy_type, cfile);
533 :
534 15 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_destroy"));
535 15 : ccall.add_argument (get_cvalue_ (value));
536 15 : ccall.add_argument (get_ccodenode (array_type.length));
537 15 : ccall.add_argument (new CCodeCastExpression (get_destroy_func_expression (array_type.element_type), get_ccode_name (delegate_target_destroy_type)));
538 :
539 15 : return ccall;
540 : } else {
541 12748 : return base.destroy_value (value, is_macro_definition);
542 : }
543 : }
544 :
545 130 : string generate_array_dup_wrapper (ArrayType array_type) {
546 130 : string dup_func = "_vala_array_dup%d".printf (++next_array_dup_id);
547 :
548 130 : if (!add_wrapper (dup_func)) {
549 : // wrapper already defined
550 130 : return dup_func;
551 : }
552 :
553 : // declaration
554 130 : generate_type_declaration (ssize_t_type, cfile);
555 :
556 130 : var function = new CCodeFunction (dup_func, get_ccode_name (array_type));
557 130 : function.modifiers = CCodeModifiers.STATIC;
558 :
559 130 : function.add_parameter (new CCodeParameter ("self", get_ccode_name (array_type)));
560 : // total length over all dimensions
561 130 : function.add_parameter (new CCodeParameter ("length", get_ccode_name (ssize_t_type)));
562 130 : if (array_type.element_type is GenericType) {
563 : // dup function array elements
564 2 : function.add_parameter (new CCodeParameter (get_ccode_copy_function (((GenericType) array_type.element_type).type_parameter), "GBoxedCopyFunc"));
565 : }
566 :
567 : // definition
568 :
569 130 : push_context (new EmitContext ());
570 130 : push_function (function);
571 :
572 260 : if (requires_copy (array_type.element_type)) {
573 78 : var cvardecl = new CCodeVariableDeclarator ("result");
574 : CCodeFunctionCall gnew;
575 78 : if (context.profile == Profile.POSIX) {
576 3 : cfile.add_include ("stdlib.h");
577 3 : gnew = new CCodeFunctionCall (new CCodeIdentifier ("calloc"));
578 : } else {
579 75 : gnew = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
580 75 : gnew.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type)));
581 : }
582 :
583 78 : CCodeExpression length_expr = new CCodeIdentifier ("length");
584 : CCodeBinaryOperator length_check_op;
585 : // add extra item to have array NULL-terminated for all reference types
586 78 : if (array_type.element_type.type_symbol != null && array_type.element_type.type_symbol.is_reference_type ()) {
587 68 : length_expr = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, length_expr, new CCodeConstant ("1"));
588 : length_check_op = CCodeBinaryOperator.GREATER_THAN_OR_EQUAL;
589 : } else {
590 : length_check_op = CCodeBinaryOperator.GREATER_THAN;
591 : }
592 78 : gnew.add_argument (length_expr);
593 :
594 81 : if (context.profile == Profile.POSIX) {
595 3 : var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
596 3 : csizeof.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type)));
597 3 : gnew.add_argument (csizeof);
598 : }
599 :
600 : // only attempt to dup if length >=/> 0, this deals with negative lengths and returns NULL
601 78 : var length_check = new CCodeBinaryExpression (length_check_op, new CCodeIdentifier ("length"), new CCodeConstant ("0"));
602 78 : ccode.open_if (length_check);
603 :
604 78 : ccode.add_declaration (get_ccode_name (array_type), cvardecl);
605 78 : ccode.add_assignment (new CCodeIdentifier ("result"), gnew);
606 :
607 78 : ccode.add_declaration (get_ccode_name (ssize_t_type), new CCodeVariableDeclarator ("i"));
608 :
609 78 : ccode.open_for (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")),
610 : new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeIdentifier ("length")),
611 : new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i")));
612 :
613 78 : ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("result"), new CCodeIdentifier ("i")), get_cvalue_ (copy_value (new GLibValue (array_type.element_type, new CCodeElementAccess (new CCodeIdentifier ("self"), new CCodeIdentifier ("i")), true), array_type)));
614 78 : ccode.close ();
615 :
616 78 : ccode.add_return (new CCodeIdentifier ("result"));
617 :
618 78 : ccode.close ();
619 78 : ccode.add_return (new CCodeConstant ("NULL"));
620 : } else {
621 : // only dup if length > 0, this deals with negative lengths and returns NULL
622 52 : var length_check = new CCodeBinaryExpression (CCodeBinaryOperator.GREATER_THAN, new CCodeIdentifier ("length"), new CCodeConstant ("0"));
623 52 : ccode.open_if (length_check);
624 :
625 52 : var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
626 52 : sizeof_call.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type)));
627 52 : var length_expr = new CCodeIdentifier ("length");
628 :
629 104 : if (context.profile == Profile.POSIX) {
630 11 : cfile.add_include ("stdlib.h");
631 11 : cfile.add_include ("string.h");
632 :
633 11 : var alloc = new CCodeFunctionCall (new CCodeIdentifier ("calloc"));
634 11 : alloc.add_argument (length_expr);
635 11 : alloc.add_argument (sizeof_call);
636 :
637 11 : var cvardecl = new CCodeVariableDeclarator ("result");
638 11 : ccode.add_declaration (get_ccode_name (array_type), cvardecl);
639 11 : ccode.add_assignment (new CCodeIdentifier ("result"), alloc);
640 :
641 11 : var dup_call = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
642 11 : dup_call.add_argument (new CCodeIdentifier ("result"));
643 11 : dup_call.add_argument (new CCodeIdentifier ("self"));
644 11 : dup_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, length_expr, sizeof_call));
645 11 : ccode.add_expression (dup_call);
646 :
647 11 : ccode.add_return (new CCodeIdentifier ("result"));
648 : } else {
649 : CCodeFunctionCall dup_call;
650 41 : if (context.require_glib_version (2, 68)) {
651 2 : dup_call = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup2"));
652 : } else {
653 39 : requires_memdup2 = true;
654 39 : dup_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_memdup2"));
655 : }
656 41 : dup_call.add_argument (new CCodeIdentifier ("self"));
657 41 : dup_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, length_expr, sizeof_call));
658 :
659 41 : ccode.add_return (dup_call);
660 : }
661 :
662 52 : ccode.close ();
663 52 : ccode.add_return (new CCodeConstant ("NULL"));
664 : }
665 :
666 : // append to file
667 :
668 130 : cfile.add_function_declaration (function);
669 130 : cfile.add_function (function);
670 :
671 130 : pop_context ();
672 :
673 130 : return dup_func;
674 : }
675 :
676 1 : string generate_array_copy_wrapper (ArrayType array_type) {
677 1 : string dup_func = "_vala_array_copy%d".printf (++next_array_dup_id);
678 :
679 1 : if (!add_wrapper (dup_func)) {
680 : // wrapper already defined
681 1 : return dup_func;
682 : }
683 :
684 : // declaration
685 :
686 1 : var function = new CCodeFunction (dup_func, "void");
687 1 : function.modifiers = CCodeModifiers.STATIC;
688 :
689 1 : function.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (array_type))));
690 1 : function.add_parameter (new CCodeParameter ("dest", "%s *".printf (get_ccode_name (array_type))));
691 :
692 : // definition
693 :
694 1 : push_context (new EmitContext ());
695 1 : push_function (function);
696 :
697 1 : if (requires_copy (array_type.element_type)) {
698 1 : ccode.add_declaration (get_ccode_name (array_type.length_type), new CCodeVariableDeclarator ("i"));
699 :
700 1 : ccode.open_for (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")),
701 : new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), get_ccodenode (array_type.length)),
702 : new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i")));
703 :
704 :
705 1 : ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("dest"), new CCodeIdentifier ("i")), get_cvalue_ (copy_value (new GLibValue (array_type.element_type, new CCodeElementAccess (new CCodeIdentifier ("self"), new CCodeIdentifier ("i")), true), array_type)));
706 : } else {
707 0 : cfile.add_include ("string.h");
708 :
709 0 : var dup_call = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
710 0 : dup_call.add_argument (new CCodeIdentifier ("dest"));
711 0 : dup_call.add_argument (new CCodeIdentifier ("self"));
712 :
713 0 : var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
714 0 : sizeof_call.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type)));
715 0 : dup_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, get_ccodenode (array_type.length), sizeof_call));
716 :
717 0 : ccode.add_expression (dup_call);
718 : }
719 :
720 : // append to file
721 :
722 1 : cfile.add_function_declaration (function);
723 1 : cfile.add_function (function);
724 :
725 1 : pop_context ();
726 :
727 1 : return dup_func;
728 : }
729 :
730 78 : string generate_array_add_wrapper (ArrayType array_type) {
731 78 : string add_func = "_vala_array_add%d".printf (++next_array_add_id);
732 :
733 78 : if (!add_wrapper (add_func)) {
734 : // wrapper already defined
735 78 : return add_func;
736 : }
737 :
738 78 : var function = new CCodeFunction (add_func, "void");
739 78 : function.modifiers = CCodeModifiers.STATIC;
740 :
741 78 : function.add_parameter (new CCodeParameter ("array", "%s *".printf (get_ccode_name (array_type))));
742 78 : function.add_parameter (new CCodeParameter ("length", "%s*".printf (get_ccode_name (array_type.length_type))));
743 78 : function.add_parameter (new CCodeParameter ("size", "%s*".printf (get_ccode_name (array_type.length_type))));
744 :
745 78 : push_function (function);
746 :
747 78 : string typename = get_ccode_name (array_type.element_type);
748 78 : CCodeExpression value = new CCodeIdentifier ("value");
749 78 : if (array_type.element_type.is_real_struct_type ()) {
750 9 : if (!array_type.element_type.nullable || !array_type.element_type.value_owned) {
751 6 : typename = "const " + typename;
752 : }
753 9 : if (!array_type.element_type.nullable) {
754 3 : typename += "*";
755 3 : value = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, value);
756 : }
757 : }
758 78 : function.add_parameter (new CCodeParameter ("value", typename));
759 :
760 78 : var array = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("array"));
761 78 : var length = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("length"));
762 78 : var size = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("size"));
763 :
764 : CCodeFunctionCall renew_call;
765 78 : if (context.profile == Profile.POSIX) {
766 4 : cfile.add_include ("stdlib.h");
767 4 : renew_call = new CCodeFunctionCall (new CCodeIdentifier ("realloc"));
768 4 : renew_call.add_argument (array);
769 : } else {
770 74 : renew_call = new CCodeFunctionCall (new CCodeIdentifier ("g_renew"));
771 74 : renew_call.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type)));
772 74 : renew_call.add_argument (array);
773 : }
774 : CCodeExpression renew_call_size;
775 78 : if (array_type.element_type.is_reference_type_or_type_parameter ()) {
776 : // NULL terminate array
777 52 : renew_call_size = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, size, new CCodeConstant ("1"));
778 : } else {
779 26 : renew_call_size = size;
780 : }
781 82 : if (context.profile == Profile.POSIX) {
782 4 : var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
783 4 : csizeof.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type)));
784 4 : renew_call_size = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, size, csizeof);
785 : }
786 78 : renew_call.add_argument (renew_call_size);
787 :
788 78 : var csizecheck = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, length, size);
789 78 : ccode.open_if (csizecheck);
790 78 : ccode.add_assignment (size, new CCodeConditionalExpression (size, new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeConstant ("2"), size), new CCodeConstant ("4")));
791 78 : ccode.add_assignment (array, renew_call);
792 78 : ccode.close ();
793 :
794 78 : ccode.add_assignment (new CCodeElementAccess (array, new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, length)), value);
795 :
796 78 : if (array_type.element_type.is_reference_type_or_type_parameter ()) {
797 : // NULL terminate array
798 52 : ccode.add_assignment (new CCodeElementAccess (array, length), new CCodeConstant ("NULL"));
799 : }
800 :
801 78 : pop_function ();
802 :
803 78 : cfile.add_function_declaration (function);
804 78 : cfile.add_function (function);
805 :
806 78 : return add_func;
807 : }
808 :
809 1059 : bool is_array_add (Assignment assignment) {
810 1059 : var binary = assignment.right as BinaryExpression;
811 106 : if (binary != null && binary.left.value_type is ArrayType) {
812 57 : if (binary.operator == BinaryOperator.PLUS) {
813 57 : if (assignment.left.symbol_reference == binary.left.symbol_reference) {
814 57 : return true;
815 : }
816 : }
817 : }
818 :
819 1002 : return false;
820 : }
821 :
822 1115 : public override void visit_assignment (Assignment assignment) {
823 1059 : if (!is_array_add (assignment)) {
824 1002 : base.visit_assignment (assignment);
825 1002 : return;
826 : }
827 :
828 57 : var binary = (BinaryExpression) assignment.right;
829 :
830 57 : var array = assignment.left;
831 57 : var array_type = (ArrayType) array.value_type;
832 57 : var element = binary.right;
833 :
834 57 : var array_var = array.symbol_reference;
835 57 : if (array_type.rank == 1 && array_var != null && array_var.is_internal_symbol ()
836 57 : && (array_var is LocalVariable || array_var is Field)) {
837 : // valid array add
838 : } else {
839 1 : Report.error (assignment.source_reference, "Array concatenation not supported for public array variables and parameters");
840 1 : return;
841 : }
842 :
843 56 : var value_param = new Parameter ("value", element.target_type);
844 :
845 56 : var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_array_add_wrapper (array_type)));
846 56 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue (array)));
847 56 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_array_length_cexpression (array)));
848 56 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_array_size_cvalue (array.target_value)));
849 56 : ccall.add_argument (handle_struct_argument (value_param, element, get_cvalue (element)));
850 :
851 56 : ccode.add_expression (ccall);
852 : }
853 :
854 3820 : public override CCodeParameter generate_parameter (Parameter param, CCodeFile decl_space, Map<int,CCodeParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
855 3820 : unowned ArrayType? array_type = param.variable_type as ArrayType;
856 3820 : if (array_type == null || param.params_array) {
857 2966 : return base.generate_parameter (param, decl_space, cparam_map, carg_map);
858 : }
859 :
860 854 : string? ctypename = get_ccode_type (param);
861 854 : if (ctypename == null) {
862 845 : ctypename = get_ccode_name (param.variable_type);
863 :
864 845 : if (param.direction != ParameterDirection.IN) {
865 151 : ctypename += "*";
866 : }
867 : }
868 :
869 854 : var main_cparam = new CCodeParameter.with_declarator (ctypename, new CCodeVariableDeclarator (get_ccode_name (param), null, get_ccode_declarator_suffix (array_type)));
870 :
871 854 : generate_type_declaration (array_type.element_type, decl_space);
872 :
873 854 : cparam_map.set (get_param_pos (get_ccode_pos (param)), main_cparam);
874 854 : if (carg_map != null) {
875 524 : carg_map.set (get_param_pos (get_ccode_pos (param)), get_parameter_cexpression (param));
876 : }
877 :
878 1622 : if (!array_type.fixed_length && get_ccode_array_length (param)) {
879 768 : var length_ctype = get_ccode_array_length_type (param);
880 768 : if (param.direction != ParameterDirection.IN) {
881 122 : length_ctype = "%s*".printf (length_ctype);
882 : }
883 :
884 2372 : for (int dim = 1; dim <= array_type.rank; dim++) {
885 802 : var cparam = new CCodeParameter (get_variable_array_length_cname (param, dim), length_ctype);
886 802 : cparam_map.set (get_param_pos (get_ccode_array_length_pos (param) + 0.01 * dim), cparam);
887 802 : if (carg_map != null) {
888 497 : carg_map.set (get_param_pos (get_ccode_array_length_pos (param) + 0.01 * dim), get_cexpression (cparam.name));
889 : }
890 : }
891 : }
892 :
893 854 : return main_cparam;
894 : }
895 :
896 44 : public override void append_params_array (Method m) {
897 22 : var local = m.params_array_var;
898 22 : var array_type = (ArrayType) local.variable_type;
899 :
900 22 : var local_length = new LocalVariable (array_type.length_type.copy (), get_array_length_cname (local.name, 1), null, local.source_reference);
901 22 : var local_size = new LocalVariable (array_type.length_type.copy (), get_array_size_cname (get_local_cname (local)));
902 :
903 : CCodeFunctionCall gnew;
904 22 : if (context.profile == Profile.POSIX) {
905 0 : cfile.add_include ("stdlib.h");
906 0 : gnew = new CCodeFunctionCall (new CCodeIdentifier ("calloc"));
907 : } else {
908 22 : gnew = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
909 22 : gnew.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type)));
910 : }
911 :
912 22 : CCodeExpression length_expr = get_local_cexpression (local_length);
913 : // add extra item to have array NULL-terminated for all reference types
914 22 : if (array_type.element_type.type_symbol != null && array_type.element_type.type_symbol.is_reference_type ()) {
915 13 : length_expr = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, length_expr, new CCodeConstant ("1"));
916 : }
917 22 : gnew.add_argument (length_expr);
918 22 : if (context.profile == Profile.POSIX) {
919 0 : var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
920 0 : csizeof.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type)));
921 0 : gnew.add_argument (csizeof);
922 : }
923 22 : ccode.add_assignment (get_local_cexpression (local), gnew);
924 :
925 22 : var element = new LocalVariable (array_type.element_type.copy (), "_%s_element".printf (get_ccode_name (local)), null, local.source_reference);
926 22 : emit_temp_var (element);
927 :
928 22 : if (context.profile == Profile.POSIX) {
929 0 : cfile.add_include ("stdarg.h");
930 : }
931 :
932 39 : if (!(m is CreationMethod) || m.parent_symbol is Struct) {
933 17 : ccode.add_declaration ("va_list", new CCodeVariableDeclarator ("_va_list_%s".printf (get_ccode_name (local))));
934 17 : var vastart = new CCodeFunctionCall (new CCodeIdentifier ("va_start"));
935 17 : vastart.add_argument (new CCodeIdentifier ("_va_list_%s".printf (get_ccode_name (local))));
936 17 : vastart.add_argument (new CCodeIdentifier ("_first_%s".printf (get_ccode_name (local))));
937 17 : ccode.add_expression (vastart);
938 : }
939 :
940 22 : ccode.add_assignment (get_local_cexpression (element), new CCodeIdentifier ("_first_%s".printf (get_ccode_name (local))));
941 22 : ccode.open_while (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_local_cexpression (element), new CCodeConstant ("NULL")));
942 :
943 22 : var vaarg = new CCodeFunctionCall (new CCodeIdentifier ("va_arg"));
944 22 : vaarg.add_argument (new CCodeIdentifier ("_va_list_%s".printf (get_ccode_name (local))));
945 22 : vaarg.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type)));
946 :
947 22 : var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_array_add_wrapper (array_type)));
948 22 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_local_cexpression (local)));
949 22 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_local_cexpression (local_length)));
950 22 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_local_cexpression (local_size)));
951 22 : ccall.add_argument (get_local_cexpression (element));
952 :
953 22 : ccode.add_expression (ccall);
954 22 : ccode.add_assignment (get_local_cexpression (element), vaarg);
955 :
956 22 : ccode.close ();
957 :
958 22 : var vaend = new CCodeFunctionCall (new CCodeIdentifier ("va_end"));
959 22 : vaend.add_argument (new CCodeIdentifier ("_va_list_%s".printf (get_ccode_name (local))));
960 22 : ccode.add_expression (vaend);
961 : }
962 : }
|