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

            Line data    Source code
       1              : /* valagsignalmodule.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         2914 : public class Vala.GSignalModule : GObjectModule {
      27          223 :         string get_marshaller_function (Signal sig, List<Parameter> params, DataType return_type, string? prefix = null) {
      28          223 :                 var signature = get_marshaller_signature (sig, params, return_type);
      29              :                 string ret;
      30              : 
      31          223 :                 if (prefix == null) {
      32          121 :                         if (predefined_marshal_set.contains (signature)) {
      33              :                                 prefix = "g_cclosure_marshal";
      34              :                         } else {
      35           76 :                                 prefix = "g_cclosure_user_marshal";
      36              :                         }
      37              :                 }
      38              : 
      39          223 :                 ret = "%s_%s_".printf (prefix, get_ccode_marshaller_type_name (return_type));
      40              : 
      41          715 :                 foreach (Parameter p in params) {
      42          246 :                         ret = "%s_%s".printf (ret, get_ccode_marshaller_type_name (p).replace (",", "_"));
      43              :                 }
      44          223 :                 if (sig.return_type.is_real_non_null_struct_type ()) {
      45            6 :                         ret = ret + "_POINTER";
      46          217 :                 } else if (params.size == 0) {
      47           58 :                         ret = ret + "_VOID";
      48              :                 }
      49              : 
      50          223 :                 return ret;
      51              :         }
      52              : 
      53           94 :         private string? get_value_type_name_from_type_reference (DataType t) {
      54           94 :                 if (t is PointerType || t is GenericType) {
      55            3 :                         return "gpointer";
      56           91 :                 } else if (t is VoidType) {
      57           16 :                         return "void";
      58           75 :                 } else if (get_ccode_type_id (t) == get_ccode_type_id (string_type)) {
      59           18 :                         return "const char*";
      60           57 :                 } else if (t.type_symbol is Class || t.type_symbol is Interface) {
      61            9 :                         return "gpointer";
      62           48 :                 } else if (t is ValueType && t.nullable) {
      63           12 :                         return "gpointer";
      64           36 :                 } else if (t.type_symbol is Struct) {
      65           28 :                         unowned Struct st = (Struct) t.type_symbol;
      66           28 :                         if (st.is_simple_type ()) {
      67           26 :                                 return get_ccode_name (t.type_symbol);
      68              :                         } else {
      69            2 :                                 return "gpointer";
      70              :                         }
      71            8 :                 } else if (t.type_symbol is Enum) {
      72            3 :                         unowned Enum en = (Enum) t.type_symbol;
      73            3 :                         if (en.is_flags) {
      74            1 :                                 return "guint";
      75              :                         } else {
      76            2 :                                 return "gint";
      77              :                         }
      78            5 :                 } else if (t is ArrayType) {
      79            3 :                         return "gpointer";
      80            2 :                 } else if (t is DelegateType) {
      81            2 :                         return "gpointer";
      82            0 :                 } else if (t is ErrorType) {
      83            0 :                         return "gpointer";
      84              :                 }
      85              : 
      86           94 :                 return null;
      87              :         }
      88              : 
      89           43 :         private string? get_value_type_name_from_parameter (Parameter p) {
      90           43 :                 if (p.direction != ParameterDirection.IN) {
      91            1 :                         return "gpointer";
      92              :                 } else {
      93           42 :                         return get_value_type_name_from_type_reference (p.variable_type);
      94              :                 }
      95              :         }
      96              : 
      97          310 :         private string get_marshaller_signature (Signal sig, List<Parameter> params, DataType return_type) {
      98              :                 string signature;
      99              : 
     100          310 :                 signature = "%s:".printf (get_ccode_marshaller_type_name (return_type));
     101          310 :                 bool first = true;
     102          950 :                 foreach (Parameter p in params) {
     103          320 :                         if (first) {
     104          220 :                                 signature = signature + get_ccode_marshaller_type_name (p);
     105          220 :                                 first = false;
     106              :                         } else {
     107          100 :                                 signature = "%s,%s".printf (signature, get_ccode_marshaller_type_name (p));
     108              :                         }
     109              :                 }
     110          310 :                 if (sig.return_type.is_real_non_null_struct_type ()) {
     111            8 :                         signature = signature + (first ? "POINTER" : ",POINTER");
     112          302 :                 } else if (params.size == 0) {
     113           88 :                         signature = signature + "VOID";
     114              :                 }
     115              : 
     116              :                 return signature;
     117              :         }
     118              : 
     119          101 :         private CCodeExpression get_signal_name_cexpression (Signal sig, Expression? detail_expr, CodeNode node) {
     120          101 :                 if (detail_expr == null) {
     121           88 :                         return get_signal_canonical_constant (sig);
     122              :                 }
     123              : 
     124           13 :                 if (detail_expr is StringLiteral) {
     125           11 :                         return get_signal_canonical_constant (sig, ((StringLiteral) detail_expr).eval ());
     126              :                 }
     127              : 
     128            2 :                 var detail_value = create_temp_value (detail_expr.value_type, false, node, true);
     129            2 :                 temp_ref_values.insert (0, detail_value);
     130              : 
     131            2 :                 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat"));
     132            2 :                 ccall.add_argument (get_signal_canonical_constant (sig, ""));
     133            2 :                 ccall.add_argument (get_cvalue (detail_expr));
     134            2 :                 ccall.add_argument (new CCodeConstant ("NULL"));
     135              : 
     136            2 :                 ccode.add_assignment (get_cvalue_ (detail_value), ccall);
     137          206 :                 return get_cvalue_ (detail_value);
     138              :         }
     139              : 
     140          267 :         private CCodeExpression get_signal_id_cexpression (Signal sig) {
     141        17501 :                 var cl = (TypeSymbol) sig.parent_symbol;
     142          267 :                 var signal_array = new CCodeIdentifier ("%s_signals".printf (get_ccode_lower_case_name (cl)));
     143          267 :                 var signal_enum_value = new CCodeIdentifier ("%s_%s_SIGNAL".printf (get_ccode_upper_case_name (cl), get_ccode_upper_case_name (sig)));
     144              : 
     145          267 :                 return new CCodeElementAccess (signal_array, signal_enum_value);
     146              :         }
     147              : 
     148            3 :         private CCodeExpression get_detail_cexpression (Expression detail_expr, CodeNode node) {
     149            3 :                 var detail_cexpr = get_cvalue (detail_expr);
     150              :                 CCodeFunctionCall detail_ccall;
     151            3 :                 if (is_constant_ccode_expression (detail_cexpr)) {
     152            1 :                         detail_ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
     153              :                 } else {
     154            2 :                         detail_ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string"));
     155              :                 }
     156            3 :                 detail_ccall.add_argument (detail_cexpr);
     157              : 
     158            3 :                 return detail_ccall;
     159              :         }
     160              : 
     161           87 :         public override void visit_signal (Signal sig) {
     162           87 :                 if (signal_enum != null && sig.parent_symbol is TypeSymbol) {
     163           87 :                         signal_enum.add_value (new CCodeEnumValue ("%s_%s_SIGNAL".printf (get_ccode_upper_case_name ((TypeSymbol) sig.parent_symbol), get_ccode_upper_case_name (sig))));
     164              :                 }
     165              : 
     166           87 :                 sig.accept_children (this);
     167              : 
     168              :                 // declare parameter type
     169           87 :                 unowned List<Parameter> params = sig.get_parameters ();
     170          235 :                 foreach (Parameter p in params) {
     171           74 :                         generate_parameter (p, cfile, new HashMap<int,CCodeParameter> (), null);
     172              :                 }
     173              : 
     174           87 :                 if (sig.return_type.is_real_non_null_struct_type ()) {
     175            2 :                         generate_marshaller (sig, params, new VoidType ());
     176              :                 } else {
     177           85 :                         generate_marshaller (sig, params, sig.return_type);
     178              :                 }
     179              :         }
     180              : 
     181          121 :         void generate_marshaller (Signal sig, List<Parameter> params, DataType return_type) {
     182              :                 string signature;
     183              :                 int n_params, i;
     184              : 
     185              :                 /* check whether a signal with the same signature already exists for this source file (or predefined) */
     186           87 :                 signature = get_marshaller_signature (sig, params, return_type);
     187           87 :                 if (predefined_marshal_set.contains (signature) || user_marshal_set.contains (signature)) {
     188           53 :                         return;
     189              :                 }
     190              : 
     191           34 :                 var signal_marshaller = new CCodeFunction (get_marshaller_function (sig, params, return_type, null), "void");
     192           34 :                 signal_marshaller.modifiers = CCodeModifiers.STATIC;
     193              : 
     194           34 :                 signal_marshaller.add_parameter (new CCodeParameter ("closure", "GClosure *"));
     195           34 :                 signal_marshaller.add_parameter (new CCodeParameter ("return_value", "GValue *"));
     196           34 :                 signal_marshaller.add_parameter (new CCodeParameter ("n_param_values", "guint"));
     197           34 :                 signal_marshaller.add_parameter (new CCodeParameter ("param_values", "const GValue *"));
     198           34 :                 signal_marshaller.add_parameter (new CCodeParameter ("invocation_hint", "gpointer"));
     199           34 :                 signal_marshaller.add_parameter (new CCodeParameter ("marshal_data", "gpointer"));
     200              : 
     201           34 :                 push_function (signal_marshaller);
     202              : 
     203           34 :                 var callback_decl = new CCodeFunctionDeclarator (get_marshaller_function (sig, params, return_type, "GMarshalFunc"));
     204           34 :                 callback_decl.add_parameter (new CCodeParameter ("data1", "gpointer"));
     205           34 :                 n_params = 1;
     206          120 :                 foreach (Parameter p in params) {
     207           43 :                         callback_decl.add_parameter (new CCodeParameter ("arg_%d".printf (n_params), get_value_type_name_from_parameter (p)));
     208           43 :                         n_params++;
     209           46 :                         if (p.variable_type is ArrayType) {
     210            3 :                                 var array_type = (ArrayType) p.variable_type;
     211            3 :                                 var length_ctype = get_ccode_array_length_type (p);
     212            8 :                                 for (var j = 0; j < array_type.rank; j++) {
     213            5 :                                         callback_decl.add_parameter (new CCodeParameter ("arg_%d".printf (n_params), length_ctype));
     214            5 :                                         n_params++;
     215              :                                 }
     216           40 :                         } else if (p.variable_type is DelegateType) {
     217            2 :                                 unowned DelegateType delegate_type = (DelegateType) p.variable_type;
     218            2 :                                 if (delegate_type.delegate_symbol.has_target) {
     219            2 :                                         callback_decl.add_parameter (new CCodeParameter ("arg_%d".printf (n_params), get_ccode_name (delegate_target_type)));
     220            2 :                                         n_params++;
     221            2 :                                         if (delegate_type.is_disposable ()) {
     222            1 :                                                 callback_decl.add_parameter (new CCodeParameter ("arg_%d".printf (n_params), get_ccode_name (delegate_target_destroy_type)));
     223            1 :                                                 n_params++;
     224              :                                         }
     225              :                                 }
     226              :                         }
     227              :                 }
     228           34 :                 if (sig.return_type.is_real_non_null_struct_type ()) {
     229            1 :                         callback_decl.add_parameter (new CCodeParameter ("arg_%d".printf (n_params), "gpointer"));
     230            1 :                         n_params++;
     231              :                 }
     232              : 
     233           34 :                 callback_decl.add_parameter (new CCodeParameter ("data2", "gpointer"));
     234           34 :                 ccode.add_statement (new CCodeTypeDefinition (get_value_type_name_from_type_reference (return_type), callback_decl));
     235              : 
     236           34 :                 ccode.add_declaration (get_marshaller_function (sig, params, return_type, "GMarshalFunc"), new CCodeVariableDeclarator ("callback"), CCodeModifiers.REGISTER);
     237              : 
     238           34 :                 ccode.add_declaration ("GCClosure *", new CCodeVariableDeclarator ("cc", new CCodeCastExpression (new CCodeIdentifier ("closure"), "GCClosure *")), CCodeModifiers.REGISTER);
     239              : 
     240           34 :                 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("data1"), CCodeModifiers.REGISTER);
     241           34 :                 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("data2"), CCodeModifiers.REGISTER);
     242              : 
     243              :                 CCodeFunctionCall fc;
     244              : 
     245           34 :                 if (return_type.type_symbol != null || return_type is ArrayType) {
     246           18 :                         ccode.add_declaration (get_value_type_name_from_type_reference (return_type), new CCodeVariableDeclarator ("v_return"));
     247              : 
     248           18 :                         fc = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
     249           18 :                         fc.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("return_value"), new CCodeConstant ("NULL")));
     250           18 :                         ccode.add_expression (fc);
     251              :                 }
     252              : 
     253           34 :                 fc = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
     254           34 :                 fc.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("n_param_values"), new CCodeConstant (n_params.to_string())));
     255           34 :                 ccode.add_expression (fc);
     256              : 
     257           34 :                 var data = new CCodeMemberAccess (new CCodeIdentifier ("closure"), "data", true);
     258           34 :                 var param = new CCodeMemberAccess (new CCodeMemberAccess (new CCodeIdentifier ("param_values"), "data[0]", true), "v_pointer");
     259           34 :                 var cond = new CCodeFunctionCall (new CCodeConstant ("G_CCLOSURE_SWAP_DATA"));
     260           34 :                 cond.add_argument (new CCodeIdentifier ("closure"));
     261           34 :                 ccode.open_if (cond);
     262           34 :                 ccode.add_assignment (new CCodeIdentifier ("data1"), data);
     263           34 :                 ccode.add_assignment (new CCodeIdentifier ("data2"), param);
     264           34 :                 ccode.add_else ();
     265           34 :                 ccode.add_assignment (new CCodeIdentifier ("data1"), param);
     266           34 :                 ccode.add_assignment (new CCodeIdentifier ("data2"), data);
     267           34 :                 ccode.close ();
     268              : 
     269           34 :                 var c_assign_rhs =  new CCodeCastExpression (new CCodeConditionalExpression (new CCodeIdentifier ("marshal_data"), new CCodeIdentifier ("marshal_data"), new CCodeMemberAccess (new CCodeIdentifier ("cc"), "callback", true)), get_marshaller_function (sig, params, return_type, "GMarshalFunc"));
     270           34 :                 ccode.add_assignment (new CCodeIdentifier ("callback"), c_assign_rhs);
     271              : 
     272           34 :                 fc = new CCodeFunctionCall (new CCodeIdentifier ("callback"));
     273           34 :                 fc.add_argument (new CCodeIdentifier ("data1"));
     274           34 :                 i = 1;
     275          120 :                 foreach (Parameter p in params) {
     276              :                         CCodeFunctionCall inner_fc;
     277           43 :                         if (p.direction != ParameterDirection.IN) {
     278            1 :                                 inner_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_pointer"));
     279           42 :                         } else if (p.variable_type is ValueType && p.variable_type.nullable) {
     280            4 :                                 inner_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_pointer"));
     281              :                         } else {
     282           38 :                                 inner_fc = new CCodeFunctionCall (get_value_getter_function (p.variable_type));
     283              :                         }
     284           43 :                         inner_fc.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("param_values"), new CCodeIdentifier (i.to_string ())));
     285           43 :                         fc.add_argument (inner_fc);
     286           43 :                         i++;
     287           46 :                         if (p.variable_type is ArrayType) {
     288            3 :                                 var array_type = (ArrayType) p.variable_type;
     289            3 :                                 var length_value_function = get_ccode_get_value_function (array_type.length_type.type_symbol);
     290            3 :                                 assert (length_value_function != null && length_value_function != "");
     291            8 :                                 for (var j = 0; j < array_type.rank; j++) {
     292            5 :                                         inner_fc = new CCodeFunctionCall (new CCodeIdentifier (length_value_function));
     293            5 :                                         inner_fc.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("param_values"), new CCodeIdentifier (i.to_string ())));
     294            5 :                                         fc.add_argument (inner_fc);
     295            5 :                                         i++;
     296              :                                 }
     297           40 :                         } else if (p.variable_type is DelegateType) {
     298            2 :                                 unowned DelegateType delegate_type = (DelegateType) p.variable_type;
     299            2 :                                 if (delegate_type.delegate_symbol.has_target) {
     300            2 :                                         inner_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_pointer"));
     301            2 :                                         inner_fc.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("param_values"), new CCodeIdentifier (i.to_string ())));
     302            2 :                                         fc.add_argument (inner_fc);
     303            2 :                                         i++;
     304            2 :                                         if (delegate_type.is_disposable ()) {
     305            1 :                                                 inner_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_pointer"));
     306            1 :                                                 inner_fc.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("param_values"), new CCodeIdentifier (i.to_string ())));
     307            1 :                                                 fc.add_argument (inner_fc);
     308            1 :                                                 i++;
     309              :                                         }
     310              :                                 }
     311              :                         }
     312              :                 }
     313           35 :                 if (sig.return_type.is_real_non_null_struct_type ()) {
     314            1 :                         var inner_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_pointer"));
     315            1 :                         inner_fc.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("param_values"), new CCodeIdentifier (i.to_string ())));
     316            1 :                         fc.add_argument (inner_fc);
     317            1 :                         i++;
     318              :                 }
     319           34 :                 fc.add_argument (new CCodeIdentifier ("data2"));
     320              : 
     321           52 :                 if (return_type.type_symbol != null || return_type is ArrayType) {
     322           18 :                         ccode.add_assignment (new CCodeIdentifier ("v_return"), fc);
     323              : 
     324              :                         CCodeFunctionCall set_fc;
     325           18 :                         if (return_type is ValueType) {
     326           11 :                                 if (return_type.nullable) {
     327            4 :                                         set_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_set_pointer"));
     328              :                                 } else {
     329            7 :                                         set_fc = new CCodeFunctionCall (get_value_setter_function (return_type));
     330              :                                 }
     331              :                         } else {
     332            7 :                                 set_fc = new CCodeFunctionCall (get_value_taker_function (return_type));
     333              :                         }
     334           18 :                         set_fc.add_argument (new CCodeIdentifier ("return_value"));
     335           18 :                         set_fc.add_argument (new CCodeIdentifier ("v_return"));
     336              : 
     337           18 :                         ccode.add_expression (set_fc);
     338              :                 } else {
     339           16 :                         ccode.add_expression (fc);
     340              :                 }
     341              : 
     342           34 :                 pop_function ();
     343              : 
     344           34 :                 cfile.add_function_declaration (signal_marshaller);
     345           34 :                 cfile.add_function (signal_marshaller);
     346           34 :                 user_marshal_set.add (signature);
     347              :         }
     348              : 
     349           87 :         public override CCodeExpression get_signal_creation (Signal sig, ObjectTypeSymbol type) {
     350              :                 CCodeFunctionCall csignew;
     351           87 :                 if (sig.default_handler == null || sig.is_virtual) {
     352           85 :                         csignew = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_new"));
     353              :                 } else {
     354            2 :                         csignew = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_new_class_handler"));
     355              :                 }
     356           87 :                 csignew.add_argument (new CCodeConstant ("\"%s\"".printf (get_ccode_name (sig))));
     357           87 :                 csignew.add_argument (new CCodeIdentifier (get_ccode_type_id (type)));
     358           87 :                 string[] flags = new string[0];
     359           87 :                 var run_type = sig.get_attribute_string ("Signal", "run");
     360           87 :                 if (run_type == "first") {
     361            0 :                         flags += "G_SIGNAL_RUN_FIRST";
     362           87 :                 } else if (run_type == "cleanup") {
     363            0 :                         flags += "G_SIGNAL_RUN_CLEANUP";
     364              :                 } else {
     365          174 :                         flags += "G_SIGNAL_RUN_LAST";
     366              :                 }
     367           87 :                 if (sig.get_attribute_bool ("Signal", "detailed")) {
     368            2 :                         flags += "G_SIGNAL_DETAILED";
     369              :                 }
     370              : 
     371           87 :                 if (sig.get_attribute_bool ("Signal", "no_recurse")) {
     372            0 :                         flags += "G_SIGNAL_NO_RECURSE";
     373              :                 }
     374              : 
     375           87 :                 if (sig.get_attribute_bool ("Signal", "action")) {
     376            0 :                         flags += "G_SIGNAL_ACTION";
     377              :                 }
     378              : 
     379           87 :                 if (sig.get_attribute_bool ("Signal", "no_hooks")) {
     380            0 :                         flags += "G_SIGNAL_NO_HOOKS";
     381              :                 }
     382              : 
     383           87 :                 if (sig.version.deprecated) {
     384            0 :                         flags += "G_SIGNAL_DEPRECATED";
     385              :                 }
     386              : 
     387           87 :                 csignew.add_argument (new CCodeConstant (string.joinv (" | ", flags)));
     388              : 
     389           87 :                 if (sig.default_handler == null) {
     390           76 :                         csignew.add_argument (new CCodeConstant ("0"));
     391           20 :                 } else if (sig.is_virtual) {
     392            9 :                         var struct_offset = new CCodeFunctionCall (new CCodeIdentifier ("G_STRUCT_OFFSET"));
     393            9 :                         struct_offset.add_argument (new CCodeIdentifier (get_ccode_type_name (type)));
     394            9 :                         struct_offset.add_argument (new CCodeIdentifier (get_ccode_vfunc_name (sig.default_handler)));
     395            9 :                         csignew.add_argument (struct_offset);
     396              :                 } else {
     397            2 :                         csignew.add_argument (new CCodeCastExpression (new CCodeIdentifier (get_ccode_real_name (sig.default_handler)), "GCallback"));
     398              :                 }
     399           87 :                 csignew.add_argument (new CCodeConstant ("NULL"));
     400           87 :                 csignew.add_argument (new CCodeConstant ("NULL"));
     401              : 
     402           87 :                 unowned List<Parameter> params = sig.get_parameters ();
     403              :                 string marshaller;
     404           87 :                 if (sig.return_type.is_real_non_null_struct_type ()) {
     405            2 :                         marshaller = get_marshaller_function (sig, params, new VoidType ());
     406              :                 } else {
     407           85 :                         marshaller = get_marshaller_function (sig, params, sig.return_type);
     408              :                 }
     409              : 
     410           87 :                 var marshal_arg = new CCodeIdentifier (marshaller);
     411           87 :                 csignew.add_argument (marshal_arg);
     412              : 
     413           87 :                 if (sig.return_type is PointerType || sig.return_type is GenericType) {
     414            2 :                         csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER"));
     415           85 :                 } else if (sig.return_type is ErrorType) {
     416            0 :                         csignew.add_argument (new CCodeConstant ("G_TYPE_ERROR"));
     417           85 :                 } else if (sig.return_type is ValueType && sig.return_type.nullable) {
     418            6 :                         csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER"));
     419           79 :                 } else if (sig.return_type.type_symbol == null) {
     420           61 :                         csignew.add_argument (new CCodeConstant ("G_TYPE_NONE"));
     421           18 :                 } else if (sig.return_type.is_real_non_null_struct_type ()) {
     422            2 :                         csignew.add_argument (new CCodeConstant ("G_TYPE_NONE"));
     423              :                 } else {
     424           16 :                         csignew.add_argument (new CCodeConstant (get_ccode_type_id (sig.return_type.type_symbol)));
     425              :                 }
     426              : 
     427           87 :                 int params_len = 0;
     428          235 :                 foreach (Parameter param in params) {
     429           74 :                         params_len++;
     430           74 :                         if (param.variable_type is ArrayType) {
     431            3 :                                 params_len += ((ArrayType) param.variable_type).rank;
     432           71 :                         } else if (param.variable_type is DelegateType) {
     433            3 :                                 unowned DelegateType delegate_type = (DelegateType) param.variable_type;
     434            3 :                                 if (delegate_type.delegate_symbol.has_target) {
     435            2 :                                         params_len++;
     436            2 :                                         if (delegate_type.is_disposable ()) {
     437            1 :                                                 params_len++;
     438              :                                         }
     439              :                                 }
     440              :                         }
     441              :                 }
     442           87 :                 if (sig.return_type.is_real_non_null_struct_type ()) {
     443            2 :                         params_len++;
     444              :                 }
     445              : 
     446           87 :                 csignew.add_argument (new CCodeConstant ("%d".printf (params_len)));
     447          235 :                 foreach (Parameter param in params) {
     448           77 :                         if (param.variable_type is ArrayType) {
     449            3 :                                 var array_type = (ArrayType) param.variable_type;
     450            3 :                                 if (array_type.element_type.type_symbol == string_type.type_symbol) {
     451            2 :                                         csignew.add_argument (new CCodeConstant ("G_TYPE_STRV"));
     452              :                                 } else {
     453            1 :                                         csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER"));
     454              :                                 }
     455            3 :                                 assert (get_ccode_has_type_id (array_type.length_type.type_symbol));
     456            3 :                                 var length_type_id = get_ccode_type_id (array_type.length_type.type_symbol);
     457            8 :                                 for (var i = 0; i < array_type.rank; i++) {
     458            5 :                                         csignew.add_argument (new CCodeConstant (length_type_id));
     459              :                                 }
     460           71 :                         } else if (param.variable_type is DelegateType) {
     461            3 :                                 unowned DelegateType delegate_type = (DelegateType) param.variable_type;
     462            3 :                                 csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER"));
     463            3 :                                 if (delegate_type.delegate_symbol.has_target) {
     464            2 :                                         csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER"));
     465            2 :                                         if (delegate_type.is_disposable ()) {
     466            1 :                                                 csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER"));
     467              :                                         }
     468              :                                 }
     469           68 :                         } else if (param.variable_type is PointerType || param.variable_type is GenericType || param.direction != ParameterDirection.IN) {
     470            5 :                                 csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER"));
     471           63 :                         } else if (param.variable_type is ErrorType) {
     472            2 :                                 csignew.add_argument (new CCodeConstant ("G_TYPE_ERROR"));
     473           61 :                         } else if (param.variable_type is ValueType && param.variable_type.nullable) {
     474            8 :                                 csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER"));
     475              :                         } else {
     476           53 :                                 csignew.add_argument (new CCodeConstant (get_ccode_type_id (param.variable_type.type_symbol)));
     477              :                         }
     478              :                 }
     479           87 :                 if (sig.return_type.is_real_non_null_struct_type ()) {
     480            2 :                         csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER"));
     481              :                 }
     482              : 
     483           87 :                 marshal_arg.name = marshaller;
     484              : 
     485          174 :                 return new CCodeAssignment (get_signal_id_cexpression (sig), csignew);
     486              :         }
     487              : 
     488         1305 :         public override void visit_element_access (ElementAccess expr) {
     489         1305 :                 if (!(expr.container is MemberAccess && expr.container.symbol_reference is Signal)) {
     490         1289 :                         base.visit_element_access (expr);
     491         1289 :                         return;
     492              :                 }
     493              : 
     494           19 :                 if (expr.parent_node is MethodCall) {
     495              :                         // detailed signal emission
     496            3 :                         unowned Signal sig = (Signal) expr.symbol_reference;
     497            3 :                         unowned MemberAccess ma = (MemberAccess) expr.container;
     498            3 :                         var detail_expr = expr.get_indices ().get (0);
     499              : 
     500            3 :                         set_cvalue (expr, emit_signal (sig, ma, detail_expr));
     501              :                 } else {
     502              :                         // signal connect or disconnect
     503              :                 }
     504              :         }
     505              : 
     506           89 :         bool in_gobject_instance (Method m) {
     507           89 :                 bool result = false;
     508           89 :                 if (m.binding == MemberBinding.INSTANCE) {
     509           30 :                         result = m.this_parameter.variable_type.type_symbol.is_subtype_of (gobject_type);
     510              :                 }
     511              :                 return result;
     512              :         }
     513              : 
     514        75800 :         public override void visit_member_access (MemberAccess expr) {
     515        75800 :                 if (!(expr.symbol_reference is Signal)) {
     516        75602 :                         base.visit_member_access (expr);
     517        75602 :                         return;
     518              :                 }
     519              : 
     520          198 :                 unowned Signal sig = (Signal) expr.symbol_reference;
     521              : 
     522          198 :                 set_cvalue (expr, emit_signal (sig, expr));
     523              :         }
     524              : 
     525          201 :         CCodeExpression emit_signal (Signal sig, MemberAccess expr, Expression? detail_expr = null) {
     526          201 :                 CCodeExpression pub_inst = null;
     527              : 
     528          201 :                 if (expr.inner != null) {
     529          201 :                         pub_inst = get_cvalue (expr.inner);
     530              :                 }
     531              : 
     532          201 :                 if (expr.inner is BaseAccess && sig.is_virtual) {
     533            2 :                         var m = sig.default_handler;
     534            2 :                         var base_class = (Class) m.parent_symbol;
     535            2 :                         var vcast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function (base_class)));
     536            2 :                         vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (current_class))));
     537            2 :                         return new CCodeMemberAccess.pointer (vcast, m.name);
     538              :                 }
     539              : 
     540          199 :                 if (!sig.external_package && expr.source_reference.file == sig.source_reference.file && !(sig is DynamicSignal)) {
     541          180 :                         var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit"));
     542          180 :                         ccall.add_argument (pub_inst);
     543          180 :                         ccall.add_argument (get_signal_id_cexpression (sig));
     544          180 :                         if (detail_expr == null) {
     545          177 :                                 ccall.add_argument (new CCodeConstant ("0"));
     546              :                         } else {
     547            3 :                                 ccall.add_argument (get_detail_cexpression (detail_expr, expr));
     548              :                         }
     549          180 :                         return ccall;
     550           19 :                 } else if (get_ccode_has_emitter (sig)) {
     551              :                         string emitter_func;
     552           11 :                         if (sig.emitter != null) {
     553           11 :                                 if (!sig.external_package && expr.source_reference.file != sig.source_reference.file) {
     554            0 :                                         generate_method_declaration (sig.emitter, cfile);
     555              :                                 }
     556           11 :                                 emitter_func = get_ccode_lower_case_name (sig.emitter);
     557              :                         } else {
     558            0 :                                 unowned TypeSymbol sym = (TypeSymbol) sig.parent_symbol;
     559            0 :                                 emitter_func = "%s_%s".printf (get_ccode_lower_case_name (sym), get_ccode_lower_case_name (sig));
     560              :                         }
     561           11 :                         var ccall = new CCodeFunctionCall (new CCodeIdentifier (emitter_func));
     562           11 :                         ccall.add_argument (pub_inst);
     563           11 :                         return ccall;
     564              :                 } else {
     565            8 :                         var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name"));
     566            8 :                         ccall.add_argument (pub_inst);
     567            8 :                         if (detail_expr == null) {
     568            8 :                                 ccall.add_argument (get_signal_canonical_constant (sig));
     569              :                         } else {
     570            0 :                                 ccall.add_argument (get_signal_name_cexpression (sig, detail_expr, expr));
     571              :                         }
     572            8 :                         return ccall;
     573              :                 }
     574              :         }
     575              : 
     576        17647 :         public override void visit_method_call (MethodCall expr) {
     577        17546 :                 var method_type = expr.call.value_type as MethodType;
     578              : 
     579        16773 :                 if (method_type == null || !(method_type.method_symbol.parent_symbol is Signal)) {
     580              :                         // no signal connect/disconnect call
     581        17445 :                         base.visit_method_call (expr);
     582        17445 :                         return;
     583              :                 }
     584              : 
     585          101 :                 var sig = (Signal) method_type.method_symbol.parent_symbol;
     586          101 :                 var signal_access = ((MemberAccess) expr.call).inner;
     587          101 :                 var handler = expr.get_argument_list ().get (0);
     588              : 
     589          101 :                 bool disconnect = (method_type.method_symbol.name == "disconnect");
     590          101 :                 bool after = (method_type.method_symbol.name == "connect_after");
     591              : 
     592          101 :                 var cexpr = connect_signal (sig, signal_access, handler, disconnect, after, expr);
     593          101 :                 set_cvalue (expr, cexpr);
     594              :         }
     595              : 
     596          101 :         CCodeExpression? connect_signal (Signal sig, Expression signal_access, Expression handler, bool disconnect, bool after, CodeNode expr) {
     597              :                 string connect_func;
     598              : 
     599          101 :                 DelegateType? dt = null;
     600          101 :                 if (handler.symbol_reference is Variable) {
     601           20 :                         dt = ((Variable) handler.symbol_reference).variable_type as DelegateType;
     602           20 :                         if (dt != null && !context.experimental) {
     603           20 :                                 Report.warning (handler.source_reference, "Connecting delegates to signals is experimental");
     604              :                         }
     605              :                         // Use actual lambda expression if available for proper target/destroy handling
     606           20 :                         if (((Variable) handler.symbol_reference).initializer is LambdaExpression) {
     607           14 :                                 handler = ((Variable) handler.symbol_reference).initializer;
     608           14 :                                 dt = null;
     609              :                         }
     610              :                 }
     611          101 :                 var m = handler.symbol_reference as Method;
     612              : 
     613          101 :                 if (!disconnect) {
     614              :                         // connect
     615           90 :                         if (!(sig is DynamicSignal) && ((m != null && m.closure) || (dt != null && dt.value_owned))) {
     616           14 :                                 connect_func = "g_signal_connect_data";
     617           76 :                         } else if (m != null && in_gobject_instance (m)) {
     618           13 :                                 connect_func = "g_signal_connect_object";
     619           63 :                         } else if (!after) {
     620           62 :                                 connect_func = "g_signal_connect";
     621              :                         } else {
     622            1 :                                 connect_func = "g_signal_connect_after";
     623              :                         }
     624              :                 } else {
     625              :                         // disconnect
     626           11 :                         if (sig is DynamicSignal) {
     627            0 :                                 connect_func = "VALA_UNSUPPORTED";
     628              :                         } else {
     629           11 :                                 connect_func = "g_signal_handlers_disconnect_matched";
     630              :                         }
     631              :                 }
     632              : 
     633          101 :                 var ccall = new CCodeFunctionCall (new CCodeIdentifier (connect_func));
     634              : 
     635          101 :                 CCodeExpression signal_name_cexpr = null;
     636              : 
     637              :                 // first argument: instance of sender
     638              :                 MemberAccess ma;
     639          114 :                 if (signal_access is ElementAccess) {
     640           13 :                         var ea = (ElementAccess) signal_access;
     641           13 :                         ma = (MemberAccess) ea.container;
     642           13 :                         var detail_expr = ea.get_indices ().get (0);
     643           13 :                         signal_name_cexpr = get_signal_name_cexpression (sig, detail_expr, expr);
     644              :                 } else {
     645           88 :                         ma = (MemberAccess) signal_access;
     646           88 :                         signal_name_cexpr = get_signal_name_cexpression (sig, null, expr);
     647              :                 }
     648          101 :                 if (ma.inner != null) {
     649          101 :                         ccall.add_argument ((CCodeExpression) get_ccodenode (ma.inner));
     650              :                 } else {
     651            0 :                         ccall.add_argument (get_this_cexpression ());
     652              :                 }
     653              : 
     654          101 :                 if (sig is DynamicSignal) {
     655              :                         // dynamic_signal_connect or dynamic_signal_disconnect
     656              : 
     657              :                         // second argument: signal name
     658            6 :                         ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_ccode_name (sig))));
     659          106 :                 } else if (!disconnect) {
     660              :                         // g_signal_connect_object or g_signal_connect
     661              : 
     662              :                         // second argument: signal name
     663           84 :                         ccall.add_argument (signal_name_cexpr);
     664              :                 } else {
     665              :                         // g_signal_handlers_disconnect_matched
     666              : 
     667              :                         // second argument: mask
     668           11 :                         if (!(signal_access is ElementAccess)) {
     669           10 :                                 ccall.add_argument (new CCodeConstant ("G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA"));
     670              :                         } else {
     671            1 :                                 ccall.add_argument (new CCodeConstant ("G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA"));
     672              :                         }
     673              : 
     674              :                         // get signal id
     675           11 :                         var temp_decl = get_temp_variable (uint_type);
     676           11 :                         emit_temp_var (temp_decl);
     677           11 :                         var parse_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_parse_name"));
     678           11 :                         parse_call.add_argument (signal_name_cexpr);
     679           11 :                         var decl_type = (TypeSymbol) sig.parent_symbol;
     680           11 :                         parse_call.add_argument (new CCodeIdentifier (get_ccode_type_id (decl_type)));
     681           11 :                         parse_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_decl.name)));
     682           11 :                         LocalVariable? detail_temp_decl = null;
     683           11 :                         if (!(signal_access is ElementAccess)) {
     684           10 :                                 parse_call.add_argument (new CCodeConstant ("NULL"));
     685           10 :                                 parse_call.add_argument (new CCodeConstant ("FALSE"));
     686              :                         } else {
     687            1 :                                 detail_temp_decl = get_temp_variable (gquark_type);
     688            1 :                                 emit_temp_var (detail_temp_decl);
     689            1 :                                 parse_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (detail_temp_decl.name)));
     690            1 :                                 parse_call.add_argument (new CCodeConstant ("TRUE"));
     691              :                         }
     692           11 :                         ccode.add_expression (parse_call);
     693              : 
     694              :                         // third argument: signal_id
     695           11 :                         ccall.add_argument (get_variable_cexpression (temp_decl.name));
     696              : 
     697              :                         // fourth argument: detail
     698           11 :                         if (detail_temp_decl == null) {
     699           10 :                                 ccall.add_argument (new CCodeConstant ("0"));
     700              :                         } else {
     701            1 :                                 ccall.add_argument (get_variable_cexpression (detail_temp_decl.name));
     702              :                         }
     703              :                         // fifth argument: closure
     704           11 :                         ccall.add_argument (new CCodeConstant ("NULL"));
     705              :                 }
     706              : 
     707              :                 // third resp. sixth argument: handler
     708          101 :                 ccall.add_argument (new CCodeCastExpression (get_cvalue (handler), "GCallback"));
     709              : 
     710          113 :                 if (m != null && m.closure) {
     711              :                         // g_signal_connect_data
     712              : 
     713              :                         // fourth argument: user_data
     714              :                         CCodeExpression handler_destroy_notify;
     715           12 :                         ccall.add_argument (get_delegate_target_cexpression (handler, out handler_destroy_notify));
     716              : 
     717              :                         // fifth argument: destroy_notify
     718           12 :                         ccall.add_argument (new CCodeCastExpression (handler_destroy_notify, "GClosureNotify"));
     719              : 
     720              :                         // sixth argument: connect_flags
     721           12 :                         if (!after)
     722           12 :                                 ccall.add_argument (new CCodeConstant ("0"));
     723              :                         else
     724            0 :                                 ccall.add_argument (new CCodeConstant ("G_CONNECT_AFTER"));
     725           89 :                 } else if (m != null && m.binding == MemberBinding.INSTANCE) {
     726              :                         // g_signal_connect_object or g_signal_handlers_disconnect_matched
     727              :                         // or dynamic_signal_connect or dynamic_signal_disconnect
     728              : 
     729              :                         // fourth resp. seventh argument: object/user_data
     730           26 :                         if (handler is MemberAccess) {
     731            6 :                                 var right_ma = (MemberAccess) handler;
     732            6 :                                 if (right_ma.inner != null) {
     733            6 :                                         ccall.add_argument (get_cvalue (right_ma.inner));
     734              :                                 } else {
     735            0 :                                         ccall.add_argument (get_this_cexpression ());
     736              :                                 }
     737           14 :                         } else if (handler is LambdaExpression) {
     738           14 :                                 ccall.add_argument (get_this_cexpression ());
     739              :                         }
     740           20 :                         if (!disconnect && in_gobject_instance (m)) {
     741              :                                 // g_signal_connect_object
     742              : 
     743              :                                 // fifth argument: connect_flags
     744           13 :                                 if (!after)
     745           12 :                                         ccall.add_argument (new CCodeConstant ("0"));
     746              :                                 else
     747            1 :                                         ccall.add_argument (new CCodeConstant ("G_CONNECT_AFTER"));
     748              :                         }
     749           75 :                 } else if (dt != null && dt.delegate_symbol.has_target) {
     750              :                         // fourth argument: user_data
     751              :                         CCodeExpression handler_destroy_notify;
     752            6 :                         ccall.add_argument (get_delegate_target_cexpression (handler, out handler_destroy_notify));
     753            6 :                         if (!disconnect && dt.value_owned) {
     754              :                                 // fifth argument: destroy_notify
     755              :                                 //FIXME handler_destroy_notify is NULL
     756            2 :                                 ccall.add_argument (new CCodeCastExpression (handler_destroy_notify, "GClosureNotify"));
     757              :                                 // sixth argument: connect_flags
     758            2 :                                 if (!after)
     759            2 :                                         ccall.add_argument (new CCodeConstant ("0"));
     760              :                                 else
     761            0 :                                         ccall.add_argument (new CCodeConstant ("G_CONNECT_AFTER"));
     762              :                         }
     763              :                 } else {
     764              :                         // g_signal_connect or g_signal_connect_after or g_signal_handlers_disconnect_matched
     765              :                         // or dynamic_signal_connect or dynamic_signal_disconnect
     766              : 
     767              :                         // fourth resp. seventh argument: user_data
     768           63 :                         ccall.add_argument (new CCodeConstant ("NULL"));
     769              :                 }
     770              : 
     771          101 :                 if (disconnect || expr.parent_node is ExpressionStatement) {
     772           93 :                         ccode.add_expression (ccall);
     773           93 :                         return null;
     774              :                 } else {
     775            8 :                         var temp_var = get_temp_variable (ulong_type);
     776            8 :                         var temp_ref = get_variable_cexpression (temp_var.name);
     777              : 
     778            8 :                         emit_temp_var (temp_var);
     779              : 
     780            8 :                         ccode.add_assignment (temp_ref, ccall);
     781              : 
     782            8 :                         return temp_ref;
     783              :                 }
     784              :         }
     785              : }
     786              : 
        

Generated by: LCOV version 2.0-1