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

            Line data    Source code
       1              : /* valagdbusservermodule.vala
       2              :  *
       3              :  * Copyright (C) 2010-2011  Jürg Billeter
       4              :  *
       5              :  * This library is free software; you can redistribute it and/or
       6              :  * modify it under the terms of the GNU Lesser General Public
       7              :  * License as published by the Free Software Foundation; either
       8              :  * version 2.1 of the License, or (at your option) any later version.
       9              : 
      10              :  * This library is distributed in the hope that it will be useful,
      11              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13              :  * Lesser General Public License for more details.
      14              : 
      15              :  * You should have received a copy of the GNU Lesser General Public
      16              :  * License along with this library; if not, write to the Free Software
      17              :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
      18              :  *
      19              :  * Author:
      20              :  *      Jürg Billeter <j@bitron.ch>
      21              :  */
      22              : 
      23         4371 : public class Vala.GDBusServerModule : GDBusClientModule {
      24          118 :         string generate_dbus_wrapper (Method m, ObjectTypeSymbol sym, bool ready = false) {
      25          118 :                 string wrapper_name = "_dbus_%s".printf (get_ccode_name (m));
      26          118 :                 bool need_goto_label = ready;
      27              : 
      28          118 :                 if (m.base_method != null) {
      29            0 :                         m = m.base_method;
      30          118 :                 } else if (m.base_interface_method != null) {
      31           62 :                         m = m.base_interface_method;
      32              :                 }
      33              : 
      34          118 :                 if (ready) {
      35              :                         // async ready function
      36           24 :                         wrapper_name += "_ready";
      37              :                 }
      38              : 
      39          118 :                 var function = new CCodeFunction (wrapper_name);
      40          118 :                 function.modifiers = CCodeModifiers.STATIC;
      41              : 
      42          118 :                 if (!ready) {
      43           94 :                         function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*"));
      44           94 :                         function.add_parameter (new CCodeParameter ("_parameters_", "GVariant*"));
      45           94 :                         function.add_parameter (new CCodeParameter ("invocation", "GDBusMethodInvocation*"));
      46              :                 } else {
      47           24 :                         function.add_parameter (new CCodeParameter ("source_object", "GObject *"));
      48           24 :                         function.add_parameter (new CCodeParameter ("_res_", "GAsyncResult *"));
      49           24 :                         function.add_parameter (new CCodeParameter ("_user_data_", "gpointer"));
      50              :                 }
      51              : 
      52          118 :                 push_function (function);
      53              : 
      54          118 :                 CCodeIdentifier ready_data_expr = m.coroutine ? new CCodeIdentifier ("_ready_data") : null;
      55          118 :                 string ready_data_struct_name = Symbol.lower_case_to_camel_case (get_ccode_name (m)) + "ReadyData";
      56              : 
      57          118 :                 if (ready) {
      58           24 :                         ccode.add_declaration (ready_data_struct_name + "*", new CCodeVariableDeclarator ("_ready_data", new CCodeIdentifier ("_user_data_")));
      59           24 :                         ccode.add_declaration ("GDBusMethodInvocation*", new CCodeVariableDeclarator ("invocation", new CCodeMemberAccess.pointer (ready_data_expr, "_invocation_")));
      60              :                 }
      61              : 
      62          118 :                 var connection = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_connection"));
      63          118 :                 connection.add_argument (new CCodeIdentifier ("invocation"));
      64              : 
      65          118 :                 bool no_reply = is_dbus_no_reply (m);
      66          118 :                 bool uses_fd = dbus_method_uses_file_descriptor (m);
      67          118 :                 if (uses_fd) {
      68            8 :                         cfile.add_include ("gio/gunixfdlist.h");
      69            8 :                         ccode.add_declaration ("GUnixFDList*", new CCodeVariableDeclarator ("_fd_list"));
      70              :                 }
      71              : 
      72          118 :                 bool uses_error = false;
      73              : 
      74          118 :                 if (!m.coroutine || ready) {
      75           94 :                         ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("error", new CCodeConstant ("NULL")));
      76              :                         uses_error = true;
      77              :                 }
      78              : 
      79          212 :                 if (!ready) {
      80           94 :                         ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator ("_arguments_iter"));
      81              : 
      82           94 :                         var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
      83           94 :                         iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_iter")));
      84           94 :                         iter_init.add_argument (new CCodeIdentifier ("_parameters_"));
      85           94 :                         ccode.add_expression (iter_init);
      86              :                 }
      87              : 
      88              :                 CCodeFunctionCall ccall;
      89          118 :                 if (!ready) {
      90           94 :                         ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (m)));
      91           94 :                         ccall.add_argument (new CCodeIdentifier ("self"));
      92              :                 } else {
      93           24 :                         ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_finish_name (m)));
      94           24 :                         ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("source_object"), get_ccode_name (sym) + "*"));
      95           24 :                         ccall.add_argument (new CCodeIdentifier ("_res_"));
      96              :                 }
      97              : 
      98          212 :                 if (!ready) {
      99           94 :                         if (uses_fd) {
     100            6 :                                 ccode.add_declaration ("gint", new CCodeVariableDeclarator.zero ("_fd_index", new CCodeConstant ("0")));
     101            6 :                                 ccode.add_declaration ("gint", new CCodeVariableDeclarator ("_fd"));
     102              :                         }
     103              : 
     104           94 :                         CCodeStruct? ready_data_struct = null;
     105              : 
     106          118 :                         if (m.coroutine) {
     107           24 :                                 ready_data_struct = new CCodeStruct ("_" + ready_data_struct_name);
     108           24 :                                 ready_data_struct.add_field ("GDBusMethodInvocation*", "_invocation_");
     109           24 :                                 append_struct (ready_data_struct);
     110              : 
     111           24 :                                 var ready_data_alloc = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0"));
     112           24 :                                 ready_data_alloc.add_argument (new CCodeIdentifier (ready_data_struct_name));
     113              : 
     114           24 :                                 ccode.add_declaration (ready_data_struct_name + "*", new CCodeVariableDeclarator ("_ready_data"));
     115           24 :                                 ccode.add_assignment (ready_data_expr, ready_data_alloc);
     116              : 
     117           24 :                                 ccode.add_assignment (new CCodeMemberAccess.pointer (ready_data_expr, "_invocation_"), new CCodeIdentifier ("invocation"));
     118              :                         }
     119              : 
     120          239 :                         foreach (Parameter param in m.get_parameters ()) {
     121           88 :                                 string param_name = get_variable_cname (param.name);
     122           88 :                                 if (param.direction != ParameterDirection.IN) {
     123           31 :                                         continue;
     124              :                                 }
     125              : 
     126           61 :                                 if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.Cancellable") {
     127            4 :                                         continue;
     128              :                                 }
     129              : 
     130           57 :                                 if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.BusName") {
     131              :                                         // ignore BusName sender parameters
     132            0 :                                         continue;
     133              :                                 }
     134              : 
     135              :                                 CCodeExpression param_expr;
     136           57 :                                 if (ready_data_expr != null) {
     137           16 :                                         param_expr = new CCodeMemberAccess.pointer (ready_data_expr, param_name);
     138              :                                 } else {
     139           41 :                                         param_expr = new CCodeIdentifier (param_name);
     140              :                                 }
     141              : 
     142           57 :                                 var owned_type = param.variable_type.copy ();
     143           57 :                                 owned_type.value_owned = true;
     144              : 
     145           57 :                                 if (ready_data_struct != null) {
     146           16 :                                         ready_data_struct.add_field (get_ccode_name (owned_type), param_name);
     147              :                                 } else {
     148           41 :                                         ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero (param_name, default_value_for_type (param.variable_type, true)));
     149              :                                 }
     150              : 
     151        16988 :                                 var array_type = param.variable_type as ArrayType;
     152           16 :                                 if (array_type != null) {
     153            8 :                                         var length_ctype = get_ccode_array_length_type (array_type);
     154           16 :                                         for (int dim = 1; dim <= array_type.rank; dim++) {
     155            8 :                                                 string length_cname = get_variable_array_length_cname (param, dim);
     156              : 
     157            8 :                                                 if (ready_data_struct != null) {
     158            2 :                                                         ready_data_struct.add_field (length_ctype, length_cname);
     159              :                                                 } else {
     160            6 :                                                         ccode.add_declaration (length_ctype, new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
     161              :                                                 }
     162              :                                         }
     163              :                                 }
     164              : 
     165           57 :                                 var message_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_message"));
     166           57 :                                 message_expr.add_argument (new CCodeIdentifier ("invocation"));
     167              : 
     168              :                                 bool may_fail;
     169           57 :                                 receive_dbus_value (param.variable_type, message_expr, new CCodeIdentifier ("_arguments_iter"), param_expr, param, new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")), out may_fail);
     170              : 
     171           69 :                                 if (may_fail) {
     172           12 :                                         if (!uses_error) {
     173            4 :                                                 ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("error", new CCodeConstant ("NULL")));
     174              :                                                 uses_error = true;
     175              :                                         }
     176              : 
     177           12 :                                         ccode.open_if (new CCodeIdentifier ("error"));
     178              : 
     179           12 :                                         var return_error = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_take_error"));
     180           12 :                                         return_error.add_argument (new CCodeIdentifier ("invocation"));
     181           12 :                                         return_error.add_argument (new CCodeIdentifier ("error"));
     182           12 :                                         ccode.add_expression (return_error);
     183              : 
     184           12 :                                         if (need_goto_label || requires_destroy (owned_type)) {
     185            6 :                                                 ccode.add_goto ("_error");
     186            6 :                                                 need_goto_label = true;
     187              :                                         } else {
     188            6 :                                                 ccode.add_return ();
     189              :                                         }
     190              : 
     191           12 :                                         ccode.close ();
     192           45 :                                 } else if (!need_goto_label && m.tree_can_fail && requires_destroy (owned_type)) {
     193           17 :                                         need_goto_label = true;
     194              :                                 }
     195              :                         }
     196              :                 }
     197              : 
     198          360 :                 foreach (Parameter param in m.get_parameters ()) {
     199          116 :                         string param_name = get_variable_cname (param.name);
     200              : 
     201              :                         CCodeExpression param_expr;
     202          116 :                         if (ready_data_expr != null && param.direction == ParameterDirection.IN) {
     203           36 :                                 param_expr = new CCodeMemberAccess.pointer (ready_data_expr, param_name);
     204              :                         } else {
     205           80 :                                 param_expr = new CCodeIdentifier (param_name);
     206              :                         }
     207              : 
     208          116 :                         if (param.direction == ParameterDirection.IN && !ready) {
     209           61 :                                 if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.Cancellable") {
     210            4 :                                         ccall.add_argument (new CCodeConstant ("NULL"));
     211            4 :                                         continue;
     212              :                                 }
     213              : 
     214           57 :                                 if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.BusName") {
     215              :                                         // ignore BusName sender parameters
     216            0 :                                         var sender = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_sender"));
     217            0 :                                         sender.add_argument (new CCodeIdentifier ("invocation"));
     218            0 :                                         ccall.add_argument (sender);
     219            0 :                                         continue;
     220              :                                 }
     221              : 
     222           57 :                                 unowned Struct? st = param.variable_type.type_symbol as Struct;
     223           57 :                                 if (st != null && !st.is_simple_type ()) {
     224            2 :                                         ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, param_expr));
     225              :                                 } else {
     226           55 :                                         ccall.add_argument (param_expr);
     227              :                                 }
     228           55 :                         } else if (param.direction == ParameterDirection.OUT && (!m.coroutine || ready)) {
     229           27 :                                 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, param_expr));
     230              :                         }
     231              : 
     232          112 :                         var array_type = param.variable_type as ArrayType;
     233          126 :                         if (array_type != null) {
     234           28 :                                 for (int dim = 1; dim <= array_type.rank; dim++) {
     235           14 :                                         string length_cname = get_variable_array_length_cname (param, dim);
     236              : 
     237              :                                         CCodeExpression length_expr;
     238           14 :                                         if (ready_data_expr != null && param.direction == ParameterDirection.IN)
     239            4 :                                                 length_expr = new CCodeMemberAccess.pointer (ready_data_expr, length_cname);
     240              :                                         else
     241           10 :                                                 length_expr = new CCodeIdentifier (length_cname);
     242              : 
     243           14 :                                         if (param.direction == ParameterDirection.IN && !ready) {
     244            8 :                                                 ccall.add_argument (length_expr);
     245            6 :                                         } else if (param.direction == ParameterDirection.OUT && !no_reply && (!m.coroutine || ready)) {
     246            4 :                                                 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, length_expr));
     247              :                                         }
     248              :                                 }
     249              :                         }
     250              :                 }
     251              : 
     252          118 :                 if (!m.coroutine || ready) {
     253           94 :                         if (!(m.return_type is VoidType)) {
     254           73 :                                 if (m.return_type.is_real_non_null_struct_type ()) {
     255            2 :                                         ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
     256              :                                 } else {
     257           57 :                                         var array_type = m.return_type as ArrayType;
     258           14 :                                         if (array_type != null) {
     259           34 :                                                 for (int dim = 1; dim <= array_type.rank; dim++) {
     260           20 :                                                         string length_cname = get_array_length_cname ("result", dim);
     261              : 
     262           20 :                                                         ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
     263              :                                                 }
     264              :                                         }
     265              :                                 }
     266              :                         }
     267              :                 }
     268              : 
     269          118 :                 if (m.coroutine && !ready) {
     270           24 :                         ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier (wrapper_name + "_ready"), "GAsyncReadyCallback"));
     271           24 :                         ccall.add_argument (ready_data_expr);
     272              :                 }
     273              : 
     274          118 :                 if (!m.coroutine || ready) {
     275           94 :                         if (m.tree_can_fail) {
     276           69 :                                 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
     277              :                         }
     278              :                 }
     279              : 
     280          210 :                 if (!no_reply && (!m.coroutine || ready)) {
     281           92 :                         if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) {
     282           35 :                                 ccode.add_expression (ccall);
     283              :                         } else {
     284           57 :                                 ccode.add_assignment (new CCodeIdentifier ("result"), ccall);
     285              :                         }
     286              : 
     287          160 :                         if (m.tree_can_fail) {
     288           68 :                                 ccode.open_if (new CCodeIdentifier ("error"));
     289              : 
     290           68 :                                 var return_error = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_take_error"));
     291           68 :                                 return_error.add_argument (new CCodeIdentifier ("invocation"));
     292           68 :                                 return_error.add_argument (new CCodeIdentifier ("error"));
     293           68 :                                 ccode.add_expression (return_error);
     294              : 
     295           68 :                                 if (need_goto_label) {
     296           32 :                                         ccode.add_goto ("_error");
     297              :                                 } else {
     298           36 :                                         ccode.add_return ();
     299              :                                 }
     300              : 
     301           68 :                                 ccode.close ();
     302              :                         }
     303              : 
     304           92 :                         ccode.add_declaration ("GDBusMessage*", new CCodeVariableDeclarator.zero ("_reply_message", new CCodeConstant ("NULL")));
     305              : 
     306           92 :                         var message_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_message"));
     307           92 :                         message_expr.add_argument (new CCodeIdentifier ("invocation"));
     308              : 
     309           92 :                         ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_new_method_reply"));
     310           92 :                         ccall.add_argument (message_expr);
     311           92 :                         ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall);
     312              : 
     313           92 :                         ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply"));
     314           92 :                         ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_reply_builder"));
     315              : 
     316           92 :                         var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
     317           92 :                         builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder")));
     318           92 :                         builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
     319           92 :                         ccode.add_expression (builder_init);
     320              : 
     321           92 :                         if (uses_fd) {
     322            6 :                                 ccode.add_assignment (new CCodeIdentifier ("_fd_list"), new CCodeFunctionCall (new CCodeIdentifier ("g_unix_fd_list_new")));
     323              :                         }
     324              : 
     325          205 :                         foreach (Parameter param in m.get_parameters ()) {
     326           86 :                                 if (param.direction != ParameterDirection.OUT) {
     327           59 :                                         continue;
     328              :                                 }
     329              : 
     330           27 :                                 string param_name = get_variable_cname (param.name);
     331           27 :                                 var owned_type = param.variable_type.copy ();
     332           27 :                                 owned_type.value_owned = true;
     333              : 
     334           27 :                                 ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero (param_name, default_value_for_type (param.variable_type, true)));
     335              : 
     336           27 :                                 var array_type = param.variable_type as ArrayType;
     337            8 :                                 if (array_type != null) {
     338            4 :                                         var length_ctype = get_ccode_array_length_type (array_type);
     339            8 :                                         for (int dim = 1; dim <= array_type.rank; dim++) {
     340            4 :                                                 string length_cname = get_variable_array_length_cname (param, dim);
     341              : 
     342            4 :                                                 ccode.add_declaration (length_ctype, new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
     343              :                                         }
     344              :                                 }
     345              : 
     346           27 :                                 send_dbus_value (param.variable_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier (param_name), param);
     347              :                         }
     348              : 
     349           92 :                         if (!(m.return_type is VoidType)) {
     350          116 :                                 if (m.return_type.is_real_non_null_struct_type ()) {
     351            2 :                                         ccode.add_declaration (get_ccode_name (m.return_type), new CCodeVariableDeclarator.zero ("result", default_value_for_type (m.return_type, true)));
     352              : 
     353            2 :                                         send_dbus_value (m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"), m);
     354              : 
     355            4 :                                         if (requires_destroy (m.return_type)) {
     356              :                                                 // keep local alive (symbol_reference is weak)
     357            2 :                                                 var local = new LocalVariable (m.return_type, ".result");
     358            2 :                                                 ccode.add_expression (destroy_local (local));
     359              :                                         }
     360              :                                 } else {
     361           57 :                                         ccode.add_declaration (get_ccode_name (m.return_type), new CCodeVariableDeclarator ("result"));
     362              : 
     363           57 :                                         var array_type = m.return_type as ArrayType;
     364           28 :                                         if (array_type != null) {
     365           14 :                                                 var length_ctype = get_ccode_array_length_type (array_type);
     366           34 :                                                 for (int dim = 1; dim <= array_type.rank; dim++) {
     367           20 :                                                         string length_cname = get_array_length_cname ("result", dim);
     368              : 
     369           20 :                                                         ccode.add_declaration (length_ctype, new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
     370              :                                                 }
     371              :                                         }
     372              : 
     373           57 :                                         send_dbus_value (m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"), m);
     374              : 
     375           95 :                                         if (requires_destroy (m.return_type)) {
     376              :                                                 // keep local alive (symbol_reference is weak)
     377           38 :                                                 var local = new LocalVariable (m.return_type, ".result");
     378           38 :                                                 ccode.add_expression (destroy_local (local));
     379              :                                         }
     380              :                                 }
     381              :                         }
     382              : 
     383           92 :                         var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
     384           92 :                         builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder")));
     385           92 :                         ccode.add_assignment (new CCodeIdentifier ("_reply"), builder_end);
     386              : 
     387           92 :                         var set_body = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_body"));
     388           92 :                         set_body.add_argument (new CCodeIdentifier ("_reply_message"));
     389           92 :                         set_body.add_argument (new CCodeIdentifier ("_reply"));
     390           92 :                         ccode.add_expression (set_body);
     391              : 
     392           92 :                         if (uses_fd) {
     393            6 :                                 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_unix_fd_list"));
     394            6 :                                 ccall.add_argument (new CCodeIdentifier ("_reply_message"));
     395            6 :                                 ccall.add_argument (new CCodeIdentifier ("_fd_list"));
     396            6 :                                 ccode.add_expression (ccall);
     397              : 
     398            6 :                                 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
     399            6 :                                 ccall.add_argument (new CCodeIdentifier ("_fd_list"));
     400            6 :                                 ccode.add_expression (ccall);
     401              :                         }
     402              :                 } else {
     403           26 :                         ccode.add_expression (ccall);
     404              :                 }
     405              : 
     406          210 :                 if (!no_reply && (!m.coroutine || ready)) {
     407           92 :                         var return_value = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message"));
     408           92 :                         return_value.add_argument (connection);
     409           92 :                         return_value.add_argument (new CCodeIdentifier ("_reply_message"));
     410           92 :                         return_value.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
     411           92 :                         return_value.add_argument (new CCodeConstant ("NULL"));
     412           92 :                         return_value.add_argument (new CCodeConstant ("NULL"));
     413           92 :                         ccode.add_expression (return_value);
     414              : 
     415              :                         // free invocation like g_dbus_method_invocation_return_*
     416           92 :                         var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
     417           92 :                         unref_call.add_argument (new CCodeIdentifier ("invocation"));
     418           92 :                         ccode.add_expression (unref_call);
     419              : 
     420           92 :                         unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
     421           92 :                         unref_call.add_argument (new CCodeIdentifier ("_reply_message"));
     422           92 :                         ccode.add_expression (unref_call);
     423              :                 }
     424              : 
     425          118 :                 if (need_goto_label) {
     426           47 :                         ccode.add_label ("_error");
     427              :                 }
     428              : 
     429          346 :                 foreach (Parameter param in m.get_parameters ()) {
     430          200 :                         if ((param.direction == ParameterDirection.IN && (ready_data_expr == null || ready)) ||
     431           55 :                             (param.direction == ParameterDirection.OUT && !no_reply && (!m.coroutine || ready))) {
     432           88 :                                 if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.Cancellable") {
     433            4 :                                         continue;
     434              :                                 }
     435              : 
     436           84 :                                 if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.BusName") {
     437              :                                         // ignore BusName sender parameters
     438            0 :                                         continue;
     439              :                                 }
     440              : 
     441           84 :                                 var owned_type = param.variable_type.copy ();
     442           84 :                                 owned_type.value_owned = true;
     443              : 
     444           84 :                                 if (requires_destroy (owned_type)) {
     445          108 :                                         if (ready_data_expr != null && param.direction == ParameterDirection.IN) {
     446           10 :                                                 var target = new GLibValue (owned_type, new CCodeMemberAccess.pointer (ready_data_expr, param.name), true);
     447              : 
     448           10 :                                                 var array_type = owned_type as ArrayType;
     449            2 :                                                 if (array_type != null) {
     450            4 :                                                         for (int dim = 1; dim <= array_type.rank; dim++) {
     451            2 :                                                                 string length_cname = get_variable_array_length_cname (param, dim);
     452              : 
     453            2 :                                                                 target.append_array_length_cvalue (new CCodeMemberAccess.pointer (ready_data_expr, length_cname));
     454              :                                                         }
     455              :                                                 }
     456              : 
     457           10 :                                                 ccode.add_expression (destroy_value (target));
     458              :                                         } else {
     459              :                                                 // keep local alive (symbol_reference is weak)
     460           44 :                                                 var local = new LocalVariable (owned_type, get_variable_cname (param.name));
     461           44 :                                                 ccode.add_expression (destroy_local (local));
     462              :                                         }
     463              :                                 }
     464              :                         }
     465              :                 }
     466              : 
     467          142 :                 if (ready) {
     468           24 :                         var freecall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
     469           24 :                         freecall.add_argument (new CCodeIdentifier (ready_data_struct_name));
     470           24 :                         freecall.add_argument (ready_data_expr);
     471           24 :                         ccode.add_expression (freecall);
     472           94 :                 } else if (need_goto_label) {
     473           23 :                         ccode.add_statement (new CCodeEmptyStatement ());
     474              :                 }
     475              : 
     476          118 :                 pop_function ();
     477              : 
     478          118 :                 cfile.add_function_declaration (function);
     479          118 :                 cfile.add_function (function);
     480              : 
     481          118 :                 if (m.coroutine && !ready) {
     482              :                         // generate ready function
     483           24 :                         generate_dbus_wrapper (m, sym, true);
     484              :                 }
     485              : 
     486          118 :                 return wrapper_name;
     487              :         }
     488              : 
     489           10 :         string generate_dbus_signal_wrapper (Signal sig, ObjectTypeSymbol sym, string dbus_iface_name) {
     490           10 :                 string wrapper_name = "_dbus_%s_%s".printf (get_ccode_lower_case_name (sym), get_ccode_lower_case_name (sig));
     491              : 
     492           10 :                 var function = new CCodeFunction (wrapper_name, "void");
     493           10 :                 function.modifiers = CCodeModifiers.STATIC;
     494              : 
     495           10 :                 function.add_parameter (new CCodeParameter ("_sender", "GObject*"));
     496              : 
     497           30 :                 foreach (var param in sig.get_parameters ()) {
     498              :                         // ensure ccodenode of parameter is set
     499           10 :                         var cparam = generate_parameter (param, cfile, new HashMap<int,CCodeParameter> (), null);
     500              : 
     501           10 :                         function.add_parameter (cparam);
     502           12 :                         if (param.variable_type is ArrayType) {
     503            2 :                                 var array_type = (ArrayType) param.variable_type;
     504            2 :                                 var length_ctype = get_ccode_array_length_type (array_type);
     505            4 :                                 for (int dim = 1; dim <= array_type.rank; dim++) {
     506            2 :                                         function.add_parameter (new CCodeParameter (get_variable_array_length_cname (param, dim), length_ctype));
     507              :                                 }
     508              :                         }
     509              :                 }
     510              : 
     511           10 :                 function.add_parameter (new CCodeParameter ("_data", "gpointer*"));
     512              : 
     513           10 :                 push_function (function);
     514              : 
     515           10 :                 ccode.add_declaration ("GDBusConnection *", new CCodeVariableDeclarator ("_connection", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("1"))));
     516           10 :                 ccode.add_declaration ("const gchar *", new CCodeVariableDeclarator ("_path", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("2"))));
     517           10 :                 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
     518           10 :                 ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder"));
     519              : 
     520           10 :                 var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
     521           10 :                 builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
     522           10 :                 builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
     523           10 :                 ccode.add_expression (builder_init);
     524              : 
     525           30 :                 foreach (Parameter param in sig.get_parameters ()) {
     526           10 :                         string param_name = get_variable_cname (param.name);
     527           10 :                         CCodeExpression expr = new CCodeIdentifier (param_name);
     528           10 :                         if (param.variable_type.is_real_struct_type ()) {
     529            0 :                                 expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr);
     530              :                         }
     531           10 :                         write_expression (param.variable_type, new CCodeIdentifier ("_arguments_builder"), expr, param);
     532              :                 }
     533              : 
     534           10 :                 var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
     535           10 :                 builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
     536           10 :                 ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end);
     537              : 
     538           10 :                 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_emit_signal"));
     539           10 :                 ccall.add_argument (new CCodeIdentifier ("_connection"));
     540           10 :                 ccall.add_argument (new CCodeConstant ("NULL"));
     541           10 :                 ccall.add_argument (new CCodeIdentifier ("_path"));
     542           10 :                 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
     543           10 :                 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
     544           10 :                 ccall.add_argument (new CCodeIdentifier ("_arguments"));
     545           10 :                 ccall.add_argument (new CCodeConstant ("NULL"));
     546           10 :                 ccode.add_expression (ccall);
     547              : 
     548           10 :                 pop_function ();
     549              : 
     550           10 :                 cfile.add_function_declaration (function);
     551           10 :                 cfile.add_function (function);
     552              : 
     553           10 :                 return wrapper_name;
     554              :         }
     555              : 
     556           12 :         string generate_dbus_property_get_wrapper (Property prop, ObjectTypeSymbol sym) {
     557           12 :                 string wrapper_name = "_dbus_%s".printf (get_ccode_name (prop.get_accessor));
     558              : 
     559           12 :                 var function = new CCodeFunction (wrapper_name, "GVariant*");
     560           12 :                 function.modifiers = CCodeModifiers.STATIC;
     561           12 :                 function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*"));
     562              : 
     563           12 :                 push_function (function);
     564              : 
     565           12 :                 var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (prop.get_accessor)));
     566           12 :                 ccall.add_argument (new CCodeIdentifier ("self"));
     567              : 
     568           12 :                 if (prop.get_accessor.value_type.is_real_non_null_struct_type ()) {
     569            2 :                         ccode.add_declaration (get_ccode_name (prop.get_accessor.value_type), new CCodeVariableDeclarator.zero ("result", default_value_for_type (prop.get_accessor.value_type, true)));
     570            2 :                         ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
     571              : 
     572            2 :                         ccode.add_expression (ccall);
     573              :                 } else {
     574           10 :                         ccode.add_declaration (get_ccode_name (prop.get_accessor.value_type), new CCodeVariableDeclarator ("result"));
     575           10 :                         ccode.add_assignment (new CCodeIdentifier ("result"), ccall);
     576              : 
     577           10 :                         var array_type = prop.get_accessor.value_type as ArrayType;
     578            4 :                         if (array_type != null) {
     579            2 :                                 var length_ctype = get_ccode_array_length_type (array_type);
     580            4 :                                 for (int dim = 1; dim <= array_type.rank; dim++) {
     581            2 :                                         string length_cname = get_array_length_cname ("result", dim);
     582              : 
     583            2 :                                         ccode.add_declaration (length_ctype, new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
     584            2 :                                         ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
     585              :                                 }
     586              :                         }
     587              :                 }
     588              : 
     589           12 :                 ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply"));
     590              : 
     591           22 :                 if (get_dbus_signature (prop) != null) {
     592              :                         // raw GVariant
     593            2 :                         ccode.add_assignment (new CCodeIdentifier ("_reply"), new CCodeIdentifier("result"));
     594              :                 } else {
     595           10 :                         var reply_expr = serialize_expression (prop.get_accessor.value_type, new CCodeIdentifier ("result"));
     596              : 
     597           10 :                         ccode.add_assignment (new CCodeIdentifier ("_reply"), reply_expr);
     598              : 
     599           18 :                         if (requires_destroy (prop.get_accessor.value_type)) {
     600              :                                 // keep local alive (symbol_reference is weak)
     601            8 :                                 var local = new LocalVariable (prop.get_accessor.value_type, ".result");
     602            8 :                                 ccode.add_expression (destroy_local (local));
     603              :                         }
     604              :                 }
     605              : 
     606           12 :                 ccode.add_return (new CCodeIdentifier ("_reply"));
     607              : 
     608           12 :                 pop_function ();
     609              : 
     610           12 :                 cfile.add_function_declaration (function);
     611           12 :                 cfile.add_function (function);
     612              : 
     613           12 :                 return wrapper_name;
     614              :         }
     615              : 
     616           12 :         string generate_dbus_property_set_wrapper (Property prop, ObjectTypeSymbol sym) {
     617           12 :                 string wrapper_name = "_dbus_%s".printf (get_ccode_name (prop.set_accessor));
     618              : 
     619           12 :                 var function = new CCodeFunction (wrapper_name);
     620           12 :                 function.modifiers = CCodeModifiers.STATIC;
     621           12 :                 function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*"));
     622           12 :                 function.add_parameter (new CCodeParameter ("_value", "GVariant*"));
     623              : 
     624           12 :                 push_function (function);
     625              : 
     626           12 :                 var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (prop.set_accessor)));
     627           12 :                 ccall.add_argument (new CCodeIdentifier ("self"));
     628              : 
     629           12 :                 var owned_type = prop.property_type.copy ();
     630           12 :                 owned_type.value_owned = true;
     631              : 
     632           12 :                 ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero ("value", default_value_for_type (prop.property_type, true)));
     633              : 
     634           12 :                 unowned Struct? st = prop.property_type.type_symbol as Struct;
     635           12 :                 if (st != null && !st.is_simple_type ()) {
     636            2 :                         ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value")));
     637              :                 } else {
     638           10 :                         ccall.add_argument (new CCodeIdentifier ("value"));
     639              : 
     640           10 :                         var array_type = prop.property_type as ArrayType;
     641            4 :                         if (array_type != null) {
     642            2 :                                 var length_ctype = get_ccode_array_length_type (array_type);
     643            4 :                                 for (int dim = 1; dim <= array_type.rank; dim++) {
     644            2 :                                         ccode.add_declaration (length_ctype, new CCodeVariableDeclarator (get_array_length_cname ("value", dim)));
     645            2 :                                         ccall.add_argument (new CCodeIdentifier (get_array_length_cname ("value", dim)));
     646              :                                 }
     647              :                         }
     648              :                 }
     649              : 
     650           12 :                 var target = new CCodeIdentifier ("value");
     651              : 
     652           22 :                 if (get_dbus_signature (prop) != null) {
     653            2 :                         ccode.add_assignment (target, new CCodeIdentifier("_value"));
     654            2 :                         ccode.add_expression (ccall);
     655              :                 } else {
     656           10 :                         var expr = deserialize_expression (prop.property_type, new CCodeIdentifier ("_value"), target);
     657           10 :                         ccode.add_assignment (target, expr);
     658           10 :                         ccode.add_expression (ccall);
     659              : 
     660           18 :                         if (requires_destroy (owned_type)) {
     661              :                                 // keep local alive (symbol_reference is weak)
     662            8 :                                 var local = new LocalVariable (owned_type, "value");
     663            8 :                                 ccode.add_expression (destroy_local (local));
     664              :                         }
     665              :                 }
     666              : 
     667           12 :                 pop_function ();
     668              : 
     669           12 :                 cfile.add_function_declaration (function);
     670           12 :                 cfile.add_function (function);
     671              : 
     672           12 :                 return wrapper_name;
     673              :         }
     674              : 
     675          216 :         void handle_signals (ObjectTypeSymbol sym, bool connect) {
     676          108 :                 string dbus_iface_name = get_dbus_name (sym);
     677          108 :                 if (dbus_iface_name == null) {
     678            0 :                         return;
     679              :                 }
     680              : 
     681          152 :                 foreach (Signal sig in sym.get_signals ()) {
     682           24 :                         if (sig.access != SymbolAccessibility.PUBLIC) {
     683            4 :                                 continue;
     684              :                         }
     685           20 :                         if (!is_dbus_visible (sig)) {
     686            0 :                                 continue;
     687              :                         }
     688              : 
     689           40 :                         if (connect) {
     690           10 :                                 var connect_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_connect"));
     691           10 :                                 connect_call.add_argument (new CCodeIdentifier ("object"));
     692           10 :                                 connect_call.add_argument (get_signal_canonical_constant (sig));
     693           10 :                                 connect_call.add_argument (new CCodeCastExpression (new CCodeIdentifier (generate_dbus_signal_wrapper (sig, sym, dbus_iface_name)), "GCallback"));
     694           10 :                                 connect_call.add_argument (new CCodeIdentifier ("data"));
     695           10 :                                 ccode.add_expression (connect_call);
     696              :                         } else {
     697              :                                 // disconnect the signals
     698           10 :                                 var disconnect_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_handlers_disconnect_by_func"));
     699           10 :                                 disconnect_call.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")));
     700           10 :                                 disconnect_call.add_argument (new CCodeIdentifier ("_dbus_%s_%s".printf (get_ccode_lower_case_name (sym), get_ccode_lower_case_name (sig))));
     701           10 :                                 disconnect_call.add_argument (new CCodeIdentifier ("data"));
     702           10 :                                 ccode.add_expression (disconnect_call);
     703              :                         }
     704              :                 }
     705              :         }
     706              : 
     707          108 :         void generate_interface_method_call_function (ObjectTypeSymbol sym) {
     708           54 :                 var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_method_call", "void");
     709           54 :                 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
     710           54 :                 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
     711           54 :                 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
     712           54 :                 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
     713           54 :                 cfunc.add_parameter (new CCodeParameter ("method_name", "const gchar*"));
     714           54 :                 cfunc.add_parameter (new CCodeParameter ("parameters", "GVariant*"));
     715           54 :                 cfunc.add_parameter (new CCodeParameter ("invocation", "GDBusMethodInvocation*"));
     716           54 :                 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
     717              : 
     718           54 :                 cfunc.modifiers |= CCodeModifiers.STATIC;
     719              : 
     720           54 :                 push_function (cfunc);
     721              : 
     722           54 :                 ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
     723           54 :                 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
     724              : 
     725           54 :                 bool first = true;
     726              : 
     727          271 :                 foreach (Method m in sym.get_methods ()) {
     728          123 :                         if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
     729           96 :                             || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
     730           27 :                                 continue;
     731              :                         }
     732           96 :                         if (!is_dbus_visible (m)) {
     733            2 :                                 continue;
     734              :                         }
     735              : 
     736           94 :                         cfile.add_include ("string.h");
     737              : 
     738           94 :                         var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
     739           94 :                         ccheck.add_argument (new CCodeIdentifier ("method_name"));
     740           94 :                         ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m))));
     741              : 
     742           94 :                         if (first) {
     743           52 :                                 ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")));
     744              :                                 first = false;
     745              :                         } else {
     746           42 :                                 ccode.else_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")));
     747              :                         }
     748              : 
     749           94 :                         var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_wrapper (m, sym)));
     750           94 :                         ccall.add_argument (new CCodeIdentifier ("object"));
     751           94 :                         ccall.add_argument (new CCodeIdentifier ("parameters"));
     752           94 :                         ccall.add_argument (new CCodeIdentifier ("invocation"));
     753           94 :                         ccode.add_expression (ccall);
     754              :                 }
     755              : 
     756           54 :                 if (!first) {
     757           52 :                         ccode.add_else ();
     758              :                 }
     759              : 
     760           54 :                 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
     761           54 :                 ccall.add_argument (new CCodeIdentifier ("invocation"));
     762           54 :                 ccode.add_expression (ccall);
     763              : 
     764           54 :                 if (!first) {
     765           52 :                         ccode.close ();
     766              :                 }
     767              : 
     768           54 :                 pop_function ();
     769              : 
     770           54 :                 cfile.add_function_declaration (cfunc);
     771           54 :                 cfile.add_function (cfunc);
     772              :         }
     773              : 
     774          108 :         void generate_interface_get_property_function (ObjectTypeSymbol sym) {
     775           54 :                 var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_get_property", "GVariant*");
     776           54 :                 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
     777           54 :                 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
     778           54 :                 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
     779           54 :                 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
     780           54 :                 cfunc.add_parameter (new CCodeParameter ("property_name", "const gchar*"));
     781           54 :                 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
     782           54 :                 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
     783              : 
     784           54 :                 cfunc.modifiers |= CCodeModifiers.STATIC;
     785              : 
     786           54 :                 cfile.add_function_declaration (cfunc);
     787              : 
     788           54 :                 push_function (cfunc);
     789              : 
     790           54 :                 ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
     791              : 
     792           54 :                 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
     793              : 
     794           54 :                 bool firstif = true;
     795              : 
     796           78 :                 foreach (Property prop in sym.get_properties ()) {
     797           12 :                         if (prop.binding != MemberBinding.INSTANCE
     798           12 :                             || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
     799            0 :                                 continue;
     800              :                         }
     801           12 :                         if (!is_dbus_visible (prop)) {
     802            0 :                                 continue;
     803              :                         }
     804           12 :                         if (prop.get_accessor == null) {
     805            0 :                                 continue;
     806              :                         }
     807              : 
     808           12 :                         cfile.add_include ("string.h");
     809              : 
     810           12 :                         var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
     811           12 :                         ccheck.add_argument (new CCodeIdentifier ("property_name"));
     812           12 :                         ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
     813              : 
     814           12 :                         var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0"));
     815           12 :                         if (firstif) {
     816           10 :                                 ccode.open_if (cond);
     817           10 :                                 firstif = false;
     818              :                         } else {
     819            2 :                                 ccode.else_if (cond);
     820              :                         }
     821              : 
     822           12 :                         var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_get_wrapper (prop, sym)));
     823           12 :                         ccall.add_argument (new CCodeIdentifier ("object"));
     824              : 
     825           12 :                         ccode.add_return (ccall);
     826              :                 }
     827           54 :                 if (!firstif) {
     828           10 :                         ccode.close ();
     829              :                 }
     830              : 
     831           54 :                 ccode.add_return (new CCodeConstant ("NULL"));
     832              : 
     833           54 :                 pop_function ();
     834           54 :                 cfile.add_function (cfunc);
     835              :         }
     836              : 
     837          108 :         void generate_interface_set_property_function (ObjectTypeSymbol sym) {
     838           54 :                 var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_set_property", "gboolean");
     839           54 :                 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
     840           54 :                 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
     841           54 :                 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
     842           54 :                 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
     843           54 :                 cfunc.add_parameter (new CCodeParameter ("property_name", "const gchar*"));
     844           54 :                 cfunc.add_parameter (new CCodeParameter ("value", "GVariant*"));
     845           54 :                 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
     846           54 :                 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
     847              : 
     848           54 :                 cfunc.modifiers |= CCodeModifiers.STATIC;
     849              : 
     850           54 :                 cfile.add_function_declaration (cfunc);
     851              : 
     852           54 :                 push_function (cfunc);
     853              : 
     854           54 :                 ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
     855              : 
     856           54 :                 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
     857              : 
     858           54 :                 bool firstif = true;
     859              : 
     860           78 :                 foreach (Property prop in sym.get_properties ()) {
     861           12 :                         if (prop.binding != MemberBinding.INSTANCE
     862           12 :                             || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
     863            0 :                                 continue;
     864              :                         }
     865           12 :                         if (!is_dbus_visible (prop)) {
     866            0 :                                 continue;
     867              :                         }
     868           12 :                         if (prop.set_accessor == null) {
     869            0 :                                 continue;
     870              :                         }
     871              : 
     872           12 :                         cfile.add_include ("string.h");
     873              : 
     874           12 :                         var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
     875           12 :                         ccheck.add_argument (new CCodeIdentifier ("property_name"));
     876           12 :                         ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
     877              : 
     878           12 :                         var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0"));
     879           12 :                         if (firstif) {
     880           10 :                                 ccode.open_if (cond);
     881           10 :                                 firstif = false;
     882              :                         } else {
     883            2 :                                 ccode.else_if (cond);
     884              :                         }
     885              : 
     886           12 :                         var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_set_wrapper (prop, sym)));
     887           12 :                         ccall.add_argument (new CCodeIdentifier ("object"));
     888           12 :                         ccall.add_argument (new CCodeIdentifier ("value"));
     889              : 
     890           12 :                         ccode.add_expression (ccall);
     891           12 :                         ccode.add_return (new CCodeConstant ("TRUE"));
     892              :                 }
     893           54 :                 if (!firstif) {
     894           10 :                         ccode.close ();
     895              :                 }
     896           54 :                 ccode.add_return (new CCodeConstant ("FALSE"));
     897              : 
     898           54 :                 pop_function ();
     899           54 :                 cfile.add_function (cfunc);
     900              :         }
     901              : 
     902           54 :         CCodeExpression get_interface_vtable (ObjectTypeSymbol sym) {
     903           54 :                 var vtable = new CCodeInitializerList ();
     904           54 :                 vtable.append (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "dbus_interface_method_call"));
     905           54 :                 vtable.append (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "dbus_interface_get_property"));
     906           54 :                 vtable.append (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "dbus_interface_set_property"));
     907              : 
     908           54 :                 generate_interface_method_call_function (sym);
     909           54 :                 generate_interface_get_property_function (sym);
     910           54 :                 generate_interface_set_property_function (sym);
     911              : 
     912           54 :                 var cdecl = new CCodeDeclaration ("const GDBusInterfaceVTable");
     913           54 :                 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_interface_vtable", vtable));
     914           54 :                 cdecl.modifiers = CCodeModifiers.STATIC;
     915           54 :                 cfile.add_constant_declaration (cdecl);
     916              : 
     917           54 :                 return new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_interface_vtable");
     918              :         }
     919              : 
     920            1 :         string generate_register_object_function () {
     921            1 :                 string register_object_func = "_vala_g_dbus_connection_register_object";
     922              : 
     923            1 :                 if (!add_wrapper (register_object_func)) {
     924            1 :                         return register_object_func;
     925              :                 }
     926              : 
     927            1 :                 cfile.add_include ("gio/gio.h");
     928              : 
     929            1 :                 var function = new CCodeFunction (register_object_func, "guint");
     930            1 :                 function.modifiers = CCodeModifiers.STATIC;
     931              : 
     932            1 :                 function.add_parameter (new CCodeParameter ("type", "GType"));
     933            1 :                 function.add_parameter (new CCodeParameter ("object", "void*"));
     934            1 :                 function.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
     935            1 :                 function.add_parameter (new CCodeParameter ("path", "const gchar*"));
     936            1 :                 function.add_parameter (new CCodeParameter ("error", "GError**"));
     937              : 
     938            1 :                 push_function (function);
     939              : 
     940            1 :                 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
     941            1 :                 quark.add_argument (new CCodeConstant ("\"vala-dbus-register-object\""));
     942              : 
     943            1 :                 var get_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata"));
     944            1 :                 get_qdata.add_argument (new CCodeIdentifier ("type"));
     945            1 :                 get_qdata.add_argument (quark);
     946              : 
     947            1 :                 ccode.add_declaration ("void", new CCodeVariableDeclarator ("*func"));
     948            1 :                 ccode.add_assignment (new CCodeIdentifier ("func"), get_qdata);
     949              : 
     950            1 :                 ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("func")));
     951              :                 // no D-Bus interface
     952              :                 // return error
     953              : 
     954            1 :                 var set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error_literal"));
     955            1 :                 set_error.add_argument (new CCodeIdentifier ("error"));
     956            1 :                 set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR"));
     957            1 :                 set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR_FAILED"));
     958            1 :                 set_error.add_argument (new CCodeConstant ("\"The specified type does not support D-Bus registration\""));
     959            1 :                 ccode.add_expression (set_error);
     960              : 
     961            1 :                 ccode.add_return (new CCodeConstant ("0"));
     962              : 
     963            1 :                 ccode.close ();
     964              : 
     965            1 :                 var register_object = new CCodeCastExpression (new CCodeIdentifier ("func"), "guint (*) (void *, GDBusConnection *, const gchar *, GError **)");
     966              : 
     967            1 :                 var ccall = new CCodeFunctionCall (register_object);
     968            1 :                 ccall.add_argument (new CCodeIdentifier ("object"));
     969            1 :                 ccall.add_argument (new CCodeIdentifier ("connection"));
     970            1 :                 ccall.add_argument (new CCodeIdentifier ("path"));
     971            1 :                 ccall.add_argument (new CCodeIdentifier ("error"));
     972              : 
     973            1 :                 ccode.add_return (ccall);
     974              : 
     975            1 :                 pop_function ();
     976              : 
     977            1 :                 cfile.add_function_declaration (function);
     978            1 :                 cfile.add_function (function);
     979              : 
     980            1 :                 return register_object_func;
     981              :         }
     982              : 
     983        17624 :         public override void visit_method_call (MethodCall expr) {
     984        17599 :                 var mtype = expr.call.value_type as MethodType;
     985        16826 :                 if (mtype == null || get_ccode_name (mtype.method_symbol) != "g_dbus_connection_register_object") {
     986        17573 :                         base.visit_method_call (expr);
     987        17573 :                         return;
     988              :                 }
     989              : 
     990           26 :                 var ma = (MemberAccess) expr.call;
     991           26 :                 var type_arg = ma.get_type_arguments ().get (0);
     992              : 
     993              :                 CCodeFunctionCall cregister;
     994              : 
     995           26 :                 var object_type = type_arg as ObjectType;
     996           26 :                 if (object_type != null) {
     997           25 :                         if (get_dbus_name (object_type.type_symbol) == null) {
     998            1 :                                 Report.error (expr.source_reference, "DBusConnection.register_object requires type argument with [DBus (name = ...)] attribute");
     999            1 :                                 return;
    1000              :                         }
    1001              : 
    1002           24 :                         cregister = new CCodeFunctionCall (new CCodeIdentifier ("%sregister_object".printf (get_ccode_lower_case_prefix (object_type.type_symbol))));
    1003              :                 } else {
    1004              :                         // use runtime type information for generic methods
    1005            1 :                         cregister = new CCodeFunctionCall (new CCodeIdentifier (generate_register_object_function ()));
    1006            1 :                         cregister.add_argument (get_type_id_expression (type_arg));
    1007              :                 }
    1008              : 
    1009           25 :                 var args = expr.get_argument_list ();
    1010           25 :                 var path_arg = args[0];
    1011           25 :                 var obj_arg = args[1];
    1012              : 
    1013              :                 // method can fail
    1014           25 :                 current_method_inner_error = true;
    1015              : 
    1016           25 :                 cregister.add_argument (get_cvalue (obj_arg));
    1017           25 :                 cregister.add_argument (get_cvalue (ma.inner));
    1018           25 :                 cregister.add_argument (get_cvalue (path_arg));
    1019           25 :                 cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_inner_error_cexpression ()));
    1020              : 
    1021           25 :                 if (expr.parent_node is ExpressionStatement) {
    1022           25 :                         ccode.add_expression (cregister);
    1023              :                 } else {
    1024            0 :                         var temp_var = get_temp_variable (expr.value_type, expr.value_type.value_owned);
    1025            0 :                         var temp_ref = get_variable_cexpression (temp_var.name);
    1026              : 
    1027            0 :                         emit_temp_var (temp_var);
    1028              : 
    1029            0 :                         ccode.add_assignment (temp_ref, cregister);
    1030            0 :                         set_cvalue (expr, temp_ref);
    1031              :                 }
    1032              :         }
    1033              : 
    1034        73585 :         public override void generate_class_declaration (Class cl, CCodeFile decl_space) {
    1035        73585 :                 base.generate_class_declaration (cl, decl_space);
    1036              : 
    1037        73585 :                 generate_object_type_symbol_declaration (cl, decl_space);
    1038              :         }
    1039              : 
    1040         4474 :         public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) {
    1041         4474 :                 base.generate_interface_declaration (iface, decl_space);
    1042              : 
    1043         4474 :                 generate_object_type_symbol_declaration (iface, decl_space);
    1044              :         }
    1045              : 
    1046          780 :         public override void visit_class (Class cl) {
    1047          780 :                 base.visit_class (cl);
    1048              : 
    1049          780 :                 visit_object_type_symbol (cl);
    1050              :         }
    1051              : 
    1052          118 :         public override void visit_interface (Interface iface) {
    1053          118 :                 base.visit_interface (iface);
    1054              : 
    1055          118 :                 visit_object_type_symbol (iface);
    1056              :         }
    1057              : 
    1058        78176 :         void generate_object_type_symbol_declaration (ObjectTypeSymbol sym, CCodeFile decl_space) {
    1059        78059 :                 string dbus_iface_name = get_dbus_name (sym);
    1060        78059 :                 if (dbus_iface_name == null) {
    1061        77027 :                         return;
    1062              :                 }
    1063              : 
    1064         1032 :                 string register_object_name = "%sregister_object".printf (get_ccode_lower_case_prefix (sym));
    1065              : 
    1066         1032 :                 if (add_symbol_declaration (decl_space, sym, register_object_name)) {
    1067          915 :                         return;
    1068              :                 }
    1069              : 
    1070          117 :                 decl_space.add_include ("gio/gio.h");
    1071              : 
    1072              :                 // declare register_object function
    1073          117 :                 var cfunc = new CCodeFunction (register_object_name, "guint");
    1074          117 :                 cfunc.add_parameter (new CCodeParameter ("object", "void*"));
    1075          117 :                 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
    1076          117 :                 cfunc.add_parameter (new CCodeParameter ("path", "const gchar*"));
    1077          117 :                 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
    1078          117 :                 if (sym.is_private_symbol ()) {
    1079            0 :                         cfunc.modifiers |= CCodeModifiers.STATIC;
    1080          117 :                 } else if (context.hide_internal && sym.is_internal_symbol ()) {
    1081            0 :                         cfunc.modifiers |= CCodeModifiers.INTERNAL;
    1082              :                 } else {
    1083          117 :                         cfunc.modifiers |= CCodeModifiers.EXTERN;
    1084          117 :                         requires_vala_extern = true;
    1085              :                 }
    1086          117 :                 decl_space.add_function_declaration (cfunc);
    1087              :         }
    1088              : 
    1089          952 :         void visit_object_type_symbol (ObjectTypeSymbol sym) {
    1090              :                 // only support registering a single D-Bus interface at a time (unlike old D-Bus support)
    1091              :                 // however, register_object can be invoked multiple times for the same object path with different interfaces
    1092          898 :                 string dbus_iface_name = get_dbus_name (sym);
    1093          898 :                 if (dbus_iface_name == null) {
    1094          844 :                         return;
    1095              :                 }
    1096              : 
    1097           54 :                 cfile.add_include ("gio/gio.h");
    1098              : 
    1099           54 :                 var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "register_object", "guint");
    1100           54 :                 cfunc.add_parameter (new CCodeParameter ("object", "gpointer"));
    1101           54 :                 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
    1102           54 :                 cfunc.add_parameter (new CCodeParameter ("path", "const gchar*"));
    1103           54 :                 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
    1104           54 :                 if (sym.is_private_symbol ()) {
    1105            0 :                         cfunc.modifiers |= CCodeModifiers.STATIC;
    1106           54 :                 } else if (context.hide_internal && sym.is_internal_symbol ()) {
    1107            0 :                         cfunc.modifiers |= CCodeModifiers.INTERNAL;
    1108              :                 }
    1109              : 
    1110           54 :                 push_function (cfunc);
    1111              : 
    1112           54 :                 ccode.add_declaration ("guint", new CCodeVariableDeclarator ("result"));
    1113              : 
    1114              : 
    1115              :                 // data consists of 3 pointers: object, connection, path
    1116           54 :                 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("*data"));
    1117              : 
    1118           54 :                 var alloc_data = new CCodeFunctionCall (new CCodeIdentifier ("g_new"));
    1119           54 :                 alloc_data.add_argument (new CCodeIdentifier ("gpointer"));
    1120           54 :                 alloc_data.add_argument (new CCodeConstant ("3"));
    1121           54 :                 ccode.add_assignment (new CCodeIdentifier ("data"), alloc_data);
    1122              : 
    1123           54 :                 var ref_function = get_ccode_ref_function (sym);
    1124           54 :                 if (sym is Interface && ref_function == null) {
    1125            0 :                         Report.error (sym.source_reference, "missing class prerequisite for interface `%s', add GLib.Object to interface declaration if unsure", sym.get_full_name ());
    1126            0 :                         return;
    1127              :                 }
    1128              : 
    1129           54 :                 var ref_object = new CCodeFunctionCall (new CCodeIdentifier (ref_function));
    1130           54 :                 ref_object.add_argument (new CCodeIdentifier ("object"));
    1131           54 :                 ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")), ref_object);
    1132              : 
    1133           54 :                 ref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref"));
    1134           54 :                 ref_object.add_argument (new CCodeIdentifier ("connection"));
    1135           54 :                 ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("1")), ref_object);
    1136              : 
    1137           54 :                 var dup_path = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup"));
    1138           54 :                 dup_path.add_argument (new CCodeIdentifier ("path"));
    1139           54 :                 ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("2")), dup_path);
    1140              : 
    1141              : 
    1142           54 :                 var cregister = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_register_object"));
    1143           54 :                 cregister.add_argument (new CCodeIdentifier ("connection"));
    1144           54 :                 cregister.add_argument (new CCodeIdentifier ("path"));
    1145              : 
    1146           54 :                 cregister.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_info (sym)), "GDBusInterfaceInfo *"));
    1147           54 :                 cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_vtable (sym)));
    1148              : 
    1149           54 :                 cregister.add_argument (new CCodeIdentifier ("data"));
    1150           54 :                 cregister.add_argument (new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "unregister_object"));
    1151           54 :                 cregister.add_argument (new CCodeIdentifier ("error"));
    1152              : 
    1153           54 :                 ccode.add_assignment (new CCodeIdentifier ("result"), cregister);
    1154              : 
    1155           54 :                 ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("result")));
    1156           54 :                 ccode.add_return (new CCodeConstant ("0"));
    1157           54 :                 ccode.close ();
    1158              : 
    1159           54 :                 handle_signals (sym, true);
    1160              : 
    1161           54 :                 ccode.add_return (new CCodeIdentifier ("result"));
    1162              : 
    1163           54 :                 pop_function ();
    1164           54 :                 cfile.add_function (cfunc);
    1165              : 
    1166              : 
    1167           54 :                 cfunc = new CCodeFunction ("_" + get_ccode_lower_case_prefix (sym) + "unregister_object");
    1168           54 :                 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
    1169           54 :                 cfunc.modifiers |= CCodeModifiers.STATIC;
    1170              : 
    1171           54 :                 push_function (cfunc);
    1172              : 
    1173           54 :                 ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
    1174              : 
    1175           54 :                 handle_signals (sym, false);
    1176              : 
    1177           54 :                 var unref_object = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (sym)));
    1178           54 :                 unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")));
    1179           54 :                 ccode.add_expression (unref_object);
    1180              : 
    1181           54 :                 unref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
    1182           54 :                 unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("1")));
    1183           54 :                 ccode.add_expression (unref_object);
    1184              : 
    1185           54 :                 var free_path = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
    1186           54 :                 free_path.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("2")));
    1187           54 :                 ccode.add_expression (free_path);
    1188              : 
    1189           54 :                 var free_data = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
    1190           54 :                 free_data.add_argument (new CCodeIdentifier ("data"));
    1191           54 :                 ccode.add_expression (free_data);
    1192              : 
    1193           54 :                 pop_function ();
    1194           54 :                 cfile.add_function_declaration (cfunc);
    1195           54 :                 cfile.add_function (cfunc);
    1196              :         }
    1197              : 
    1198          905 :         public override void register_dbus_info (CCodeBlock block, ObjectTypeSymbol sym) {
    1199          851 :                 string dbus_iface_name = get_dbus_name (sym);
    1200          851 :                 if (dbus_iface_name == null) {
    1201          797 :                         return;
    1202              :                 }
    1203              : 
    1204           54 :                 base.register_dbus_info (block, sym);
    1205              : 
    1206           54 :                 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
    1207           54 :                 quark.add_argument (new CCodeConstant ("\"vala-dbus-register-object\""));
    1208              : 
    1209           54 :                 var set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
    1210           54 :                 set_qdata.add_argument (new CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (sym, null))));
    1211           54 :                 set_qdata.add_argument (quark);
    1212           54 :                 set_qdata.add_argument (new CCodeCastExpression (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "register_object"), "void*"));
    1213              : 
    1214           54 :                 block.add_statement (new CCodeExpressionStatement (set_qdata));
    1215              :         }
    1216              : }
        

Generated by: LCOV version 2.0-1