Changeset View
Changeset View
Standalone View
Standalone View
tools/glib-ginterface-gen.py
Show All 20 Lines | |||||
21 | # You should have received a copy of the GNU Lesser General Public | 21 | # You should have received a copy of the GNU Lesser General Public | ||
22 | # License along with this library; if not, write to the Free Software | 22 | # License along with this library; if not, write to the Free Software | ||
23 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 23 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | 24 | | |||
25 | import sys | 25 | import sys | ||
26 | import os.path | 26 | import os.path | ||
27 | import xml.dom.minidom | 27 | import xml.dom.minidom | ||
28 | 28 | | |||
29 | from libglibcodegen import Signature, type_to_gtype, cmp_by_name, \ | 29 | from libtpcodegen import file_set_contents, key_by_name, u | ||
30 | NS_TP, dbus_gutils_wincaps_to_uscore, \ | 30 | from libglibcodegen import Signature, type_to_gtype, \ | ||
31 | signal_to_marshal_name, method_to_glue_marshal_name | 31 | NS_TP, dbus_gutils_wincaps_to_uscore | ||
32 | 32 | | |||
33 | 33 | | |||
34 | NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" | 34 | NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" | ||
35 | 35 | | |||
36 | def get_emits_changed(node): | ||||
37 | try: | ||||
38 | return [ | ||||
39 | annotation.getAttribute('value') | ||||
40 | for annotation in node.getElementsByTagName('annotation') | ||||
41 | if annotation.getAttribute('name') == 'org.freedesktop.DBus.Property.EmitsChangedSignal' | ||||
42 | ][0] | ||||
43 | except IndexError: | ||||
44 | return None | ||||
45 | | ||||
36 | class Generator(object): | 46 | class Generator(object): | ||
37 | 47 | | |||
38 | def __init__(self, dom, prefix, basename, signal_marshal_prefix, | 48 | def __init__(self, dom, prefix, basename, signal_marshal_prefix, | ||
39 | headers, end_headers, not_implemented_func, | 49 | headers, end_headers, not_implemented_func, | ||
40 | allow_havoc): | 50 | allow_havoc): | ||
41 | self.dom = dom | 51 | self.dom = dom | ||
42 | self.__header = [] | 52 | self.__header = [] | ||
43 | self.__body = [] | 53 | self.__body = [] | ||
54 | self.__docs = [] | ||||
44 | 55 | | |||
45 | assert prefix.endswith('_') | 56 | assert prefix.endswith('_') | ||
46 | assert not signal_marshal_prefix.endswith('_') | 57 | assert not signal_marshal_prefix.endswith('_') | ||
47 | 58 | | |||
48 | # The main_prefix, sub_prefix thing is to get: | 59 | # The main_prefix, sub_prefix thing is to get: | ||
49 | # FOO_ -> (FOO_, _) | 60 | # FOO_ -> (FOO_, _) | ||
50 | # FOO_SVC_ -> (FOO_, _SVC_) | 61 | # FOO_SVC_ -> (FOO_, _SVC_) | ||
51 | # but | 62 | # but | ||
Show All 22 Lines | |||||
74 | self.allow_havoc = allow_havoc | 85 | self.allow_havoc = allow_havoc | ||
75 | 86 | | |||
76 | def h(self, s): | 87 | def h(self, s): | ||
77 | self.__header.append(s) | 88 | self.__header.append(s) | ||
78 | 89 | | |||
79 | def b(self, s): | 90 | def b(self, s): | ||
80 | self.__body.append(s) | 91 | self.__body.append(s) | ||
81 | 92 | | |||
93 | def d(self, s): | ||||
94 | self.__docs.append(s) | ||||
95 | | ||||
82 | def do_node(self, node): | 96 | def do_node(self, node): | ||
83 | node_name = node.getAttribute('name').replace('/', '') | 97 | node_name = node.getAttribute('name').replace('/', '') | ||
84 | node_name_mixed = self.node_name_mixed = node_name.replace('_', '') | 98 | node_name_mixed = self.node_name_mixed = node_name.replace('_', '') | ||
85 | node_name_lc = self.node_name_lc = node_name.lower() | 99 | node_name_lc = self.node_name_lc = node_name.lower() | ||
86 | node_name_uc = self.node_name_uc = node_name.upper() | 100 | node_name_uc = self.node_name_uc = node_name.upper() | ||
87 | 101 | | |||
88 | interfaces = node.getElementsByTagName('interface') | 102 | interfaces = node.getElementsByTagName('interface') | ||
89 | assert len(interfaces) == 1, interfaces | 103 | assert len(interfaces) == 1, interfaces | ||
90 | interface = interfaces[0] | 104 | interface = interfaces[0] | ||
91 | self.iface_name = interface.getAttribute('name') | 105 | self.iface_name = interface.getAttribute('name') | ||
92 | 106 | | |||
93 | tmp = interface.getAttribute('tp:implement-service') | 107 | tmp = interface.getAttribute('tp:implement-service') | ||
94 | if tmp == "no": | 108 | if tmp == "no": | ||
95 | return | 109 | return | ||
96 | 110 | | |||
97 | tmp = interface.getAttribute('tp:causes-havoc') | 111 | tmp = interface.getAttribute('tp:causes-havoc') | ||
98 | if tmp and not self.allow_havoc: | 112 | if tmp and not self.allow_havoc: | ||
99 | raise AssertionError('%s is %s' % (self.iface_name, tmp)) | 113 | raise AssertionError('%s is %s' % (self.iface_name, tmp)) | ||
100 | 114 | | |||
115 | iface_emits_changed = get_emits_changed(interface) | ||||
116 | | ||||
101 | self.b('static const DBusGObjectInfo _%s%s_object_info;' | 117 | self.b('static const DBusGObjectInfo _%s%s_object_info;' | ||
102 | % (self.prefix_, node_name_lc)) | 118 | % (self.prefix_, node_name_lc)) | ||
103 | self.b('') | 119 | self.b('') | ||
104 | 120 | | |||
105 | methods = interface.getElementsByTagName('method') | 121 | methods = interface.getElementsByTagName('method') | ||
106 | signals = interface.getElementsByTagName('signal') | 122 | signals = interface.getElementsByTagName('signal') | ||
107 | properties = interface.getElementsByTagName('property') | 123 | properties = interface.getElementsByTagName('property') | ||
108 | # Don't put properties in dbus-glib glue | 124 | # Don't put properties in dbus-glib glue | ||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Line(s) | |||||
153 | self.b(' type = g_type_register_static (G_TYPE_INTERFACE,') | 169 | self.b(' type = g_type_register_static (G_TYPE_INTERFACE,') | ||
154 | self.b(' "%s%s", &info, 0);' % (self.Prefix, node_name_mixed)) | 170 | self.b(' "%s%s", &info, 0);' % (self.Prefix, node_name_mixed)) | ||
155 | self.b(' }') | 171 | self.b(' }') | ||
156 | self.b('') | 172 | self.b('') | ||
157 | self.b(' return type;') | 173 | self.b(' return type;') | ||
158 | self.b('}') | 174 | self.b('}') | ||
159 | self.b('') | 175 | self.b('') | ||
160 | 176 | | |||
161 | self.h('/**') | 177 | self.d('/**') | ||
162 | self.h(' * %s%s:' % (self.Prefix, node_name_mixed)) | 178 | self.d(' * %s%s:' % (self.Prefix, node_name_mixed)) | ||
163 | self.h(' *') | 179 | self.d(' *') | ||
164 | self.h(' * Dummy typedef representing any implementation of this ' | 180 | self.d(' * Dummy typedef representing any implementation of this ' | ||
165 | 'interface.') | 181 | 'interface.') | ||
166 | self.h(' */') | 182 | self.d(' */') | ||
183 | | ||||
167 | self.h('typedef struct _%s%s %s%s;' | 184 | self.h('typedef struct _%s%s %s%s;' | ||
168 | % (self.Prefix, node_name_mixed, self.Prefix, node_name_mixed)) | 185 | % (self.Prefix, node_name_mixed, self.Prefix, node_name_mixed)) | ||
169 | self.h('') | 186 | self.h('') | ||
170 | self.h('/**') | 187 | | ||
171 | self.h(' * %s%sClass:' % (self.Prefix, node_name_mixed)) | 188 | self.d('/**') | ||
172 | self.h(' *') | 189 | self.d(' * %s%sClass:' % (self.Prefix, node_name_mixed)) | ||
173 | self.h(' * The class of %s%s.' % (self.Prefix, node_name_mixed)) | 190 | self.d(' *') | ||
191 | self.d(' * The class of %s%s.' % (self.Prefix, node_name_mixed)) | ||||
174 | 192 | | |||
175 | if methods: | 193 | if methods: | ||
176 | self.h(' *') | 194 | self.d(' *') | ||
177 | self.h(' * In a full implementation of this interface (i.e. all') | 195 | self.d(' * In a full implementation of this interface (i.e. all') | ||
178 | self.h(' * methods implemented), the interface initialization') | 196 | self.d(' * methods implemented), the interface initialization') | ||
179 | self.h(' * function used in G_IMPLEMENT_INTERFACE() would') | 197 | self.d(' * function used in G_IMPLEMENT_INTERFACE() would') | ||
180 | self.h(' * typically look like this:') | 198 | self.d(' * typically look like this:') | ||
181 | self.h(' *') | 199 | self.d(' *') | ||
182 | self.h(' * <programlisting>') | 200 | self.d(' * <programlisting>') | ||
183 | self.h(' * static void') | 201 | self.d(' * static void') | ||
184 | self.h(' * implement_%s (gpointer klass,' % self.node_name_lc) | 202 | self.d(' * implement_%s (gpointer klass,' % self.node_name_lc) | ||
185 | self.h(' * gpointer unused G_GNUC_UNUSED)') | 203 | self.d(' * gpointer unused G_GNUC_UNUSED)') | ||
186 | self.h(' * {') | 204 | self.d(' * {') | ||
187 | # "#" is special to gtkdoc under some circumstances; it appears | 205 | self.d(' * #define IMPLEMENT(x) %s%s_implement_##x (\\' | ||
188 | # that escaping "##" as "#<!---->#" or "##" doesn't work, | | |||
189 | # but adding an extra hash symbol does. Thanks, gtkdoc :-( | | |||
190 | self.h(' * #define IMPLEMENT(x) %s%s_implement_###x (\\' | | |||
191 | % (self.prefix_, self.node_name_lc)) | 206 | % (self.prefix_, self.node_name_lc)) | ||
192 | self.h(' * klass, my_object_###x)') | 207 | self.d(' * klass, my_object_##x)') | ||
193 | 208 | | |||
194 | for method in methods: | 209 | for method in methods: | ||
195 | class_member_name = method.getAttribute('tp:name-for-bindings') | 210 | class_member_name = method.getAttribute('tp:name-for-bindings') | ||
196 | class_member_name = class_member_name.lower() | 211 | class_member_name = class_member_name.lower() | ||
197 | self.h(' * IMPLEMENT (%s);' % class_member_name) | 212 | self.d(' * IMPLEMENT (%s);' % class_member_name) | ||
198 | 213 | | |||
199 | self.h(' * #undef IMPLEMENT') | 214 | self.d(' * #undef IMPLEMENT') | ||
200 | self.h(' * }') | 215 | self.d(' * }') | ||
201 | self.h(' * </programlisting>') | 216 | self.d(' * </programlisting>') | ||
202 | else: | 217 | else: | ||
203 | self.h(' * This interface has no D-Bus methods, so an') | 218 | self.d(' * This interface has no D-Bus methods, so an') | ||
204 | self.h(' * implementation can typically pass %NULL to') | 219 | self.d(' * implementation can typically pass %NULL to') | ||
205 | self.h(' * G_IMPLEMENT_INTERFACE() as the interface') | 220 | self.d(' * G_IMPLEMENT_INTERFACE() as the interface') | ||
206 | self.h(' * initialization function.') | 221 | self.d(' * initialization function.') | ||
207 | 222 | | |||
208 | self.h(' */') | 223 | self.d(' */') | ||
224 | self.d('') | ||||
209 | 225 | | |||
210 | self.h('typedef struct _%s%sClass %s%sClass;' | 226 | self.h('typedef struct _%s%sClass %s%sClass;' | ||
211 | % (self.Prefix, node_name_mixed, self.Prefix, node_name_mixed)) | 227 | % (self.Prefix, node_name_mixed, self.Prefix, node_name_mixed)) | ||
212 | self.h('') | 228 | self.h('') | ||
213 | self.h('GType %s%s_get_type (void);' | 229 | self.h('GType %s%s_get_type (void);' | ||
214 | % (self.prefix_, node_name_lc)) | 230 | % (self.prefix_, node_name_lc)) | ||
215 | 231 | | |||
216 | gtype = self.current_gtype = \ | 232 | gtype = self.current_gtype = \ | ||
Show All 38 Lines | 267 | for m in properties: | |||
255 | if access == 'read': | 271 | if access == 'read': | ||
256 | flags = 'TP_DBUS_PROPERTIES_MIXIN_FLAG_READ' | 272 | flags = 'TP_DBUS_PROPERTIES_MIXIN_FLAG_READ' | ||
257 | elif access == 'write': | 273 | elif access == 'write': | ||
258 | flags = 'TP_DBUS_PROPERTIES_MIXIN_FLAG_WRITE' | 274 | flags = 'TP_DBUS_PROPERTIES_MIXIN_FLAG_WRITE' | ||
259 | else: | 275 | else: | ||
260 | flags = ('TP_DBUS_PROPERTIES_MIXIN_FLAG_READ | ' | 276 | flags = ('TP_DBUS_PROPERTIES_MIXIN_FLAG_READ | ' | ||
261 | 'TP_DBUS_PROPERTIES_MIXIN_FLAG_WRITE') | 277 | 'TP_DBUS_PROPERTIES_MIXIN_FLAG_WRITE') | ||
262 | 278 | | |||
279 | prop_emits_changed = get_emits_changed(m) | ||||
280 | | ||||
281 | if prop_emits_changed is None: | ||||
282 | prop_emits_changed = iface_emits_changed | ||||
283 | | ||||
284 | if prop_emits_changed == 'true': | ||||
285 | flags += ' | TP_DBUS_PROPERTIES_MIXIN_FLAG_EMITS_CHANGED' | ||||
286 | elif prop_emits_changed == 'invalidates': | ||||
287 | flags += ' | TP_DBUS_PROPERTIES_MIXIN_FLAG_EMITS_INVALIDATED' | ||||
288 | | ||||
263 | self.b(' { 0, %s, "%s", 0, NULL, NULL }, /* %s */' | 289 | self.b(' { 0, %s, "%s", 0, NULL, NULL }, /* %s */' | ||
264 | % (flags, m.getAttribute('type'), m.getAttribute('name'))) | 290 | % (flags, m.getAttribute('type'), m.getAttribute('name'))) | ||
265 | 291 | | |||
266 | self.b(' { 0, 0, NULL, 0, NULL, NULL }') | 292 | self.b(' { 0, 0, NULL, 0, NULL, NULL }') | ||
267 | self.b(' };') | 293 | self.b(' };') | ||
268 | self.b(' static TpDBusPropertiesMixinIfaceInfo interface =') | 294 | self.b(' static TpDBusPropertiesMixinIfaceInfo interface =') | ||
269 | self.b(' { 0, properties, NULL, NULL };') | 295 | self.b(' { 0, properties, NULL, NULL };') | ||
270 | self.b('') | 296 | self.b('') | ||
▲ Show 20 Lines • Show All 113 Lines • ▼ Show 20 Line(s) | |||||
384 | 410 | | |||
385 | def do_method_glue(self, method, offset): | 411 | def do_method_glue(self, method, offset): | ||
386 | lc_name = method.getAttribute('tp:name-for-bindings') | 412 | lc_name = method.getAttribute('tp:name-for-bindings') | ||
387 | if method.getAttribute('name') != lc_name.replace('_', ''): | 413 | if method.getAttribute('name') != lc_name.replace('_', ''): | ||
388 | raise AssertionError('Method %s tp:name-for-bindings (%s) does ' | 414 | raise AssertionError('Method %s tp:name-for-bindings (%s) does ' | ||
389 | 'not match' % (method.getAttribute('name'), lc_name)) | 415 | 'not match' % (method.getAttribute('name'), lc_name)) | ||
390 | lc_name = lc_name.lower() | 416 | lc_name = lc_name.lower() | ||
391 | 417 | | |||
392 | marshaller = method_to_glue_marshal_name(method, | 418 | marshaller = 'g_cclosure_marshal_generic' | ||
393 | self.signal_marshal_prefix) | | |||
394 | wrapper = self.prefix_ + self.node_name_lc + '_' + lc_name | 419 | wrapper = self.prefix_ + self.node_name_lc + '_' + lc_name | ||
395 | 420 | | |||
396 | self.b(" { (GCallback) %s, %s, %d }," % (wrapper, marshaller, offset)) | 421 | self.b(" { (GCallback) %s, %s, %d }," % (wrapper, marshaller, offset)) | ||
397 | 422 | | |||
398 | def get_signal_glue(self, signals): | 423 | def get_signal_glue(self, signals): | ||
399 | info = [] | 424 | info = [] | ||
400 | 425 | | |||
401 | for signal in signals: | 426 | for signal in signals: | ||
Show All 11 Lines | 435 | def get_method_impl_names(self, method): | |||
413 | class_member_name = method.getAttribute('tp:name-for-bindings') | 438 | class_member_name = method.getAttribute('tp:name-for-bindings') | ||
414 | if dbus_method_name != class_member_name.replace('_', ''): | 439 | if dbus_method_name != class_member_name.replace('_', ''): | ||
415 | raise AssertionError('Method %s tp:name-for-bindings (%s) does ' | 440 | raise AssertionError('Method %s tp:name-for-bindings (%s) does ' | ||
416 | 'not match' % (dbus_method_name, class_member_name)) | 441 | 'not match' % (dbus_method_name, class_member_name)) | ||
417 | class_member_name = class_member_name.lower() | 442 | class_member_name = class_member_name.lower() | ||
418 | 443 | | |||
419 | stub_name = (self.prefix_ + self.node_name_lc + '_' + | 444 | stub_name = (self.prefix_ + self.node_name_lc + '_' + | ||
420 | class_member_name) | 445 | class_member_name) | ||
421 | return (stub_name + '_impl', class_member_name) | 446 | return (stub_name + '_impl', class_member_name + '_cb') | ||
422 | 447 | | |||
423 | def do_method(self, method): | 448 | def do_method(self, method): | ||
424 | assert self.node_name_mixed is not None | 449 | assert self.node_name_mixed is not None | ||
425 | 450 | | |||
426 | in_class = [] | 451 | in_class = [] | ||
427 | 452 | | |||
428 | # Examples refer to Thing.DoStuff (su) -> ii | 453 | # Examples refer to Thing.DoStuff (su) -> ii | ||
429 | 454 | | |||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Line(s) | 479 | for i in method.getElementsByTagName('arg'): | |||
472 | 497 | | |||
473 | struct = (ctype, name) | 498 | struct = (ctype, name) | ||
474 | 499 | | |||
475 | if direction == 'in': | 500 | if direction == 'in': | ||
476 | in_args.append(struct) | 501 | in_args.append(struct) | ||
477 | else: | 502 | else: | ||
478 | out_args.append(struct) | 503 | out_args.append(struct) | ||
479 | 504 | | |||
480 | # Implementation type declaration (in header, docs in body) | 505 | # Implementation type declaration (in header, docs separated) | ||
481 | self.b('/**') | 506 | self.d('/**') | ||
482 | self.b(' * %s:' % impl_name) | 507 | self.d(' * %s:' % impl_name) | ||
483 | self.b(' * @self: The object implementing this interface') | 508 | self.d(' * @self: The object implementing this interface') | ||
484 | for (ctype, name) in in_args: | 509 | for (ctype, name) in in_args: | ||
485 | self.b(' * @%s: %s (FIXME, generate documentation)' | 510 | self.d(' * @%s: %s (FIXME, generate documentation)' | ||
486 | % (name, ctype)) | 511 | % (name, ctype)) | ||
487 | self.b(' * @context: Used to return values or throw an error') | 512 | self.d(' * @context: Used to return values or throw an error') | ||
488 | self.b(' *') | 513 | self.d(' *') | ||
489 | self.b(' * The signature of an implementation of the D-Bus method') | 514 | self.d(' * The signature of an implementation of the D-Bus method') | ||
490 | self.b(' * %s on interface %s.' % (dbus_method_name, self.iface_name)) | 515 | self.d(' * %s on interface %s.' % (dbus_method_name, self.iface_name)) | ||
491 | self.b(' */') | 516 | self.d(' */') | ||
517 | | ||||
492 | self.h('typedef void (*%s) (%s%s *self,' | 518 | self.h('typedef void (*%s) (%s%s *self,' | ||
493 | % (impl_name, self.Prefix, self.node_name_mixed)) | 519 | % (impl_name, self.Prefix, self.node_name_mixed)) | ||
494 | for (ctype, name) in in_args: | 520 | for (ctype, name) in in_args: | ||
495 | self.h(' %s%s,' % (ctype, name)) | 521 | self.h(' %s%s,' % (ctype, name)) | ||
496 | self.h(' DBusGMethodInvocation *context);') | 522 | self.h(' DBusGMethodInvocation *context);') | ||
497 | 523 | | |||
498 | # Class member (in class definition) | 524 | # Class member (in class definition) | ||
499 | in_class.append(' %s %s;' % (impl_name, class_member_name)) | 525 | in_class.append(' %s %s;' % (impl_name, class_member_name)) | ||
500 | 526 | | |||
501 | # Stub definition (in body only - it's static) | 527 | # Stub definition (in body only - it's static) | ||
502 | self.b('static void') | 528 | self.b('static void') | ||
503 | self.b('%s (%s%s *self,' | 529 | self.b('%s (%s%s *self,' | ||
504 | % (stub_name, self.Prefix, self.node_name_mixed)) | 530 | % (stub_name, self.Prefix, self.node_name_mixed)) | ||
505 | for (ctype, name) in in_args: | 531 | for (ctype, name) in in_args: | ||
506 | self.b(' %s%s,' % (ctype, name)) | 532 | self.b(' %s%s,' % (ctype, name)) | ||
507 | self.b(' DBusGMethodInvocation *context)') | 533 | self.b(' DBusGMethodInvocation *context)') | ||
508 | self.b('{') | 534 | self.b('{') | ||
509 | self.b(' %s impl = (%s%s_GET_CLASS (self)->%s);' | 535 | self.b(' %s impl = (%s%s_GET_CLASS (self)->%s_cb);' | ||
510 | % (impl_name, self.PREFIX_, self.node_name_uc, class_member_name)) | 536 | % (impl_name, self.PREFIX_, self.node_name_uc, class_member_name)) | ||
511 | self.b('') | 537 | self.b('') | ||
512 | self.b(' if (impl != NULL)') | 538 | self.b(' if (impl != NULL)') | ||
513 | tmp = ['self'] + [name for (ctype, name) in in_args] + ['context'] | 539 | tmp = ['self'] + [name for (ctype, name) in in_args] + ['context'] | ||
514 | self.b(' {') | 540 | self.b(' {') | ||
515 | self.b(' (impl) (%s);' % ',\n '.join(tmp)) | 541 | self.b(' (impl) (%s);' % ',\n '.join(tmp)) | ||
516 | self.b(' }') | 542 | self.b(' }') | ||
517 | self.b(' else') | 543 | self.b(' else') | ||
Show All 10 Lines | |||||
528 | self.b('}') | 554 | self.b('}') | ||
529 | self.b('') | 555 | self.b('') | ||
530 | 556 | | |||
531 | # Implementation registration (in both header and body) | 557 | # Implementation registration (in both header and body) | ||
532 | self.h('void %s%s_implement_%s (%s%sClass *klass, %s impl);' | 558 | self.h('void %s%s_implement_%s (%s%sClass *klass, %s impl);' | ||
533 | % (self.prefix_, self.node_name_lc, class_member_name, | 559 | % (self.prefix_, self.node_name_lc, class_member_name, | ||
534 | self.Prefix, self.node_name_mixed, impl_name)) | 560 | self.Prefix, self.node_name_mixed, impl_name)) | ||
535 | 561 | | |||
536 | self.b('/**') | 562 | self.d('/**') | ||
537 | self.b(' * %s%s_implement_%s:' | 563 | self.d(' * %s%s_implement_%s:' | ||
538 | % (self.prefix_, self.node_name_lc, class_member_name)) | 564 | % (self.prefix_, self.node_name_lc, class_member_name)) | ||
539 | self.b(' * @klass: A class whose instances implement this interface') | 565 | self.d(' * @klass: A class whose instances implement this interface') | ||
540 | self.b(' * @impl: A callback used to implement the %s D-Bus method' | 566 | self.d(' * @impl: A callback used to implement the %s D-Bus method' | ||
541 | % dbus_method_name) | 567 | % dbus_method_name) | ||
542 | self.b(' *') | 568 | self.d(' *') | ||
543 | self.b(' * Register an implementation for the %s method in the vtable' | 569 | self.d(' * Register an implementation for the %s method in the vtable' | ||
544 | % dbus_method_name) | 570 | % dbus_method_name) | ||
545 | self.b(' * of an implementation of this interface. To be called from') | 571 | self.d(' * of an implementation of this interface. To be called from') | ||
546 | self.b(' * the interface init function.') | 572 | self.d(' * the interface init function.') | ||
547 | self.b(' */') | 573 | self.d(' */') | ||
574 | | ||||
548 | self.b('void') | 575 | self.b('void') | ||
549 | self.b('%s%s_implement_%s (%s%sClass *klass, %s impl)' | 576 | self.b('%s%s_implement_%s (%s%sClass *klass, %s impl)' | ||
550 | % (self.prefix_, self.node_name_lc, class_member_name, | 577 | % (self.prefix_, self.node_name_lc, class_member_name, | ||
551 | self.Prefix, self.node_name_mixed, impl_name)) | 578 | self.Prefix, self.node_name_mixed, impl_name)) | ||
552 | self.b('{') | 579 | self.b('{') | ||
553 | self.b(' klass->%s = impl;' % class_member_name) | 580 | self.b(' klass->%s_cb = impl;' % class_member_name) | ||
554 | self.b('}') | 581 | self.b('}') | ||
555 | self.b('') | 582 | self.b('') | ||
556 | 583 | | |||
557 | # Return convenience function (static inline, in header) | 584 | # Return convenience function (static inline, in header) | ||
558 | self.h('/**') | 585 | self.d('/**') | ||
559 | self.h(' * %s:' % ret_name) | 586 | self.d(' * %s:' % ret_name) | ||
560 | self.h(' * @context: The D-Bus method invocation context') | 587 | self.d(' * @context: The D-Bus method invocation context') | ||
561 | for (ctype, name) in out_args: | 588 | for (ctype, name) in out_args: | ||
562 | self.h(' * @%s: %s (FIXME, generate documentation)' | 589 | self.d(' * @%s: %s (FIXME, generate documentation)' | ||
563 | % (name, ctype)) | 590 | % (name, ctype)) | ||
564 | self.h(' *') | 591 | self.d(' *') | ||
565 | self.h(' * Return successfully by calling dbus_g_method_return().') | 592 | self.d(' * Return successfully by calling dbus_g_method_return().') | ||
566 | self.h(' * This inline function exists only to provide type-safety.') | 593 | self.d(' * This inline function exists only to provide type-safety.') | ||
567 | self.h(' */') | 594 | self.d(' */') | ||
595 | self.d('') | ||||
596 | | ||||
568 | tmp = (['DBusGMethodInvocation *context'] + | 597 | tmp = (['DBusGMethodInvocation *context'] + | ||
569 | [ctype + name for (ctype, name) in out_args]) | 598 | [ctype + name for (ctype, name) in out_args]) | ||
570 | self.h('static inline') | 599 | self.h('static inline') | ||
571 | self.h('/* this comment is to stop gtkdoc realising this is static */') | 600 | self.h('/* this comment is to stop gtkdoc realising this is static */') | ||
572 | self.h(('void %s (' % ret_name) + (',\n '.join(tmp)) + ');') | 601 | self.h(('void %s (' % ret_name) + (',\n '.join(tmp)) + ');') | ||
573 | self.h('static inline void') | 602 | self.h('static inline void') | ||
574 | self.h(('%s (' % ret_name) + (',\n '.join(tmp)) + ')') | 603 | self.h(('%s (' % ret_name) + (',\n '.join(tmp)) + ')') | ||
575 | self.h('{') | 604 | self.h('{') | ||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Line(s) | 617 | def do_signal(self, signal): | |||
629 | 658 | | |||
630 | tmp = (['gpointer instance'] + | 659 | tmp = (['gpointer instance'] + | ||
631 | [ctype + name for (ctype, name, gtype) in args]) | 660 | [ctype + name for (ctype, name, gtype) in args]) | ||
632 | 661 | | |||
633 | self.h(('void %s (' % stub_name) + (',\n '.join(tmp)) + ');') | 662 | self.h(('void %s (' % stub_name) + (',\n '.join(tmp)) + ');') | ||
634 | 663 | | |||
635 | # FIXME: emit docs | 664 | # FIXME: emit docs | ||
636 | 665 | | |||
637 | self.b('/**') | 666 | self.d('/**') | ||
638 | self.b(' * %s:' % stub_name) | 667 | self.d(' * %s:' % stub_name) | ||
639 | self.b(' * @instance: The object implementing this interface') | 668 | self.d(' * @instance: The object implementing this interface') | ||
640 | for (ctype, name, gtype) in args: | 669 | for (ctype, name, gtype) in args: | ||
641 | self.b(' * @%s: %s (FIXME, generate documentation)' | 670 | self.d(' * @%s: %s (FIXME, generate documentation)' | ||
642 | % (name, ctype)) | 671 | % (name, ctype)) | ||
643 | self.b(' *') | 672 | self.d(' *') | ||
644 | self.b(' * Type-safe wrapper around g_signal_emit to emit the') | 673 | self.d(' * Type-safe wrapper around g_signal_emit to emit the') | ||
645 | self.b(' * %s signal on interface %s.' | 674 | self.d(' * %s signal on interface %s.' | ||
646 | % (dbus_name, self.iface_name)) | 675 | % (dbus_name, self.iface_name)) | ||
647 | self.b(' */') | 676 | self.d(' */') | ||
648 | 677 | | |||
649 | self.b('void') | 678 | self.b('void') | ||
650 | self.b(('%s (' % stub_name) + (',\n '.join(tmp)) + ')') | 679 | self.b(('%s (' % stub_name) + (',\n '.join(tmp)) + ')') | ||
651 | self.b('{') | 680 | self.b('{') | ||
652 | self.b(' g_assert (instance != NULL);') | 681 | self.b(' g_assert (instance != NULL);') | ||
653 | self.b(' g_assert (G_TYPE_CHECK_INSTANCE_TYPE (instance, %s));' | 682 | self.b(' g_assert (G_TYPE_CHECK_INSTANCE_TYPE (instance, %s));' | ||
654 | % (self.current_gtype)) | 683 | % (self.current_gtype)) | ||
655 | tmp = (['instance', '%s_signals[%s]' % (self.node_name_lc, const_name), | 684 | tmp = (['instance', '%s_signals[%s]' % (self.node_name_lc, const_name), | ||
656 | '0'] + [name for (ctype, name, gtype) in args]) | 685 | '0'] + [name for (ctype, name, gtype) in args]) | ||
657 | self.b(' g_signal_emit (' + ',\n '.join(tmp) + ');') | 686 | self.b(' g_signal_emit (' + ',\n '.join(tmp) + ');') | ||
658 | self.b('}') | 687 | self.b('}') | ||
659 | self.b('') | 688 | self.b('') | ||
660 | 689 | | |||
661 | signal_name = dbus_gutils_wincaps_to_uscore(dbus_name).replace('_', | 690 | signal_name = dbus_gutils_wincaps_to_uscore(dbus_name).replace('_', | ||
662 | '-') | 691 | '-') | ||
663 | in_base_init.append(' /**') | 692 | | ||
664 | in_base_init.append(' * %s%s::%s:' | 693 | self.d('/**') | ||
694 | self.d(' * %s%s::%s:' | ||||
665 | % (self.Prefix, self.node_name_mixed, signal_name)) | 695 | % (self.Prefix, self.node_name_mixed, signal_name)) | ||
696 | self.d(' * @self: an object') | ||||
666 | for (ctype, name, gtype) in args: | 697 | for (ctype, name, gtype) in args: | ||
667 | in_base_init.append(' * @%s: %s (FIXME, generate documentation)' | 698 | self.d(' * @%s: %s (FIXME, generate documentation)' | ||
668 | % (name, ctype)) | 699 | % (name, ctype)) | ||
669 | in_base_init.append(' *') | 700 | self.d(' *') | ||
670 | in_base_init.append(' * The %s D-Bus signal is emitted whenever ' | 701 | self.d(' * The %s D-Bus signal is emitted whenever ' | ||
671 | 'this GObject signal is.' % dbus_name) | 702 | 'this GObject signal is.' % dbus_name) | ||
672 | in_base_init.append(' */') | 703 | self.d(' */') | ||
704 | self.d('') | ||||
705 | | ||||
673 | in_base_init.append(' %s_signals[%s] =' | 706 | in_base_init.append(' %s_signals[%s] =' | ||
674 | % (self.node_name_lc, const_name)) | 707 | % (self.node_name_lc, const_name)) | ||
675 | in_base_init.append(' g_signal_new ("%s",' % signal_name) | 708 | in_base_init.append(' g_signal_new ("%s",' % signal_name) | ||
676 | in_base_init.append(' G_OBJECT_CLASS_TYPE (klass),') | 709 | in_base_init.append(' G_OBJECT_CLASS_TYPE (klass),') | ||
677 | in_base_init.append(' G_SIGNAL_RUN_LAST|G_SIGNAL_DETAILED,') | 710 | in_base_init.append(' G_SIGNAL_RUN_LAST|G_SIGNAL_DETAILED,') | ||
678 | in_base_init.append(' 0,') | 711 | in_base_init.append(' 0,') | ||
679 | in_base_init.append(' NULL, NULL,') | 712 | in_base_init.append(' NULL, NULL,') | ||
680 | in_base_init.append(' %s,' | 713 | in_base_init.append(' g_cclosure_marshal_generic,') | ||
681 | % signal_to_marshal_name(signal, self.signal_marshal_prefix)) | | |||
682 | in_base_init.append(' G_TYPE_NONE,') | 714 | in_base_init.append(' G_TYPE_NONE,') | ||
683 | tmp = ['%d' % len(args)] + [gtype for (ctype, name, gtype) in args] | 715 | tmp = ['%d' % len(args)] + [gtype for (ctype, name, gtype) in args] | ||
684 | in_base_init.append(' %s);' % ',\n '.join(tmp)) | 716 | in_base_init.append(' %s);' % ',\n '.join(tmp)) | ||
685 | in_base_init.append('') | 717 | in_base_init.append('') | ||
686 | 718 | | |||
687 | return in_base_init | 719 | return in_base_init | ||
688 | 720 | | |||
689 | def have_properties(self, nodes): | 721 | def have_properties(self, nodes): | ||
690 | for node in nodes: | 722 | for node in nodes: | ||
691 | interface = node.getElementsByTagName('interface')[0] | 723 | interface = node.getElementsByTagName('interface')[0] | ||
692 | if interface.getElementsByTagName('property'): | 724 | if interface.getElementsByTagName('property'): | ||
693 | return True | 725 | return True | ||
694 | return False | 726 | return False | ||
695 | 727 | | |||
696 | def __call__(self): | 728 | def __call__(self): | ||
697 | nodes = self.dom.getElementsByTagName('node') | 729 | nodes = self.dom.getElementsByTagName('node') | ||
698 | nodes.sort(cmp_by_name) | 730 | nodes.sort(key=key_by_name) | ||
699 | 731 | | |||
700 | self.h('#include <glib-object.h>') | 732 | self.h('#include <glib-object.h>') | ||
701 | self.h('#include <dbus/dbus-glib.h>') | 733 | self.h('#include <dbus/dbus-glib.h>') | ||
702 | 734 | | |||
703 | if self.have_properties(nodes): | 735 | for header in self.headers: | ||
704 | self.h('#include <telepathy-glib/dbus-properties-mixin.h>') | 736 | self.h('#include %s' % header) | ||
737 | self.h('') | ||||
705 | 738 | | |||
706 | self.h('') | 739 | self.h('') | ||
707 | self.h('G_BEGIN_DECLS') | 740 | self.h('G_BEGIN_DECLS') | ||
708 | self.h('') | 741 | self.h('') | ||
709 | 742 | | |||
710 | self.b('#include "%s.h"' % self.basename) | 743 | self.b('#include "%s.h"' % self.basename) | ||
711 | self.b('') | 744 | self.b('') | ||
712 | for header in self.headers: | | |||
713 | self.b('#include %s' % header) | | |||
714 | self.b('') | | |||
715 | 745 | | |||
716 | for node in nodes: | 746 | for node in nodes: | ||
717 | self.do_node(node) | 747 | self.do_node(node) | ||
718 | 748 | | |||
719 | self.h('') | 749 | self.h('') | ||
720 | self.h('G_END_DECLS') | 750 | self.h('G_END_DECLS') | ||
721 | 751 | | |||
722 | self.b('') | 752 | self.b('') | ||
723 | for header in self.end_headers: | 753 | for header in self.end_headers: | ||
724 | self.b('#include %s' % header) | 754 | self.b('#include %s' % header) | ||
725 | 755 | | |||
726 | self.h('') | 756 | self.h('') | ||
727 | self.b('') | 757 | self.b('') | ||
728 | open(self.basename + '.h', 'w').write('\n'.join(self.__header)) | 758 | file_set_contents(self.basename + '.h', u('\n').join(self.__header).encode('utf-8')) | ||
729 | open(self.basename + '.c', 'w').write('\n'.join(self.__body)) | 759 | file_set_contents(self.basename + '.c', u('\n').join(self.__body).encode('utf-8')) | ||
730 | 760 | file_set_contents(self.basename + '-gtk-doc.h', u('\n').join(self.__docs).encode('utf-8')) | |||
731 | 761 | | |||
732 | def cmdline_error(): | 762 | def cmdline_error(): | ||
733 | print """\ | 763 | print("""\ | ||
734 | usage: | 764 | usage: | ||
735 | gen-ginterface [OPTIONS] xmlfile Prefix_ | 765 | gen-ginterface [OPTIONS] xmlfile Prefix_ | ||
736 | options: | 766 | options: | ||
737 | --include='<header.h>' (may be repeated) | 767 | --include='<header.h>' (may be repeated) | ||
738 | --include='"header.h"' (ditto) | 768 | --include='"header.h"' (ditto) | ||
739 | --include-end='"header.h"' (ditto) | 769 | --include-end='"header.h"' (ditto) | ||
740 | Include extra headers in the generated .c file | 770 | Include extra headers in the generated .c file | ||
741 | --signal-marshal-prefix='prefix' | 771 | --signal-marshal-prefix='prefix' | ||
742 | Use the given prefix on generated signal marshallers (default is | 772 | Use the given prefix on generated signal marshallers (default is | ||
743 | prefix.lower()). | 773 | prefix.lower()). | ||
744 | --filename='BASENAME' | 774 | --filename='BASENAME' | ||
745 | Set the basename for the output files (default is prefix.lower() | 775 | Set the basename for the output files (default is prefix.lower() | ||
746 | + 'ginterfaces') | 776 | + 'ginterfaces') | ||
747 | --not-implemented-func='symbol' | 777 | --not-implemented-func='symbol' | ||
748 | Set action when methods not implemented in the interface vtable are | 778 | Set action when methods not implemented in the interface vtable are | ||
749 | called. symbol must have signature | 779 | called. symbol must have signature | ||
750 | void symbol (DBusGMethodInvocation *context) | 780 | void symbol (DBusGMethodInvocation *context) | ||
751 | and return some sort of "not implemented" error via | 781 | and return some sort of "not implemented" error via | ||
752 | dbus_g_method_return_error (context, ...) | 782 | dbus_g_method_return_error (context, ...) | ||
753 | """ | 783 | """) | ||
754 | sys.exit(1) | 784 | sys.exit(1) | ||
755 | 785 | | |||
756 | 786 | | |||
757 | if __name__ == '__main__': | 787 | if __name__ == '__main__': | ||
758 | from getopt import gnu_getopt | 788 | from getopt import gnu_getopt | ||
759 | 789 | | |||
760 | options, argv = gnu_getopt(sys.argv[1:], '', | 790 | options, argv = gnu_getopt(sys.argv[1:], '', | ||
761 | ['filename=', 'signal-marshal-prefix=', | 791 | ['filename=', 'signal-marshal-prefix=', | ||
▲ Show 20 Lines • Show All 41 Lines • Show Last 20 Lines |