]> git.proxmox.com Git - mirror_qemu.git/blame - scripts/qapi-commands.py
qcow2: insert assert into qcow2_get_specific_info()
[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
f9e6102b
EB
178 # 'goto out' produced by gen_marshal_input_visit->gen_visit_fields()
179 # for each arg_type member, and by gen_call() for ret_type
180 if (arg_type and arg_type.members) or ret_type:
297a3646 181 ret += mcgen('''
c17d9908
MR
182
183out:
184''')
185 ret += mcgen('''
2a0f50e8 186 error_propagate(errp, err);
1f9a7a1a 187''')
f1538019 188 ret += gen_marshal_input_visit(arg_type, dealloc=True)
1f9a7a1a 189 ret += mcgen('''
485febc6 190}
1f9a7a1a 191''')
c17d9908
MR
192 return ret
193
e98859a9 194
ee446028 195def gen_register_command(name, success_response):
ee446028
MA
196 options = 'QCO_NO_OPTIONS'
197 if not success_response:
198 options = 'QCO_NO_SUCCESS_RESP'
d34b867d 199
ee446028 200 ret = mcgen('''
05372f70 201 qmp_register_command("%(name)s", qmp_marshal_%(c_name)s, %(opts)s);
c17d9908 202''',
e98859a9
MA
203 name=name, c_name=c_name(name),
204 opts=options)
ee446028
MA
205 return ret
206
e98859a9 207
ee446028 208def gen_registry(registry):
c17d9908 209 ret = mcgen('''
ee446028 210
c17d9908
MR
211static void qmp_init_marshal(void)
212{
1f9a7a1a
MA
213''')
214 ret += registry
215 ret += mcgen('''
c17d9908
MR
216}
217
218qapi_init(qmp_init_marshal);
1f9a7a1a 219''')
c17d9908
MR
220 return ret
221
ee446028
MA
222
223class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
224 def __init__(self):
225 self.decl = None
226 self.defn = None
227 self._regy = None
56d92b00 228 self._visited_ret_types = None
ee446028
MA
229
230 def visit_begin(self, schema):
231 self.decl = ''
232 self.defn = ''
233 self._regy = ''
56d92b00 234 self._visited_ret_types = set()
ee446028
MA
235
236 def visit_end(self):
237 if not middle_mode:
238 self.defn += gen_registry(self._regy)
239 self._regy = None
56d92b00 240 self._visited_ret_types = None
ee446028
MA
241
242 def visit_command(self, name, info, arg_type, ret_type,
243 gen, success_response):
244 if not gen:
245 return
e98859a9 246 self.decl += gen_command_decl(name, arg_type, ret_type)
56d92b00
MA
247 if ret_type and ret_type not in self._visited_ret_types:
248 self._visited_ret_types.add(ret_type)
249 self.defn += gen_marshal_output(ret_type)
ee446028 250 if middle_mode:
f1538019
MA
251 self.decl += gen_marshal_decl(name)
252 self.defn += gen_marshal(name, arg_type, ret_type)
ee446028
MA
253 if not middle_mode:
254 self._regy += gen_register_command(name, success_response)
255
256
776574d6 257middle_mode = False
c17d9908 258
2114f5a9
MA
259(input_file, output_dir, do_c, do_h, prefix, opts) = \
260 parse_command_line("m", ["middle"])
8d3bc517 261
c17d9908 262for o, a in opts:
2114f5a9 263 if o in ("-m", "--middle"):
776574d6 264 middle_mode = True
c17d9908 265
12f8e1b9
MA
266c_comment = '''
267/*
268 * schema-defined QMP->QAPI command dispatch
269 *
270 * Copyright IBM, Corp. 2011
271 *
272 * Authors:
273 * Anthony Liguori <aliguori@us.ibm.com>
274 *
275 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
276 * See the COPYING.LIB file in the top-level directory.
277 *
278 */
279'''
280h_comment = '''
281/*
282 * schema-defined QAPI function prototypes
283 *
284 * Copyright IBM, Corp. 2011
285 *
286 * Authors:
287 * Anthony Liguori <aliguori@us.ibm.com>
288 *
289 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
290 * See the COPYING.LIB file in the top-level directory.
291 *
292 */
293'''
294
295(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
296 'qmp-marshal.c', 'qmp-commands.h',
297 c_comment, h_comment)
298
4180978c
MA
299fdef.write(mcgen('''
300#include "qemu-common.h"
301#include "qemu/module.h"
4180978c
MA
302#include "qapi/qmp/types.h"
303#include "qapi/qmp/dispatch.h"
304#include "qapi/visitor.h"
305#include "qapi/qmp-output-visitor.h"
306#include "qapi/qmp-input-visitor.h"
307#include "qapi/dealloc-visitor.h"
308#include "%(prefix)sqapi-types.h"
309#include "%(prefix)sqapi-visit.h"
310#include "%(prefix)sqmp-commands.h"
311
312''',
e98859a9 313 prefix=prefix))
4180978c
MA
314
315fdecl.write(mcgen('''
316#include "%(prefix)sqapi-types.h"
317#include "qapi/qmp/qdict.h"
318#include "qapi/error.h"
319
320''',
ee446028 321 prefix=prefix))
72aaa73a 322
ee446028
MA
323schema = QAPISchema(input_file)
324gen = QAPISchemaGenCommandVisitor()
325schema.visit(gen)
326fdef.write(gen.defn)
327fdecl.write(gen.decl)
c17d9908 328
12f8e1b9 329close_output(fdef, fdecl)