LCOV - code coverage report
Current view: top level - codegen - valaccodearraymodule.vala (source / functions) Coverage Total Hit
Test: vala 0.57.0.298-a8cae1 Lines: 96.8 % 563 545
Test Date: 2024-04-25 11:34:36 Functions: - 0 0

            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              : }
        

Generated by: LCOV version 2.0-1