]> git.proxmox.com Git - mirror_qemu.git/blame - scripts/qapi-commands.py
pc: Add a comment explaining why pc_compat_2_4() doesn't exist
[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
8102307f
MA
28def gen_err_check(err):
29 if not err:
30 return ''
31 return mcgen('''
32if (%(err)s) {
297a3646
MA
33 goto out;
34}
8102307f
MA
35''',
36 err=err)
297a3646 37
e98859a9
MA
38
39def gen_call(name, arg_type, ret_type):
40 ret = ''
41
42 argstr = ''
43 if arg_type:
44 for memb in arg_type.members:
ee446028 45 if memb.optional:
e98859a9
MA
46 argstr += 'has_%s, ' % c_name(memb.name)
47 argstr += '%s, ' % c_name(memb.name)
48
49 lhs = ''
50 if ret_type:
51 lhs = 'retval = '
52
5aa05d3f 53 push_indent()
c17d9908 54 ret = mcgen('''
f1538019 55
e98859a9 56%(lhs)sqmp_%(c_name)s(%(args)s&local_err);
c17d9908 57''',
e98859a9 58 c_name=c_name(name), args=argstr, lhs=lhs)
c17d9908 59 if ret_type:
1f9a7a1a 60 ret += gen_err_check('local_err')
e02bca28
MA
61 ret += mcgen('''
62
63qmp_marshal_output_%(c_name)s(retval, ret, &local_err);
c17d9908 64''',
56d92b00 65 c_name=ret_type.c_name())
5aa05d3f 66 pop_indent()
1f9a7a1a 67 return ret
c17d9908 68
e98859a9 69
f1538019
MA
70def gen_marshal_vars(arg_type, ret_type):
71 ret = mcgen('''
72 Error *local_err = NULL;
73''')
c17d9908
MR
74
75 push_indent()
f1538019
MA
76
77 if ret_type:
78 ret += mcgen('''
79%(c_type)s retval;
80''',
81 c_type=ret_type.c_type())
82
e98859a9 83 if arg_type:
c17d9908 84 ret += mcgen('''
5aa05d3f 85QmpInputVisitor *mi = qmp_input_visitor_new_strict(QOBJECT(args));
c17d9908
MR
86QapiDeallocVisitor *md;
87Visitor *v;
5aa05d3f 88''')
c17d9908 89
e98859a9 90 for memb in arg_type.members:
ee446028
MA
91 if memb.optional:
92 ret += mcgen('''
e98859a9 93bool has_%(c_name)s = false;
c17d9908 94''',
e98859a9 95 c_name=c_name(memb.name))
5710153e
MA
96 ret += mcgen('''
97%(c_type)s %(c_name)s = %(c_null)s;
c17d9908 98''',
5710153e
MA
99 c_name=c_name(memb.name),
100 c_type=memb.type.c_type(),
101 c_null=memb.type.c_null())
f1538019
MA
102 ret += '\n'
103 else:
104 ret += mcgen('''
105
106(void)args;
107''')
c17d9908
MR
108
109 pop_indent()
1f9a7a1a 110 return ret
c17d9908 111
e98859a9 112
f1538019 113def gen_marshal_input_visit(arg_type, dealloc=False):
e98859a9 114 ret = ''
8f91ad8a 115
e98859a9 116 if not arg_type:
c17d9908
MR
117 return ret
118
119 push_indent()
120
121 if dealloc:
8f91ad8a 122 errparg = 'NULL'
e98859a9 123 errarg = None
c17d9908 124 ret += mcgen('''
f9bee751 125qmp_input_visitor_cleanup(mi);
c17d9908
MR
126md = qapi_dealloc_visitor_new();
127v = qapi_dealloc_get_visitor(md);
128''')
129 else:
f1538019
MA
130 errparg = '&local_err'
131 errarg = 'local_err'
c17d9908 132 ret += mcgen('''
c17d9908 133v = qmp_input_get_visitor(mi);
f9bee751 134''')
c17d9908 135
e98859a9 136 for memb in arg_type.members:
ee446028 137 if memb.optional:
c17d9908 138 ret += mcgen('''
e2cd0f4f 139visit_optional(v, &has_%(c_name)s, "%(name)s", %(errp)s);
c17d9908 140''',
ee446028
MA
141 c_name=c_name(memb.name), name=memb.name,
142 errp=errparg)
297a3646
MA
143 ret += gen_err_check(errarg)
144 ret += mcgen('''
145if (has_%(c_name)s) {
146''',
ee446028 147 c_name=c_name(memb.name))
c17d9908
MR
148 push_indent()
149 ret += mcgen('''
e98859a9 150visit_type_%(c_type)s(v, &%(c_name)s, "%(name)s", %(errp)s);
c17d9908 151''',
ee446028 152 c_name=c_name(memb.name), name=memb.name,
e98859a9 153 c_type=memb.type.c_name(), errp=errparg)
297a3646 154 ret += gen_err_check(errarg)
ee446028 155 if memb.optional:
c17d9908
MR
156 pop_indent()
157 ret += mcgen('''
158}
e2cd0f4f 159''')
c17d9908
MR
160
161 if dealloc:
162 ret += mcgen('''
163qapi_dealloc_visitor_cleanup(md);
c17d9908
MR
164''')
165 pop_indent()
1f9a7a1a 166 return ret
c17d9908 167
e98859a9 168
56d92b00 169def gen_marshal_output(ret_type):
f1538019 170 return mcgen('''
ee446028 171
56d92b00 172static void qmp_marshal_output_%(c_name)s(%(c_type)s ret_in, QObject **ret_out, Error **errp)
c17d9908 173{
297a3646 174 Error *local_err = NULL;
c17d9908 175 QmpOutputVisitor *mo = qmp_output_visitor_new();
f9bee751 176 QapiDeallocVisitor *md;
c17d9908
MR
177 Visitor *v;
178
179 v = qmp_output_get_visitor(mo);
e98859a9 180 visit_type_%(c_name)s(v, &ret_in, "unused", &local_err);
297a3646
MA
181 if (local_err) {
182 goto out;
c17d9908 183 }
297a3646
MA
184 *ret_out = qmp_output_get_qobject(mo);
185
186out:
187 error_propagate(errp, local_err);
c17d9908 188 qmp_output_visitor_cleanup(mo);
f9bee751 189 md = qapi_dealloc_visitor_new();
c17d9908 190 v = qapi_dealloc_get_visitor(md);
e98859a9 191 visit_type_%(c_name)s(v, &ret_in, "unused", NULL);
c17d9908
MR
192 qapi_dealloc_visitor_cleanup(md);
193}
194''',
56d92b00 195 c_type=ret_type.c_type(), c_name=ret_type.c_name())
c17d9908 196
e98859a9 197
f1538019 198def gen_marshal_proto(name):
7fad30f0 199 ret = 'void qmp_marshal_%s(QDict *args, QObject **ret, Error **errp)' % c_name(name)
485febc6 200 if not middle_mode:
e98859a9 201 ret = 'static ' + ret
485febc6 202 return ret
776574d6 203
e98859a9 204
f1538019
MA
205def gen_marshal_decl(name):
206 return mcgen('''
207%(proto)s;
208''',
209 proto=gen_marshal_proto(name))
210
776574d6 211
f1538019 212def gen_marshal(name, arg_type, ret_type):
c17d9908 213 ret = mcgen('''
ee446028 214
f1538019 215%(proto)s
c17d9908 216{
c17d9908 217''',
f1538019 218 proto=gen_marshal_proto(name))
c17d9908 219
f1538019
MA
220 ret += gen_marshal_vars(arg_type, ret_type)
221 ret += gen_marshal_input_visit(arg_type)
e98859a9 222 ret += gen_call(name, arg_type, ret_type)
1f9a7a1a 223
e98859a9 224 if re.search('^ *goto out;', ret, re.MULTILINE):
297a3646 225 ret += mcgen('''
c17d9908
MR
226
227out:
228''')
229 ret += mcgen('''
485febc6 230 error_propagate(errp, local_err);
1f9a7a1a 231''')
f1538019 232 ret += gen_marshal_input_visit(arg_type, dealloc=True)
1f9a7a1a 233 ret += mcgen('''
485febc6 234}
1f9a7a1a 235''')
c17d9908
MR
236 return ret
237
e98859a9 238
ee446028 239def gen_register_command(name, success_response):
c17d9908 240 push_indent()
ee446028
MA
241 options = 'QCO_NO_OPTIONS'
242 if not success_response:
243 options = 'QCO_NO_SUCCESS_RESP'
d34b867d 244
ee446028 245 ret = mcgen('''
7fad30f0 246qmp_register_command("%(name)s", qmp_marshal_%(c_name)s, %(opts)s);
c17d9908 247''',
e98859a9
MA
248 name=name, c_name=c_name(name),
249 opts=options)
c17d9908 250 pop_indent()
ee446028
MA
251 return ret
252
e98859a9 253
ee446028 254def gen_registry(registry):
c17d9908 255 ret = mcgen('''
ee446028 256
c17d9908
MR
257static void qmp_init_marshal(void)
258{
1f9a7a1a
MA
259''')
260 ret += registry
261 ret += mcgen('''
c17d9908
MR
262}
263
264qapi_init(qmp_init_marshal);
1f9a7a1a 265''')
c17d9908
MR
266 return ret
267
ee446028
MA
268
269class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
270 def __init__(self):
271 self.decl = None
272 self.defn = None
273 self._regy = None
56d92b00 274 self._visited_ret_types = None
ee446028
MA
275
276 def visit_begin(self, schema):
277 self.decl = ''
278 self.defn = ''
279 self._regy = ''
56d92b00 280 self._visited_ret_types = set()
ee446028
MA
281
282 def visit_end(self):
283 if not middle_mode:
284 self.defn += gen_registry(self._regy)
285 self._regy = None
56d92b00 286 self._visited_ret_types = None
ee446028
MA
287
288 def visit_command(self, name, info, arg_type, ret_type,
289 gen, success_response):
290 if not gen:
291 return
e98859a9 292 self.decl += gen_command_decl(name, arg_type, ret_type)
56d92b00
MA
293 if ret_type and ret_type not in self._visited_ret_types:
294 self._visited_ret_types.add(ret_type)
295 self.defn += gen_marshal_output(ret_type)
ee446028 296 if middle_mode:
f1538019
MA
297 self.decl += gen_marshal_decl(name)
298 self.defn += gen_marshal(name, arg_type, ret_type)
ee446028
MA
299 if not middle_mode:
300 self._regy += gen_register_command(name, success_response)
301
302
776574d6 303middle_mode = False
c17d9908 304
2114f5a9
MA
305(input_file, output_dir, do_c, do_h, prefix, opts) = \
306 parse_command_line("m", ["middle"])
8d3bc517 307
c17d9908 308for o, a in opts:
2114f5a9 309 if o in ("-m", "--middle"):
776574d6 310 middle_mode = True
c17d9908 311
12f8e1b9
MA
312c_comment = '''
313/*
314 * schema-defined QMP->QAPI command dispatch
315 *
316 * Copyright IBM, Corp. 2011
317 *
318 * Authors:
319 * Anthony Liguori <aliguori@us.ibm.com>
320 *
321 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
322 * See the COPYING.LIB file in the top-level directory.
323 *
324 */
325'''
326h_comment = '''
327/*
328 * schema-defined QAPI function prototypes
329 *
330 * Copyright IBM, Corp. 2011
331 *
332 * Authors:
333 * Anthony Liguori <aliguori@us.ibm.com>
334 *
335 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
336 * See the COPYING.LIB file in the top-level directory.
337 *
338 */
339'''
340
341(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
342 'qmp-marshal.c', 'qmp-commands.h',
343 c_comment, h_comment)
344
4180978c
MA
345fdef.write(mcgen('''
346#include "qemu-common.h"
347#include "qemu/module.h"
4180978c
MA
348#include "qapi/qmp/types.h"
349#include "qapi/qmp/dispatch.h"
350#include "qapi/visitor.h"
351#include "qapi/qmp-output-visitor.h"
352#include "qapi/qmp-input-visitor.h"
353#include "qapi/dealloc-visitor.h"
354#include "%(prefix)sqapi-types.h"
355#include "%(prefix)sqapi-visit.h"
356#include "%(prefix)sqmp-commands.h"
357
358''',
e98859a9 359 prefix=prefix))
4180978c
MA
360
361fdecl.write(mcgen('''
362#include "%(prefix)sqapi-types.h"
363#include "qapi/qmp/qdict.h"
364#include "qapi/error.h"
365
366''',
ee446028 367 prefix=prefix))
72aaa73a 368
ee446028
MA
369schema = QAPISchema(input_file)
370gen = QAPISchemaGenCommandVisitor()
371schema.visit(gen)
372fdef.write(gen.defn)
373fdecl.write(gen.decl)
c17d9908 374
12f8e1b9 375close_output(fdef, fdecl)