[vala] Support GVariant casts and GDBus clients and servers
- From: Jürg Billeter <juergbi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala] Support GVariant casts and GDBus clients and servers
- Date: Sun, 20 Jun 2010 10:02:08 +0000 (UTC)
commit f0615f3438758c60a7f7860c992d27ee447af964
Author: Jürg Billeter <j bitron ch>
Date: Sat Jun 19 21:43:44 2010 +0200
Support GVariant casts and GDBus clients and servers
codegen/Makefile.am | 6 +-
codegen/valaccodebasemodule.vala | 113 +++
codegen/valaccodegenerator.vala | 17 +-
codegen/valagdbusclientmodule.vala | 908 ++++++++++++++++++++++
codegen/valagdbusmodule.vala | 110 +++
codegen/valagdbusservermodule.vala | 1186 +++++++++++++++++++++++++++++
codegen/valagvariantmodule.vala | 788 +++++++++++++++++++
vala/valaarraytype.vala | 5 +
vala/valadatatype.vala | 7 +-
vapi/gio-2.0.vapi | 4 +-
vapi/packages/gio-2.0/gio-2.0-custom.vala | 6 +
vapi/packages/gio-2.0/gio-2.0.metadata | 1 +
12 files changed, 3145 insertions(+), 6 deletions(-)
---
diff --git a/codegen/Makefile.am b/codegen/Makefile.am
index 7581eb6..49406d1 100644
--- a/codegen/Makefile.am
+++ b/codegen/Makefile.am
@@ -47,12 +47,16 @@ libvala_la_VALASOURCES = \
valadovastructmodule.vala \
valadovavaluemodule.vala \
valaenumregisterfunction.vala \
+ valagasyncmodule.vala \
+ valagdbusclientmodule.vala \
+ valagdbusmodule.vala \
+ valagdbusservermodule.vala \
valagerrormodule.vala \
valagirwriter.vala \
valagobjectmodule.vala \
valagsignalmodule.vala \
valagtypemodule.vala \
- valagasyncmodule.vala \
+ valagvariantmodule.vala \
valainterfaceregisterfunction.vala \
valastructregisterfunction.vala \
valatyperegisterfunction.vala \
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 63f8795..1d2691f 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -196,8 +196,10 @@ public class Vala.CCodeBaseModule : CCodeModule {
public DataType gquark_type;
public DataType genumvalue_type;
public Struct gvalue_type;
+ public Class gvariant_type;
public Struct mutex_type;
public TypeSymbol type_module_type;
+ public TypeSymbol dbus_proxy_type;
public TypeSymbol dbus_object_type;
public bool in_plugin = false;
@@ -336,6 +338,7 @@ public class Vala.CCodeBaseModule : CCodeModule {
gquark_type = new IntegerType ((Struct) glib_ns.scope.lookup ("Quark"));
genumvalue_type = new ObjectType ((Class) glib_ns.scope.lookup ("EnumValue"));
gvalue_type = (Struct) glib_ns.scope.lookup ("Value");
+ gvariant_type = (Class) glib_ns.scope.lookup ("Variant");
mutex_type = (Struct) glib_ns.scope.lookup ("StaticRecMutex");
type_module_type = (TypeSymbol) glib_ns.scope.lookup ("TypeModule");
@@ -355,6 +358,8 @@ public class Vala.CCodeBaseModule : CCodeModule {
}
}
+ dbus_proxy_type = (TypeSymbol) glib_ns.scope.lookup ("DBusProxy");
+
var dbus_ns = root_symbol.scope.lookup ("DBus");
if (dbus_ns != null) {
dbus_object_type = (TypeSymbol) dbus_ns.scope.lookup ("Object");
@@ -4428,6 +4433,66 @@ public class Vala.CCodeBaseModule : CCodeModule {
return rv;
}
+ int next_variant_function_id = 0;
+
+ public CCodeExpression? try_cast_variant_to_type (CCodeExpression ccodeexpr, DataType from, DataType to, Expression? expr = null) {
+ if (from == null || gvariant_type == null || from.data_type != gvariant_type) {
+ return null;
+ }
+
+ string variant_func = "_variant_get%d".printf (++next_variant_function_id);
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier (variant_func));
+ ccall.add_argument (ccodeexpr);
+
+ var cfunc = new CCodeFunction (variant_func);
+ cfunc.modifiers = CCodeModifiers.STATIC;
+ cfunc.add_parameter (new CCodeFormalParameter ("value", "GVariant*"));
+
+ if (!to.is_real_non_null_struct_type ()) {
+ cfunc.return_type = to.get_cname ();
+ }
+
+ if (to.is_real_non_null_struct_type ()) {
+ // structs are returned via out parameter
+ cfunc.add_parameter (new CCodeFormalParameter ("result", to.get_cname () + "*"));
+ } else if (to is ArrayType) {
+ // return array length if appropriate
+ var array_type = (ArrayType) to;
+
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ var temp_decl = get_temp_variable (int_type, false, expr);
+ temp_vars.add (temp_decl);
+
+ ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_decl.name)));
+ cfunc.add_parameter (new CCodeFormalParameter (head.get_array_length_cname ("result", dim), "int*"));
+ expr.append_array_size (new CCodeIdentifier (temp_decl.name));
+ }
+ }
+
+ var block = new CCodeBlock ();
+ var fragment = new CCodeFragment ();
+ var result = deserialize_expression (fragment, to, new CCodeIdentifier ("value"), new CCodeIdentifier ("*result"));
+
+ block.add_statement (fragment);
+ block.add_statement (new CCodeReturnStatement (result));
+
+ source_declarations.add_type_member_declaration (cfunc.copy ());
+
+ cfunc.block = block;
+ source_type_member_definition.append (cfunc);
+
+ return ccall;
+ }
+
+ public virtual CCodeExpression? deserialize_expression (CCodeFragment fragment, DataType type, CCodeExpression variant_expr, CCodeExpression? expr) {
+ return null;
+ }
+
+ public virtual CCodeExpression? serialize_expression (CCodeFragment fragment, DataType type, CCodeExpression expr) {
+ return null;
+ }
+
public override void visit_cast_expression (CastExpression expr) {
var valuecast = try_cast_value_to_type ((CCodeExpression) expr.inner.ccodenode, expr.inner.value_type, expr.type_reference, expr);
if (valuecast != null) {
@@ -4435,6 +4500,12 @@ public class Vala.CCodeBaseModule : CCodeModule {
return;
}
+ var variantcast = try_cast_variant_to_type ((CCodeExpression) expr.inner.ccodenode, expr.inner.value_type, expr.type_reference, expr);
+ if (variantcast != null) {
+ expr.ccodenode = variantcast;
+ return;
+ }
+
generate_type_declaration (expr.type_reference, source_declarations);
var cl = expr.type_reference.data_type as Class;
@@ -4908,6 +4979,10 @@ public class Vala.CCodeBaseModule : CCodeModule {
&& target_type.data_type == gvalue_type
&& !(expression_type is NullType)
&& expression_type.get_type_id () != "G_TYPE_VALUE");
+ bool gvariant_boxing = (context.profile == Profile.GOBJECT
+ && target_type != null
+ && target_type.data_type == gvariant_type
+ && expression_type.data_type != gvariant_type);
if (expression_type.value_owned
&& (target_type == null || !target_type.value_owned || boxing || unboxing)) {
@@ -5002,6 +5077,44 @@ public class Vala.CCodeBaseModule : CCodeModule {
cexpr = ccomma;
return cexpr;
+ } else if (gvariant_boxing) {
+ // implicit conversion to GVariant
+ string variant_func = "_variant_new%d".printf (++next_variant_function_id);
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier (variant_func));
+ ccall.add_argument (cexpr);
+
+ var cfunc = new CCodeFunction (variant_func, "GVariant*");
+ cfunc.modifiers = CCodeModifiers.STATIC;
+ cfunc.add_parameter (new CCodeFormalParameter ("value", expression_type.get_cname ()));
+
+ if (expression_type is ArrayType) {
+ // return array length if appropriate
+ var array_type = (ArrayType) expression_type;
+
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ ccall.add_argument (head.get_array_length_cexpression (expr, dim));
+ cfunc.add_parameter (new CCodeFormalParameter (head.get_array_length_cname ("value", dim), "gint"));
+ }
+ }
+
+ var block = new CCodeBlock ();
+ var fragment = new CCodeFragment ();
+ var result = serialize_expression (fragment, expression_type, new CCodeIdentifier ("value"));
+
+ // sink floating reference
+ var sink = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_ref_sink"));
+ sink.add_argument (result);
+
+ block.add_statement (fragment);
+ block.add_statement (new CCodeReturnStatement (sink));
+
+ source_declarations.add_type_member_declaration (cfunc.copy ());
+
+ cfunc.block = block;
+ source_type_member_definition.append (cfunc);
+
+ return ccall;
} else if (boxing) {
// value needs to be boxed
diff --git a/codegen/valaccodegenerator.vala b/codegen/valaccodegenerator.vala
index b32ba3c..d621f04 100644
--- a/codegen/valaccodegenerator.vala
+++ b/codegen/valaccodegenerator.vala
@@ -1,6 +1,6 @@
/* valaccodegenerator.vala
*
- * Copyright (C) 2006-2009 Jürg Billeter
+ * Copyright (C) 2006-2010 Jürg Billeter
* Copyright (C) 2006-2008 Raffaele Sandrini
*
* This library is free software; you can redistribute it and/or
@@ -50,9 +50,20 @@ public class Vala.CCodeGenerator : CodeGenerator {
head = new GObjectModule (this, head);
head = new GSignalModule (this, head);
head = new GAsyncModule (this, head);
- head = new DBusClientModule (this, head);
*/
- head = new DBusServerModule (this, head);
+ if (context.has_package ("dbus-glib-1")) {
+ /*
+ head = new DBusModule (this, head);
+ head = new DBusClientModule (this, head);
+ */
+ head = new DBusServerModule (this, head);
+ } else {
+ /*
+ head = new GVariantModule (this, head);
+ head = new GDBusClientModule (this, head);
+ */
+ head = new GDBusServerModule (this, head);
+ }
} else if (context.profile == Profile.DOVA) {
/* included by inheritance
head = new DovaBaseModule (this, head);
diff --git a/codegen/valagdbusclientmodule.vala b/codegen/valagdbusclientmodule.vala
new file mode 100644
index 0000000..673e792
--- /dev/null
+++ b/codegen/valagdbusclientmodule.vala
@@ -0,0 +1,908 @@
+/* valagdbusclientmodule.vala
+ *
+ * Copyright (C) 2010 Jürg Billeter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Jürg Billeter <j bitron ch>
+ * Philip Van Hoof <pvanhoof gnome org>
+ */
+
+public class Vala.GDBusClientModule : GDBusModule {
+ public GDBusClientModule (CCodeGenerator codegen, CCodeModule? next) {
+ base (codegen, next);
+ }
+
+ public CCodeConstant get_dbus_timeout (Symbol symbol) {
+ int timeout = -1;
+
+ var dbus = symbol.get_attribute ("DBus");
+ if (dbus != null && dbus.has_argument ("timeout")) {
+ timeout = dbus.get_integer ("timeout");
+ } else if (symbol.parent_symbol != null) {
+ return get_dbus_timeout (symbol.parent_symbol);
+ }
+
+ return new CCodeConstant (timeout.to_string ());
+ }
+
+ public override void generate_dynamic_method_wrapper (DynamicMethod method) {
+ var dynamic_method = (DynamicMethod) method;
+
+ var func = new CCodeFunction (method.get_cname ());
+ func.modifiers = CCodeModifiers.STATIC;
+
+ var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
+
+ generate_cparameters (method, source_declarations, cparam_map, func);
+
+ var block = new CCodeBlock ();
+ if (dynamic_method.dynamic_type.data_type == dbus_proxy_type) {
+ generate_dbus_method_wrapper (method, block);
+ } else {
+ Report.error (method.source_reference, "dynamic methods are not supported for `%s'".printf (dynamic_method.dynamic_type.to_string ()));
+ }
+
+ // append to C source file
+ source_declarations.add_type_member_declaration (func.copy ());
+
+ func.block = block;
+ source_type_member_definition.append (func);
+ }
+
+ void generate_dbus_method_wrapper (Method m, CCodeBlock block) {
+ var prefragment = new CCodeFragment ();
+ var postfragment = new CCodeFragment ();
+
+ var cdecl = new CCodeDeclaration ("GVariant");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("*_arguments"));
+ cdecl.add_declarator (new CCodeVariableDeclarator ("*_reply"));
+ block.add_statement (cdecl);
+
+ generate_marshalling (m, prefragment, postfragment);
+
+ block.add_statement (prefragment);
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_call_sync"));
+ ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *"));
+ ccall.add_argument (new CCodeConstant ("\"%s\"".printf (m.name)));
+ ccall.add_argument (new CCodeIdentifier ("_arguments"));
+ ccall.add_argument (new CCodeConstant ("G_DBUS_CALL_FLAGS_NONE"));
+ ccall.add_argument (get_dbus_timeout (m));
+ ccall.add_argument (new CCodeConstant ("NULL"));
+ ccall.add_argument (new CCodeConstant ("error"));
+ block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
+
+ // return on error
+ var error_block = new CCodeBlock ();
+ if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) {
+ error_block.add_statement (new CCodeReturnStatement ());
+ } else {
+ error_block.add_statement (new CCodeReturnStatement (default_value_for_type (m.return_type, false)));
+ }
+ block.add_statement (new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_reply")), error_block));
+
+ block.add_statement (postfragment);
+
+ var unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
+ unref_reply.add_argument (new CCodeIdentifier ("_reply"));
+ block.add_statement (new CCodeExpressionStatement (unref_reply));
+
+ if (!(m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ())) {
+ block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_result")));
+ }
+ }
+
+ void generate_proxy_interface_init (Interface main_iface, Interface iface) {
+ // also generate proxy for prerequisites
+ foreach (var prereq in iface.get_prerequisites ()) {
+ if (prereq.data_type is Interface) {
+ generate_proxy_interface_init (main_iface, (Interface) prereq.data_type);
+ }
+ }
+
+ string lower_cname = main_iface.get_lower_case_cprefix () + "proxy";
+
+ var proxy_iface_init = new CCodeFunction (lower_cname + "_" + iface.get_lower_case_cprefix () + "interface_init", "void");
+ proxy_iface_init.add_parameter (new CCodeFormalParameter ("iface", iface.get_cname () + "Iface*"));
+
+ var iface_block = new CCodeBlock ();
+
+ foreach (Method m in iface.get_methods ()) {
+ var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), m.vfunc_name);
+ if (!m.coroutine) {
+ iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_method (main_iface, iface, m)))));
+ } else {
+ iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_async_dbus_proxy_method (main_iface, iface, m)))));
+ vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), m.get_finish_vfunc_name ());
+ iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_finish_dbus_proxy_method (main_iface, iface, m)))));
+ }
+ }
+
+ foreach (Property prop in iface.get_properties ()) {
+ if (prop.get_accessor != null) {
+ var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), "get_" + prop.name);
+ iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_property_get (main_iface, iface, prop)))));
+ }
+ if (prop.set_accessor != null) {
+ var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), "set_" + prop.name);
+ iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_property_set (main_iface, iface, prop)))));
+ }
+ }
+
+ proxy_iface_init.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_type_member_declaration (proxy_iface_init.copy ());
+ proxy_iface_init.block = iface_block;
+ source_type_member_definition.append (proxy_iface_init);
+ }
+
+ string implement_interface (CCodeFunctionCall define_type, Interface main_iface, Interface iface) {
+ string result = "";
+
+ // also implement prerequisites
+ foreach (var prereq in iface.get_prerequisites ()) {
+ if (prereq.data_type is Interface) {
+ result += implement_interface (define_type, main_iface, (Interface) prereq.data_type);
+ }
+ }
+
+ result += "G_IMPLEMENT_INTERFACE (%s, %sproxy_%sinterface_init) ".printf (
+ iface.get_upper_case_cname ("TYPE_"),
+ main_iface.get_lower_case_cprefix (),
+ iface.get_lower_case_cprefix ());
+ return result;
+ }
+
+ public override void generate_interface_declaration (Interface iface, CCodeDeclarationSpace decl_space) {
+ base.generate_interface_declaration (iface, decl_space);
+
+ string dbus_iface_name = get_dbus_name (iface);
+ if (dbus_iface_name == null) {
+ return;
+ }
+
+ string get_type_name = "%sproxy_get_type".printf (iface.get_lower_case_cprefix ());
+
+ if (decl_space.add_symbol_declaration (iface, get_type_name)) {
+ return;
+ }
+
+ decl_space.add_type_declaration (new CCodeNewline ());
+ var macro = "(%s ())".printf (get_type_name);
+ decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_PROXY".printf (iface.get_type_id ()), macro));
+
+ // declare proxy_get_type function
+ var proxy_get_type = new CCodeFunction (get_type_name, "GType");
+ decl_space.add_type_member_declaration (proxy_get_type);
+ }
+
+ public override void visit_interface (Interface iface) {
+ base.visit_interface (iface);
+
+ string dbus_iface_name = get_dbus_name (iface);
+ if (dbus_iface_name == null) {
+ return;
+ }
+
+ // create proxy class
+ string cname = iface.get_cname () + "Proxy";
+ string lower_cname = iface.get_lower_case_cprefix () + "proxy";
+
+ source_declarations.add_type_declaration (new CCodeTypeDefinition ("GDBusProxy", new CCodeVariableDeclarator (cname)));
+ source_declarations.add_type_declaration (new CCodeTypeDefinition ("GDBusProxyClass", new CCodeVariableDeclarator (cname + "Class")));
+
+ var define_type = new CCodeFunctionCall (new CCodeIdentifier ("G_DEFINE_TYPE_EXTENDED"));
+ define_type.add_argument (new CCodeIdentifier (cname));
+ define_type.add_argument (new CCodeIdentifier (lower_cname));
+ define_type.add_argument (new CCodeIdentifier ("G_TYPE_DBUS_PROXY"));
+ define_type.add_argument (new CCodeConstant ("0"));
+ define_type.add_argument (new CCodeIdentifier (implement_interface (define_type, iface, iface)));
+
+ source_type_member_definition.append (new CCodeExpressionStatement (define_type));
+
+ var proxy_class_init = new CCodeFunction (lower_cname + "_class_init", "void");
+ proxy_class_init.add_parameter (new CCodeFormalParameter ("klass", cname + "Class*"));
+ proxy_class_init.modifiers = CCodeModifiers.STATIC;
+ proxy_class_init.block = new CCodeBlock ();
+ var proxy_class = new CCodeFunctionCall (new CCodeIdentifier ("G_DBUS_PROXY_CLASS"));
+ proxy_class.add_argument (new CCodeIdentifier ("klass"));
+ proxy_class_init.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (proxy_class, "g_signal"), new CCodeIdentifier (lower_cname + "_g_signal"))));
+ source_type_member_definition.append (proxy_class_init);
+
+ generate_signal_handler_function (iface);
+
+ var proxy_instance_init = new CCodeFunction (lower_cname + "_init", "void");
+ proxy_instance_init.add_parameter (new CCodeFormalParameter ("self", cname + "*"));
+ proxy_instance_init.modifiers = CCodeModifiers.STATIC;
+ proxy_instance_init.block = new CCodeBlock ();
+ source_type_member_definition.append (proxy_instance_init);
+
+ generate_proxy_interface_init (iface, iface);
+ }
+
+ public override void visit_method_call (MethodCall expr) {
+ var mtype = expr.call.value_type as MethodType;
+ bool get_proxy_sync = (mtype != null && mtype.method_symbol.get_cname () == "g_bus_get_proxy_sync");
+ if (!get_proxy_sync) {
+ base.visit_method_call (expr);
+ return;
+ }
+
+ var ma = (MemberAccess) expr.call;
+ var type_arg = (ObjectType) ma.get_type_arguments ().get (0);
+ var iface = (Interface) type_arg.type_symbol;
+
+ var args = expr.get_argument_list ();
+ Expression bus_type = args.get (0);
+ Expression name = args.get (1);
+ Expression object_path = args.get (2);
+ Expression cancellable = args.get (3);
+
+ // method can fail
+ current_method_inner_error = true;
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_initable_new"));
+ ccall.add_argument (new CCodeIdentifier ("%s_PROXY".printf (iface.get_type_id ())));
+ cancellable.accept (codegen);
+ ccall.add_argument ((CCodeExpression) cancellable.ccodenode);
+ ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression ("_inner_error_")));
+ ccall.add_argument (new CCodeConstant ("\"g-flags\""));
+ ccall.add_argument (new CCodeConstant ("G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES"));
+ ccall.add_argument (new CCodeConstant ("\"g-name\""));
+ name.accept (codegen);
+ ccall.add_argument ((CCodeExpression) name.ccodenode);
+ ccall.add_argument (new CCodeConstant ("\"g-bus-type\""));
+ bus_type.accept (codegen);
+ ccall.add_argument ((CCodeExpression) bus_type.ccodenode);
+ ccall.add_argument (new CCodeConstant ("\"g-object-path\""));
+ object_path.accept (codegen);
+ ccall.add_argument ((CCodeExpression) object_path.ccodenode);
+ ccall.add_argument (new CCodeConstant ("\"g-interface-name\""));
+ ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name (iface))));
+ ccall.add_argument (new CCodeConstant ("NULL"));
+ expr.ccodenode = ccall;
+ }
+
+ string generate_dbus_signal_handler (Signal sig, ObjectTypeSymbol sym) {
+ string wrapper_name = "_dbus_handle_%s_%s".printf (sym.get_lower_case_cname (), sig.get_cname ());
+
+ // declaration
+
+ CCodeDeclaration cdecl;
+
+ var function = new CCodeFunction (wrapper_name);
+ function.modifiers = CCodeModifiers.STATIC;
+ function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*"));
+ function.add_parameter (new CCodeFormalParameter ("parameters", "GVariant*"));
+ var block = new CCodeBlock ();
+
+ var prefragment = new CCodeFragment ();
+ var postfragment = new CCodeFragment ();
+
+ block.add_statement (prefragment);
+
+ cdecl = new CCodeDeclaration ("GVariantIter");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_arguments_iter"));
+ block.add_statement (cdecl);
+
+ var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
+ iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_iter")));
+ iter_init.add_argument (new CCodeIdentifier ("parameters"));
+ prefragment.append (new CCodeExpressionStatement (iter_init));
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name"));
+ ccall.add_argument (new CCodeIdentifier ("self"));
+ ccall.add_argument (sig.get_canonical_cconstant ());
+
+ foreach (FormalParameter param in sig.get_parameters ()) {
+ var owned_type = param.parameter_type.copy ();
+ owned_type.value_owned = true;
+
+ cdecl = new CCodeDeclaration (owned_type.get_cname ());
+ cdecl.add_declarator (new CCodeVariableDeclarator.zero (param.name, default_value_for_type (param.parameter_type, true)));
+ prefragment.append (cdecl);
+
+ var st = param.parameter_type.data_type as Struct;
+ if (st != null && !st.is_simple_type ()) {
+ ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
+ } else {
+ ccall.add_argument (new CCodeIdentifier (param.name));
+ }
+
+ if (param.parameter_type is ArrayType) {
+ var array_type = (ArrayType) param.parameter_type;
+
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ string length_cname = get_array_length_cname (param.name, dim);
+
+ cdecl = new CCodeDeclaration ("int");
+ cdecl.add_declarator (new CCodeVariableDeclarator (length_cname, new CCodeConstant ("0")));
+ prefragment.append (cdecl);
+ ccall.add_argument (new CCodeIdentifier (length_cname));
+ }
+ }
+
+ read_expression (prefragment, param.parameter_type, new CCodeIdentifier ("_arguments_iter"), new CCodeIdentifier (param.name));
+
+ if (requires_destroy (owned_type)) {
+ // keep local alive (symbol_reference is weak)
+ var local = new LocalVariable (owned_type, param.name);
+ var ma = new MemberAccess.simple (param.name);
+ ma.symbol_reference = local;
+ var stmt = new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (param.name), owned_type, ma));
+ postfragment.append (stmt);
+ }
+ }
+
+ block.add_statement (new CCodeExpressionStatement (ccall));
+
+ block.add_statement (postfragment);
+
+ source_declarations.add_type_member_declaration (function.copy ());
+
+ function.block = block;
+ source_type_member_definition.append (function);
+
+ return wrapper_name;
+ }
+
+ void generate_signal_handler_function (ObjectTypeSymbol sym) {
+ var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "proxy_g_signal", "void");
+ cfunc.add_parameter (new CCodeFormalParameter ("proxy", "GDBusProxy*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("sender_name", "const gchar*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("signal_name", "const gchar*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("parameters", "GVariant*"));
+
+ cfunc.modifiers |= CCodeModifiers.STATIC;
+
+ source_declarations.add_type_member_declaration (cfunc.copy ());
+
+ var block = new CCodeBlock ();
+ cfunc.block = block;
+
+ CCodeIfStatement clastif = null;
+
+ foreach (Signal sig in sym.get_signals ()) {
+ if (sig.access != SymbolAccessibility.PUBLIC) {
+ continue;
+ }
+
+ var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
+ ccheck.add_argument (new CCodeIdentifier ("signal_name"));
+ ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
+
+ var callblock = new CCodeBlock ();
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_signal_handler (sig, sym)));
+ ccall.add_argument (new CCodeIdentifier ("proxy"));
+ ccall.add_argument (new CCodeIdentifier ("parameters"));
+
+ callblock.add_statement (new CCodeExpressionStatement (ccall));
+
+ var cif = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")), callblock);
+ if (clastif == null) {
+ block.add_statement (cif);
+ } else {
+ clastif.false_statement = cif;
+ }
+
+ clastif = cif;
+ }
+
+ source_type_member_definition.append (cfunc);
+ }
+
+ void generate_marshalling (Method m, CCodeFragment prefragment, CCodeFragment postfragment) {
+ CCodeDeclaration cdecl;
+
+ cdecl = new CCodeDeclaration ("GVariantBuilder");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_arguments_builder"));
+ prefragment.append (cdecl);
+
+ var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
+ builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
+ builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
+ prefragment.append (new CCodeExpressionStatement (builder_init));
+
+ cdecl = new CCodeDeclaration ("GVariantIter");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_reply_iter"));
+ postfragment.append (cdecl);
+
+ var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
+ iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_iter")));
+ iter_init.add_argument (new CCodeIdentifier ("_reply"));
+ postfragment.append (new CCodeExpressionStatement (iter_init));
+
+ foreach (FormalParameter param in m.get_parameters ()) {
+ if (param.direction == ParameterDirection.IN) {
+ CCodeExpression expr = new CCodeIdentifier (param.name);
+ if (param.parameter_type.is_real_struct_type ()) {
+ expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr);
+ }
+ write_expression (prefragment, param.parameter_type, new CCodeIdentifier ("_arguments_builder"), expr);
+ } else {
+ cdecl = new CCodeDeclaration (param.parameter_type.get_cname ());
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_" + param.name));
+ postfragment.append (cdecl);
+
+ var array_type = param.parameter_type as ArrayType;
+
+ if (array_type != null) {
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ cdecl = new CCodeDeclaration ("int");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_%s_length%d".printf (param.name, dim), new CCodeConstant ("0")));
+ postfragment.append (cdecl);
+ }
+ }
+
+ var target = new CCodeIdentifier ("_" + param.name);
+ read_expression (postfragment, param.parameter_type, new CCodeIdentifier ("_reply_iter"), target);
+
+ // TODO check that parameter is not NULL (out parameters are optional)
+ // free value if parameter is NULL
+ postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (param.name)), target)));
+
+ if (array_type != null) {
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ // TODO check that parameter is not NULL (out parameters are optional)
+ postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("%s_length%d".printf (param.name, dim))), new CCodeIdentifier ("_%s_length%d".printf (param.name, dim)))));
+ }
+ }
+ }
+ }
+
+ if (!(m.return_type is VoidType)) {
+ if (m.return_type.is_real_non_null_struct_type ()) {
+ var target = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result"));
+ read_expression (postfragment, m.return_type, new CCodeIdentifier ("_reply_iter"), target);
+ } else {
+ cdecl = new CCodeDeclaration (m.return_type.get_cname ());
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_result"));
+ postfragment.append (cdecl);
+
+ var array_type = m.return_type as ArrayType;
+
+ if (array_type != null) {
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ cdecl = new CCodeDeclaration ("int");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0")));
+ postfragment.append (cdecl);
+ }
+ }
+
+ read_expression (postfragment, m.return_type, new CCodeIdentifier ("_reply_iter"), new CCodeIdentifier ("_result"));
+
+ if (array_type != null) {
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ // TODO check that parameter is not NULL (out parameters are optional)
+ postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length%d".printf (dim))), new CCodeIdentifier ("_result_length%d".printf (dim)))));
+ }
+ }
+ }
+ }
+
+ var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
+ builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
+ prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_arguments"), builder_end)));
+ }
+
+ string generate_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
+ string proxy_name = "%sproxy_%s".printf (main_iface.get_lower_case_cprefix (), m.name);
+
+ string dbus_iface_name = get_dbus_name (iface);
+
+ CCodeDeclaration cdecl;
+
+ var function = new CCodeFunction (proxy_name);
+ function.modifiers = CCodeModifiers.STATIC;
+
+ var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
+
+ generate_cparameters (m, source_declarations, cparam_map, function);
+
+ var block = new CCodeBlock ();
+ var prefragment = new CCodeFragment ();
+ var postfragment = new CCodeFragment ();
+
+ cdecl = new CCodeDeclaration ("GVariant");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("*_arguments"));
+ cdecl.add_declarator (new CCodeVariableDeclarator ("*_reply"));
+ block.add_statement (cdecl);
+
+ generate_marshalling (m, prefragment, postfragment);
+
+ block.add_statement (prefragment);
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_call_sync"));
+ ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *"));
+ ccall.add_argument (new CCodeConstant ("\"%s.%s\"".printf (dbus_iface_name, get_dbus_name_for_member (m))));
+ ccall.add_argument (new CCodeIdentifier ("_arguments"));
+ ccall.add_argument (new CCodeConstant ("G_DBUS_CALL_FLAGS_NONE"));
+ ccall.add_argument (get_dbus_timeout (m));
+ ccall.add_argument (new CCodeConstant ("NULL"));
+ ccall.add_argument (new CCodeConstant ("error"));
+ block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
+
+ // return on error
+ var error_block = new CCodeBlock ();
+ if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) {
+ error_block.add_statement (new CCodeReturnStatement ());
+ } else {
+ error_block.add_statement (new CCodeReturnStatement (default_value_for_type (m.return_type, false)));
+ }
+ block.add_statement (new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_reply")), error_block));
+
+ block.add_statement (postfragment);
+
+ var unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
+ unref_reply.add_argument (new CCodeIdentifier ("_reply"));
+ block.add_statement (new CCodeExpressionStatement (unref_reply));
+
+ if (!(m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ())) {
+ block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_result")));
+ }
+
+ source_declarations.add_type_member_declaration (function.copy ());
+ function.block = block;
+ source_type_member_definition.append (function);
+
+ return proxy_name;
+ }
+
+ string generate_async_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
+ string proxy_name = "%sproxy_%s_async".printf (main_iface.get_lower_case_cprefix (), m.name);
+
+ string dbus_iface_name = get_dbus_name (iface);
+
+ CCodeDeclaration cdecl;
+
+ var function = new CCodeFunction (proxy_name, "void");
+ function.modifiers = CCodeModifiers.STATIC;
+
+ var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
+
+ cparam_map.set (get_param_pos (-1), new CCodeFormalParameter ("_callback_", "GAsyncReadyCallback"));
+ cparam_map.set (get_param_pos (-0.9), new CCodeFormalParameter ("_user_data_", "gpointer"));
+
+ generate_cparameters (m, source_declarations, cparam_map, function, null, null, null, 1);
+
+ var block = new CCodeBlock ();
+ var prefragment = new CCodeFragment ();
+ var postfragment = new CCodeFragment ();
+
+ cdecl = new CCodeDeclaration ("GVariant");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("*_arguments"));
+ block.add_statement (cdecl);
+
+ generate_marshalling (m, prefragment, postfragment);
+
+ block.add_statement (prefragment);
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_call"));
+ ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *"));
+ ccall.add_argument (new CCodeConstant ("\"%s.%s\"".printf (dbus_iface_name, get_dbus_name_for_member (m))));
+ ccall.add_argument (new CCodeIdentifier ("_arguments"));
+ ccall.add_argument (new CCodeConstant ("G_DBUS_CALL_FLAGS_NONE"));
+ ccall.add_argument (get_dbus_timeout (m));
+ ccall.add_argument (new CCodeConstant ("NULL"));
+ ccall.add_argument (new CCodeIdentifier ("_callback_"));
+ ccall.add_argument (new CCodeIdentifier ("_user_data_"));
+ block.add_statement (new CCodeExpressionStatement (ccall));
+
+ source_declarations.add_type_member_declaration (function.copy ());
+ function.block = block;
+ source_type_member_definition.append (function);
+
+ return proxy_name;
+ }
+
+ string generate_finish_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
+ string proxy_name = "%sproxy_%s_finish".printf (main_iface.get_lower_case_cprefix (), m.name);
+
+ CCodeDeclaration cdecl;
+
+ var function = new CCodeFunction (proxy_name);
+ function.modifiers = CCodeModifiers.STATIC;
+
+ var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
+
+ cparam_map.set (get_param_pos (0.1), new CCodeFormalParameter ("_res_", "GAsyncResult*"));
+
+ generate_cparameters (m, source_declarations, cparam_map, function, null, null, null, 2);
+
+ var block = new CCodeBlock ();
+ var prefragment = new CCodeFragment ();
+ var postfragment = new CCodeFragment ();
+
+ cdecl = new CCodeDeclaration ("GVariant");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("*_reply"));
+ block.add_statement (cdecl);
+
+ generate_marshalling (m, prefragment, postfragment);
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_call_finish"));
+ ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *"));
+ ccall.add_argument (new CCodeIdentifier ("_res_"));
+ ccall.add_argument (new CCodeConstant ("error"));
+ block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
+
+ // return on error
+ var error_block = new CCodeBlock ();
+ if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) {
+ error_block.add_statement (new CCodeReturnStatement ());
+ } else {
+ error_block.add_statement (new CCodeReturnStatement (default_value_for_type (m.return_type, false)));
+ }
+ block.add_statement (new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_reply")), error_block));
+
+ block.add_statement (postfragment);
+
+ var unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
+ unref_reply.add_argument (new CCodeIdentifier ("_reply"));
+ block.add_statement (new CCodeExpressionStatement (unref_reply));
+
+ if (!(m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ())) {
+ block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_result")));
+ }
+
+ source_declarations.add_type_member_declaration (function.copy ());
+ function.block = block;
+ source_type_member_definition.append (function);
+
+ return proxy_name;
+ }
+
+ string generate_dbus_proxy_property_get (Interface main_iface, Interface iface, Property prop) {
+ string proxy_name = "%sdbus_proxy_get_%s".printf (main_iface.get_lower_case_cprefix (), prop.name);
+
+ string dbus_iface_name = get_dbus_name (iface);
+
+ var owned_type = prop.get_accessor.value_type.copy ();
+ owned_type.value_owned = true;
+ if (owned_type.is_disposable () && !prop.get_accessor.value_type.value_owned) {
+ Report.error (prop.get_accessor.value_type.source_reference, "Properties used in D-Bus clients require owned get accessor");
+ }
+
+ var array_type = prop.get_accessor.value_type as ArrayType;
+
+ CCodeDeclaration cdecl;
+
+ var function = new CCodeFunction (proxy_name);
+ function.modifiers = CCodeModifiers.STATIC;
+
+ function.add_parameter (new CCodeFormalParameter ("self", "%s*".printf (iface.get_cname ())));
+
+ if (prop.property_type.is_real_non_null_struct_type ()) {
+ function.add_parameter (new CCodeFormalParameter ("result", "%s*".printf (prop.get_accessor.value_type.get_cname ())));
+ } else {
+ if (array_type != null) {
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ function.add_parameter (new CCodeFormalParameter ("result_length%d".printf (dim), "int*"));
+ }
+ }
+
+ function.return_type = prop.get_accessor.value_type.get_cname ();
+ }
+
+ var block = new CCodeBlock ();
+ var prefragment = new CCodeFragment ();
+ var postfragment = new CCodeFragment ();
+
+ cdecl = new CCodeDeclaration ("GVariant");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("*_arguments"));
+ cdecl.add_declarator (new CCodeVariableDeclarator ("*_reply"));
+ cdecl.add_declarator (new CCodeVariableDeclarator ("*_inner_reply"));
+ block.add_statement (cdecl);
+
+ block.add_statement (prefragment);
+
+ cdecl = new CCodeDeclaration ("GVariantBuilder");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_arguments_builder"));
+ prefragment.append (cdecl);
+
+ var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
+ builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
+ builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
+ prefragment.append (new CCodeExpressionStatement (builder_init));
+
+ // interface name
+ write_expression (prefragment, string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
+ // property name
+ write_expression (prefragment, string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
+
+ var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
+ builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
+ prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_arguments"), builder_end)));
+
+ cdecl = new CCodeDeclaration ("GVariantIter");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_reply_iter"));
+ postfragment.append (cdecl);
+
+ var get_variant = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get_child_value"));
+ get_variant.add_argument (new CCodeIdentifier ("_reply"));
+ get_variant.add_argument (new CCodeConstant ("0"));
+ postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_inner_reply"), get_variant)));
+
+ var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
+ iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_iter")));
+ iter_init.add_argument (new CCodeIdentifier ("_inner_reply"));
+ postfragment.append (new CCodeExpressionStatement (iter_init));
+
+ if (prop.property_type.is_real_non_null_struct_type ()) {
+ var target = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result"));
+ read_expression (postfragment, prop.get_accessor.value_type, new CCodeIdentifier ("_reply_iter"), target);
+ } else {
+ cdecl = new CCodeDeclaration (prop.get_accessor.value_type.get_cname ());
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_result"));
+ postfragment.append (cdecl);
+
+ if (array_type != null) {
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ cdecl = new CCodeDeclaration ("int");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0")));
+ postfragment.append (cdecl);
+ }
+ }
+
+ read_expression (postfragment, prop.get_accessor.value_type, new CCodeIdentifier ("_reply_iter"), new CCodeIdentifier ("_result"));
+
+ if (array_type != null) {
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ // TODO check that parameter is not NULL (out parameters are optional)
+ postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length%d".printf (dim))), new CCodeIdentifier ("_result_length%d".printf (dim)))));
+ }
+ }
+ }
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_call_sync"));
+ ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *"));
+ ccall.add_argument (new CCodeConstant ("\"org.freedesktop.DBus.Properties.Get\""));
+ ccall.add_argument (new CCodeIdentifier ("_arguments"));
+ ccall.add_argument (new CCodeConstant ("G_DBUS_CALL_FLAGS_NONE"));
+ ccall.add_argument (get_dbus_timeout (prop));
+ ccall.add_argument (new CCodeConstant ("NULL"));
+ ccall.add_argument (new CCodeConstant ("NULL"));
+
+ block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
+
+ // return on error
+ var error_block = new CCodeBlock ();
+ if (prop.property_type.is_real_non_null_struct_type ()) {
+ error_block.add_statement (new CCodeReturnStatement ());
+ } else {
+ error_block.add_statement (new CCodeReturnStatement (default_value_for_type (prop.property_type, false)));
+ }
+ block.add_statement (new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_reply")), error_block));
+
+ block.add_statement (postfragment);
+
+ var unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
+ unref_reply.add_argument (new CCodeIdentifier ("_reply"));
+ block.add_statement (new CCodeExpressionStatement (unref_reply));
+
+ if (prop.property_type.is_real_non_null_struct_type ()) {
+ block.add_statement (new CCodeReturnStatement ());
+ } else {
+ block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_result")));
+ }
+
+ source_declarations.add_type_member_declaration (function.copy ());
+ function.block = block;
+ source_type_member_definition.append (function);
+
+ return proxy_name;
+ }
+
+ string generate_dbus_proxy_property_set (Interface main_iface, Interface iface, Property prop) {
+ string proxy_name = "%sdbus_proxy_set_%s".printf (main_iface.get_lower_case_cprefix (), prop.name);
+
+ string dbus_iface_name = get_dbus_name (iface);
+
+ var array_type = prop.set_accessor.value_type as ArrayType;
+
+ CCodeDeclaration cdecl;
+
+ var function = new CCodeFunction (proxy_name);
+ function.modifiers = CCodeModifiers.STATIC;
+
+ function.add_parameter (new CCodeFormalParameter ("self", "%s*".printf (iface.get_cname ())));
+
+ if (prop.property_type.is_real_non_null_struct_type ()) {
+ function.add_parameter (new CCodeFormalParameter ("value", "%s*".printf (prop.set_accessor.value_type.get_cname ())));
+ } else {
+ function.add_parameter (new CCodeFormalParameter ("value", prop.set_accessor.value_type.get_cname ()));
+
+ if (array_type != null) {
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ function.add_parameter (new CCodeFormalParameter ("value_length%d".printf (dim), "int"));
+ }
+ }
+ }
+
+ var block = new CCodeBlock ();
+ var prefragment = new CCodeFragment ();
+ var postfragment = new CCodeFragment ();
+
+ cdecl = new CCodeDeclaration ("GVariant");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("*_arguments"));
+ cdecl.add_declarator (new CCodeVariableDeclarator ("*_reply"));
+ block.add_statement (cdecl);
+
+ block.add_statement (prefragment);
+
+ cdecl = new CCodeDeclaration ("GVariantBuilder");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_arguments_builder"));
+ prefragment.append (cdecl);
+
+ var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
+ builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
+ builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
+ prefragment.append (new CCodeExpressionStatement (builder_init));
+
+ // interface name
+ write_expression (prefragment, string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
+ // property name
+ write_expression (prefragment, string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
+
+ // property value (as variant)
+ var builder_open = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_open"));
+ builder_open.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
+ builder_open.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_VARIANT"));
+ prefragment.append (new CCodeExpressionStatement (builder_open));
+
+ if (prop.property_type.is_real_non_null_struct_type ()) {
+ write_expression (prefragment, prop.set_accessor.value_type, new CCodeIdentifier ("_arguments_builder"), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("value")));
+ } else {
+ write_expression (prefragment, prop.set_accessor.value_type, new CCodeIdentifier ("_arguments_builder"), new CCodeIdentifier ("value"));
+ }
+
+ var builder_close = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_close"));
+ builder_close.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
+ prefragment.append (new CCodeExpressionStatement (builder_close));
+
+ var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
+ builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
+ prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_arguments"), builder_end)));
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_call_sync"));
+ ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *"));
+ ccall.add_argument (new CCodeConstant ("\"org.freedesktop.DBus.Properties.Set\""));
+ ccall.add_argument (new CCodeIdentifier ("_arguments"));
+ ccall.add_argument (new CCodeConstant ("G_DBUS_CALL_FLAGS_NONE"));
+ ccall.add_argument (get_dbus_timeout (prop));
+ ccall.add_argument (new CCodeConstant ("NULL"));
+ ccall.add_argument (new CCodeConstant ("NULL"));
+
+ block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
+
+ // return on error
+ var error_block = new CCodeBlock ();
+ error_block.add_statement (new CCodeReturnStatement ());
+ block.add_statement (new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_reply")), error_block));
+
+ block.add_statement (postfragment);
+
+ var unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
+ unref_reply.add_argument (new CCodeIdentifier ("_reply"));
+ block.add_statement (new CCodeExpressionStatement (unref_reply));
+
+ source_declarations.add_type_member_declaration (function.copy ());
+ function.block = block;
+ source_type_member_definition.append (function);
+
+ return proxy_name;
+ }
+}
diff --git a/codegen/valagdbusmodule.vala b/codegen/valagdbusmodule.vala
new file mode 100644
index 0000000..1e32ea7
--- /dev/null
+++ b/codegen/valagdbusmodule.vala
@@ -0,0 +1,110 @@
+/* valagdbusmodule.vala
+ *
+ * Copyright (C) 2010 Jürg Billeter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Jürg Billeter <j bitron ch>
+ */
+
+public class Vala.GDBusModule : GVariantModule {
+ public GDBusModule (CCodeGenerator codegen, CCodeModule? next) {
+ base (codegen, next);
+ }
+
+ public static string? get_dbus_name (TypeSymbol symbol) {
+ var dbus = symbol.get_attribute ("DBus");
+ if (dbus == null) {
+ return null;
+ }
+
+ return dbus.get_string ("name");
+ }
+
+ public static string get_dbus_name_for_member (Symbol symbol) {
+ var dbus = symbol.get_attribute ("DBus");
+ if (dbus != null && dbus.has_argument ("name")) {
+ return dbus.get_string ("name");
+ }
+
+ return Symbol.lower_case_to_camel_case (symbol.name);
+ }
+
+ public override void visit_error_domain (ErrorDomain edomain) {
+ var edomain_dbus_name = get_dbus_name (edomain);
+ if (edomain_dbus_name == null) {
+ base.visit_error_domain (edomain);
+ return;
+ }
+
+ generate_error_domain_declaration (edomain, source_declarations);
+
+ if (!edomain.is_internal_symbol ()) {
+ generate_error_domain_declaration (edomain, header_declarations);
+ }
+ if (!edomain.is_private_symbol ()) {
+ generate_error_domain_declaration (edomain, internal_header_declarations);
+ }
+
+ var error_entries = new CCodeInitializerList ();
+ foreach (ErrorCode ecode in edomain.get_codes ()) {
+ var ecode_dbus_name = get_dbus_name (ecode);
+ if (ecode_dbus_name == null) {
+ ecode_dbus_name = Symbol.lower_case_to_camel_case (ecode.name.down ());
+ }
+
+ var error_entry = new CCodeInitializerList ();
+ error_entry.append (new CCodeIdentifier (ecode.get_cname ()));
+ error_entry.append (new CCodeConstant ("\"%s\"".printf (ecode_dbus_name)));
+ error_entries.append (error_entry);
+ }
+
+ var cdecl = new CCodeDeclaration ("const GDBusErrorEntry");
+ cdecl.add_declarator (new CCodeVariableDeclarator (edomain.get_lower_case_cname () + "_entries[]", error_entries));
+ cdecl.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_constant_declaration (cdecl);
+
+ string quark_fun_name = edomain.get_lower_case_cprefix () + "quark";
+
+ var cquark_fun = new CCodeFunction (quark_fun_name, gquark_type.data_type.get_cname ());
+ var cquark_block = new CCodeBlock ();
+
+ string quark_name = "%squark_volatile".printf (edomain.get_lower_case_cprefix ());
+
+ cdecl = new CCodeDeclaration ("gsize");
+ cdecl.add_declarator (new CCodeVariableDeclarator (quark_name, new CCodeConstant ("0")));
+ cdecl.modifiers = CCodeModifiers.STATIC | CCodeModifiers.VOLATILE;
+ cquark_block.add_statement (cdecl);
+
+ var register_call = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_error_register_error_domain"));
+ register_call.add_argument (new CCodeConstant ("\"" + edomain.get_lower_case_cname () + "-quark\""));
+ register_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (quark_name)));
+ register_call.add_argument (new CCodeIdentifier (edomain.get_lower_case_cname () + "_entries"));
+ var nentries = new CCodeFunctionCall (new CCodeIdentifier ("G_N_ELEMENTS"));
+ nentries.add_argument (new CCodeIdentifier (edomain.get_lower_case_cname () + "_entries"));
+ register_call.add_argument (nentries);
+ cquark_block.add_statement (new CCodeExpressionStatement (register_call));
+
+ cquark_block.add_statement (new CCodeReturnStatement (new CCodeCastExpression (new CCodeIdentifier (quark_name), "GQuark")));
+
+ cquark_fun.block = cquark_block;
+ source_type_member_definition.append (cquark_fun);
+ }
+
+ public override CCodeFragment register_dbus_info (ObjectTypeSymbol sym) {
+ return new CCodeFragment ();
+ }
+}
diff --git a/codegen/valagdbusservermodule.vala b/codegen/valagdbusservermodule.vala
new file mode 100644
index 0000000..3914117
--- /dev/null
+++ b/codegen/valagdbusservermodule.vala
@@ -0,0 +1,1186 @@
+/* valagdbusservermodule.vala
+ *
+ * Copyright (C) 2010 Jürg Billeter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Jürg Billeter <j bitron ch>
+ */
+
+public class Vala.GDBusServerModule : GDBusClientModule {
+ public GDBusServerModule (CCodeGenerator codegen, CCodeModule? next) {
+ base (codegen, next);
+ }
+
+ public static bool is_dbus_visible (CodeNode node) {
+ var dbus_attribute = node.get_attribute ("DBus");
+ if (dbus_attribute != null
+ && dbus_attribute.has_argument ("visible")
+ && !dbus_attribute.get_bool ("visible")) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public static string dbus_result_name (Method m) {
+ var dbus_attribute = m.get_attribute ("DBus");
+ if (dbus_attribute != null
+ && dbus_attribute.has_argument ("result")) {
+ var result_name = dbus_attribute.get_string ("result");
+ if (result_name != null && result_name != "") {
+ return result_name;
+ }
+ }
+
+ return "result";
+ }
+
+ string generate_dbus_wrapper (Method m, ObjectTypeSymbol sym) {
+ string wrapper_name = "_dbus_%s".printf (m.get_cname ());
+
+ // declaration
+
+ CCodeDeclaration cdecl;
+
+ var function = new CCodeFunction (wrapper_name);
+ function.modifiers = CCodeModifiers.STATIC;
+ function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*"));
+ function.add_parameter (new CCodeFormalParameter ("parameters", "GVariant*"));
+ function.add_parameter (new CCodeFormalParameter ("invocation", "GDBusMethodInvocation*"));
+ var block = new CCodeBlock ();
+
+ CCodeFunction ready_function = null;
+ CCodeBlock ready_block = null;
+ if (m.coroutine) {
+ // GAsyncResult
+ source_declarations.add_include ("gio/gio.h");
+
+ ready_function = new CCodeFunction (wrapper_name + "_ready", "void");
+ ready_function.modifiers = CCodeModifiers.STATIC;
+ ready_function.add_parameter (new CCodeFormalParameter ("source_object", "GObject *"));
+ ready_function.add_parameter (new CCodeFormalParameter ("_res_", "GAsyncResult *"));
+ ready_function.add_parameter (new CCodeFormalParameter ("_user_data_", "gpointer *"));
+ ready_block = new CCodeBlock ();
+
+ cdecl = new CCodeDeclaration ("GDBusMethodInvocation *");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("invocation", new CCodeIdentifier ("_user_data_")));
+ ready_block.add_statement (cdecl);
+ }
+
+ var in_prefragment = new CCodeFragment ();
+ var in_postfragment = new CCodeFragment ();
+ var out_prefragment = in_prefragment;
+ var out_postfragment = in_postfragment;
+ if (m.coroutine) {
+ out_prefragment = new CCodeFragment ();
+ out_postfragment = new CCodeFragment ();
+ }
+
+ cdecl = new CCodeDeclaration ("GError*");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("error", new CCodeConstant ("NULL")));
+ if (m.coroutine) {
+ ready_block.add_statement (cdecl);
+ } else {
+ block.add_statement (cdecl);
+ }
+
+ block.add_statement (in_prefragment);
+ if (m.coroutine) {
+ ready_block.add_statement (out_prefragment);
+ }
+
+ cdecl = new CCodeDeclaration ("GVariant*");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_reply"));
+ out_postfragment.append (cdecl);
+
+ cdecl = new CCodeDeclaration ("GVariantIter");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_arguments_iter"));
+ block.add_statement (cdecl);
+
+ var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
+ iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_iter")));
+ iter_init.add_argument (new CCodeIdentifier ("parameters"));
+ in_prefragment.append (new CCodeExpressionStatement (iter_init));
+
+ cdecl = new CCodeDeclaration ("GVariantBuilder");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_reply_builder"));
+ out_postfragment.append (cdecl);
+
+ var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
+ builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder")));
+ builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
+ out_postfragment.append (new CCodeExpressionStatement (builder_init));
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname ()));
+
+ CCodeFunctionCall finish_ccall = null;
+ if (m.coroutine) {
+ finish_ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_finish_cname ()));
+ finish_ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("source_object"), sym.get_cname () + "*"));
+ finish_ccall.add_argument (new CCodeIdentifier ("_res_"));
+ }
+
+ ccall.add_argument (new CCodeIdentifier ("self"));
+
+ foreach (FormalParameter param in m.get_parameters ()) {
+ var owned_type = param.parameter_type.copy ();
+ owned_type.value_owned = true;
+
+ cdecl = new CCodeDeclaration (owned_type.get_cname ());
+ cdecl.add_declarator (new CCodeVariableDeclarator.zero (param.name, default_value_for_type (param.parameter_type, true)));
+ if (param.direction == ParameterDirection.IN) {
+ in_prefragment.append (cdecl);
+ } else {
+ out_prefragment.append (cdecl);
+ }
+
+ if (!m.coroutine || param.direction == ParameterDirection.IN) {
+ var st = param.parameter_type.data_type as Struct;
+ if (param.direction != ParameterDirection.IN
+ || (st != null && !st.is_simple_type ())) {
+ ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
+ } else {
+ ccall.add_argument (new CCodeIdentifier (param.name));
+ }
+ } else {
+ finish_ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
+ }
+
+ if (param.parameter_type is ArrayType) {
+ var array_type = (ArrayType) param.parameter_type;
+
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ string length_cname = get_array_length_cname (param.name, dim);
+
+ cdecl = new CCodeDeclaration ("int");
+ cdecl.add_declarator (new CCodeVariableDeclarator (length_cname, new CCodeConstant ("0")));
+ if (!m.coroutine || param.direction == ParameterDirection.IN) {
+ if (param.direction != ParameterDirection.IN) {
+ out_prefragment.append (cdecl);
+ ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
+ } else {
+ in_prefragment.append (cdecl);
+ ccall.add_argument (new CCodeIdentifier (length_cname));
+ }
+ } else {
+ out_prefragment.append (cdecl);
+ finish_ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
+ }
+ }
+ }
+
+ if (param.direction == ParameterDirection.IN) {
+ read_expression (in_prefragment, param.parameter_type, new CCodeIdentifier ("_arguments_iter"), new CCodeIdentifier (param.name));
+ } else {
+ write_expression (out_postfragment, param.parameter_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier (param.name));
+ }
+
+ if (requires_destroy (owned_type)) {
+ // keep local alive (symbol_reference is weak)
+ var local = new LocalVariable (owned_type, param.name);
+ var ma = new MemberAccess.simple (param.name);
+ ma.symbol_reference = local;
+ var stmt = new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (param.name), owned_type, ma));
+ if (param.direction == ParameterDirection.IN) {
+ in_postfragment.append (stmt);
+ } else {
+ out_postfragment.append (stmt);
+ }
+ }
+ }
+
+ if (!(m.return_type is VoidType)) {
+ if (m.return_type.is_real_non_null_struct_type ()) {
+ cdecl = new CCodeDeclaration (m.return_type.get_cname ());
+ cdecl.add_declarator (new CCodeVariableDeclarator.zero ("result", default_value_for_type (m.return_type, true)));
+ out_prefragment.append (cdecl);
+
+ if (!m.coroutine) {
+ ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
+ } else {
+ finish_ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
+ }
+
+ write_expression (out_postfragment, m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"));
+
+ if (requires_destroy (m.return_type)) {
+ // keep local alive (symbol_reference is weak)
+ // space before `result' is work around to not trigger
+ // variable renaming, we really mean C identifier `result' here
+ var local = new LocalVariable (m.return_type, " result");
+ var ma = new MemberAccess.simple ("result");
+ ma.symbol_reference = local;
+ out_postfragment.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier ("result"), m.return_type, ma)));
+ }
+
+ block.add_statement (new CCodeExpressionStatement (ccall));
+ if (m.coroutine) {
+ ready_block.add_statement (new CCodeExpressionStatement (finish_ccall));
+ }
+ } else {
+ cdecl = new CCodeDeclaration (m.return_type.get_cname ());
+ cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
+ out_prefragment.append (cdecl);
+ if (!m.coroutine) {
+ block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), ccall)));
+ } else {
+ block.add_statement (new CCodeExpressionStatement (ccall));
+ ready_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), finish_ccall)));
+ }
+
+ if (m.return_type is ArrayType) {
+ var array_type = (ArrayType) m.return_type;
+
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ string length_cname = get_array_length_cname ("result", dim);
+
+ cdecl = new CCodeDeclaration ("int");
+ cdecl.add_declarator (new CCodeVariableDeclarator (length_cname, new CCodeConstant ("0")));
+ out_prefragment.append (cdecl);
+ if (!m.coroutine) {
+ ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
+ } else {
+ finish_ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
+ }
+ }
+ }
+
+ write_expression (out_postfragment, m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"));
+
+ if (requires_destroy (m.return_type)) {
+ // keep local alive (symbol_reference is weak)
+ // space before `result' is work around to not trigger
+ // variable renaming, we really mean C identifier `result' here
+ var local = new LocalVariable (m.return_type, " result");
+ var ma = new MemberAccess.simple ("result");
+ ma.symbol_reference = local;
+ out_postfragment.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier ("result"), m.return_type, ma)));
+ }
+ }
+ } else {
+ block.add_statement (new CCodeExpressionStatement (ccall));
+ if (m.coroutine) {
+ ready_block.add_statement (new CCodeExpressionStatement (finish_ccall));
+ }
+ }
+
+ var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
+ builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder")));
+ out_postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), builder_end)));
+
+ if (m.coroutine) {
+ ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier (wrapper_name + "_ready"), "GAsyncReadyCallback"));
+
+ var ref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref"));
+ ref_call.add_argument (new CCodeIdentifier ("invocation"));
+
+ ccall.add_argument (ref_call);
+ }
+
+ if (m.get_error_types ().size > 0) {
+ if (m.coroutine) {
+ finish_ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
+ } else {
+ ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
+ }
+
+ var error_block = new CCodeBlock ();
+
+ var return_error = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
+ return_error.add_argument (new CCodeIdentifier ("invocation"));
+ return_error.add_argument (new CCodeIdentifier ("error"));
+
+ error_block.add_statement (new CCodeReturnStatement ());
+
+ if (m.coroutine) {
+ ready_block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("error"), error_block));
+ } else {
+ block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("error"), error_block));
+ }
+ }
+
+ block.add_statement (in_postfragment);
+
+ if (!m.coroutine) {
+ var return_value = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_return_value"));
+ return_value.add_argument (new CCodeIdentifier ("invocation"));
+ return_value.add_argument (new CCodeIdentifier ("_reply"));
+ block.add_statement (new CCodeExpressionStatement (return_value));
+ } else {
+ ready_block.add_statement (out_postfragment);
+
+ var return_value = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_return_value"));
+ return_value.add_argument (new CCodeIdentifier ("invocation"));
+ return_value.add_argument (new CCodeIdentifier ("_reply"));
+ ready_block.add_statement (new CCodeExpressionStatement (return_value));
+
+ var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
+ unref_call.add_argument (new CCodeIdentifier ("invocation"));
+ ready_block.add_statement (new CCodeExpressionStatement (unref_call));
+
+ unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
+ unref_call.add_argument (new CCodeIdentifier ("_reply"));
+ ready_block.add_statement (new CCodeExpressionStatement (unref_call));
+ }
+
+ source_declarations.add_type_member_declaration (function.copy ());
+
+ function.block = block;
+ source_type_member_definition.append (function);
+
+ if (m.coroutine) {
+ source_declarations.add_type_member_declaration (ready_function.copy ());
+
+ ready_function.block = ready_block;
+ source_type_member_definition.append (ready_function);
+ }
+
+ return wrapper_name;
+ }
+
+ string generate_dbus_signal_wrapper (Signal sig, ObjectTypeSymbol sym, string dbus_iface_name) {
+ string wrapper_name = "_dbus_%s_%s".printf (sym.get_lower_case_cname (), sig.get_cname ());
+
+ // declaration
+
+ CCodeDeclaration cdecl;
+
+ var function = new CCodeFunction (wrapper_name, "void");
+ function.modifiers = CCodeModifiers.STATIC;
+
+ function.add_parameter (new CCodeFormalParameter ("_sender", "GObject*"));
+
+ foreach (var param in sig.get_parameters ()) {
+ // ensure ccodenode of parameter is set
+ generate_parameter (param, source_declarations, new HashMap<int,CCodeFormalParameter> (), null);
+
+ function.add_parameter ((CCodeFormalParameter) get_ccodenode (param));
+ if (param.parameter_type is ArrayType) {
+ var array_type = (ArrayType) param.parameter_type;
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ function.add_parameter (new CCodeFormalParameter (head.get_array_length_cname (param.name, dim), "int"));
+ }
+ }
+ }
+
+ function.add_parameter (new CCodeFormalParameter ("_data", "gpointer*"));
+
+ var block = new CCodeBlock ();
+ var prefragment = new CCodeFragment ();
+
+ cdecl = new CCodeDeclaration ("GDBusConnection *");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_connection", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("1"))));
+ block.add_statement (cdecl);
+
+ cdecl = new CCodeDeclaration ("const gchar *");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_path", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("2"))));
+ block.add_statement (cdecl);
+
+ cdecl = new CCodeDeclaration ("GVariant");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("*_arguments"));
+ block.add_statement (cdecl);
+
+ cdecl = new CCodeDeclaration ("GVariantBuilder");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_arguments_builder"));
+ prefragment.append (cdecl);
+
+ var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
+ builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
+ builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
+ prefragment.append (new CCodeExpressionStatement (builder_init));
+
+ foreach (FormalParameter param in sig.get_parameters ()) {
+ CCodeExpression expr = new CCodeIdentifier (param.name);
+ if (param.parameter_type.is_real_struct_type ()) {
+ expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr);
+ }
+ write_expression (prefragment, param.parameter_type, new CCodeIdentifier ("_arguments_builder"), expr);
+ }
+
+ var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
+ builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
+ prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_arguments"), builder_end)));
+
+ block.add_statement (prefragment);
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_emit_signal"));
+ ccall.add_argument (new CCodeIdentifier ("_connection"));
+ ccall.add_argument (new CCodeConstant ("NULL"));
+ ccall.add_argument (new CCodeIdentifier ("_path"));
+ ccall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
+ ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
+ ccall.add_argument (new CCodeIdentifier ("_arguments"));
+ ccall.add_argument (new CCodeConstant ("NULL"));
+ block.add_statement (new CCodeExpressionStatement (ccall));
+
+ source_declarations.add_type_member_declaration (function.copy ());
+ function.block = block;
+ source_type_member_definition.append (function);
+
+ return wrapper_name;
+ }
+
+ string generate_dbus_property_get_wrapper (Property prop, ObjectTypeSymbol sym) {
+ string wrapper_name = "_dbus_%s".printf (prop.get_accessor.get_cname ());
+
+ // declaration
+
+ CCodeDeclaration cdecl;
+
+ var function = new CCodeFunction (wrapper_name, "GVariant*");
+ function.modifiers = CCodeModifiers.STATIC;
+ function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*"));
+ var block = new CCodeBlock ();
+
+ var prefragment = new CCodeFragment ();
+ var postfragment = new CCodeFragment ();
+
+ block.add_statement (prefragment);
+
+ cdecl = new CCodeDeclaration ("GVariant*");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_reply"));
+ postfragment.append (cdecl);
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.get_accessor.get_cname ()));
+ ccall.add_argument (new CCodeIdentifier ("self"));
+
+ if (prop.property_type.is_real_non_null_struct_type ()) {
+ cdecl = new CCodeDeclaration (prop.property_type.get_cname ());
+ cdecl.add_declarator (new CCodeVariableDeclarator.zero ("result", default_value_for_type (prop.property_type, true)));
+ prefragment.append (cdecl);
+
+ ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
+
+ block.add_statement (new CCodeExpressionStatement (ccall));
+ } else {
+ cdecl = new CCodeDeclaration (prop.property_type.get_cname ());
+ cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
+ prefragment.append (cdecl);
+
+ block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), ccall)));
+
+ var array_type = prop.property_type as ArrayType;
+ if (array_type != null) {
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ string length_cname = get_array_length_cname ("result", dim);
+
+ cdecl = new CCodeDeclaration ("int");
+ cdecl.add_declarator (new CCodeVariableDeclarator (length_cname));
+ postfragment.append (cdecl);
+
+ ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
+ }
+ }
+ }
+
+ var reply_expr = serialize_expression (postfragment, prop.property_type, new CCodeIdentifier ("result"));
+
+ postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), reply_expr)));
+
+ if (requires_destroy (prop.property_type)) {
+ // keep local alive (symbol_reference is weak)
+ // space before `result' is work around to not trigger
+ // variable renaming, we really mean C identifier `result' here
+ var local = new LocalVariable (prop.property_type, " result");
+ var ma = new MemberAccess.simple ("result");
+ ma.symbol_reference = local;
+ postfragment.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier ("result"), prop.property_type, ma)));
+ }
+
+ block.add_statement (postfragment);
+
+ block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_reply")));
+
+ source_declarations.add_type_member_declaration (function.copy ());
+
+ function.block = block;
+ source_type_member_definition.append (function);
+
+ return wrapper_name;
+ }
+
+ string generate_dbus_property_set_wrapper (Property prop, ObjectTypeSymbol sym) {
+ string wrapper_name = "_dbus_%s".printf (prop.set_accessor.get_cname ());
+
+ // declaration
+
+ CCodeDeclaration cdecl;
+
+ var function = new CCodeFunction (wrapper_name);
+ function.modifiers = CCodeModifiers.STATIC;
+ function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*"));
+ function.add_parameter (new CCodeFormalParameter ("_value", "GVariant*"));
+ var block = new CCodeBlock ();
+
+ var prefragment = new CCodeFragment ();
+ var postfragment = new CCodeFragment ();
+
+ block.add_statement (prefragment);
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.set_accessor.get_cname ()));
+ ccall.add_argument (new CCodeIdentifier ("self"));
+
+ var owned_type = prop.property_type.copy ();
+ owned_type.value_owned = true;
+
+ cdecl = new CCodeDeclaration (owned_type.get_cname ());
+ cdecl.add_declarator (new CCodeVariableDeclarator.zero ("value", default_value_for_type (prop.property_type, true)));
+ prefragment.append (cdecl);
+
+ var st = prop.property_type.data_type as Struct;
+ if (st != null && !st.is_simple_type ()) {
+ ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value")));
+ } else {
+ ccall.add_argument (new CCodeIdentifier ("value"));
+
+ var array_type = prop.property_type as ArrayType;
+ if (array_type != null) {
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ cdecl = new CCodeDeclaration ("int");
+ cdecl.add_declarator (new CCodeVariableDeclarator (head.get_array_length_cname ("value", dim)));
+ prefragment.append (cdecl);
+
+ ccall.add_argument (new CCodeIdentifier (head.get_array_length_cname ("value", dim)));
+ }
+ }
+ }
+
+ var target = new CCodeIdentifier ("value");
+ var expr = deserialize_expression (prefragment, prop.property_type, new CCodeIdentifier ("_value"), target);
+ prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
+
+ if (requires_destroy (owned_type)) {
+ // keep local alive (symbol_reference is weak)
+ var local = new LocalVariable (owned_type, "value");
+ var ma = new MemberAccess.simple ("value");
+ ma.symbol_reference = local;
+ var stmt = new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier ("value"), owned_type, ma));
+ postfragment.append (stmt);
+ }
+
+ block.add_statement (new CCodeExpressionStatement (ccall));
+
+ block.add_statement (postfragment);
+
+ source_declarations.add_type_member_declaration (function.copy ());
+
+ function.block = block;
+ source_type_member_definition.append (function);
+
+ return wrapper_name;
+ }
+
+ void handle_signals (ObjectTypeSymbol sym, CCodeBlock block) {
+ string dbus_iface_name = get_dbus_name (sym);
+ if (dbus_iface_name == null) {
+ return;
+ }
+
+ foreach (Signal sig in sym.get_signals ()) {
+ if (sig.access != SymbolAccessibility.PUBLIC) {
+ continue;
+ }
+ if (!is_dbus_visible (sig)) {
+ continue;
+ }
+
+ var connect = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_connect"));
+ connect.add_argument (new CCodeIdentifier ("object"));
+ connect.add_argument (sig.get_canonical_cconstant (null));
+ connect.add_argument (new CCodeCastExpression (new CCodeIdentifier (generate_dbus_signal_wrapper (sig, sym, dbus_iface_name)), "GCallback"));
+ connect.add_argument (new CCodeIdentifier ("data"));
+ block.add_statement (new CCodeExpressionStatement (connect));
+ }
+ }
+
+ void generate_interface_method_call_function (ObjectTypeSymbol sym) {
+ var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "dbus_interface_method_call", "void");
+ cfunc.add_parameter (new CCodeFormalParameter ("connection", "GDBusConnection*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("sender", "const gchar*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("object_path", "const gchar*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("interface_name", "const gchar*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("method_name", "const gchar*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("parameters", "GVariant*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("invocation", "GDBusMethodInvocation*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("data", "gpointer*"));
+
+ cfunc.modifiers |= CCodeModifiers.STATIC;
+
+ source_declarations.add_type_member_declaration (cfunc.copy ());
+
+ var block = new CCodeBlock ();
+ cfunc.block = block;
+
+ var cdecl = new CCodeDeclaration ("gpointer");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
+ block.add_statement (cdecl);
+
+ CCodeIfStatement clastif = null;
+
+ foreach (Method m in sym.get_methods ()) {
+ if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
+ || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
+ continue;
+ }
+ if (!is_dbus_visible (m)) {
+ continue;
+ }
+
+ var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
+ ccheck.add_argument (new CCodeIdentifier ("method_name"));
+ ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m))));
+
+ var callblock = new CCodeBlock ();
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_wrapper (m, sym)));
+ ccall.add_argument (new CCodeIdentifier ("object"));
+ ccall.add_argument (new CCodeIdentifier ("parameters"));
+ ccall.add_argument (new CCodeIdentifier ("invocation"));
+
+ callblock.add_statement (new CCodeExpressionStatement (ccall));
+
+ var cif = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")), callblock);
+ if (clastif == null) {
+ block.add_statement (cif);
+ } else {
+ clastif.false_statement = cif;
+ }
+
+ clastif = cif;
+ }
+
+ source_type_member_definition.append (cfunc);
+ }
+
+ void generate_interface_get_property_function (ObjectTypeSymbol sym) {
+ var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "dbus_interface_get_property", "GVariant*");
+ cfunc.add_parameter (new CCodeFormalParameter ("connection", "GDBusConnection*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("sender", "const gchar*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("object_path", "const gchar*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("interface_name", "const gchar*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("property_name", "const gchar*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("error", "GError**"));
+ cfunc.add_parameter (new CCodeFormalParameter ("data", "gpointer*"));
+
+ cfunc.modifiers |= CCodeModifiers.STATIC;
+
+ source_declarations.add_type_member_declaration (cfunc.copy ());
+
+ var block = new CCodeBlock ();
+ cfunc.block = block;
+
+ var cdecl = new CCodeDeclaration ("gpointer");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
+ block.add_statement (cdecl);
+
+ CCodeIfStatement clastif = null;
+
+ foreach (Property prop in sym.get_properties ()) {
+ if (prop.binding != MemberBinding.INSTANCE
+ || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
+ continue;
+ }
+ if (!is_dbus_visible (prop)) {
+ continue;
+ }
+ if (prop.get_accessor == null) {
+ continue;
+ }
+
+ var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
+ ccheck.add_argument (new CCodeIdentifier ("property_name"));
+ ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
+
+ var callblock = new CCodeBlock ();
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_get_wrapper (prop, sym)));
+ ccall.add_argument (new CCodeIdentifier ("object"));
+
+ callblock.add_statement (new CCodeReturnStatement (ccall));
+
+ var cif = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")), callblock);
+ if (clastif == null) {
+ block.add_statement (cif);
+ } else {
+ clastif.false_statement = cif;
+ }
+
+ clastif = cif;
+ }
+
+ block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL")));
+
+ source_type_member_definition.append (cfunc);
+ }
+
+ void generate_interface_set_property_function (ObjectTypeSymbol sym) {
+ var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "dbus_interface_set_property", "gboolean");
+ cfunc.add_parameter (new CCodeFormalParameter ("connection", "GDBusConnection*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("sender", "const gchar*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("object_path", "const gchar*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("interface_name", "const gchar*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("property_name", "const gchar*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("value", "GVariant*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("error", "GError**"));
+ cfunc.add_parameter (new CCodeFormalParameter ("data", "gpointer*"));
+
+ cfunc.modifiers |= CCodeModifiers.STATIC;
+
+ source_declarations.add_type_member_declaration (cfunc.copy ());
+
+ var block = new CCodeBlock ();
+ cfunc.block = block;
+
+ var cdecl = new CCodeDeclaration ("gpointer");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
+ block.add_statement (cdecl);
+
+ CCodeIfStatement clastif = null;
+
+ foreach (Property prop in sym.get_properties ()) {
+ if (prop.binding != MemberBinding.INSTANCE
+ || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
+ continue;
+ }
+ if (!is_dbus_visible (prop)) {
+ continue;
+ }
+ if (prop.set_accessor == null) {
+ continue;
+ }
+
+ var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
+ ccheck.add_argument (new CCodeIdentifier ("property_name"));
+ ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
+
+ var callblock = new CCodeBlock ();
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_set_wrapper (prop, sym)));
+ ccall.add_argument (new CCodeIdentifier ("object"));
+ ccall.add_argument (new CCodeIdentifier ("value"));
+
+ callblock.add_statement (new CCodeExpressionStatement (ccall));
+ callblock.add_statement (new CCodeReturnStatement (new CCodeConstant ("TRUE")));
+
+ var cif = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")), callblock);
+ if (clastif == null) {
+ block.add_statement (cif);
+ } else {
+ clastif.false_statement = cif;
+ }
+
+ clastif = cif;
+ }
+
+ block.add_statement (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
+
+ source_type_member_definition.append (cfunc);
+ }
+
+ CCodeExpression get_method_info (ObjectTypeSymbol sym) {
+ var infos = new CCodeInitializerList ();
+
+ foreach (Method m in sym.get_methods ()) {
+ if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
+ || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
+ continue;
+ }
+ if (!is_dbus_visible (m)) {
+ continue;
+ }
+
+ var in_args_info = new CCodeInitializerList ();
+ var out_args_info = new CCodeInitializerList ();
+
+ foreach (FormalParameter param in m.get_parameters ()) {
+ var info = new CCodeInitializerList ();
+ info.append (new CCodeConstant ("-1"));
+ info.append (new CCodeConstant ("\"%s\"".printf (param.name)));
+ info.append (new CCodeConstant ("\"%s\"".printf (get_type_signature (param.parameter_type))));
+
+ var cdecl = new CCodeDeclaration ("const GDBusArgInfo");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_" + param.name, info));
+ cdecl.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_constant_declaration (cdecl);
+
+ if (param.direction == ParameterDirection.IN) {
+ in_args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_" + param.name)));
+ } else {
+ out_args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_" + param.name)));
+ }
+ }
+
+ if (!(m.return_type is VoidType)) {
+ var info = new CCodeInitializerList ();
+ info.append (new CCodeConstant ("-1"));
+ info.append (new CCodeConstant ("\"%s\"".printf (dbus_result_name (m))));
+ info.append (new CCodeConstant ("\"%s\"".printf (get_type_signature (m.return_type))));
+
+ var cdecl = new CCodeDeclaration ("const GDBusArgInfo");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_result", info));
+ cdecl.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_constant_declaration (cdecl);
+
+ out_args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_result")));
+ }
+
+ in_args_info.append (new CCodeConstant ("NULL"));
+ out_args_info.append (new CCodeConstant ("NULL"));
+
+ var cdecl = new CCodeDeclaration ("const GDBusArgInfo * const");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_in[]", in_args_info));
+ cdecl.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_constant_declaration (cdecl);
+
+ cdecl = new CCodeDeclaration ("const GDBusArgInfo * const");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_out[]", out_args_info));
+ cdecl.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_constant_declaration (cdecl);
+
+ var info = new CCodeInitializerList ();
+ info.append (new CCodeConstant ("-1"));
+ info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m))));
+ info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_in")));
+ info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_out")));
+
+ cdecl = new CCodeDeclaration ("const GDBusMethodInfo");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_method_info_" + m.name, info));
+ cdecl.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_constant_declaration (cdecl);
+
+ infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_method_info_" + m.name)));
+ }
+
+ infos.append (new CCodeConstant ("NULL"));
+
+ var cdecl = new CCodeDeclaration ("const GDBusMethodInfo * const");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_method_info[]", infos));
+ cdecl.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_constant_declaration (cdecl);
+
+ return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_method_info");
+ }
+
+ CCodeExpression get_signal_info (ObjectTypeSymbol sym) {
+ var infos = new CCodeInitializerList ();
+
+ foreach (Signal sig in sym.get_signals ()) {
+ if (sig.access != SymbolAccessibility.PUBLIC) {
+ continue;
+ }
+ if (!is_dbus_visible (sig)) {
+ continue;
+ }
+
+ var args_info = new CCodeInitializerList ();
+
+ foreach (FormalParameter param in sig.get_parameters ()) {
+ var info = new CCodeInitializerList ();
+ info.append (new CCodeConstant ("-1"));
+ info.append (new CCodeConstant ("\"%s\"".printf (param.name)));
+ info.append (new CCodeConstant ("\"%s\"".printf (get_type_signature (param.parameter_type))));
+
+ var cdecl = new CCodeDeclaration ("const GDBusArgInfo");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + sig.get_cname () + "_" + param.name, info));
+ cdecl.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_constant_declaration (cdecl);
+
+ args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + sig.get_cname () + "_" + param.name)));
+ }
+
+ args_info.append (new CCodeConstant ("NULL"));
+
+ var cdecl = new CCodeDeclaration ("const GDBusArgInfo * const");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + sig.get_cname () + "[]", args_info));
+ cdecl.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_constant_declaration (cdecl);
+
+ var info = new CCodeInitializerList ();
+ info.append (new CCodeConstant ("-1"));
+ info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
+ info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + sig.get_cname ())));
+
+ cdecl = new CCodeDeclaration ("const GDBusSignalInfo");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_signal_info_" + sig.get_cname (), info));
+ cdecl.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_constant_declaration (cdecl);
+
+ infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_signal_info_" + sig.get_cname ())));
+ }
+
+ infos.append (new CCodeConstant ("NULL"));
+
+ var cdecl = new CCodeDeclaration ("const GDBusSignalInfo * const");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_signal_info[]", infos));
+ cdecl.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_constant_declaration (cdecl);
+
+ return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_signal_info");
+ }
+
+ CCodeExpression get_property_info (ObjectTypeSymbol sym) {
+ var infos = new CCodeInitializerList ();
+
+ foreach (Property prop in sym.get_properties ()) {
+ if (prop.binding != MemberBinding.INSTANCE
+ || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
+ continue;
+ }
+ if (!is_dbus_visible (prop)) {
+ continue;
+ }
+
+ var info = new CCodeInitializerList ();
+ info.append (new CCodeConstant ("-1"));
+ info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
+ info.append (new CCodeConstant ("\"%s\"".printf (get_type_signature (prop.property_type))));
+ if (prop.get_accessor != null && prop.set_accessor != null) {
+ info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE"));
+ } else if (prop.get_accessor != null) {
+ info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_READABLE"));
+ } else if (prop.set_accessor != null) {
+ info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE"));
+ } else {
+ info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_NONE"));
+ }
+
+ var cdecl = new CCodeDeclaration ("const GDBusPropertyInfo");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_property_info_" + prop.name, info));
+ cdecl.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_constant_declaration (cdecl);
+
+ infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_property_info_" + prop.name)));
+ }
+
+ infos.append (new CCodeConstant ("NULL"));
+
+ var cdecl = new CCodeDeclaration ("const GDBusPropertyInfo * const");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_property_info[]", infos));
+ cdecl.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_constant_declaration (cdecl);
+
+ return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_property_info");
+ }
+
+ CCodeExpression get_interface_info (ObjectTypeSymbol sym) {
+ var info = new CCodeInitializerList ();
+ info.append (new CCodeConstant ("-1"));
+ info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name (sym))));
+ info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_method_info (sym)));
+ info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_signal_info (sym)));
+ info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_property_info (sym)));
+
+ var cdecl = new CCodeDeclaration ("const GDBusInterfaceInfo");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_interface_info", info));
+ cdecl.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_constant_declaration (cdecl);
+
+ return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_interface_info");
+ }
+
+ CCodeExpression get_interface_vtable (ObjectTypeSymbol sym) {
+ var vtable = new CCodeInitializerList ();
+ vtable.append (new CCodeIdentifier (sym.get_lower_case_cprefix () + "dbus_interface_method_call"));
+ vtable.append (new CCodeIdentifier (sym.get_lower_case_cprefix () + "dbus_interface_get_property"));
+ vtable.append (new CCodeIdentifier (sym.get_lower_case_cprefix () + "dbus_interface_set_property"));
+
+ generate_interface_method_call_function (sym);
+ generate_interface_get_property_function (sym);
+ generate_interface_set_property_function (sym);
+
+ var cdecl = new CCodeDeclaration ("const GDBusInterfaceVTable");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_interface_vtable", vtable));
+ cdecl.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_constant_declaration (cdecl);
+
+ return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_interface_vtable");
+ }
+
+ public override void visit_method_call (MethodCall expr) {
+ var mtype = expr.call.value_type as MethodType;
+ if (mtype == null || mtype.method_symbol.get_cname () != "g_dbus_connection_register_object") {
+ base.visit_method_call (expr);
+ return;
+ }
+
+ expr.accept_children (codegen);
+
+ var ma = (MemberAccess) expr.call;
+ var type_arg = (ObjectType) ma.get_type_arguments ().get (0);
+
+ var args = expr.get_argument_list ();
+ var path_arg = args[0];
+ var obj_arg = args[1];
+
+ // method can fail
+ current_method_inner_error = true;
+
+ var cregister = new CCodeFunctionCall (new CCodeIdentifier ("%sregister_object".printf (type_arg.type_symbol.get_lower_case_cprefix ())));
+ cregister.add_argument ((CCodeExpression) obj_arg.ccodenode);
+ cregister.add_argument ((CCodeExpression) ma.inner.ccodenode);
+ cregister.add_argument ((CCodeExpression) path_arg.ccodenode);
+ cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression ("_inner_error_")));
+ expr.ccodenode = cregister;
+ }
+
+ public override void generate_class_declaration (Class cl, CCodeDeclarationSpace decl_space) {
+ base.generate_class_declaration (cl, decl_space);
+
+ generate_object_type_symbol_declaration (cl, decl_space);
+ }
+
+ public override void generate_interface_declaration (Interface iface, CCodeDeclarationSpace decl_space) {
+ base.generate_interface_declaration (iface, decl_space);
+
+ generate_object_type_symbol_declaration (iface, decl_space);
+ }
+
+ public override void visit_class (Class cl) {
+ base.visit_class (cl);
+
+ visit_object_type_symbol (cl);
+ }
+
+ public override void visit_interface (Interface iface) {
+ base.visit_interface (iface);
+
+ visit_object_type_symbol (iface);
+ }
+
+ void generate_object_type_symbol_declaration (ObjectTypeSymbol sym, CCodeDeclarationSpace decl_space) {
+ string dbus_iface_name = get_dbus_name (sym);
+ if (dbus_iface_name == null) {
+ return;
+ }
+
+ string register_object_name = "%sregister_object".printf (sym.get_lower_case_cprefix ());
+
+ if (decl_space.add_symbol_declaration (sym, register_object_name)) {
+ return;
+ }
+
+ // declare register_object function
+ var cfunc = new CCodeFunction (register_object_name, "guint");
+ cfunc.add_parameter (new CCodeFormalParameter ("object", "void*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("connection", "GDBusConnection*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("path", "const gchar*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("error", "GError**"));
+ if (sym.is_private_symbol ()) {
+ cfunc.modifiers |= CCodeModifiers.STATIC;
+ }
+ decl_space.add_type_member_declaration (cfunc);
+ }
+
+ void visit_object_type_symbol (ObjectTypeSymbol sym) {
+ // only support registering a single D-Bus interface at a time (unlike old D-Bus support)
+ // however, register_object can be invoked multiple times for the same object path with different interfaces
+ string dbus_iface_name = get_dbus_name (sym);
+ if (dbus_iface_name == null) {
+ return;
+ }
+
+ var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "register_object", "guint");
+ cfunc.add_parameter (new CCodeFormalParameter ("object", "gpointer"));
+ cfunc.add_parameter (new CCodeFormalParameter ("connection", "GDBusConnection*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("path", "const gchar*"));
+ cfunc.add_parameter (new CCodeFormalParameter ("error", "GError**"));
+ if (sym.is_private_symbol ()) {
+ cfunc.modifiers |= CCodeModifiers.STATIC;
+ }
+
+ var block = new CCodeBlock ();
+ cfunc.block = block;
+
+ var cdecl = new CCodeDeclaration ("guint");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
+ block.add_statement (cdecl);
+
+
+ // data consists of 3 pointers: object, connection, path
+ cdecl = new CCodeDeclaration ("gpointer");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("*data"));
+ block.add_statement (cdecl);
+
+ var alloc_data = new CCodeFunctionCall (new CCodeIdentifier ("g_new"));
+ alloc_data.add_argument (new CCodeIdentifier ("gpointer"));
+ alloc_data.add_argument (new CCodeConstant ("3"));
+ block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("data"), alloc_data)));
+
+ var ref_object = new CCodeFunctionCall (new CCodeIdentifier (sym.get_ref_function ()));
+ ref_object.add_argument (new CCodeIdentifier ("object"));
+ block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")), ref_object)));
+
+ ref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref"));
+ ref_object.add_argument (new CCodeIdentifier ("connection"));
+ block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("1")), ref_object)));
+
+ var dup_path = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup"));
+ dup_path.add_argument (new CCodeIdentifier ("path"));
+ block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("2")), dup_path)));
+
+
+ var cregister = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_register_object"));
+ cregister.add_argument (new CCodeIdentifier ("connection"));
+ cregister.add_argument (new CCodeIdentifier ("path"));
+
+ cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_info (sym)));
+ cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_vtable (sym)));
+
+ cregister.add_argument (new CCodeIdentifier ("data"));
+ cregister.add_argument (new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "unregister_object"));
+ cregister.add_argument (new CCodeIdentifier ("error"));
+
+ block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), cregister)));
+
+ var error_block = new CCodeBlock ();
+ error_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("0")));
+ block.add_statement (new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("result")), error_block));
+
+ handle_signals (sym, block);
+
+ block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
+
+ source_type_member_definition.append (cfunc);
+
+
+ cfunc = new CCodeFunction ("_" + sym.get_lower_case_cprefix () + "unregister_object");
+ cfunc.add_parameter (new CCodeFormalParameter ("data", "gpointer*"));
+ cfunc.modifiers |= CCodeModifiers.STATIC;
+ source_declarations.add_type_member_declaration (cfunc.copy ());
+
+ block = new CCodeBlock ();
+ cfunc.block = block;
+
+ var unref_object = new CCodeFunctionCall (new CCodeIdentifier (sym.get_unref_function ()));
+ unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")));
+ block.add_statement (new CCodeExpressionStatement (unref_object));
+
+ unref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
+ unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("1")));
+ block.add_statement (new CCodeExpressionStatement (unref_object));
+
+ var free_path = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
+ free_path.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("2")));
+ block.add_statement (new CCodeExpressionStatement (free_path));
+
+ var free_data = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
+ free_data.add_argument (new CCodeIdentifier ("data"));
+ block.add_statement (new CCodeExpressionStatement (free_data));
+
+ source_type_member_definition.append (cfunc);
+ }
+}
diff --git a/codegen/valagvariantmodule.vala b/codegen/valagvariantmodule.vala
new file mode 100644
index 0000000..0f3861e
--- /dev/null
+++ b/codegen/valagvariantmodule.vala
@@ -0,0 +1,788 @@
+/* valagvariantmodule.vala
+ *
+ * Copyright (C) 2010 Jürg Billeter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Jürg Billeter <j bitron ch>
+ */
+
+public class Vala.GVariantModule : GAsyncModule {
+ struct BasicTypeInfo {
+ public unowned string signature;
+ public unowned string type_name;
+ public bool is_string;
+ }
+
+ const BasicTypeInfo[] basic_types = {
+ { "y", "byte", false },
+ { "b", "boolean", false },
+ { "n", "int16", false },
+ { "q", "uint16", false },
+ { "i", "int32", false },
+ { "u", "uint32", false },
+ { "x", "int64", false },
+ { "t", "uint64", false },
+ { "d", "double", false },
+ { "s", "string", true },
+ { "o", "object_path", true },
+ { "g", "signature", true }
+ };
+
+ public GVariantModule (CCodeGenerator codegen, CCodeModule? next) {
+ base (codegen, next);
+ }
+
+ static bool is_string_marshalled_enum (TypeSymbol? symbol) {
+ if (symbol != null && symbol is Enum) {
+ var dbus = symbol.get_attribute ("DBus");
+ return dbus != null && dbus.get_bool ("use_string_marshalling");
+ }
+ return false;
+ }
+
+ string get_dbus_value (EnumValue value, string default_value) {
+ var dbus = value.get_attribute ("DBus");
+ if (dbus == null) {
+ return default_value;
+ }
+
+ string dbus_value = dbus.get_string ("value");
+ if (dbus_value == null) {
+ return default_value;
+ }
+ return dbus_value;
+ }
+
+ bool get_basic_type_info (string signature, out BasicTypeInfo basic_type) {
+ foreach (BasicTypeInfo info in basic_types) {
+ if (info.signature == signature) {
+ basic_type = info;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static string? get_type_signature (DataType datatype) {
+ var array_type = datatype as ArrayType;
+
+ if (array_type != null) {
+ string element_type_signature = get_type_signature (array_type.element_type);
+
+ if (element_type_signature == null) {
+ return null;
+ }
+
+ return string.nfill (array_type.rank, 'a') + element_type_signature;
+ } else if (is_string_marshalled_enum (datatype.data_type)) {
+ return "s";
+ } else if (datatype.data_type != null) {
+ string sig = null;
+
+ var ccode = datatype.data_type.get_attribute ("CCode");
+ if (ccode != null) {
+ sig = ccode.get_string ("type_signature");
+ }
+
+ var st = datatype.data_type as Struct;
+ var en = datatype.data_type as Enum;
+ if (sig == null && st != null) {
+ var str = new StringBuilder ();
+ str.append_c ('(');
+ foreach (Field f in st.get_fields ()) {
+ if (f.binding == MemberBinding.INSTANCE) {
+ str.append (get_type_signature (f.field_type));
+ }
+ }
+ str.append_c (')');
+ sig = str.str;
+ } else if (sig == null && en != null) {
+ if (en.is_flags) {
+ return "u";
+ } else {
+ return "i";
+ }
+ }
+
+ var type_args = datatype.get_type_arguments ();
+ if (sig != null && sig.str ("%s") != null && type_args.size > 0) {
+ string element_sig = "";
+ foreach (DataType type_arg in type_args) {
+ var s = get_type_signature (type_arg);
+ if (s != null) {
+ element_sig += s;
+ }
+ }
+
+ sig = sig.printf (element_sig);
+ }
+
+ return sig;
+ } else {
+ return null;
+ }
+ }
+
+ public override void visit_enum (Enum en) {
+ base.visit_enum (en);
+
+ if (is_string_marshalled_enum (en)) {
+ // strcmp
+ source_declarations.add_include ("string.h");
+
+ source_type_member_definition.append (generate_enum_from_string_function (en));
+ source_type_member_definition.append (generate_enum_to_string_function (en));
+ }
+ }
+
+ public override bool generate_enum_declaration (Enum en, CCodeDeclarationSpace decl_space) {
+ if (base.generate_enum_declaration (en, decl_space)) {
+ if (is_string_marshalled_enum (en)) {
+ decl_space.add_type_member_declaration (generate_enum_from_string_function_declaration (en));
+ decl_space.add_type_member_declaration (generate_enum_to_string_function_declaration (en));
+ }
+ return true;
+ }
+ return false;
+ }
+
+ CCodeExpression? get_array_length (CCodeExpression expr, int dim) {
+ var id = expr as CCodeIdentifier;
+ var ma = expr as CCodeMemberAccess;
+ if (id != null) {
+ return new CCodeIdentifier ("%s_length%d".printf (id.name, dim));
+ } else if (ma != null) {
+ if (ma.is_pointer) {
+ return new CCodeMemberAccess.pointer (ma.inner, "%s_length%d".printf (ma.member_name, dim));
+ } else {
+ return new CCodeMemberAccess (ma.inner, "%s_length%d".printf (ma.member_name, dim));
+ }
+ } else {
+ // must be NULL-terminated
+ var len_call = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length"));
+ len_call.add_argument (expr);
+ return len_call;
+ }
+ }
+
+ CCodeExpression? generate_enum_value_from_string (CCodeFragment fragment, EnumValueType type, CCodeExpression? expr) {
+ var en = type.type_symbol as Enum;
+ var from_string_name = "%s_from_string".printf (en.get_lower_case_cname (null));
+
+ var from_string_call = new CCodeFunctionCall (new CCodeIdentifier (from_string_name));
+ from_string_call.add_argument (expr);
+
+ return from_string_call;
+ }
+
+ public CCodeFunction generate_enum_from_string_function_declaration (Enum en) {
+ var from_string_name = "%s_from_string".printf (en.get_lower_case_cname (null));
+
+ var from_string_func = new CCodeFunction (from_string_name, en.get_cname ());
+ from_string_func.add_parameter (new CCodeFormalParameter ("str", "const char*"));
+
+ return from_string_func;
+ }
+
+ public CCodeFunction generate_enum_from_string_function (Enum en) {
+ var from_string_name = "%s_from_string".printf (en.get_lower_case_cname (null));
+
+ var from_string_func = new CCodeFunction (from_string_name, en.get_cname ());
+ from_string_func.add_parameter (new CCodeFormalParameter ("str", "const char*"));
+
+ var from_string_block = new CCodeBlock ();
+ from_string_func.block = from_string_block;
+
+ var cdecl = new CCodeDeclaration (en.get_cname ());
+ cdecl.add_declarator (new CCodeVariableDeclarator ("value"));
+ from_string_block.add_statement (cdecl);
+
+ CCodeStatement if_else_if = null;
+ CCodeIfStatement last_statement = null;
+ foreach (EnumValue enum_value in en.get_values ()) {
+ var true_block = new CCodeBlock ();
+ true_block.suppress_newline = true;
+ true_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("value"), new CCodeIdentifier (enum_value.get_cname ()))));
+
+ string dbus_value = get_dbus_value (enum_value, enum_value.name);
+ var string_comparison = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
+ string_comparison.add_argument (new CCodeIdentifier ("str"));
+ string_comparison.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_value)));
+ var stmt = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, string_comparison, new CCodeConstant ("0")), true_block);
+
+ if (last_statement != null) {
+ last_statement.false_statement = stmt;
+ } else {
+ if_else_if = stmt;
+ }
+ last_statement = stmt;
+ }
+
+ from_string_block.add_statement (if_else_if);
+
+ from_string_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("value")));
+
+ return from_string_func;
+ }
+
+ CCodeExpression deserialize_basic (CCodeFragment fragment, BasicTypeInfo basic_type, CCodeExpression variant_expr, bool transfer = false) {
+ var get_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get_" + basic_type.type_name));
+ get_call.add_argument (variant_expr);
+
+ if (basic_type.is_string) {
+ if (transfer) {
+ get_call.call = new CCodeIdentifier ("g_variant_get_string");
+ } else {
+ get_call.call = new CCodeIdentifier ("g_variant_dup_string");
+ }
+ get_call.add_argument (new CCodeConstant ("NULL"));
+ }
+
+ return get_call;
+ }
+
+ CCodeExpression deserialize_array (CCodeFragment fragment, ArrayType array_type, CCodeExpression variant_expr, CCodeExpression? expr) {
+ string temp_name = "_tmp%d_".printf (next_temp_var_id++);
+
+ var new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_new"));
+ new_call.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
+ // add one extra element for NULL-termination
+ new_call.add_argument (new CCodeConstant ("5"));
+
+ var cdecl = new CCodeDeclaration (array_type.get_cname ());
+ cdecl.add_declarator (new CCodeVariableDeclarator (temp_name, new_call));
+ fragment.append (cdecl);
+
+ cdecl = new CCodeDeclaration ("int");
+ cdecl.add_declarator (new CCodeVariableDeclarator (temp_name + "_length", new CCodeConstant ("0")));
+ fragment.append (cdecl);
+
+ cdecl = new CCodeDeclaration ("int");
+ cdecl.add_declarator (new CCodeVariableDeclarator (temp_name + "_size", new CCodeConstant ("4")));
+ fragment.append (cdecl);
+
+ deserialize_array_dim (fragment, array_type, 1, temp_name, variant_expr, expr);
+
+ if (array_type.element_type.is_reference_type_or_type_parameter ()) {
+ // NULL terminate array
+ var length = new CCodeIdentifier (temp_name + "_length");
+ var element_access = new CCodeElementAccess (new CCodeIdentifier (temp_name), length);
+ fragment.append (new CCodeExpressionStatement (new CCodeAssignment (element_access, new CCodeIdentifier ("NULL"))));
+ }
+
+ return new CCodeIdentifier (temp_name);
+ }
+
+ void deserialize_array_dim (CCodeFragment fragment, ArrayType array_type, int dim, string temp_name, CCodeExpression variant_expr, CCodeExpression? expr) {
+ string subiter_name = "_tmp%d_".printf (next_temp_var_id++);
+ string element_name = "_tmp%d_".printf (next_temp_var_id++);
+
+ var cdecl = new CCodeDeclaration ("int");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("%s_length%d".printf (temp_name, dim), new CCodeConstant ("0")));
+ fragment.append (cdecl);
+
+ cdecl = new CCodeDeclaration ("GVariantIter");
+ cdecl.add_declarator (new CCodeVariableDeclarator (subiter_name));
+ fragment.append (cdecl);
+
+ cdecl = new CCodeDeclaration ("GVariant*");
+ cdecl.add_declarator (new CCodeVariableDeclarator (element_name));
+ fragment.append (cdecl);
+
+ var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
+ iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name)));
+ iter_call.add_argument (variant_expr);
+ fragment.append (new CCodeExpressionStatement (iter_call));
+
+ iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_next_value"));
+ iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name)));
+
+ var cforblock = new CCodeBlock ();
+ var cforfragment = new CCodeFragment ();
+ cforblock.add_statement (cforfragment);
+ var cfor = new CCodeForStatement (new CCodeAssignment (new CCodeIdentifier (element_name), iter_call), cforblock);
+ cfor.add_iterator (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("%s_length%d".printf (temp_name, dim))));
+
+ if (dim < array_type.rank) {
+ deserialize_array_dim (cforfragment, array_type, dim + 1, temp_name, new CCodeIdentifier (element_name), expr);
+ } else {
+ var size_check = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier (temp_name + "_size"), new CCodeIdentifier (temp_name + "_length"));
+ var renew_block = new CCodeBlock ();
+
+ // tmp_size = (2 * tmp_size);
+ var new_size = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeConstant ("2"), new CCodeIdentifier (temp_name + "_size"));
+ renew_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier (temp_name + "_size"), new_size)));
+
+ var renew_call = new CCodeFunctionCall (new CCodeIdentifier ("g_renew"));
+ renew_call.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
+ renew_call.add_argument (new CCodeIdentifier (temp_name));
+ // add one extra element for NULL-termination
+ renew_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (temp_name + "_size"), new CCodeConstant ("1")));
+ var renew_stmt = new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier (temp_name), renew_call));
+ renew_block.add_statement (renew_stmt);
+
+ var cif = new CCodeIfStatement (size_check, renew_block);
+ cforfragment.append (cif);
+
+ var element_access = new CCodeElementAccess (new CCodeIdentifier (temp_name), new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier (temp_name + "_length")));
+ var element_expr = deserialize_expression (cforfragment, array_type.element_type, new CCodeIdentifier (element_name), null);
+ cforfragment.append (new CCodeExpressionStatement (new CCodeAssignment (element_access, element_expr)));
+ }
+
+ var unref = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
+ unref.add_argument (new CCodeIdentifier (element_name));
+ cforfragment.append (new CCodeExpressionStatement (unref));
+
+ fragment.append (cfor);
+
+ if (expr != null) {
+ fragment.append (new CCodeExpressionStatement (new CCodeAssignment (get_array_length (expr, dim), new CCodeIdentifier ("%s_length%d".printf (temp_name, dim)))));
+ }
+ }
+
+ CCodeExpression? deserialize_struct (CCodeFragment fragment, Struct st, CCodeExpression variant_expr) {
+ string temp_name = "_tmp%d_".printf (next_temp_var_id++);
+ string subiter_name = "_tmp%d_".printf (next_temp_var_id++);
+
+ var cdecl = new CCodeDeclaration (st.get_cname ());
+ cdecl.add_declarator (new CCodeVariableDeclarator (temp_name));
+ fragment.append (cdecl);
+
+ cdecl = new CCodeDeclaration ("GVariantIter");
+ cdecl.add_declarator (new CCodeVariableDeclarator (subiter_name));
+ fragment.append (cdecl);
+
+ var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
+ iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name)));
+ iter_call.add_argument (variant_expr);
+ fragment.append (new CCodeExpressionStatement (iter_call));
+
+ bool field_found = false;;
+
+ foreach (Field f in st.get_fields ()) {
+ if (f.binding != MemberBinding.INSTANCE) {
+ continue;
+ }
+
+ field_found = true;
+
+ read_expression (fragment, f.field_type, new CCodeIdentifier (subiter_name), new CCodeMemberAccess (new CCodeIdentifier (temp_name), f.get_cname ()));
+ }
+
+ if (!field_found) {
+ return null;
+ }
+
+ return new CCodeIdentifier (temp_name);
+ }
+
+ CCodeExpression deserialize_hash_table (CCodeFragment fragment, ObjectType type, CCodeExpression variant_expr) {
+ string temp_name = "_tmp%d_".printf (next_temp_var_id++);
+ string subiter_name = "_tmp%d_".printf (next_temp_var_id++);
+ string key_name = "_tmp%d_".printf (next_temp_var_id++);
+ string value_name = "_tmp%d_".printf (next_temp_var_id++);
+
+ var type_args = type.get_type_arguments ();
+ assert (type_args.size == 2);
+ var key_type = type_args.get (0);
+ var value_type = type_args.get (1);
+
+ var cdecl = new CCodeDeclaration ("GHashTable*");
+ cdecl.add_declarator (new CCodeVariableDeclarator (temp_name));
+ fragment.append (cdecl);
+
+ cdecl = new CCodeDeclaration ("GVariantIter");
+ cdecl.add_declarator (new CCodeVariableDeclarator (subiter_name));
+ fragment.append (cdecl);
+
+ cdecl = new CCodeDeclaration ("GVariant*");
+ cdecl.add_declarator (new CCodeVariableDeclarator (key_name));
+ fragment.append (cdecl);
+
+ cdecl = new CCodeDeclaration ("GVariant*");
+ cdecl.add_declarator (new CCodeVariableDeclarator (value_name));
+ fragment.append (cdecl);
+
+ var hash_table_new = new CCodeFunctionCall (new CCodeIdentifier ("g_hash_table_new_full"));
+ if (key_type.data_type == string_type.data_type) {
+ hash_table_new.add_argument (new CCodeIdentifier ("g_str_hash"));
+ hash_table_new.add_argument (new CCodeIdentifier ("g_str_equal"));
+ } else {
+ hash_table_new.add_argument (new CCodeIdentifier ("g_direct_hash"));
+ hash_table_new.add_argument (new CCodeIdentifier ("g_direct_equal"));
+ }
+ if (key_type.data_type == string_type.data_type) {
+ hash_table_new.add_argument (new CCodeIdentifier ("g_free"));
+ } else {
+ hash_table_new.add_argument (new CCodeIdentifier ("NULL"));
+ }
+ if (value_type.data_type == string_type.data_type) {
+ hash_table_new.add_argument (new CCodeIdentifier ("g_free"));
+ } else {
+ hash_table_new.add_argument (new CCodeIdentifier ("NULL"));
+ }
+ fragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier (temp_name), hash_table_new)));
+
+ var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
+ iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name)));
+ iter_call.add_argument (variant_expr);
+ fragment.append (new CCodeExpressionStatement (iter_call));
+
+ iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_loop"));
+ iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name)));
+ iter_call.add_argument (new CCodeConstant ("\"{?*}\""));
+ iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (key_name)));
+ iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (value_name)));
+
+ var cwhileblock = new CCodeBlock ();
+ var cwhilefragment = new CCodeFragment ();
+ cwhileblock.add_statement (cwhilefragment);
+ var cwhile = new CCodeWhileStatement (iter_call, cwhileblock);
+
+ var key_expr = deserialize_expression (cwhilefragment, key_type, new CCodeIdentifier (key_name), null);
+ var value_expr = deserialize_expression (cwhilefragment, value_type, new CCodeIdentifier (value_name), null);
+
+ var hash_table_insert = new CCodeFunctionCall (new CCodeIdentifier ("g_hash_table_insert"));
+ hash_table_insert.add_argument (new CCodeIdentifier (temp_name));
+ hash_table_insert.add_argument (convert_to_generic_pointer (key_expr, key_type));
+ hash_table_insert.add_argument (convert_to_generic_pointer (value_expr, value_type));
+ cwhilefragment.append (new CCodeExpressionStatement (hash_table_insert));
+
+ fragment.append (cwhile);
+
+ return new CCodeIdentifier (temp_name);
+ }
+
+ public override CCodeExpression? deserialize_expression (CCodeFragment fragment, DataType type, CCodeExpression variant_expr, CCodeExpression? expr) {
+ BasicTypeInfo basic_type;
+ CCodeExpression result = null;
+ if (is_string_marshalled_enum (type.data_type)) {
+ get_basic_type_info ("s", out basic_type);
+ result = deserialize_basic (fragment, basic_type, variant_expr, true);
+ result = generate_enum_value_from_string (fragment, type as EnumValueType, result);
+ } else if (get_basic_type_info (get_type_signature (type), out basic_type)) {
+ result = deserialize_basic (fragment, basic_type, variant_expr);
+ } else if (type is ArrayType) {
+ result = deserialize_array (fragment, (ArrayType) type, variant_expr, expr);
+ } else if (type.data_type is Struct) {
+ var st = (Struct) type.data_type;
+ result = deserialize_struct (fragment, st, variant_expr);
+ if (result != null && type.nullable) {
+ var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
+ csizeof.add_argument (new CCodeIdentifier (st.get_cname ()));
+ var cdup = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup"));
+ cdup.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, result));
+ cdup.add_argument (csizeof);
+ result = cdup;
+ }
+ } else if (type is ObjectType) {
+ if (type.data_type.get_full_name () == "GLib.Variant") {
+ var variant_get = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get_variant"));
+ variant_get.add_argument (variant_expr);
+ result = variant_get;
+ } else if (type.data_type.get_full_name () == "GLib.HashTable") {
+ result = deserialize_hash_table (fragment, (ObjectType) type, variant_expr);
+ }
+ }
+
+ if (result == null) {
+ Report.error (type.source_reference, "GVariant deserialization of type `%s' is not supported".printf (type.to_string ()));
+ }
+
+ return result;
+ }
+
+ public void read_expression (CCodeFragment fragment, DataType type, CCodeExpression iter_expr, CCodeExpression target_expr) {
+ string temp_name = "_tmp%d_".printf (next_temp_var_id++);
+
+ var cdecl = new CCodeDeclaration ("GVariant*");
+ cdecl.add_declarator (new CCodeVariableDeclarator (temp_name));
+ fragment.append (cdecl);
+
+ var variant_expr = new CCodeIdentifier (temp_name);
+
+ var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_next_value"));
+ iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, iter_expr));
+ fragment.append (new CCodeExpressionStatement (new CCodeAssignment (variant_expr, iter_call)));
+
+ var result = deserialize_expression (fragment, type, variant_expr, target_expr);
+ fragment.append (new CCodeExpressionStatement (new CCodeAssignment (target_expr, result)));
+
+ var unref = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
+ unref.add_argument (variant_expr);
+ fragment.append (new CCodeExpressionStatement (unref));
+ }
+
+ CCodeExpression? generate_enum_value_to_string (CCodeFragment fragment, EnumValueType type, CCodeExpression? expr) {
+ var en = type.type_symbol as Enum;
+ var to_string_name = "%s_to_string".printf (en.get_lower_case_cname (null));
+
+ var to_string_call = new CCodeFunctionCall (new CCodeIdentifier (to_string_name));
+ to_string_call.add_argument (expr);
+
+ return to_string_call;
+ }
+
+ public CCodeFunction generate_enum_to_string_function_declaration (Enum en) {
+ var to_string_name = "%s_to_string".printf (en.get_lower_case_cname (null));
+
+ var to_string_func = new CCodeFunction (to_string_name, "const char*");
+ to_string_func.add_parameter (new CCodeFormalParameter ("value", en.get_cname ()));
+
+ return to_string_func;
+ }
+
+ public CCodeFunction generate_enum_to_string_function (Enum en) {
+ var to_string_name = "%s_to_string".printf (en.get_lower_case_cname (null));
+
+ var to_string_func = new CCodeFunction (to_string_name, "const char*");
+ to_string_func.add_parameter (new CCodeFormalParameter ("value", en.get_cname ()));
+
+ var to_string_block = new CCodeBlock ();
+ to_string_func.block = to_string_block;
+
+ var cdecl = new CCodeDeclaration ("const char *");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("str"));
+ to_string_block.add_statement (cdecl);
+
+ var cswitch = new CCodeSwitchStatement (new CCodeIdentifier ("value"));
+ foreach (EnumValue enum_value in en.get_values ()) {
+ string dbus_value = get_dbus_value (enum_value, enum_value.name);
+ cswitch.add_statement (new CCodeCaseStatement (new CCodeIdentifier (enum_value.get_cname ())));
+ cswitch.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("str"), new CCodeConstant ("\"%s\"".printf (dbus_value)))));
+ cswitch.add_statement (new CCodeBreakStatement ());
+ }
+ to_string_block.add_statement (cswitch);
+
+ to_string_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("str")));
+
+ return to_string_func;
+ }
+
+ CCodeExpression? serialize_basic (CCodeFragment fragment, BasicTypeInfo basic_type, CCodeExpression expr) {
+ var new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_new_" + basic_type.type_name));
+ new_call.add_argument (expr);
+ return new_call;
+ }
+
+ CCodeExpression? serialize_array (CCodeFragment fragment, ArrayType array_type, CCodeExpression array_expr) {
+ string array_iter_name = "_tmp%d_".printf (next_temp_var_id++);
+
+ var cdecl = new CCodeDeclaration (array_type.get_cname ());
+ cdecl.add_declarator (new CCodeVariableDeclarator (array_iter_name));
+ fragment.append (cdecl);
+
+ fragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier (array_iter_name), array_expr)));
+
+ return serialize_array_dim (fragment, array_type, 1, array_expr, new CCodeIdentifier (array_iter_name));
+ }
+
+ CCodeExpression? serialize_array_dim (CCodeFragment fragment, ArrayType array_type, int dim, CCodeExpression array_expr, CCodeExpression array_iter_expr) {
+ string builder_name = "_tmp%d_".printf (next_temp_var_id++);
+ string index_name = "_tmp%d_".printf (next_temp_var_id++);
+
+ var cdecl = new CCodeDeclaration ("GVariantBuilder");
+ cdecl.add_declarator (new CCodeVariableDeclarator (builder_name));
+ fragment.append (cdecl);
+
+ cdecl = new CCodeDeclaration ("int");
+ cdecl.add_declarator (new CCodeVariableDeclarator (index_name));
+ fragment.append (cdecl);
+
+ var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
+ builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (builder_name)));
+ builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_ARRAY"));
+ fragment.append (new CCodeExpressionStatement (builder_init));
+
+ var cforblock = new CCodeBlock ();
+ var cforfragment = new CCodeFragment ();
+ cforblock.add_statement (cforfragment);
+ var cfor = new CCodeForStatement (new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier (index_name), get_array_length (array_expr, dim)), cforblock);
+ cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (index_name), new CCodeConstant ("0")));
+ cfor.add_iterator (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier (index_name)));
+
+ CCodeExpression element_variant;
+ if (dim < array_type.rank) {
+ element_variant = serialize_array_dim (cforfragment, array_type, dim + 1, array_expr, array_iter_expr);
+ } else {
+ var element_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, array_iter_expr);
+ element_variant = serialize_expression (cforfragment, array_type.element_type, element_expr);
+ }
+
+ var builder_add = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_add_value"));
+ builder_add.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (builder_name)));
+ builder_add.add_argument (element_variant);
+ cforfragment.append (new CCodeExpressionStatement (builder_add));
+
+ if (dim == array_type.rank) {
+ var array_iter_incr = new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, array_iter_expr);
+ cforfragment.append (new CCodeExpressionStatement (array_iter_incr));
+ }
+
+ fragment.append (cfor);
+
+ var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
+ builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (builder_name)));
+ return builder_end;
+ }
+
+ CCodeExpression? serialize_struct (CCodeFragment fragment, Struct st, CCodeExpression struct_expr) {
+ string builder_name = "_tmp%d_".printf (next_temp_var_id++);
+
+ var cdecl = new CCodeDeclaration ("GVariantBuilder");
+ cdecl.add_declarator (new CCodeVariableDeclarator (builder_name));
+ fragment.append (cdecl);
+
+ var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
+ iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (builder_name)));
+ iter_call.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
+ fragment.append (new CCodeExpressionStatement (iter_call));
+
+ bool field_found = false;;
+
+ foreach (Field f in st.get_fields ()) {
+ if (f.binding != MemberBinding.INSTANCE) {
+ continue;
+ }
+
+ field_found = true;
+
+ write_expression (fragment, f.field_type, new CCodeIdentifier (builder_name), new CCodeMemberAccess (struct_expr, f.get_cname ()));
+ }
+
+ if (!field_found) {
+ return null;
+ }
+
+ var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
+ builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (builder_name)));
+ return builder_end;
+ }
+
+ CCodeExpression serialize_hash_table (CCodeFragment fragment, ObjectType type, CCodeExpression hash_table_expr) {
+ string subiter_name = "_tmp%d_".printf (next_temp_var_id++);
+ string tableiter_name = "_tmp%d_".printf (next_temp_var_id++);
+ string key_name = "_tmp%d_".printf (next_temp_var_id++);
+ string value_name = "_tmp%d_".printf (next_temp_var_id++);
+
+ var type_args = type.get_type_arguments ();
+ assert (type_args.size == 2);
+ var key_type = type_args.get (0);
+ var value_type = type_args.get (1);
+
+ var cdecl = new CCodeDeclaration ("GVariantBuilder");
+ cdecl.add_declarator (new CCodeVariableDeclarator (subiter_name));
+ fragment.append (cdecl);
+
+ cdecl = new CCodeDeclaration ("GHashTableIter");
+ cdecl.add_declarator (new CCodeVariableDeclarator (tableiter_name));
+ fragment.append (cdecl);
+
+ cdecl = new CCodeDeclaration ("gpointer");
+ cdecl.add_declarator (new CCodeVariableDeclarator (key_name));
+ cdecl.add_declarator (new CCodeVariableDeclarator (value_name));
+ fragment.append (cdecl);
+
+ var iter_init_call = new CCodeFunctionCall (new CCodeIdentifier ("g_hash_table_iter_init"));
+ iter_init_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (tableiter_name)));
+ iter_init_call.add_argument (hash_table_expr);
+ fragment.append (new CCodeExpressionStatement (iter_init_call));
+
+ var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
+ iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name)));
+ iter_call.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_DICTIONARY"));
+ fragment.append (new CCodeExpressionStatement (iter_call));
+
+ var iter_next_call = new CCodeFunctionCall (new CCodeIdentifier ("g_hash_table_iter_next"));
+ iter_next_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (tableiter_name)));
+ iter_next_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (key_name)));
+ iter_next_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (value_name)));
+
+ var cwhileblock = new CCodeBlock ();
+ var cwhilefragment = new CCodeFragment ();
+ cwhileblock.add_statement (cwhilefragment);
+ var cwhile = new CCodeWhileStatement (iter_next_call, cwhileblock);
+
+ cdecl = new CCodeDeclaration (key_type.get_cname ());
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_key"));
+ cwhilefragment.append (cdecl);
+
+ cdecl = new CCodeDeclaration (value_type.get_cname ());
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_value"));
+ cwhilefragment.append (cdecl);
+
+ cwhilefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_key"), convert_from_generic_pointer (new CCodeIdentifier (key_name), key_type))));
+ cwhilefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_value"), convert_from_generic_pointer (new CCodeIdentifier (value_name), value_type))));
+
+ iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_add"));
+ iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name)));
+ iter_call.add_argument (new CCodeConstant ("\"{?*}\""));
+ iter_call.add_argument (serialize_expression (cwhilefragment, key_type, new CCodeIdentifier ("_key")));
+ iter_call.add_argument (serialize_expression (cwhilefragment, value_type, new CCodeIdentifier ("_value")));
+ cwhilefragment.append (new CCodeExpressionStatement (iter_call));
+
+ fragment.append (cwhile);
+
+ iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
+ iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name)));
+ return iter_call;
+ }
+
+ public override CCodeExpression? serialize_expression (CCodeFragment fragment, DataType type, CCodeExpression expr) {
+ BasicTypeInfo basic_type;
+ CCodeExpression result = null;
+ if (is_string_marshalled_enum (type.data_type)) {
+ get_basic_type_info ("s", out basic_type);
+ result = generate_enum_value_to_string (fragment, type as EnumValueType, expr);
+ result = serialize_basic (fragment, basic_type, result);
+ } else if (get_basic_type_info (get_type_signature (type), out basic_type)) {
+ result = serialize_basic (fragment, basic_type, expr);
+ } else if (type is ArrayType) {
+ result = serialize_array (fragment, (ArrayType) type, expr);
+ } else if (type.data_type is Struct) {
+ var st_expr = expr;
+ if (type.nullable) {
+ st_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, st_expr);
+ }
+ result = serialize_struct (fragment, (Struct) type.data_type, st_expr);
+ } else if (type is ObjectType) {
+ if (type.data_type.get_full_name () == "GLib.Variant") {
+ var variant_new = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_new_variant"));
+ variant_new.add_argument (expr);
+ result = variant_new;
+ } else if (type.data_type.get_full_name () == "GLib.HashTable") {
+ result = serialize_hash_table (fragment, (ObjectType) type, expr);
+ }
+ }
+
+ if (result == null) {
+ Report.error (type.source_reference, "GVariant serialization of type `%s' is not supported".printf (type.to_string ()));
+ }
+
+ return result;
+ }
+
+ public void write_expression (CCodeFragment fragment, DataType type, CCodeExpression builder_expr, CCodeExpression expr) {
+ var variant_expr = serialize_expression (fragment, type, expr);
+ if (variant_expr != null) {
+ var builder_add = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_add_value"));
+ builder_add.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, builder_expr));
+ builder_add.add_argument (variant_expr);
+ fragment.append (new CCodeExpressionStatement (builder_add));
+ }
+ }
+}
diff --git a/vala/valaarraytype.vala b/vala/valaarraytype.vala
index be626f5..c1d9e0e 100644
--- a/vala/valaarraytype.vala
+++ b/vala/valaarraytype.vala
@@ -186,6 +186,11 @@ public class Vala.ArrayType : ReferenceType {
return true;
}
+ if (target_type.get_type_id () == "G_TYPE_VARIANT") {
+ // allow implicit conversion to GVariant
+ return true;
+ }
+
if (target_type is PointerType || (target_type.data_type != null && target_type.data_type.get_attribute ("PointerType") != null)) {
/* any array type can be cast to a generic pointer */
return true;
diff --git a/vala/valadatatype.vala b/vala/valadatatype.vala
index 2027bb9..f756415 100644
--- a/vala/valadatatype.vala
+++ b/vala/valadatatype.vala
@@ -1,6 +1,6 @@
/* valadatatype.vala
*
- * Copyright (C) 2006-2009 Jürg Billeter
+ * Copyright (C) 2006-2010 Jürg Billeter
* Copyright (C) 2006-2008 Raffaele Sandrini
*
* This library is free software; you can redistribute it and/or
@@ -314,6 +314,11 @@ public abstract class Vala.DataType : CodeNode {
return true;
}
+ if (target_type.get_type_id () == "G_TYPE_VARIANT") {
+ // allow implicit conversion to GVariant
+ return true;
+ }
+
if (target_type is DelegateType && this is DelegateType) {
return ((DelegateType) target_type).delegate_symbol == ((DelegateType) this).delegate_symbol;
}
diff --git a/vapi/gio-2.0.vapi b/vapi/gio-2.0.vapi
index 5b744a8..e038979 100644
--- a/vapi/gio-2.0.vapi
+++ b/vapi/gio-2.0.vapi
@@ -7,6 +7,8 @@ namespace GLib {
[CCode (cheader_filename = "gio/gio.h")]
public static async GLib.DBusConnection @get (GLib.BusType bus_type, GLib.Cancellable? cancellable = null) throws GLib.IOError;
[CCode (cheader_filename = "gio/gio.h")]
+ public static T get_proxy_sync<T> (GLib.BusType bus_type, string name, string object_path, GLib.Cancellable? cancellable = null) throws GLib.IOError;
+ [CCode (cheader_filename = "gio/gio.h")]
public static GLib.DBusConnection get_sync (GLib.BusType bus_type, GLib.Cancellable? cancellable = null) throws GLib.IOError;
[CCode (cheader_filename = "gio/gio.h")]
public static uint own_name (GLib.BusType bus_type, string name, GLib.BusNameOwnerFlags flags, GLib.BusAcquiredCallback bus_acquired_handler, GLib.BusNameAcquiredCallback name_acquired_handler, GLib.BusNameLostCallback name_lost_handler);
@@ -206,7 +208,7 @@ namespace GLib {
public unowned GLib.IOStream get_stream ();
public unowned string get_unique_name ();
public bool is_closed ();
- public uint register_object (string object_path, GLib.DBusInterfaceInfo introspection_data, GLib.DBusInterfaceVTable vtable, GLib.DestroyNotify user_data_free_func) throws GLib.Error;
+ public uint register_object<T> (string object_path, T object) throws GLib.IOError;
public uint register_subtree (string object_path, GLib.DBusSubtreeVTable vtable, GLib.DBusSubtreeFlags flags, GLib.DestroyNotify user_data_free_func) throws GLib.Error;
public void remove_filter (uint filter_id);
public bool send_message (GLib.DBusMessage message, uint32 out_serial) throws GLib.Error;
diff --git a/vapi/packages/gio-2.0/gio-2.0-custom.vala b/vapi/packages/gio-2.0/gio-2.0-custom.vala
index 02e9294..9cea5a0 100644
--- a/vapi/packages/gio-2.0/gio-2.0-custom.vala
+++ b/vapi/packages/gio-2.0/gio-2.0-custom.vala
@@ -56,6 +56,7 @@ namespace GLib {
namespace Bus {
public async GLib.DBusConnection get (GLib.BusType bus_type, GLib.Cancellable? cancellable = null) throws GLib.IOError;
public GLib.DBusConnection get_sync (GLib.BusType bus_type, GLib.Cancellable? cancellable = null) throws GLib.IOError;
+ public T get_proxy_sync<T> (GLib.BusType bus_type, string name, string object_path, GLib.Cancellable? cancellable = null) throws GLib.IOError;
public uint own_name (GLib.BusType bus_type, string name, GLib.BusNameOwnerFlags flags, GLib.BusAcquiredCallback bus_acquired_handler, GLib.BusNameAcquiredCallback name_acquired_handler, GLib.BusNameLostCallback name_lost_handler);
public uint own_name_on_connection (GLib.DBusConnection connection, string name, GLib.BusNameOwnerFlags flags, GLib.BusNameAcquiredCallback name_acquired_handler, GLib.BusNameLostCallback name_lost_handler);
public uint own_name_on_connection_with_closures (GLib.DBusConnection connection, string name, GLib.BusNameOwnerFlags flags, GLib.Closure name_acquired_closure, GLib.Closure name_lost_closure);
@@ -67,4 +68,9 @@ namespace GLib {
public uint watch_name_on_connection_with_closures (GLib.DBusConnection connection, string name, GLib.BusNameWatcherFlags flags, GLib.Closure name_appeared_closure, GLib.Closure name_vanished_closure);
public uint watch_name_with_closures (GLib.BusType bus_type, string name, GLib.BusNameWatcherFlags flags, GLib.Closure name_appeared_closure, GLib.Closure name_vanished_closure);
}
+
+ [CCode (cname = "GDBusConnection")]
+ public class DBusConnection {
+ public uint register_object<T> (string object_path, T object) throws GLib.IOError;
+ }
}
diff --git a/vapi/packages/gio-2.0/gio-2.0.metadata b/vapi/packages/gio-2.0/gio-2.0.metadata
index 2333be8..8a0dd55 100644
--- a/vapi/packages/gio-2.0/gio-2.0.metadata
+++ b/vapi/packages/gio-2.0/gio-2.0.metadata
@@ -202,3 +202,4 @@ g_zlib_compressor_new.level default_value="-1"
uid_t name="uint"
g_bus_* hidden="1"
+g_dbus_connection_register_object hidden="1"
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]