codegen: Treat input file as binary
[platform/upstream/glib.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     iface_obj = None
60     for i in iface_list:
61         if i.name == iface:
62             iface_obj = i
63             break
64
65     if iface_obj == None:
66         raise RuntimeError('No interface %s'%iface)
67
68     target_obj = None
69
70     if method:
71         method_obj = find_method(iface_obj, method)
72         if method_obj == None:
73             raise RuntimeError('No method %s on interface %s'%(method, iface))
74         if arg:
75             arg_obj = find_arg(method_obj.in_args, arg)
76             if (arg_obj == None):
77                 arg_obj = find_arg(method_obj.out_args, arg)
78                 if (arg_obj == None):
79                     raise RuntimeError('No arg %s on method %s on interface %s'%(arg, method, iface))
80             target_obj = arg_obj
81         else:
82             target_obj = method_obj
83     elif signal:
84         signal_obj = find_signal(iface_obj, signal)
85         if signal_obj == None:
86             raise RuntimeError('No signal %s on interface %s'%(signal, iface))
87         if arg:
88             arg_obj = find_arg(signal_obj.args, arg)
89             if (arg_obj == None):
90                 raise RuntimeError('No arg %s on signal %s on interface %s'%(arg, signal, iface))
91             target_obj = arg_obj
92         else:
93             target_obj = signal_obj
94     elif prop:
95         prop_obj = find_prop(iface_obj, prop)
96         if prop_obj == None:
97             raise RuntimeError('No property %s on interface %s'%(prop, iface))
98         target_obj = prop_obj
99     else:
100         target_obj = iface_obj
101     target_obj.annotations.insert(0, dbustypes.Annotation(key, value))
102
103
104 def apply_annotations(iface_list, annotation_list):
105     # apply annotations given on the command line
106     for (what, key, value) in annotation_list:
107         pos = what.find('::')
108         if pos != -1:
109             # signal
110             iface = what[0:pos];
111             signal = what[pos + 2:]
112             pos = signal.find('[')
113             if pos != -1:
114                 arg = signal[pos + 1:]
115                 signal = signal[0:pos]
116                 pos = arg.find(']')
117                 arg = arg[0:pos]
118                 apply_annotation(iface_list, iface, None, signal, None, arg, key, value)
119             else:
120                 apply_annotation(iface_list, iface, None, signal, None, None, key, value)
121         else:
122             pos = what.find(':')
123             if pos != -1:
124                 # property
125                 iface = what[0:pos];
126                 prop = what[pos + 1:]
127                 apply_annotation(iface_list, iface, None, None, prop, None, key, value)
128             else:
129                 pos = what.find('()')
130                 if pos != -1:
131                     # method
132                     combined = what[0:pos]
133                     pos = combined.rfind('.')
134                     iface = combined[0:pos]
135                     method = combined[pos + 1:]
136                     pos = what.find('[')
137                     if pos != -1:
138                         arg = what[pos + 1:]
139                         pos = arg.find(']')
140                         arg = arg[0:pos]
141                         apply_annotation(iface_list, iface, method, None, None, arg, key, value)
142                     else:
143                         apply_annotation(iface_list, iface, method, None, None, None, key, value)
144                 else:
145                     # must be an interface
146                     iface = what
147                     apply_annotation(iface_list, iface, None, None, None, None, key, value)
148
149 def codegen_main():
150     arg_parser = optparse.OptionParser('%prog [options]')
151     arg_parser.add_option('', '--xml-files', metavar='FILE', action='append',
152                           help='D-Bus introspection XML file')
153     arg_parser.add_option('', '--interface-prefix', metavar='PREFIX', default='',
154                             help='String to strip from D-Bus interface names for code and docs')
155     arg_parser.add_option('', '--c-namespace', metavar='NAMESPACE', default='',
156                             help='The namespace to use for generated C code')
157     arg_parser.add_option('', '--c-generate-object-manager', action='store_true',
158                             help='Generate a GDBusObjectManagerClient subclass when generating C code')
159     arg_parser.add_option('', '--generate-c-code', metavar='OUTFILES',
160                           help='Generate C code in OUTFILES.[ch]')
161     arg_parser.add_option('', '--generate-docbook', metavar='OUTFILES',
162                           help='Generate Docbook in OUTFILES-org.Project.IFace.xml')
163     arg_parser.add_option('', '--annotate', nargs=3, action='append', metavar='WHAT KEY VALUE',
164                           help='Add annotation (may be used several times)')
165     (opts, args) = arg_parser.parse_args();
166
167     all_ifaces = []
168     for fname in args:
169         f = open(fname, 'rb')
170         xml_data = f.read()
171         f.close()
172         parsed_ifaces = parser.parse_dbus_xml(xml_data)
173         all_ifaces.extend(parsed_ifaces)
174
175     if opts.annotate != None:
176         apply_annotations(all_ifaces, opts.annotate)
177
178     for i in all_ifaces:
179         i.post_process(opts.interface_prefix, opts.c_namespace)
180
181     docbook = opts.generate_docbook
182     docbook_gen = codegen_docbook.DocbookCodeGenerator(all_ifaces, docbook);
183     if docbook:
184         ret = docbook_gen.generate()
185
186     c_code = opts.generate_c_code
187     if c_code:
188         h = open(c_code + '.h', 'w')
189         c = open(c_code + '.c', 'w')
190         gen = codegen.CodeGenerator(all_ifaces,
191                                     opts.c_namespace,
192                                     opts.interface_prefix,
193                                     opts.c_generate_object_manager,
194                                     docbook_gen,
195                                     h, c);
196         ret = gen.generate()
197         h.close()
198         c.close()
199
200     sys.exit(0)
201
202 if __name__ == "__main__":
203     codegen_main()