glib/gio/gdbus-codegen/codegen_main.py
David Zeuthen 0b9229beca Add gdbus-codegen(1) command
It doesn't work yet without the user manually adding ffi bits. That's
the topic of the next commit.

Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-04-08 17:11:38 -04:00

172 lines
6.0 KiB
Python

# -*- Mode: Python -*-
import sys
import argparse
import config
import utils
import dbustypes
import parser
import codegen
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):
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 = argparse.ArgumentParser(description='GDBus Code Generator')
arg_parser.add_argument('xml_files', metavar='FILE', type=file, nargs='+',
help='D-Bus introspection XML file')
arg_parser.add_argument('--interface-prefix', nargs='?', metavar='PREFIX', default='',
help='String to strip from D-Bus interface names for code and docs')
arg_parser.add_argument('--c-namespace', nargs='?', metavar='NAMESPACE', default='',
help='The namespace to use for generated C code')
arg_parser.add_argument('--generate-c-code', nargs='?', metavar='OUTFILES',
help='Generate C code in OUTFILES.[ch]')
arg_parser.add_argument('--generate-docbook', nargs='?', metavar='OUTFILES',
help='Generate Docbook in OUTFILES-org.Project.IFace.xml')
arg_parser.add_argument('--annotate', nargs=3, action='append', metavar=('WHAT', 'KEY', 'VALUE'),
help='Add annotation (may be used several times)')
args = arg_parser.parse_args();
all_ifaces = []
for f in args.xml_files:
xml_data = f.read()
f.close()
parsed_ifaces = parser.parse_dbus_xml(xml_data)
all_ifaces.extend(parsed_ifaces)
if args.annotate != None:
apply_annotations(all_ifaces, args.annotate)
for i in parsed_ifaces:
i.post_process(args.interface_prefix, args.c_namespace)
c_code = args.generate_c_code
if c_code:
h = file(c_code + '.h', 'w')
c = file(c_code + '.c', 'w')
gen = codegen.CodeGenerator(all_ifaces, args.c_namespace, args.interface_prefix, h, c);
ret = gen.generate()
docbook = args.generate_docbook
if docbook:
gen = codegen_docbook.DocbookCodeGenerator(all_ifaces, docbook);
ret = gen.generate()
sys.exit(0)
if __name__ == "__main__":
codegen_main()