]> git.proxmox.com Git - mirror_qemu.git/blame - scripts/qapi-commands.py
build-sys: split util-obj- on multi-lines
[mirror_qemu.git] / scripts / qapi-commands.py
CommitLineData
c17d9908
MR
1#
2# QAPI command marshaller generator
3#
4# Copyright IBM, Corp. 2011
d708cdbe 5# Copyright (C) 2014-2015 Red Hat, Inc.
c17d9908
MR
6#
7# Authors:
8# Anthony Liguori <aliguori@us.ibm.com>
9# Michael Roth <mdroth@linux.vnet.ibm.com>
297a3646 10# Markus Armbruster <armbru@redhat.com>
c17d9908 11#
678e48a2
MA
12# This work is licensed under the terms of the GNU GPL, version 2.
13# See the COPYING file in the top-level directory.
c17d9908 14
c17d9908 15from qapi import *
297a3646 16import re
c17d9908 17
e98859a9
MA
18
19def gen_command_decl(name, arg_type, ret_type):
c17d9908 20 return mcgen('''
03b4367a 21%(c_type)s qmp_%(c_name)s(%(params)s);
c17d9908 22''',
e98859a9
MA
23 c_type=(ret_type and ret_type.c_type()) or 'void',
24 c_name=c_name(name),
03b4367a 25 params=gen_params(arg_type, 'Error **errp'))
e98859a9 26
c17d9908 27
e98859a9
MA
28def gen_call(name, arg_type, ret_type):
29 ret = ''
30
31 argstr = ''
32 if arg_type:
33 for memb in arg_type.members:
ee446028 34 if memb.optional:
e98859a9
MA
35 argstr += 'has_%s, ' % c_name(memb.name)
36 argstr += '%s, ' % c_name(memb.name)
37
38 lhs = ''
39 if ret_type:
40 lhs = 'retval = '
41
c17d9908 42 ret = mcgen('''
f1538019 43
05372f70 44 %(lhs)sqmp_%(c_name)s(%(args)s&err);
c17d9908 45''',
e98859a9 46 c_name=c_name(name), args=argstr, lhs=lhs)
c17d9908 47 if ret_type:
1f353344 48 ret += gen_err_check()
e02bca28
MA
49 ret += mcgen('''
50
05372f70 51 qmp_marshal_output_%(c_name)s(retval, ret, &err);
c17d9908 52''',
56d92b00 53 c_name=ret_type.c_name())
1f9a7a1a 54 return ret
c17d9908 55
e98859a9 56
f1538019
MA
57def gen_marshal_vars(arg_type, ret_type):
58 ret = mcgen('''
2a0f50e8 59 Error *err = NULL;
f1538019 60''')
c17d9908 61
f1538019
MA
62 if ret_type:
63 ret += mcgen('''
05372f70 64 %(c_type)s retval;
f1538019
MA
65''',
66 c_type=ret_type.c_type())
67
e98859a9 68 if arg_type:
c17d9908 69 ret += mcgen('''
05372f70
EB
70 QmpInputVisitor *qiv = qmp_input_visitor_new_strict(QOBJECT(args));
71 QapiDeallocVisitor *qdv;
72 Visitor *v;
5aa05d3f 73''')
c17d9908 74
e98859a9 75 for memb in arg_type.members:
ee446028
MA
76 if memb.optional:
77 ret += mcgen('''
05372f70 78 bool has_%(c_name)s = false;
c17d9908 79''',
e98859a9 80 c_name=c_name(memb.name))
5710153e 81 ret += mcgen('''
05372f70 82 %(c_type)s %(c_name)s = %(c_null)s;
c17d9908 83''',
5710153e
MA
84 c_name=c_name(memb.name),
85 c_type=memb.type.c_type(),
86 c_null=memb.type.c_null())
f1538019
MA
87 ret += '\n'
88 else:
89 ret += mcgen('''
90
05372f70 91 (void)args;
f1538019 92''')
c17d9908 93
1f9a7a1a 94 return ret
c17d9908 95
e98859a9 96
f1538019 97def gen_marshal_input_visit(arg_type, dealloc=False):
e98859a9 98 ret = ''
8f91ad8a 99
e98859a9 100 if not arg_type:
c17d9908
MR
101 return ret
102
c17d9908
MR
103 if dealloc:
104 ret += mcgen('''
05372f70
EB
105 qmp_input_visitor_cleanup(qiv);
106 qdv = qapi_dealloc_visitor_new();
107 v = qapi_dealloc_get_visitor(qdv);
c17d9908
MR
108''')
109 else:
110 ret += mcgen('''
05372f70 111 v = qmp_input_get_visitor(qiv);
f9bee751 112''')
c17d9908 113
18bdbc3a 114 ret += gen_visit_fields(arg_type.members, skiperr=dealloc)
c17d9908
MR
115
116 if dealloc:
117 ret += mcgen('''
05372f70 118 qapi_dealloc_visitor_cleanup(qdv);
c17d9908 119''')
1f9a7a1a 120 return ret
c17d9908 121
e98859a9 122
56d92b00 123def gen_marshal_output(ret_type):
f1538019 124 return mcgen('''
ee446028 125
56d92b00 126static void qmp_marshal_output_%(c_name)s(%(c_type)s ret_in, QObject **ret_out, Error **errp)
c17d9908 127{
2a0f50e8 128 Error *err = NULL;
f8b7f1a8
EB
129 QmpOutputVisitor *qov = qmp_output_visitor_new();
130 QapiDeallocVisitor *qdv;
c17d9908
MR
131 Visitor *v;
132
f8b7f1a8 133 v = qmp_output_get_visitor(qov);
2a0f50e8
EB
134 visit_type_%(c_name)s(v, &ret_in, "unused", &err);
135 if (err) {
297a3646 136 goto out;
c17d9908 137 }
f8b7f1a8 138 *ret_out = qmp_output_get_qobject(qov);
297a3646
MA
139
140out:
2a0f50e8 141 error_propagate(errp, err);
f8b7f1a8
EB
142 qmp_output_visitor_cleanup(qov);
143 qdv = qapi_dealloc_visitor_new();
144 v = qapi_dealloc_get_visitor(qdv);
e98859a9 145 visit_type_%(c_name)s(v, &ret_in, "unused", NULL);
f8b7f1a8 146 qapi_dealloc_visitor_cleanup(qdv);
c17d9908
MR
147}
148''',
56d92b00 149 c_type=ret_type.c_type(), c_name=ret_type.c_name())
c17d9908 150
e98859a9 151
f1538019 152def gen_marshal_proto(name):
7fad30f0 153 ret = 'void qmp_marshal_%s(QDict *args, QObject **ret, Error **errp)' % c_name(name)
485febc6 154 if not middle_mode:
e98859a9 155 ret = 'static ' + ret
485febc6 156 return ret
776574d6 157
e98859a9 158
f1538019
MA
159def gen_marshal_decl(name):
160 return mcgen('''
161%(proto)s;
162''',
163 proto=gen_marshal_proto(name))
164
776574d6 165
f1538019 166def gen_marshal(name, arg_type, ret_type):
c17d9908 167 ret = mcgen('''
ee446028 168
f1538019 169%(proto)s
c17d9908 170{
c17d9908 171''',
f1538019 172 proto=gen_marshal_proto(name))
c17d9908 173
f1538019
MA
174 ret += gen_marshal_vars(arg_type, ret_type)
175 ret += gen_marshal_input_visit(arg_type)
e98859a9 176 ret += gen_call(name, arg_type, ret_type)
1f9a7a1a 177
e98859a9 178 if re.search('^ *goto out;', ret, re.MULTILINE):
297a3646 179 ret += mcgen('''
c17d9908
MR
180
181out:
182''')
183 ret += mcgen('''
2a0f50e8 184 error_propagate(errp, err);
1f9a7a1a 185''')
f1538019 186 ret += gen_marshal_input_visit(arg_type, dealloc=True)
1f9a7a1a 187 ret += mcgen('''
485febc6 188}
1f9a7a1a 189''')
c17d9908
MR
190 return ret
191
e98859a9 192
ee446028 193def gen_register_command(name, success_response):
ee446028
MA
194 options = 'QCO_NO_OPTIONS'
195 if not success_response:
196 options = 'QCO_NO_SUCCESS_RESP'
d34b867d 197
ee446028 198 ret = mcgen('''
05372f70 199 qmp_register_command("%(name)s", qmp_marshal_%(c_name)s, %(opts)s);
c17d9908 200''',
e98859a9
MA
201 name=name, c_name=c_name(name),
202 opts=options)
ee446028
MA
203 return ret
204
e98859a9 205
ee446028 206def gen_registry(registry):
c17d9908 207 ret = mcgen('''
ee446028 208
c17d9908
MR
209static void qmp_init_marshal(void)
210{
1f9a7a1a
MA
211''')
212 ret += registry
213 ret += mcgen('''
c17d9908
MR
214}
215
216qapi_init(qmp_init_marshal);
1f9a7a1a 217''')
c17d9908
MR
218 return ret
219
ee446028
MA
220
221class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
222 def __init__(self):
223 self.decl = None
224 self.defn = None
225 self._regy = None
56d92b00 226 self._visited_ret_types = None
ee446028
MA
227
228 def visit_begin(self, schema):
229 self.decl = ''
230 self.defn = ''
231 self._regy = ''
56d92b00 232 self._visited_ret_types = set()
ee446028
MA
233
234 def visit_end(self):
235 if not middle_mode:
236 self.defn += gen_registry(self._regy)
237 self._regy = None
56d92b00 238 self._visited_ret_types = None
ee446028
MA
239
240 def visit_command(self, name, info, arg_type, ret_type,
241 gen, success_response):
242 if not gen:
243 return
e98859a9 244 self.decl += gen_command_decl(name, arg_type, ret_type)
56d92b00
MA
245 if ret_type and ret_type not in self._visited_ret_types:
246 self._visited_ret_types.add(ret_type)
247 self.defn += gen_marshal_output(ret_type)
ee446028 248 if middle_mode:
f1538019
MA
249 self.decl += gen_marshal_decl(name)
250 self.defn += gen_marshal(name, arg_type, ret_type)
ee446028
MA
251 if not middle_mode:
252 self._regy += gen_register_command(name, success_response)
253
254
776574d6 255middle_mode = False
c17d9908 256
2114f5a9
MA
257(input_file, output_dir, do_c, do_h, prefix, opts) = \
258 parse_command_line("m", ["middle"])
8d3bc517 259
c17d9908 260for o, a in opts:
2114f5a9 261 if o in ("-m", "--middle"):
776574d6 262 middle_mode = True
c17d9908 263
12f8e1b9
MA
264c_comment = '''
265/*
266 * schema-defined QMP->QAPI command dispatch
267 *
268 * Copyright IBM, Corp. 2011
269 *
270 * Authors:
271 * Anthony Liguori <aliguori@us.ibm.com>
272 *
273 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
274 * See the COPYING.LIB file in the top-level directory.
275 *
276 */
277'''
278h_comment = '''
279/*
280 * schema-defined QAPI function prototypes
281 *
282 * Copyright IBM, Corp. 2011
283 *
284 * Authors:
285 * Anthony Liguori <aliguori@us.ibm.com>
286 *
287 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
288 * See the COPYING.LIB file in the top-level directory.
289 *
290 */
291'''
292
293(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
294 'qmp-marshal.c', 'qmp-commands.h',
295 c_comment, h_comment)
296
4180978c
MA
297fdef.write(mcgen('''
298#include "qemu-common.h"
299#include "qemu/module.h"
4180978c
MA
300#include "qapi/qmp/types.h"
301#include "qapi/qmp/dispatch.h"
302#include "qapi/visitor.h"
303#include "qapi/qmp-output-visitor.h"
304#include "qapi/qmp-input-visitor.h"
305#include "qapi/dealloc-visitor.h"
306#include "%(prefix)sqapi-types.h"
307#include "%(prefix)sqapi-visit.h"
308#include "%(prefix)sqmp-commands.h"
309
310''',
e98859a9 311 prefix=prefix))
4180978c
MA
312
313fdecl.write(mcgen('''
314#include "%(prefix)sqapi-types.h"
315#include "qapi/qmp/qdict.h"
316#include "qapi/error.h"
317
318''',
ee446028 319 prefix=prefix))
72aaa73a 320
ee446028
MA
321schema = QAPISchema(input_file)
322gen = QAPISchemaGenCommandVisitor()
323schema.visit(gen)
324fdef.write(gen.defn)
325fdecl.write(gen.decl)
c17d9908 326
12f8e1b9 327close_output(fdef, fdecl)