#
# QAPI command marshaller generator
#
# Copyright IBM, Corp. 2011
# Copyright (C) 2014-2015 Red Hat, Inc.
#
# Authors:
#  Anthony Liguori <aliguori@us.ibm.com>
#  Michael Roth    <mdroth@linux.vnet.ibm.com>
#  Markus Armbruster <armbru@redhat.com>
#
# This work is licensed under the terms of the GNU GPL, version 2.
# See the COPYING file in the top-level directory.

from qapi import *
import re


def gen_command_decl(name, arg_type, ret_type):
    return mcgen('''
%(c_type)s qmp_%(c_name)s(%(params)s);
''',
                 c_type=(ret_type and ret_type.c_type()) or 'void',
                 c_name=c_name(name),
                 params=gen_params(arg_type, 'Error **errp'))


def gen_call(name, arg_type, ret_type):
    ret = ''

    argstr = ''
    if arg_type:
        for memb in arg_type.members:
            if memb.optional:
                argstr += 'has_%s, ' % c_name(memb.name)
            argstr += '%s, ' % c_name(memb.name)

    lhs = ''
    if ret_type:
        lhs = 'retval = '

    ret = mcgen('''

    %(lhs)sqmp_%(c_name)s(%(args)s&err);
''',
                c_name=c_name(name), args=argstr, lhs=lhs)
    if ret_type:
        ret += gen_err_check()
        ret += mcgen('''

    qmp_marshal_output_%(c_name)s(retval, ret, &err);
''',
                     c_name=ret_type.c_name())
    return ret


def gen_marshal_vars(arg_type, ret_type):
    ret = mcgen('''
    Error *err = NULL;
''')

    if ret_type:
        ret += mcgen('''
    %(c_type)s retval;
''',
                     c_type=ret_type.c_type())

    if arg_type:
        ret += mcgen('''
    QmpInputVisitor *qiv = qmp_input_visitor_new_strict(QOBJECT(args));
    QapiDeallocVisitor *qdv;
    Visitor *v;
''')

        for memb in arg_type.members:
            if memb.optional:
                ret += mcgen('''
    bool has_%(c_name)s = false;
''',
                             c_name=c_name(memb.name))
            ret += mcgen('''
    %(c_type)s %(c_name)s = %(c_null)s;
''',
                         c_name=c_name(memb.name),
                         c_type=memb.type.c_type(),
                         c_null=memb.type.c_null())
        ret += '\n'
    else:
        ret += mcgen('''

    (void)args;
''')

    return ret


def gen_marshal_input_visit(arg_type, dealloc=False):
    ret = ''

    if not arg_type:
        return ret

    if dealloc:
        ret += mcgen('''
    qmp_input_visitor_cleanup(qiv);
    qdv = qapi_dealloc_visitor_new();
    v = qapi_dealloc_get_visitor(qdv);
''')
    else:
        ret += mcgen('''
    v = qmp_input_get_visitor(qiv);
''')

    ret += gen_visit_fields(arg_type.members, skiperr=dealloc)

    if dealloc:
        ret += mcgen('''
    qapi_dealloc_visitor_cleanup(qdv);
''')
    return ret


def gen_marshal_output(ret_type):
    return mcgen('''

static void qmp_marshal_output_%(c_name)s(%(c_type)s ret_in, QObject **ret_out, Error **errp)
{
    Error *err = NULL;
    QmpOutputVisitor *qov = qmp_output_visitor_new();
    QapiDeallocVisitor *qdv;
    Visitor *v;

    v = qmp_output_get_visitor(qov);
    visit_type_%(c_name)s(v, &ret_in, "unused", &err);
    if (err) {
        goto out;
    }
    *ret_out = qmp_output_get_qobject(qov);

out:
    error_propagate(errp, err);
    qmp_output_visitor_cleanup(qov);
    qdv = qapi_dealloc_visitor_new();
    v = qapi_dealloc_get_visitor(qdv);
    visit_type_%(c_name)s(v, &ret_in, "unused", NULL);
    qapi_dealloc_visitor_cleanup(qdv);
}
''',
                 c_type=ret_type.c_type(), c_name=ret_type.c_name())


def gen_marshal_proto(name):
    ret = 'void qmp_marshal_%s(QDict *args, QObject **ret, Error **errp)' % c_name(name)
    if not middle_mode:
        ret = 'static ' + ret
    return ret


def gen_marshal_decl(name):
    return mcgen('''
%(proto)s;
''',
                 proto=gen_marshal_proto(name))


def gen_marshal(name, arg_type, ret_type):
    ret = mcgen('''

%(proto)s
{
''',
                proto=gen_marshal_proto(name))

    ret += gen_marshal_vars(arg_type, ret_type)
    ret += gen_marshal_input_visit(arg_type)
    ret += gen_call(name, arg_type, ret_type)

    # 'goto out' produced by gen_marshal_input_visit->gen_visit_fields()
    # for each arg_type member, and by gen_call() for ret_type
    if (arg_type and arg_type.members) or ret_type:
        ret += mcgen('''

out:
''')
    ret += mcgen('''
    error_propagate(errp, err);
''')
    ret += gen_marshal_input_visit(arg_type, dealloc=True)
    ret += mcgen('''
}
''')
    return ret


def gen_register_command(name, success_response):
    options = 'QCO_NO_OPTIONS'
    if not success_response:
        options = 'QCO_NO_SUCCESS_RESP'

    ret = mcgen('''
    qmp_register_command("%(name)s", qmp_marshal_%(c_name)s, %(opts)s);
''',
                name=name, c_name=c_name(name),
                opts=options)
    return ret


def gen_registry(registry):
    ret = mcgen('''

static void qmp_init_marshal(void)
{
''')
    ret += registry
    ret += mcgen('''
}

qapi_init(qmp_init_marshal);
''')
    return ret


class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
    def __init__(self):
        self.decl = None
        self.defn = None
        self._regy = None
        self._visited_ret_types = None

    def visit_begin(self, schema):
        self.decl = ''
        self.defn = ''
        self._regy = ''
        self._visited_ret_types = set()

    def visit_end(self):
        if not middle_mode:
            self.defn += gen_registry(self._regy)
        self._regy = None
        self._visited_ret_types = None

    def visit_command(self, name, info, arg_type, ret_type,
                      gen, success_response):
        if not gen:
            return
        self.decl += gen_command_decl(name, arg_type, ret_type)
        if ret_type and ret_type not in self._visited_ret_types:
            self._visited_ret_types.add(ret_type)
            self.defn += gen_marshal_output(ret_type)
        if middle_mode:
            self.decl += gen_marshal_decl(name)
        self.defn += gen_marshal(name, arg_type, ret_type)
        if not middle_mode:
            self._regy += gen_register_command(name, success_response)


middle_mode = False

(input_file, output_dir, do_c, do_h, prefix, opts) = \
    parse_command_line("m", ["middle"])

for o, a in opts:
    if o in ("-m", "--middle"):
        middle_mode = True

c_comment = '''
/*
 * schema-defined QMP->QAPI command dispatch
 *
 * Copyright IBM, Corp. 2011
 *
 * Authors:
 *  Anthony Liguori   <aliguori@us.ibm.com>
 *
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
 * See the COPYING.LIB file in the top-level directory.
 *
 */
'''
h_comment = '''
/*
 * schema-defined QAPI function prototypes
 *
 * Copyright IBM, Corp. 2011
 *
 * Authors:
 *  Anthony Liguori   <aliguori@us.ibm.com>
 *
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
 * See the COPYING.LIB file in the top-level directory.
 *
 */
'''

(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
                            'qmp-marshal.c', 'qmp-commands.h',
                            c_comment, h_comment)

fdef.write(mcgen('''
#include "qemu-common.h"
#include "qemu/module.h"
#include "qapi/qmp/types.h"
#include "qapi/qmp/dispatch.h"
#include "qapi/visitor.h"
#include "qapi/qmp-output-visitor.h"
#include "qapi/qmp-input-visitor.h"
#include "qapi/dealloc-visitor.h"
#include "%(prefix)sqapi-types.h"
#include "%(prefix)sqapi-visit.h"
#include "%(prefix)sqmp-commands.h"

''',
                 prefix=prefix))

fdecl.write(mcgen('''
#include "%(prefix)sqapi-types.h"
#include "qapi/qmp/qdict.h"
#include "qapi/error.h"

''',
                  prefix=prefix))

schema = QAPISchema(input_file)
gen = QAPISchemaGenCommandVisitor()
schema.visit(gen)
fdef.write(gen.defn)
fdecl.write(gen.decl)

close_output(fdef, fdecl)
