Commit 776574d6 authored by Anthony Liguori's avatar Anthony Liguori Committed by Luiz Capitulino
Browse files

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: default avatarAnthony Liguori <aliguori@us.ibm.com>
Signed-off-by: default avatarLuiz Capitulino <lcapitulino@redhat.com>
parent 2a82d936
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -17,4 +17,7 @@
#include "qemu-common.h"
#include "error.h"

/* FIXME this is temporary until we remove middle mode */
#include "monitor.h"

#endif
+65 −14
Original line number Diff line number Diff line
@@ -167,9 +167,10 @@ qmp_input_visitor_cleanup(mi);
    pop_indent()
    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:
        return ""

    ret = mcgen('''
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);
}
''',
            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

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('''
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 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_vars_decl=gen_visitor_input_vars_decl(args),
                     visitor_input_block=gen_visitor_input_block(args, "QOBJECT(args)"))
    else:
        ret += mcgen('''
    (void)args;
''')

    ret += mcgen('''
    if (error_is_set(errp)) {
@@ -234,10 +257,29 @@ out:
''')
    ret += mcgen('''
%(visitor_input_block_cleanup)s
''',
                 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('''
}
''',
                 visitor_input_block_cleanup=gen_visitor_input_block(args, None, dealloc=True))
''')

    return ret

def gen_registry(commands):
@@ -284,7 +326,7 @@ def gen_command_decl_prologue(header, guard, prefix=""):
#include "error.h"

''',
                 header=basename(h_file), guard=guardname(h_file), prefix=prefix)
                 header=basename(header), guard=guardname(header), prefix=prefix)
    return ret

def gen_command_def_prologue(prefix="", proxy=False):
@@ -317,11 +359,11 @@ def gen_command_def_prologue(prefix="", proxy=False):
                prefix=prefix)
    if not proxy:
        ret += '#include "%sqmp-commands.h"' % prefix
    return ret + "\n"
    return ret + "\n\n"


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:
    print str(err)
    sys.exit(1)
@@ -331,6 +373,7 @@ prefix = ""
dispatch_type = "sync"
c_file = 'qmp-marshal.c'
h_file = 'qmp-commands.h'
middle_mode = False

for o, a in opts:
    if o in ("-p", "--prefix"):
@@ -339,6 +382,8 @@ for o, a in opts:
        output_dir = a + "/"
    elif o in ("-t", "--type"):
        dispatch_type = a
    elif o in ("-m", "--middle"):
        middle_mode = True

c_file = output_dir + prefix + c_file
h_file = output_dir + prefix + h_file
@@ -370,12 +415,18 @@ if dispatch_type == "sync":
        ret = generate_command_decl(cmd['command'], arglist, ret_type) + "\n"
        fdecl.write(ret)
        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)
        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)

    fdecl.write("\n#endif\n");

    if not middle_mode:
        ret = gen_registry(commands)
        fdef.write(ret)

+3 −0
Original line number Diff line number Diff line
@@ -268,3 +268,6 @@ fdecl.write('''

fdecl.flush()
fdecl.close()

fdef.flush()
fdef.close()
+3 −1
Original line number Diff line number Diff line
@@ -200,4 +200,6 @@ def basename(filename):
    return filename.split("/")[-1]

def guardname(filename):
    return filename.replace("/", "_").replace("-", "_").split(".")[0].upper()
    if filename.startswith('./'):
        filename = filename[2:]
    return filename.replace("/", "_").replace("-", "_").split(".")[0].upper() + '_H'