Tizen 2.1 base
[platform/upstream/glib2.0.git] / gio / gdbus-2.0 / codegen / codegen_main.py
1 # -*- Mode: Python -*-
2
3 # GDBus - GLib D-Bus Library
4 #
5 # Copyright (C) 2008-2011 Red Hat, Inc.
6 #
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2 of the License, or (at your option) any later version.
11 #
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 # Lesser General Public License for more details.
16 #
17 # You should have received a copy of the GNU Lesser General
18 # Public License along with this library; if not, write to the
19 # Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20 # Boston, MA 02111-1307, USA.
21 #
22 # Author: David Zeuthen <davidz@redhat.com>
23
24 import sys
25 import optparse
26
27 from . import config
28 from . import utils
29 from . import dbustypes
30 from . import parser
31 from . import codegen
32 from . import codegen_docbook
33
34 def find_arg(arg_list, arg_name):
35     for a in arg_list:
36         if a.name == arg_name:
37             return a
38     return None
39
40 def find_method(iface, method):
41     for m in iface.methods:
42         if m.name == method:
43             return m
44     return None
45
46 def find_signal(iface, signal):
47     for m in iface.signals:
48         if m.name == signal:
49             return m
50     return None
51
52 def find_prop(iface, prop):
53     for m in iface.properties:
54         if m.name == prop:
55             return m
56     return None
57
58 def apply_annotation(iface_list, iface, method, signal, prop, arg, key, value):
59     for i in iface_list:
60         if i.name == iface:
61             iface_obj = i
62             break
63
64     if iface_obj == None:
65         raise RuntimeError('No interface %s'%iface)
66
67     target_obj = None
68
69     if method:
70         method_obj = find_method(iface_obj, method)
71         if method_obj == None:
72             raise RuntimeError('No method %s on interface %s'%(method, iface))
73         if arg:
74             arg_obj = find_arg(method_obj.in_args, arg)
75             if (arg_obj == None):
76                 arg_obj = find_arg(method_obj.out_args, arg)
77                 if (arg_obj == None):
78                     raise RuntimeError('No arg %s on method %s on interface %s'%(arg, method, iface))
79             target_obj = arg_obj
80         else:
81             target_obj = method_obj
82     elif signal:
83         signal_obj = find_signal(iface_obj, signal)
84         if signal_obj == None:
85             raise RuntimeError('No signal %s on interface %s'%(signal, iface))
86         if arg:
87             arg_obj = find_arg(signal_obj.args, arg)
88             if (arg_obj == None):
89                 raise RuntimeError('No arg %s on signal %s on interface %s'%(arg, signal, iface))
90             target_obj = arg_obj
91         else:
92             target_obj = signal_obj
93     elif prop:
94         prop_obj = find_prop(iface_obj, prop)
95         if prop_obj == None:
96             raise RuntimeError('No property %s on interface %s'%(prop, iface))
97         target_obj = prop_obj
98     else:
99         target_obj = iface_obj
100     target_obj.annotations.insert(0, dbustypes.Annotation(key, value))
101
102
103 def apply_annotations(iface_list, annotation_list):
104     # apply annotations given on the command line
105     for (what, key, value) in annotation_list:
106         pos = what.find('::')
107         if pos != -1:
108             # signal
109             iface = what[0:pos];
110             signal = what[pos + 2:]
111             pos = signal.find('[')
112             if pos != -1:
113                 arg = signal[pos + 1:]
114                 signal = signal[0:pos]
115                 pos = arg.find(']')
116                 arg = arg[0:pos]
117                 apply_annotation(iface_list, iface, None, signal, None, arg, key, value)
118             else:
119                 apply_annotation(iface_list, iface, None, signal, None, None, key, value)
120         else:
121             pos = what.find(':')
122             if pos != -1:
123                 # property
124                 iface = what[0:pos];
125                 prop = what[pos + 1:]
126                 apply_annotation(iface_list, iface, None, None, prop, None, key, value)
127             else:
128                 pos = what.find('()')
129                 if pos != -1:
130                     # method
131                     combined = what[0:pos]
132                     pos = combined.rfind('.')
133                     iface = combined[0:pos]
134                     method = combined[pos + 1:]
135                     pos = what.find('[')
136                     if pos != -1:
137                         arg = what[pos + 1:]
138                         pos = arg.find(']')
139                         arg = arg[0:pos]
140                         apply_annotation(iface_list, iface, method, None, None, arg, key, value)
141                     else:
142                         apply_annotation(iface_list, iface, method, None, None, None, key, value)
143                 else:
144                     # must be an interface
145                     iface = what
146                     apply_annotation(iface_list, iface, None, None, None, None, key, value)
147
148 def codegen_main():
149     arg_parser = optparse.OptionParser('%prog [options]')
150     arg_parser.add_option('', '--xml-files', metavar='FILE', action='append',
151                           help='D-Bus introspection XML file')
152     arg_parser.add_option('', '--interface-prefix', metavar='PREFIX', default='',
153                             help='String to strip from D-Bus interface names for code and docs')
154     arg_parser.add_option('', '--c-namespace', metavar='NAMESPACE', default='',
155                             help='The namespace to use for generated C code')
156     arg_parser.add_option('', '--c-generate-object-manager', action='store_true',
157                             help='Generate a GDBusObjectManagerClient subclass when generating C code')
158     arg_parser.add_option('', '--generate-c-code', metavar='OUTFILES',
159                           help='Generate C code in OUTFILES.[ch]')
160     arg_parser.add_option('', '--generate-docbook', metavar='OUTFILES',
161                           help='Generate Docbook in OUTFILES-org.Project.IFace.xml')
162     arg_parser.add_option('', '--annotate', nargs=3, action='append', metavar='WHAT KEY VALUE',
163                           help='Add annotation (may be used several times)')
164     (opts, args) = arg_parser.parse_args();
165
166     all_ifaces = []
167     for fname in args:
168         f = open(fname)
169         xml_data = f.read()
170         f.close()
171         parsed_ifaces = parser.parse_dbus_xml(xml_data)
172         all_ifaces.extend(parsed_ifaces)
173
174     if opts.annotate != None:
175         apply_annotations(all_ifaces, opts.annotate)
176
177     for i in all_ifaces:
178         i.post_process(opts.interface_prefix, opts.c_namespace)
179
180     docbook = opts.generate_docbook
181     docbook_gen = codegen_docbook.DocbookCodeGenerator(all_ifaces, docbook);
182     if docbook:
183         ret = docbook_gen.generate()
184
185     c_code = opts.generate_c_code
186     if c_code:
187         h = file(c_code + '.h', 'w')
188         c = file(c_code + '.c', 'w')
189         gen = codegen.CodeGenerator(all_ifaces,
190                                     opts.c_namespace,
191                                     opts.interface_prefix,
192                                     opts.c_generate_object_manager,
193                                     docbook_gen,
194                                     h, c);
195         ret = gen.generate()
196
197     sys.exit(0)
198
199 if __name__ == "__main__":
200     codegen_main()