qapi: add code generation support for middle mode
To get the ball rolling merging QAPI, this patch introduces a "middle mode" to the code generator. In middle mode, the code generator generates marshalling functions that are compatible with the current QMP server. We absolutely need to replace the current QMP server in order to support proper asynchronous commands but using a middle mode provides a middle-ground that lets us start converting commands in tree. Note that all of the commands have been converted already in my glib branch. Middle mode only exists until we finish merging them from my branch into the main tree. Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
This commit is contained in:
parent
2a82d936a2
commit
776574d641
@ -17,4 +17,7 @@
|
|||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
||||||
|
/* FIXME this is temporary until we remove middle mode */
|
||||||
|
#include "monitor.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -167,9 +167,10 @@ qmp_input_visitor_cleanup(mi);
|
|||||||
pop_indent()
|
pop_indent()
|
||||||
return ret.rstrip()
|
return ret.rstrip()
|
||||||
|
|
||||||
def gen_marshal_output(name, args, ret_type):
|
def gen_marshal_output(name, args, ret_type, middle_mode):
|
||||||
if not ret_type:
|
if not ret_type:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
ret = mcgen('''
|
ret = mcgen('''
|
||||||
static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_out, Error **errp)
|
static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_out, Error **errp)
|
||||||
{
|
{
|
||||||
@ -188,16 +189,34 @@ static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_o
|
|||||||
qapi_dealloc_visitor_cleanup(md);
|
qapi_dealloc_visitor_cleanup(md);
|
||||||
}
|
}
|
||||||
''',
|
''',
|
||||||
c_ret_type=c_type(ret_type), c_name=c_var(name), ret_type=ret_type)
|
c_ret_type=c_type(ret_type), c_name=c_var(name),
|
||||||
|
ret_type=ret_type)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def gen_marshal_input(name, args, ret_type):
|
def gen_marshal_input_decl(name, args, ret_type, middle_mode):
|
||||||
|
if middle_mode:
|
||||||
|
return 'int qmp_marshal_input_%s(Monitor *mon, const QDict *qdict, QObject **ret)' % c_var(name)
|
||||||
|
else:
|
||||||
|
return 'static void qmp_marshal_input_%s(QDict *args, QObject **ret, Error **errp)' % c_var(name)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def gen_marshal_input(name, args, ret_type, middle_mode):
|
||||||
|
hdr = gen_marshal_input_decl(name, args, ret_type, middle_mode)
|
||||||
|
|
||||||
ret = mcgen('''
|
ret = mcgen('''
|
||||||
static void qmp_marshal_input_%(c_name)s(QDict *args, QObject **ret, Error **errp)
|
%(header)s
|
||||||
{
|
{
|
||||||
''',
|
''',
|
||||||
c_name=c_var(name))
|
header=hdr)
|
||||||
|
|
||||||
|
if middle_mode:
|
||||||
|
ret += mcgen('''
|
||||||
|
Error *local_err = NULL;
|
||||||
|
Error **errp = &local_err;
|
||||||
|
QDict *args = (QDict *)qdict;
|
||||||
|
''')
|
||||||
|
|
||||||
if ret_type:
|
if ret_type:
|
||||||
if c_type(ret_type).endswith("*"):
|
if c_type(ret_type).endswith("*"):
|
||||||
@ -220,6 +239,10 @@ static void qmp_marshal_input_%(c_name)s(QDict *args, QObject **ret, Error **err
|
|||||||
visitor_input_containers_decl=gen_visitor_input_containers_decl(args),
|
visitor_input_containers_decl=gen_visitor_input_containers_decl(args),
|
||||||
visitor_input_vars_decl=gen_visitor_input_vars_decl(args),
|
visitor_input_vars_decl=gen_visitor_input_vars_decl(args),
|
||||||
visitor_input_block=gen_visitor_input_block(args, "QOBJECT(args)"))
|
visitor_input_block=gen_visitor_input_block(args, "QOBJECT(args)"))
|
||||||
|
else:
|
||||||
|
ret += mcgen('''
|
||||||
|
(void)args;
|
||||||
|
''')
|
||||||
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
if (error_is_set(errp)) {
|
if (error_is_set(errp)) {
|
||||||
@ -234,10 +257,29 @@ out:
|
|||||||
''')
|
''')
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
%(visitor_input_block_cleanup)s
|
%(visitor_input_block_cleanup)s
|
||||||
return;
|
|
||||||
}
|
|
||||||
''',
|
''',
|
||||||
visitor_input_block_cleanup=gen_visitor_input_block(args, None, dealloc=True))
|
visitor_input_block_cleanup=gen_visitor_input_block(args, None,
|
||||||
|
dealloc=True))
|
||||||
|
|
||||||
|
if middle_mode:
|
||||||
|
ret += mcgen('''
|
||||||
|
|
||||||
|
if (local_err) {
|
||||||
|
qerror_report_err(local_err);
|
||||||
|
error_free(local_err);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
''')
|
||||||
|
else:
|
||||||
|
ret += mcgen('''
|
||||||
|
return;
|
||||||
|
''')
|
||||||
|
|
||||||
|
ret += mcgen('''
|
||||||
|
}
|
||||||
|
''')
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def gen_registry(commands):
|
def gen_registry(commands):
|
||||||
@ -284,7 +326,7 @@ def gen_command_decl_prologue(header, guard, prefix=""):
|
|||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
||||||
''',
|
''',
|
||||||
header=basename(h_file), guard=guardname(h_file), prefix=prefix)
|
header=basename(header), guard=guardname(header), prefix=prefix)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def gen_command_def_prologue(prefix="", proxy=False):
|
def gen_command_def_prologue(prefix="", proxy=False):
|
||||||
@ -317,11 +359,11 @@ def gen_command_def_prologue(prefix="", proxy=False):
|
|||||||
prefix=prefix)
|
prefix=prefix)
|
||||||
if not proxy:
|
if not proxy:
|
||||||
ret += '#include "%sqmp-commands.h"' % prefix
|
ret += '#include "%sqmp-commands.h"' % prefix
|
||||||
return ret + "\n"
|
return ret + "\n\n"
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
opts, args = getopt.gnu_getopt(sys.argv[1:], "p:o:", ["prefix=", "output-dir=", "type="])
|
opts, args = getopt.gnu_getopt(sys.argv[1:], "p:o:m", ["prefix=", "output-dir=", "type=", "middle"])
|
||||||
except getopt.GetoptError, err:
|
except getopt.GetoptError, err:
|
||||||
print str(err)
|
print str(err)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@ -331,6 +373,7 @@ prefix = ""
|
|||||||
dispatch_type = "sync"
|
dispatch_type = "sync"
|
||||||
c_file = 'qmp-marshal.c'
|
c_file = 'qmp-marshal.c'
|
||||||
h_file = 'qmp-commands.h'
|
h_file = 'qmp-commands.h'
|
||||||
|
middle_mode = False
|
||||||
|
|
||||||
for o, a in opts:
|
for o, a in opts:
|
||||||
if o in ("-p", "--prefix"):
|
if o in ("-p", "--prefix"):
|
||||||
@ -339,6 +382,8 @@ for o, a in opts:
|
|||||||
output_dir = a + "/"
|
output_dir = a + "/"
|
||||||
elif o in ("-t", "--type"):
|
elif o in ("-t", "--type"):
|
||||||
dispatch_type = a
|
dispatch_type = a
|
||||||
|
elif o in ("-m", "--middle"):
|
||||||
|
middle_mode = True
|
||||||
|
|
||||||
c_file = output_dir + prefix + c_file
|
c_file = output_dir + prefix + c_file
|
||||||
h_file = output_dir + prefix + h_file
|
h_file = output_dir + prefix + h_file
|
||||||
@ -370,14 +415,20 @@ if dispatch_type == "sync":
|
|||||||
ret = generate_command_decl(cmd['command'], arglist, ret_type) + "\n"
|
ret = generate_command_decl(cmd['command'], arglist, ret_type) + "\n"
|
||||||
fdecl.write(ret)
|
fdecl.write(ret)
|
||||||
if ret_type:
|
if ret_type:
|
||||||
ret = gen_marshal_output(cmd['command'], arglist, ret_type) + "\n"
|
ret = gen_marshal_output(cmd['command'], arglist, ret_type, middle_mode) + "\n"
|
||||||
fdef.write(ret)
|
fdef.write(ret)
|
||||||
ret = gen_marshal_input(cmd['command'], arglist, ret_type) + "\n"
|
|
||||||
|
if middle_mode:
|
||||||
|
fdecl.write('%s;\n' % gen_marshal_input_decl(cmd['command'], arglist, ret_type, middle_mode))
|
||||||
|
|
||||||
|
ret = gen_marshal_input(cmd['command'], arglist, ret_type, middle_mode) + "\n"
|
||||||
fdef.write(ret)
|
fdef.write(ret)
|
||||||
|
|
||||||
fdecl.write("\n#endif\n");
|
fdecl.write("\n#endif\n");
|
||||||
ret = gen_registry(commands)
|
|
||||||
fdef.write(ret)
|
if not middle_mode:
|
||||||
|
ret = gen_registry(commands)
|
||||||
|
fdef.write(ret)
|
||||||
|
|
||||||
fdef.flush()
|
fdef.flush()
|
||||||
fdef.close()
|
fdef.close()
|
||||||
|
@ -268,3 +268,6 @@ fdecl.write('''
|
|||||||
|
|
||||||
fdecl.flush()
|
fdecl.flush()
|
||||||
fdecl.close()
|
fdecl.close()
|
||||||
|
|
||||||
|
fdef.flush()
|
||||||
|
fdef.close()
|
||||||
|
@ -200,4 +200,6 @@ def basename(filename):
|
|||||||
return filename.split("/")[-1]
|
return filename.split("/")[-1]
|
||||||
|
|
||||||
def guardname(filename):
|
def guardname(filename):
|
||||||
return filename.replace("/", "_").replace("-", "_").split(".")[0].upper()
|
if filename.startswith('./'):
|
||||||
|
filename = filename[2:]
|
||||||
|
return filename.replace("/", "_").replace("-", "_").split(".")[0].upper() + '_H'
|
||||||
|
Loading…
Reference in New Issue
Block a user