mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-27 16:06:16 +01:00
98f86beed6
This adds a new --c-generate-autocleanup option to gdbus-codegen which can be used to instruct gdbus-codegen about what autocleanup definitions to emit. Doing this unconditionally was found to interfere with existing code out in the wild. The new option takes an argument that can be none, objects or all; to indicate whether to generate no autocleanup functions, only do it for object types, or do it for interface types as well. The default is 'objects', which matches the unconditional behavior of gdbus-codegen on the 2.48 branch. https://bugzilla.gnome.org/show_bug.cgi?id=763379
205 lines
7.5 KiB
Python
Executable File
205 lines
7.5 KiB
Python
Executable File
# -*- Mode: Python -*-
|
|
|
|
# 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, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
# Author: David Zeuthen <davidz@redhat.com>
|
|
|
|
import sys
|
|
import optparse
|
|
|
|
from . import config
|
|
from . import utils
|
|
from . import dbustypes
|
|
from . import parser
|
|
from . import codegen
|
|
from . import codegen_docbook
|
|
|
|
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):
|
|
iface_obj = None
|
|
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():
|
|
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='',
|
|
help='String to strip from D-Bus interface names for code and docs')
|
|
arg_parser.add_option('', '--c-namespace', metavar='NAMESPACE', default='',
|
|
help='The namespace to use for generated C code')
|
|
arg_parser.add_option('', '--c-generate-object-manager', action='store_true',
|
|
help='Generate a GDBusObjectManagerClient subclass when generating C code')
|
|
arg_parser.add_option('', '--generate-c-code', metavar='OUTFILES',
|
|
help='Generate C code in OUTFILES.[ch]')
|
|
arg_parser.add_option('', '--c-generate-autocleanup', type='choice', choices=['none', 'objects', 'all'], default='objects',
|
|
help='Generate autocleanup support')
|
|
arg_parser.add_option('', '--generate-docbook', metavar='OUTFILES',
|
|
help='Generate Docbook in OUTFILES-org.Project.IFace.xml')
|
|
arg_parser.add_option('', '--annotate', nargs=3, action='append', metavar='WHAT KEY VALUE',
|
|
help='Add annotation (may be used several times)')
|
|
(opts, args) = arg_parser.parse_args();
|
|
|
|
all_ifaces = []
|
|
for fname in args:
|
|
f = open(fname, 'rb')
|
|
xml_data = f.read()
|
|
f.close()
|
|
parsed_ifaces = parser.parse_dbus_xml(xml_data)
|
|
all_ifaces.extend(parsed_ifaces)
|
|
|
|
if opts.annotate != None:
|
|
apply_annotations(all_ifaces, opts.annotate)
|
|
|
|
for i in all_ifaces:
|
|
i.post_process(opts.interface_prefix, opts.c_namespace)
|
|
|
|
docbook = opts.generate_docbook
|
|
docbook_gen = codegen_docbook.DocbookCodeGenerator(all_ifaces, docbook);
|
|
if docbook:
|
|
ret = docbook_gen.generate()
|
|
|
|
c_code = opts.generate_c_code
|
|
if c_code:
|
|
h = open(c_code + '.h', 'w')
|
|
c = open(c_code + '.c', 'w')
|
|
gen = codegen.CodeGenerator(all_ifaces,
|
|
opts.c_namespace,
|
|
opts.interface_prefix,
|
|
opts.c_generate_object_manager,
|
|
opts.c_generate_autocleanup,
|
|
docbook_gen,
|
|
h, c);
|
|
ret = gen.generate()
|
|
h.close()
|
|
c.close()
|
|
|
|
sys.exit(0)
|
|
|
|
if __name__ == "__main__":
|
|
codegen_main()
|