2011-04-08 22:57:31 +02:00
|
|
|
# -*- Mode: Python -*-
|
|
|
|
|
2011-04-15 14:33:30 +02:00
|
|
|
# GDBus - GLib D-Bus Library
|
|
|
|
#
|
|
|
|
# Copyright (C) 2008-2011 Red Hat, Inc.
|
|
|
|
#
|
|
|
|
# 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 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., 59 Temple Place, Suite 330,
|
|
|
|
# Boston, MA 02111-1307, USA.
|
|
|
|
#
|
|
|
|
# Author: David Zeuthen <davidz@redhat.com>
|
|
|
|
|
2011-04-08 22:57:31 +02:00
|
|
|
import sys
|
2011-05-11 21:02:23 +02:00
|
|
|
import optparse
|
2011-04-08 22:57:31 +02:00
|
|
|
|
2011-08-23 17:37:35 +02:00
|
|
|
from . import config
|
2011-08-23 07:35:01 +02:00
|
|
|
from . import utils
|
|
|
|
from . import dbustypes
|
|
|
|
from . import parser
|
|
|
|
from . import codegen
|
|
|
|
from . import codegen_docbook
|
2011-04-08 22:57:31 +02:00
|
|
|
|
|
|
|
def find_arg(arg_list, arg_name):
|
|
|
|
for a in arg_list:
|
|
|
|
if a.name == arg_name:
|
|
|
|
return a
|
|
|
|
return None
|
|
|
|
|
|
|
|
def find_method(iface, method):
|
|
|
|
for m in iface.methods:
|
|
|
|
if m.name == method:
|
|
|
|
return m
|
|
|
|
return None
|
|
|
|
|
|
|
|
def find_signal(iface, signal):
|
|
|
|
for m in iface.signals:
|
|
|
|
if m.name == signal:
|
|
|
|
return m
|
|
|
|
return None
|
|
|
|
|
|
|
|
def find_prop(iface, prop):
|
|
|
|
for m in iface.properties:
|
|
|
|
if m.name == prop:
|
|
|
|
return m
|
|
|
|
return None
|
|
|
|
|
|
|
|
def apply_annotation(iface_list, iface, method, signal, prop, arg, key, value):
|
gdbus-codegen: avoid error when wrong interface is provided to --annotate
If the interface given cannot be matched, `iface_obj' was left uninitialized and
the iface_obj == None check would end up crashing:
Traceback (most recent call last):
File "/usr/bin/gdbus-codegen", line 41, in <module>
sys.exit(codegen_main.codegen_main())
File "/usr/lib64/gdbus-2.0/codegen/codegen_main.py", line 175, in codegen_main
apply_annotations(all_ifaces, opts.annotate)
File "/usr/lib64/gdbus-2.0/codegen/codegen_main.py", line 146, in apply_annotations
apply_annotation(iface_list, iface, None, None, None, None, key, value)
File "/usr/lib64/gdbus-2.0/codegen/codegen_main.py", line 64, in apply_annotation
if iface_obj == None:
UnboundLocalError: local variable 'iface_obj' referenced before assignment
Fixes https://bugzilla.gnome.org/show_bug.cgi?id=683088
2012-08-31 11:41:53 +02:00
|
|
|
iface_obj = None
|
2011-04-08 22:57:31 +02:00
|
|
|
for i in iface_list:
|
|
|
|
if i.name == iface:
|
|
|
|
iface_obj = i
|
|
|
|
break
|
|
|
|
|
|
|
|
if iface_obj == None:
|
|
|
|
raise RuntimeError('No interface %s'%iface)
|
|
|
|
|
|
|
|
target_obj = None
|
|
|
|
|
|
|
|
if method:
|
|
|
|
method_obj = find_method(iface_obj, method)
|
|
|
|
if method_obj == None:
|
|
|
|
raise RuntimeError('No method %s on interface %s'%(method, iface))
|
|
|
|
if arg:
|
|
|
|
arg_obj = find_arg(method_obj.in_args, arg)
|
|
|
|
if (arg_obj == None):
|
|
|
|
arg_obj = find_arg(method_obj.out_args, arg)
|
|
|
|
if (arg_obj == None):
|
|
|
|
raise RuntimeError('No arg %s on method %s on interface %s'%(arg, method, iface))
|
|
|
|
target_obj = arg_obj
|
|
|
|
else:
|
|
|
|
target_obj = method_obj
|
|
|
|
elif signal:
|
|
|
|
signal_obj = find_signal(iface_obj, signal)
|
|
|
|
if signal_obj == None:
|
|
|
|
raise RuntimeError('No signal %s on interface %s'%(signal, iface))
|
|
|
|
if arg:
|
|
|
|
arg_obj = find_arg(signal_obj.args, arg)
|
|
|
|
if (arg_obj == None):
|
|
|
|
raise RuntimeError('No arg %s on signal %s on interface %s'%(arg, signal, iface))
|
|
|
|
target_obj = arg_obj
|
|
|
|
else:
|
|
|
|
target_obj = signal_obj
|
|
|
|
elif prop:
|
|
|
|
prop_obj = find_prop(iface_obj, prop)
|
|
|
|
if prop_obj == None:
|
|
|
|
raise RuntimeError('No property %s on interface %s'%(prop, iface))
|
|
|
|
target_obj = prop_obj
|
|
|
|
else:
|
|
|
|
target_obj = iface_obj
|
|
|
|
target_obj.annotations.insert(0, dbustypes.Annotation(key, value))
|
|
|
|
|
|
|
|
|
|
|
|
def apply_annotations(iface_list, annotation_list):
|
|
|
|
# apply annotations given on the command line
|
|
|
|
for (what, key, value) in annotation_list:
|
|
|
|
pos = what.find('::')
|
|
|
|
if pos != -1:
|
|
|
|
# signal
|
|
|
|
iface = what[0:pos];
|
|
|
|
signal = what[pos + 2:]
|
|
|
|
pos = signal.find('[')
|
|
|
|
if pos != -1:
|
|
|
|
arg = signal[pos + 1:]
|
|
|
|
signal = signal[0:pos]
|
|
|
|
pos = arg.find(']')
|
|
|
|
arg = arg[0:pos]
|
|
|
|
apply_annotation(iface_list, iface, None, signal, None, arg, key, value)
|
|
|
|
else:
|
|
|
|
apply_annotation(iface_list, iface, None, signal, None, None, key, value)
|
|
|
|
else:
|
|
|
|
pos = what.find(':')
|
|
|
|
if pos != -1:
|
|
|
|
# property
|
|
|
|
iface = what[0:pos];
|
|
|
|
prop = what[pos + 1:]
|
|
|
|
apply_annotation(iface_list, iface, None, None, prop, None, key, value)
|
|
|
|
else:
|
|
|
|
pos = what.find('()')
|
|
|
|
if pos != -1:
|
|
|
|
# method
|
|
|
|
combined = what[0:pos]
|
|
|
|
pos = combined.rfind('.')
|
|
|
|
iface = combined[0:pos]
|
|
|
|
method = combined[pos + 1:]
|
|
|
|
pos = what.find('[')
|
|
|
|
if pos != -1:
|
|
|
|
arg = what[pos + 1:]
|
|
|
|
pos = arg.find(']')
|
|
|
|
arg = arg[0:pos]
|
|
|
|
apply_annotation(iface_list, iface, method, None, None, arg, key, value)
|
|
|
|
else:
|
|
|
|
apply_annotation(iface_list, iface, method, None, None, None, key, value)
|
|
|
|
else:
|
|
|
|
# must be an interface
|
|
|
|
iface = what
|
|
|
|
apply_annotation(iface_list, iface, None, None, None, None, key, value)
|
|
|
|
|
|
|
|
def codegen_main():
|
2011-05-11 21:02:23 +02:00
|
|
|
arg_parser = optparse.OptionParser('%prog [options]')
|
|
|
|
arg_parser.add_option('', '--xml-files', metavar='FILE', action='append',
|
|
|
|
help='D-Bus introspection XML file')
|
|
|
|
arg_parser.add_option('', '--interface-prefix', metavar='PREFIX', default='',
|
2011-04-08 22:57:31 +02:00
|
|
|
help='String to strip from D-Bus interface names for code and docs')
|
2011-05-11 21:02:23 +02:00
|
|
|
arg_parser.add_option('', '--c-namespace', metavar='NAMESPACE', default='',
|
2011-04-08 22:57:31 +02:00
|
|
|
help='The namespace to use for generated C code')
|
2011-05-11 21:02:23 +02:00
|
|
|
arg_parser.add_option('', '--c-generate-object-manager', action='store_true',
|
2011-04-12 17:50:34 +02:00
|
|
|
help='Generate a GDBusObjectManagerClient subclass when generating C code')
|
2011-05-11 21:02:23 +02:00
|
|
|
arg_parser.add_option('', '--generate-c-code', metavar='OUTFILES',
|
|
|
|
help='Generate C code in OUTFILES.[ch]')
|
|
|
|
arg_parser.add_option('', '--generate-docbook', metavar='OUTFILES',
|
|
|
|
help='Generate Docbook in OUTFILES-org.Project.IFace.xml')
|
2011-05-11 23:13:57 +02:00
|
|
|
arg_parser.add_option('', '--annotate', nargs=3, action='append', metavar='WHAT KEY VALUE',
|
2011-05-11 21:02:23 +02:00
|
|
|
help='Add annotation (may be used several times)')
|
|
|
|
(opts, args) = arg_parser.parse_args();
|
2011-04-08 22:57:31 +02:00
|
|
|
|
|
|
|
all_ifaces = []
|
2011-05-11 21:02:23 +02:00
|
|
|
for fname in args:
|
2013-08-16 17:44:14 +02:00
|
|
|
f = open(fname, 'rb')
|
2011-04-08 22:57:31 +02:00
|
|
|
xml_data = f.read()
|
|
|
|
f.close()
|
|
|
|
parsed_ifaces = parser.parse_dbus_xml(xml_data)
|
|
|
|
all_ifaces.extend(parsed_ifaces)
|
|
|
|
|
2011-05-11 21:02:23 +02:00
|
|
|
if opts.annotate != None:
|
|
|
|
apply_annotations(all_ifaces, opts.annotate)
|
2011-04-08 22:57:31 +02:00
|
|
|
|
2011-09-01 20:28:57 +02:00
|
|
|
for i in all_ifaces:
|
2011-05-11 21:02:23 +02:00
|
|
|
i.post_process(opts.interface_prefix, opts.c_namespace)
|
2011-04-08 22:57:31 +02:00
|
|
|
|
2011-05-11 21:02:23 +02:00
|
|
|
docbook = opts.generate_docbook
|
2011-04-18 20:23:19 +02:00
|
|
|
docbook_gen = codegen_docbook.DocbookCodeGenerator(all_ifaces, docbook);
|
|
|
|
if docbook:
|
|
|
|
ret = docbook_gen.generate()
|
|
|
|
|
2011-05-11 21:02:23 +02:00
|
|
|
c_code = opts.generate_c_code
|
2011-04-08 22:57:31 +02:00
|
|
|
if c_code:
|
2012-06-14 08:20:17 +02:00
|
|
|
h = open(c_code + '.h', 'w')
|
|
|
|
c = open(c_code + '.c', 'w')
|
2011-04-12 17:50:34 +02:00
|
|
|
gen = codegen.CodeGenerator(all_ifaces,
|
2011-05-11 21:02:23 +02:00
|
|
|
opts.c_namespace,
|
|
|
|
opts.interface_prefix,
|
|
|
|
opts.c_generate_object_manager,
|
2011-04-18 20:23:19 +02:00
|
|
|
docbook_gen,
|
2011-04-12 17:50:34 +02:00
|
|
|
h, c);
|
2011-04-08 22:57:31 +02:00
|
|
|
ret = gen.generate()
|
2012-09-26 21:44:33 +02:00
|
|
|
h.close()
|
|
|
|
c.close()
|
2011-04-08 22:57:31 +02:00
|
|
|
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
codegen_main()
|