59ab1de8b76af8591176c8a4fb1ae68c6e783483
[roobuilder] / src / codegen / valagdbusmodule.vala
1 /* valagdbusmodule.vala
2  *
3  * Copyright (C) 2010-2012  Jürg Billeter
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
18  *
19  * Author:
20  *      Jürg Billeter <j@bitron.ch>
21  */
22
23 public class Vala.GDBusModule : GVariantModule {
24         public static string? get_dbus_name (TypeSymbol symbol) {
25                 return symbol.get_attribute_string ("DBus", "name");
26         }
27
28         public static string get_dbus_name_for_member (Symbol symbol) {
29                 var dbus_name = symbol.get_attribute_string ("DBus", "name");
30                 if (dbus_name != null) {
31                         return dbus_name;
32                 }
33
34                 return Symbol.lower_case_to_camel_case (symbol.name);
35         }
36
37         public static int get_dbus_timeout_for_member (Symbol symbol) {
38                 return symbol.get_attribute_integer ("DBus", "timeout", -1);
39         }
40
41         public static bool is_dbus_visible (CodeNode node) {
42                 var dbus_attribute = node.get_attribute ("DBus");
43                 if (dbus_attribute != null
44                     && dbus_attribute.has_argument ("visible")
45                     && !dbus_attribute.get_bool ("visible")) {
46                         return false;
47                 }
48
49                 return true;
50         }
51
52         public static bool is_dbus_no_reply (Method m) {
53                 return m.get_attribute_bool ("DBus", "no_reply");
54         }
55
56         public static string dbus_result_name (Method m) {
57                 var dbus_name = m.get_attribute_string ("DBus", "result");
58                 if (dbus_name != null && dbus_name != "") {
59                         return dbus_name;
60                 }
61
62                 return "result";
63         }
64
65         public override void visit_error_domain (ErrorDomain edomain) {
66                 var edomain_dbus_name = get_dbus_name (edomain);
67                 if (edomain_dbus_name == null) {
68                         base.visit_error_domain (edomain);
69                         return;
70                 }
71
72                 cfile.add_include ("gio/gio.h");
73
74                 generate_error_domain_declaration (edomain, cfile);
75
76                 if (!edomain.is_internal_symbol ()) {
77                         generate_error_domain_declaration (edomain, header_file);
78                 }
79                 if (!edomain.is_private_symbol ()) {
80                         generate_error_domain_declaration (edomain, internal_header_file);
81                 }
82
83                 var error_entries = new CCodeInitializerList ();
84                 foreach (ErrorCode ecode in edomain.get_codes ()) {
85                         var ecode_dbus_name = get_dbus_name (ecode);
86                         if (ecode_dbus_name == null) {
87                                 ecode_dbus_name = Symbol.lower_case_to_camel_case (ecode.name.ascii_down ());
88                         }
89
90                         var error_entry = new CCodeInitializerList ();
91                         error_entry.append (new CCodeIdentifier (get_ccode_name (ecode)));
92                         error_entry.append (new CCodeConstant ("\"%s.%s\"".printf (edomain_dbus_name, ecode_dbus_name)));
93                         error_entries.append (error_entry);
94                 }
95
96                 var cdecl = new CCodeDeclaration ("const GDBusErrorEntry");
97                 cdecl.add_declarator (new CCodeVariableDeclarator (get_ccode_lower_case_name (edomain) + "_entries[]", error_entries));
98                 cdecl.modifiers = CCodeModifiers.STATIC;
99                 cfile.add_constant_declaration (cdecl);
100
101                 string quark_fun_name = get_ccode_lower_case_prefix (edomain) + "quark";
102
103                 var cquark_fun = new CCodeFunction (quark_fun_name, get_ccode_name (gquark_type.type_symbol));
104                 push_function (cquark_fun);
105
106                 string quark_name = "%squark_volatile".printf (get_ccode_lower_case_prefix (edomain));
107
108                 ccode.add_declaration ("gsize", new CCodeVariableDeclarator (quark_name, new CCodeConstant ("0")), CCodeModifiers.STATIC | CCodeModifiers.VOLATILE);
109
110                 var register_call = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_error_register_error_domain"));
111                 register_call.add_argument (new CCodeConstant ("\"" + get_ccode_quark_name (edomain) + "\""));
112                 register_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (quark_name)));
113                 register_call.add_argument (new CCodeIdentifier (get_ccode_lower_case_name (edomain) + "_entries"));
114                 var nentries = new CCodeFunctionCall (new CCodeIdentifier ("G_N_ELEMENTS"));
115                 nentries.add_argument (new CCodeIdentifier (get_ccode_lower_case_name (edomain) + "_entries"));
116                 register_call.add_argument (nentries);
117                 ccode.add_expression (register_call);
118
119                 ccode.add_return (new CCodeCastExpression (new CCodeIdentifier (quark_name), "GQuark"));
120
121                 pop_function ();
122                 cfile.add_function (cquark_fun);
123         }
124
125         bool is_file_descriptor (DataType type) {
126                 if (type is ObjectType) {
127                         if (type.type_symbol.get_full_name () == "GLib.UnixInputStream" ||
128                             type.type_symbol.get_full_name () == "GLib.UnixOutputStream" ||
129                             type.type_symbol.get_full_name () == "GLib.Socket" ||
130                             type.type_symbol.get_full_name () == "GLib.FileDescriptorBased") {
131                                 return true;
132                         }
133                 }
134
135                 return false;
136         }
137
138         public bool dbus_method_uses_file_descriptor (Method method) {
139                 foreach (Parameter param in method.get_parameters ()) {
140                         if (is_file_descriptor (param.variable_type)) {
141                                 return true;
142                         }
143                 }
144
145                 if (is_file_descriptor (method.return_type)) {
146                         return true;
147                 }
148
149                 return false;
150         }
151
152         CCodeExpression? get_file_descriptor (DataType type, CCodeExpression expr) {
153                 if (type is ObjectType) {
154                         if (type.type_symbol.get_full_name () == "GLib.UnixInputStream") {
155                                 var result = new CCodeFunctionCall (new CCodeIdentifier ("g_unix_input_stream_get_fd"));
156                                 result.add_argument (expr);
157                                 return result;
158                         } else if (type.type_symbol.get_full_name () == "GLib.UnixOutputStream") {
159                                 var result = new CCodeFunctionCall (new CCodeIdentifier ("g_unix_output_stream_get_fd"));
160                                 result.add_argument (expr);
161                                 return result;
162                         } else if (type.type_symbol.get_full_name () == "GLib.Socket") {
163                                 var result = new CCodeFunctionCall (new CCodeIdentifier ("g_socket_get_fd"));
164                                 result.add_argument (expr);
165                                 return result;
166                         } else if (type.type_symbol.get_full_name () == "GLib.FileDescriptorBased") {
167                                 var result = new CCodeFunctionCall (new CCodeIdentifier ("g_file_descriptor_based_get_fd"));
168                                 result.add_argument (expr);
169                                 return result;
170                         }
171                 }
172
173                 return null;
174         }
175
176         public void send_dbus_value (DataType type, CCodeExpression builder_expr, CCodeExpression expr, Symbol? sym) {
177                 var fd = get_file_descriptor (type, expr);
178                 if (fd != null) {
179                         // add file descriptor to the file descriptor list
180                         var fd_append = new CCodeFunctionCall (new CCodeIdentifier ("g_unix_fd_list_append"));
181                         fd_append.add_argument (new CCodeIdentifier ("_fd_list"));
182                         fd_append.add_argument (fd);
183                         fd_append.add_argument (new CCodeConstant ("NULL"));
184
185                         // add index to file descriptor to gvariant
186                         var builder_add = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_add"));
187                         builder_add.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, builder_expr));
188                         builder_add.add_argument (new CCodeConstant ("\"h\""));
189                         builder_add.add_argument (fd_append);
190                         ccode.add_expression (builder_add);
191                 } else {
192                         write_expression (type, builder_expr, expr, sym);
193                 }
194         }
195
196         CCodeExpression? create_from_file_descriptor (DataType type, CCodeExpression expr) {
197                 if (type is ObjectType) {
198                         if (type.type_symbol.get_full_name () == "GLib.UnixInputStream") {
199                                 var result = new CCodeFunctionCall (new CCodeIdentifier ("g_unix_input_stream_new"));
200                                 result.add_argument (expr);
201                                 result.add_argument (new CCodeConstant ("TRUE"));
202                                 return new CCodeCastExpression (result, "GUnixInputStream *");
203                         } else if (type.type_symbol.get_full_name () == "GLib.UnixOutputStream") {
204                                 var result = new CCodeFunctionCall (new CCodeIdentifier ("g_unix_output_stream_new"));
205                                 result.add_argument (expr);
206                                 result.add_argument (new CCodeConstant ("TRUE"));
207                                 return new CCodeCastExpression (result, "GUnixOutputStream *");
208                         } else if (type.type_symbol.get_full_name () == "GLib.Socket") {
209                                 var result = new CCodeFunctionCall (new CCodeIdentifier ("g_socket_new_from_fd"));
210                                 result.add_argument (expr);
211                                 result.add_argument (new CCodeConstant ("NULL"));
212                                 return result;
213                         }
214                 }
215
216                 return null;
217         }
218
219         public void receive_dbus_value (DataType type, CCodeExpression message_expr, CCodeExpression iter_expr, CCodeExpression target_expr, Symbol? sym, CCodeExpression? error_expr = null, out bool may_fail = null) {
220                 var fd_list = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_get_unix_fd_list"));
221                 fd_list.add_argument (message_expr);
222
223                 var fd_var = new CCodeIdentifier ("_fd");
224
225                 var stream = create_from_file_descriptor (type, fd_var);
226                 if (stream != null) {
227                         var fd_list_var = new CCodeIdentifier ("_fd_list");
228
229                         var fd = new CCodeFunctionCall (new CCodeIdentifier ("g_unix_fd_list_get"));
230                         fd.add_argument (fd_list_var);
231                         fd.add_argument (new CCodeIdentifier ("_fd_index"));
232                         fd.add_argument (error_expr);
233
234                         ccode.add_assignment (fd_list_var, fd_list);
235                         ccode.open_if (fd_list_var);
236
237                         var get_fd = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_next"));
238                         get_fd.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, iter_expr));
239                         get_fd.add_argument (new CCodeConstant ("\"h\""));
240                         get_fd.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_fd_index")));
241                         ccode.add_expression (get_fd);
242
243                         ccode.add_assignment (fd_var, fd);
244                         ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.GREATER_THAN_OR_EQUAL, fd_var, new CCodeConstant ("0")));
245
246                         ccode.add_assignment (target_expr, stream);
247                         may_fail = true;
248
249                         ccode.close ();
250
251                         ccode.add_else ();
252                         var set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error_literal"));
253                         set_error.add_argument (error_expr);
254                         set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR"));
255                         set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR_FAILED"));
256                         set_error.add_argument (new CCodeConstant ("\"FD List is NULL\""));
257                         ccode.add_expression (set_error);
258                         ccode.close ();
259                 } else {
260                         read_expression (type, iter_expr, target_expr, sym, error_expr, out may_fail);
261                 }
262         }
263         CCodeExpression get_method_info (ObjectTypeSymbol sym) {
264                 var infos = new CCodeInitializerList ();
265
266                 foreach (Method m in sym.get_methods ()) {
267                         if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
268                             || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
269                                 continue;
270                         }
271                         if (!is_dbus_visible (m)) {
272                                 continue;
273                         }
274
275                         var in_args_info = new CCodeInitializerList ();
276                         var out_args_info = new CCodeInitializerList ();
277
278                         foreach (Parameter param in m.get_parameters ()) {
279                                 if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.Cancellable") {
280                                         continue;
281                                 }
282                                 if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.BusName") {
283                                         continue;
284                                 }
285
286                                 var info = new CCodeInitializerList ();
287                                 info.append (new CCodeConstant ("-1"));
288                                 info.append (new CCodeConstant ("\"%s\"".printf (param.name)));
289                                 info.append (new CCodeConstant ("\"%s\"".printf (param.variable_type.get_type_signature (param))));
290                                 info.append (new CCodeConstant ("NULL"));
291
292                                 var cdecl = new CCodeDeclaration ("const GDBusArgInfo");
293                                 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + m.name + "_" + param.name, info));
294                                 cdecl.modifiers = CCodeModifiers.STATIC;
295                                 cfile.add_constant_declaration (cdecl);
296
297                                 if (param.direction == ParameterDirection.IN) {
298                                         in_args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + m.name + "_" + param.name)));
299                                 } else {
300                                         out_args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + m.name + "_" + param.name)));
301                                 }
302                         }
303
304                         if (!(m.return_type is VoidType)) {
305                                 var info = new CCodeInitializerList ();
306                                 info.append (new CCodeConstant ("-1"));
307                                 info.append (new CCodeConstant ("\"%s\"".printf (dbus_result_name (m))));
308                                 info.append (new CCodeConstant ("\"%s\"".printf (m.return_type.get_type_signature (m))));
309                                 info.append (new CCodeConstant ("NULL"));
310
311                                 var cdecl = new CCodeDeclaration ("const GDBusArgInfo");
312                                 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + m.name + "_result", info));
313                                 cdecl.modifiers = CCodeModifiers.STATIC;
314                                 cfile.add_constant_declaration (cdecl);
315
316                                 out_args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + m.name + "_result")));
317                         }
318
319                         in_args_info.append (new CCodeConstant ("NULL"));
320                         out_args_info.append (new CCodeConstant ("NULL"));
321
322                         var cdecl = new CCodeDeclaration ("const GDBusArgInfo * const");
323                         cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + m.name + "_in[]", in_args_info));
324                         cdecl.modifiers = CCodeModifiers.STATIC;
325                         cfile.add_constant_declaration (cdecl);
326
327                         cdecl = new CCodeDeclaration ("const GDBusArgInfo * const");
328                         cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + m.name + "_out[]", out_args_info));
329                         cdecl.modifiers = CCodeModifiers.STATIC;
330                         cfile.add_constant_declaration (cdecl);
331
332                         var info = new CCodeInitializerList ();
333                         info.append (new CCodeConstant ("-1"));
334                         info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m))));
335                         info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + m.name + "_in")), "GDBusArgInfo **"));
336                         info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + m.name + "_out")), "GDBusArgInfo **"));
337                         info.append (new CCodeConstant ("NULL"));
338
339                         cdecl = new CCodeDeclaration ("const GDBusMethodInfo");
340                         cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_method_info_" + m.name, info));
341                         cdecl.modifiers = CCodeModifiers.STATIC;
342                         cfile.add_constant_declaration (cdecl);
343
344                         infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_method_info_" + m.name)));
345                 }
346
347                 infos.append (new CCodeConstant ("NULL"));
348
349                 var cdecl = new CCodeDeclaration ("const GDBusMethodInfo * const");
350                 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_method_info[]", infos));
351                 cdecl.modifiers = CCodeModifiers.STATIC;
352                 cfile.add_constant_declaration (cdecl);
353
354                 return new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_method_info");
355         }
356
357         CCodeExpression get_signal_info (ObjectTypeSymbol sym) {
358                 var infos = new CCodeInitializerList ();
359
360                 foreach (Signal sig in sym.get_signals ()) {
361                         if (sig.access != SymbolAccessibility.PUBLIC) {
362                                 continue;
363                         }
364                         if (!is_dbus_visible (sig)) {
365                                 continue;
366                         }
367
368                         var args_info = new CCodeInitializerList ();
369
370                         foreach (Parameter param in sig.get_parameters ()) {
371                                 var info = new CCodeInitializerList ();
372                                 info.append (new CCodeConstant ("-1"));
373                                 info.append (new CCodeConstant ("\"%s\"".printf (param.name)));
374                                 info.append (new CCodeConstant ("\"%s\"".printf (param.variable_type.get_type_signature (param))));
375                                 info.append (new CCodeConstant ("NULL"));
376
377                                 var cdecl = new CCodeDeclaration ("const GDBusArgInfo");
378                                 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + get_ccode_lower_case_name (sig) + "_" + param.name, info));
379                                 cdecl.modifiers = CCodeModifiers.STATIC;
380                                 cfile.add_constant_declaration (cdecl);
381
382                                 args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + get_ccode_lower_case_name (sig) + "_" + param.name)));
383                         }
384
385                         args_info.append (new CCodeConstant ("NULL"));
386
387                         var cdecl = new CCodeDeclaration ("const GDBusArgInfo * const");
388                         cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + get_ccode_lower_case_name (sig) + "[]", args_info));
389                         cdecl.modifiers = CCodeModifiers.STATIC;
390                         cfile.add_constant_declaration (cdecl);
391
392                         var info = new CCodeInitializerList ();
393                         info.append (new CCodeConstant ("-1"));
394                         info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
395                         info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + get_ccode_lower_case_name (sig))), "GDBusArgInfo **"));
396                         info.append (new CCodeConstant ("NULL"));
397
398                         cdecl = new CCodeDeclaration ("const GDBusSignalInfo");
399                         cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_signal_info_" + get_ccode_lower_case_name (sig), info));
400                         cdecl.modifiers = CCodeModifiers.STATIC;
401                         cfile.add_constant_declaration (cdecl);
402
403                         infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_signal_info_" + get_ccode_lower_case_name (sig))));
404                 }
405
406                 infos.append (new CCodeConstant ("NULL"));
407
408                 var cdecl = new CCodeDeclaration ("const GDBusSignalInfo * const");
409                 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_signal_info[]", infos));
410                 cdecl.modifiers = CCodeModifiers.STATIC;
411                 cfile.add_constant_declaration (cdecl);
412
413                 return new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_signal_info");
414         }
415
416         CCodeExpression get_property_info (ObjectTypeSymbol sym) {
417                 var infos = new CCodeInitializerList ();
418
419                 foreach (Property prop in sym.get_properties ()) {
420                         if (prop.binding != MemberBinding.INSTANCE
421                             || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
422                                 continue;
423                         }
424                         if (!is_dbus_visible (prop)) {
425                                 continue;
426                         }
427
428                         var info = new CCodeInitializerList ();
429                         info.append (new CCodeConstant ("-1"));
430                         info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
431                         info.append (new CCodeConstant ("\"%s\"".printf (prop.property_type.get_type_signature (prop))));
432                         if (prop.get_accessor != null && prop.set_accessor != null) {
433                                 info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE"));
434                         } else if (prop.get_accessor != null) {
435                                 info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_READABLE"));
436                         } else if (prop.set_accessor != null) {
437                                 info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE"));
438                         } else {
439                                 info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_NONE"));
440                         }
441                         info.append (new CCodeConstant ("NULL"));
442
443                         var cdecl = new CCodeDeclaration ("const GDBusPropertyInfo");
444                         cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_property_info_" + prop.name, info));
445                         cdecl.modifiers = CCodeModifiers.STATIC;
446                         cfile.add_constant_declaration (cdecl);
447
448                         infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_property_info_" + prop.name)));
449                 }
450
451                 infos.append (new CCodeConstant ("NULL"));
452
453                 var cdecl = new CCodeDeclaration ("const GDBusPropertyInfo * const");
454                 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_property_info[]", infos));
455                 cdecl.modifiers = CCodeModifiers.STATIC;
456                 cfile.add_constant_declaration (cdecl);
457
458                 return new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_property_info");
459         }
460
461         void declare_interface_info (ObjectTypeSymbol sym) {
462                 var info = new CCodeInitializerList ();
463                 info.append (new CCodeConstant ("-1"));
464                 info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name (sym))));
465                 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_method_info (sym)), "GDBusMethodInfo **"));
466                 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_signal_info (sym)), "GDBusSignalInfo **"));
467                 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_property_info (sym)), "GDBusPropertyInfo **"));
468                 info.append (new CCodeConstant ("NULL"));
469
470                 var cdecl = new CCodeDeclaration ("const GDBusInterfaceInfo");
471                 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_interface_info", info));
472                 cdecl.modifiers = CCodeModifiers.STATIC;
473                 cfile.add_constant_declaration (cdecl);
474         }
475
476         protected CCodeExpression get_interface_info (ObjectTypeSymbol sym) {
477                 return new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_interface_info");
478         }
479
480         public override void visit_class (Class cl) {
481                 base.visit_class (cl);
482
483                 visit_object_type_symbol (cl);
484         }
485
486         public override void visit_interface (Interface iface) {
487                 base.visit_interface (iface);
488
489                 visit_object_type_symbol (iface);
490         }
491
492         void visit_object_type_symbol (ObjectTypeSymbol sym) {
493                 if (get_dbus_name (sym) == null) {
494                         return;
495                 }
496
497                 declare_interface_info(sym);
498         }
499 }