2
# QAPI command marshaller generator
4
# Copyright IBM, Corp. 2011
7
# Anthony Liguori <aliguori@us.ibm.com>
8
# Michael Roth <mdroth@linux.vnet.ibm.com>
10
# This work is licensed under the terms of the GNU GPLv2.
11
# See the COPYING.LIB file in the top-level directory.
13
from ordereddict import OrderedDict
20
def generate_decl_enum(name, members, genlist=True):
23
void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **errp);
27
def generate_command_decl(name, args, ret_type):
29
for argname, argtype, optional, structured in parse_args(args):
30
argtype = c_type(argtype)
31
if argtype == "char *":
32
argtype = "const char *"
34
arglist += "bool has_%s, " % c_var(argname)
35
arglist += "%s %s, " % (argtype, c_var(argname))
37
%(ret_type)s qmp_%(name)s(%(args)sError **errp);
39
ret_type=c_type(ret_type), name=c_var(name), args=arglist).strip()
41
def gen_sync_call(name, args, ret_type, indent=0):
47
for argname, argtype, optional, structured in parse_args(args):
49
arglist += "has_%s, " % c_var(argname)
50
arglist += "%s, " % (c_var(argname))
53
%(retval)sqmp_%(name)s(%(args)serrp);
56
name=c_var(name), args=arglist, retval=retval).rstrip()
58
ret += "\n" + mcgen(''''
59
%(marshal_output_call)s
61
marshal_output_call=gen_marshal_output_call(name, ret_type)).rstrip()
66
def gen_marshal_output_call(name, ret_type):
69
return "qmp_marshal_output_%s(retval, ret, errp);" % c_var(name)
71
def gen_visitor_output_containers_decl(ret_type):
77
QapiDeallocVisitor *md;
84
def gen_visitor_input_containers_decl(args):
91
QapiDeallocVisitor *md;
98
def gen_visitor_input_vars_decl(args):
101
for argname, argtype, optional, structured in parse_args(args):
104
bool has_%(argname)s = false;
106
argname=c_var(argname))
107
if c_type(argtype).endswith("*"):
109
%(argtype)s %(argname)s = NULL;
111
argname=c_var(argname), argtype=c_type(argtype))
114
%(argtype)s %(argname)s;
116
argname=c_var(argname), argtype=c_type(argtype))
121
def gen_visitor_input_block(args, obj, dealloc=False):
130
md = qapi_dealloc_visitor_new();
131
v = qapi_dealloc_get_visitor(md);
135
mi = qmp_input_visitor_new(%(obj)s);
136
v = qmp_input_get_visitor(mi);
140
for argname, argtype, optional, structured in parse_args(args):
143
visit_start_optional(v, &has_%(c_name)s, "%(name)s", errp);
144
if (has_%(c_name)s) {
146
c_name=c_var(argname), name=argname)
149
visit_type_%(argtype)s(v, &%(c_name)s, "%(name)s", errp);
151
c_name=c_var(argname), name=argname, argtype=argtype)
156
visit_end_optional(v, errp);
161
qapi_dealloc_visitor_cleanup(md);
165
qmp_input_visitor_cleanup(mi);
170
def gen_marshal_output(name, args, ret_type):
174
static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_out, Error **errp)
176
QapiDeallocVisitor *md = qapi_dealloc_visitor_new();
177
QmpOutputVisitor *mo = qmp_output_visitor_new();
180
v = qmp_output_get_visitor(mo);
181
visit_type_%(ret_type)s(v, &ret_in, "unused", errp);
182
if (!error_is_set(errp)) {
183
*ret_out = qmp_output_get_qobject(mo);
185
qmp_output_visitor_cleanup(mo);
186
v = qapi_dealloc_get_visitor(md);
187
visit_type_%(ret_type)s(v, &ret_in, "unused", errp);
188
qapi_dealloc_visitor_cleanup(md);
191
c_ret_type=c_type(ret_type), c_name=c_var(name), ret_type=ret_type)
195
def gen_marshal_input(name, args, ret_type):
197
static void qmp_marshal_input_%(c_name)s(QDict *args, QObject **ret, Error **errp)
203
if c_type(ret_type).endswith("*"):
204
retval = " %s retval = NULL;" % c_type(ret_type)
206
retval = " %s retval;" % c_type(ret_type)
214
%(visitor_input_containers_decl)s
215
%(visitor_input_vars_decl)s
217
%(visitor_input_block)s
220
visitor_input_containers_decl=gen_visitor_input_containers_decl(args),
221
visitor_input_vars_decl=gen_visitor_input_vars_decl(args),
222
visitor_input_block=gen_visitor_input_block(args, "QOBJECT(args)"))
225
if (error_is_set(errp)) {
230
sync_call=gen_sync_call(name, args, ret_type, indent=4))
236
%(visitor_input_block_cleanup)s
240
visitor_input_block_cleanup=gen_visitor_input_block(args, None, dealloc=True))
243
def gen_registry(commands):
247
registry += mcgen('''
248
qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s);
250
name=cmd['command'], c_name=c_var(cmd['command']))
253
static void qmp_init_marshal(void)
258
qapi_init(qmp_init_marshal);
260
registry=registry.rstrip())
263
def gen_command_decl_prologue(header, guard, prefix=""):
265
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
268
* schema-defined QAPI function prototypes
270
* Copyright IBM, Corp. 2011
273
* Anthony Liguori <aliguori@us.ibm.com>
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.
283
#include "%(prefix)sqapi-types.h"
287
header=basename(h_file), guard=guardname(h_file), prefix=prefix)
290
def gen_command_def_prologue(prefix="", proxy=False):
292
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
295
* schema-defined QMP->QAPI command dispatch
297
* Copyright IBM, Corp. 2011
300
* Anthony Liguori <aliguori@us.ibm.com>
302
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
303
* See the COPYING.LIB file in the top-level directory.
307
#include "qemu-objects.h"
308
#include "qapi/qmp-core.h"
309
#include "qapi/qapi-visit-core.h"
310
#include "qapi/qmp-output-visitor.h"
311
#include "qapi/qmp-input-visitor.h"
312
#include "qapi/qapi-dealloc-visitor.h"
313
#include "%(prefix)sqapi-types.h"
314
#include "%(prefix)sqapi-visit.h"
319
ret += '#include "%sqmp-commands.h"' % prefix
324
opts, args = getopt.gnu_getopt(sys.argv[1:], "p:o:", ["prefix=", "output-dir=", "type="])
325
except getopt.GetoptError, err:
331
dispatch_type = "sync"
332
c_file = 'qmp-marshal.c'
333
h_file = 'qmp-commands.h'
336
if o in ("-p", "--prefix"):
338
elif o in ("-o", "--output-dir"):
340
elif o in ("-t", "--type"):
343
c_file = output_dir + prefix + c_file
344
h_file = output_dir + prefix + h_file
347
os.makedirs(output_dir)
349
if e.errno != errno.EEXIST:
352
exprs = parse_schema(sys.stdin)
353
commands = filter(lambda expr: expr.has_key('command'), exprs)
355
if dispatch_type == "sync":
356
fdecl = open(h_file, 'w')
357
fdef = open(c_file, 'w')
358
ret = gen_command_decl_prologue(header=basename(h_file), guard=guardname(h_file), prefix=prefix)
360
ret = gen_command_def_prologue(prefix=prefix)
366
if cmd.has_key('data'):
367
arglist = cmd['data']
368
if cmd.has_key('returns'):
369
ret_type = cmd['returns']
370
ret = generate_command_decl(cmd['command'], arglist, ret_type) + "\n"
373
ret = gen_marshal_output(cmd['command'], arglist, ret_type) + "\n"
375
ret = gen_marshal_input(cmd['command'], arglist, ret_type) + "\n"
378
fdecl.write("\n#endif");
379
ret = gen_registry(commands)