Commit e98859a9 authored by Markus Armbruster's avatar Markus Armbruster
Browse files

qapi: Clean up after recent conversions to QAPISchemaVisitor



Generate just 'FOO' instead of 'struct FOO' when possible.

Drop helper functions that are now unused.

Make pep8 and pylint reasonably happy.

Rename generate_FOO() functions to gen_FOO() for consistency.

Use more consistent and sensible variable names.

Consistently use c_ for mapping keys when their value is a C
identifier or type.

Simplify gen_enum() and gen_visit_union()

Consistently use single quotes for C text string literals.

Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
Message-Id: <1442401589-24189-14-git-send-email-armbru@redhat.com>
Reviewed-by: default avatarDaniel P. Berrange <berrange@redhat.com>
Reviewed-by: default avatarEric Blake <eblake@redhat.com>
parent 5710153e
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -598,7 +598,7 @@ Example:
            UserDefOne *value;
            uint64_t padding;
        };
        struct UserDefOneList *next;
        UserDefOneList *next;
    };

    void qapi_free_UserDefOneList(UserDefOneList *obj);
+77 −63
Original line number Diff line number Diff line
@@ -15,20 +15,22 @@
from qapi import *
import re

def generate_command_decl(name, args, ret_type):
    arglist=""
    if args:
        for memb in args.members:
            argtype = memb.type.c_type(is_param=True)

def gen_command_decl(name, arg_type, ret_type):
    argstr = ''
    if arg_type:
        for memb in arg_type.members:
            if memb.optional:
                arglist += "bool has_%s, " % c_name(memb.name)
            arglist += "%s %s, " % (argtype, c_name(memb.name))
                argstr += 'bool has_%s, ' % c_name(memb.name)
            argstr += '%s %s, ' % (memb.type.c_type(is_param=True),
                                   c_name(memb.name))
    return mcgen('''
%(ret_type)s qmp_%(name)s(%(args)sError **errp);
%(c_type)s qmp_%(c_name)s(%(args)sError **errp);
''',
                 ret_type=(ret_type and ret_type.c_type()) or 'void',
                 name=c_name(name),
                 args=arglist)
                 c_type=(ret_type and ret_type.c_type()) or 'void',
                 c_name=c_name(name),
                 args=argstr)


def gen_err_check(err):
    if not err:
@@ -40,22 +42,26 @@ if (%(err)s) {
''',
                 err=err)

def gen_sync_call(name, args, ret_type):
    ret = ""
    arglist=""
    retval=""
    if ret_type:
        retval = "retval = "
    if args:
        for memb in args.members:

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

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

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

    push_indent()
    ret = mcgen('''
%(retval)sqmp_%(name)s(%(args)s&local_err);
%(lhs)sqmp_%(c_name)s(%(args)s&local_err);
''',
                name=c_name(name), args=arglist, retval=retval)
                c_name=c_name(name), args=argstr, lhs=lhs)
    if ret_type:
        ret += gen_err_check('local_err')
        ret += mcgen('''
@@ -66,11 +72,12 @@ qmp_marshal_output_%(c_name)s(retval, ret, &local_err);
    pop_indent()
    return ret

def gen_visitor_input_containers_decl(args):
    ret = ""

def gen_visitor_input_containers_decl(arg_type):
    ret = ''

    push_indent()
    if args:
    if arg_type:
        ret += mcgen('''
QmpInputVisitor *mi = qmp_input_visitor_new_strict(QOBJECT(args));
QapiDeallocVisitor *md;
@@ -80,17 +87,18 @@ Visitor *v;

    return ret

def gen_visitor_input_vars_decl(args):
    ret = ""

def gen_visitor_input_vars_decl(arg_type):
    ret = ''
    push_indent()

    if args:
        for memb in args.members:
    if arg_type:
        for memb in arg_type.members:
            if memb.optional:
                ret += mcgen('''
bool has_%(argname)s = false;
bool has_%(c_name)s = false;
''',
                             argname=c_name(memb.name))
                             c_name=c_name(memb.name))
            ret += mcgen('''
%(c_type)s %(c_name)s = %(c_null)s;
''',
@@ -101,19 +109,20 @@ bool has_%(argname)s = false;
    pop_indent()
    return ret

def gen_visitor_input_block(args, dealloc=False):
    ret = ""

def gen_visitor_input_block(arg_type, dealloc=False):
    ret = ''
    errparg = '&local_err'
    errarg = 'local_err'

    if not args:
    if not arg_type:
        return ret

    push_indent()

    if dealloc:
        errparg = 'NULL'
        errarg = None;
        errarg = None
        ret += mcgen('''
qmp_input_visitor_cleanup(mi);
md = qapi_dealloc_visitor_new();
@@ -124,7 +133,7 @@ v = qapi_dealloc_get_visitor(md);
v = qmp_input_get_visitor(mi);
''')

    for memb in args.members:
    for memb in arg_type.members:
        if memb.optional:
            ret += mcgen('''
visit_optional(v, &has_%(c_name)s, "%(name)s", %(errp)s);
@@ -138,10 +147,10 @@ if (has_%(c_name)s) {
                         c_name=c_name(memb.name))
            push_indent()
        ret += mcgen('''
visit_type_%(visitor)s(v, &%(c_name)s, "%(name)s", %(errp)s);
visit_type_%(c_type)s(v, &%(c_name)s, "%(name)s", %(errp)s);
''',
                     c_name=c_name(memb.name), name=memb.name,
                     visitor=memb.type.c_name(), errp=errparg)
                     c_type=memb.type.c_name(), errp=errparg)
        ret += gen_err_check(errarg)
        if memb.optional:
            pop_indent()
@@ -156,13 +165,14 @@ qapi_dealloc_visitor_cleanup(md);
    pop_indent()
    return ret


def gen_marshal_output(name, ret_type):
    if not ret_type:
        return ""
        return ''

    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_cmd_name)s(%(c_type)s ret_in, QObject **ret_out, Error **errp)
{
    Error *local_err = NULL;
    QmpOutputVisitor *mo = qmp_output_visitor_new();
@@ -170,7 +180,7 @@ static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_o
    Visitor *v;

    v = qmp_output_get_visitor(mo);
    visit_type_%(visitor)s(v, &ret_in, "unused", &local_err);
    visit_type_%(c_name)s(v, &ret_in, "unused", &local_err);
    if (local_err) {
        goto out;
    }
@@ -181,23 +191,25 @@ out:
    qmp_output_visitor_cleanup(mo);
    md = qapi_dealloc_visitor_new();
    v = qapi_dealloc_get_visitor(md);
    visit_type_%(visitor)s(v, &ret_in, "unused", NULL);
    visit_type_%(c_name)s(v, &ret_in, "unused", NULL);
    qapi_dealloc_visitor_cleanup(md);
}
''',
                c_ret_type=ret_type.c_type(), c_name=c_name(name),
                visitor=ret_type.c_name())
                c_type=ret_type.c_type(), c_cmd_name=c_name(name),
                c_name=ret_type.c_name())

    return ret

def gen_marshal_input_decl(name, middle_mode):

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

def gen_marshal_input(name, args, ret_type, middle_mode):
    hdr = gen_marshal_input_decl(name, middle_mode)

def gen_marshal_input(name, arg_type, ret_type):
    hdr = gen_marshal_input_decl(name)

    ret = mcgen('''

@@ -213,10 +225,10 @@ def gen_marshal_input(name, args, ret_type, middle_mode):
''',
                     c_type=ret_type.c_type())

    if args:
        ret += gen_visitor_input_containers_decl(args)
        ret += gen_visitor_input_vars_decl(args) + '\n'
        ret += gen_visitor_input_block(args) + '\n'
    if arg_type:
        ret += gen_visitor_input_containers_decl(arg_type)
        ret += gen_visitor_input_vars_decl(arg_type) + '\n'
        ret += gen_visitor_input_block(arg_type) + '\n'
    else:
        ret += mcgen('''

@@ -224,9 +236,9 @@ def gen_marshal_input(name, args, ret_type, middle_mode):

''')

    ret += gen_sync_call(name, args, ret_type)
    ret += gen_call(name, arg_type, ret_type)

    if re.search('^ *goto out\\;', ret, re.MULTILINE):
    if re.search('^ *goto out;', ret, re.MULTILINE):
        ret += mcgen('''

out:
@@ -234,12 +246,13 @@ out:
    ret += mcgen('''
    error_propagate(errp, local_err);
''')
    ret += gen_visitor_input_block(args, dealloc=True)
    ret += gen_visitor_input_block(arg_type, dealloc=True)
    ret += mcgen('''
}
''')
    return ret


def gen_register_command(name, success_response):
    push_indent()
    options = 'QCO_NO_OPTIONS'
@@ -254,6 +267,7 @@ qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s, %(opts)s);
    pop_indent()
    return ret


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

@@ -289,12 +303,12 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
                      gen, success_response):
        if not gen:
            return
        self.decl += generate_command_decl(name, arg_type, ret_type)
        self.decl += gen_command_decl(name, arg_type, ret_type)
        if ret_type:
            self.defn += gen_marshal_output(name, ret_type)
        if middle_mode:
            self.decl += gen_marshal_input_decl(name, middle_mode) + ';\n'
        self.defn += gen_marshal_input(name, arg_type, ret_type, middle_mode)
            self.decl += gen_marshal_input_decl(name) + ';\n'
        self.defn += gen_marshal_input(name, arg_type, ret_type)
        if not middle_mode:
            self._regy += gen_register_command(name, success_response)

+58 −64
Original line number Diff line number Diff line
@@ -13,12 +13,13 @@

from qapi import *

def _generate_event_api_name(event_name, params):
    api_name = "void qapi_event_send_%s(" % c_name(event_name).lower();

def gen_event_send_proto(name, arg_type):
    api_name = "void qapi_event_send_%s(" % c_name(name).lower()
    l = len(api_name)

    if params:
        for m in params.members:
    if arg_type:
        for m in arg_type.members:
            if m.optional:
                api_name += "bool has_%s,\n" % c_name(m.name)
                api_name += "".ljust(l)
@@ -28,53 +29,49 @@ def _generate_event_api_name(event_name, params):
            api_name += "".ljust(l)

    api_name += "Error **errp)"
    return api_name;

    return api_name

# Following are the core functions that generate C APIs to emit event.

def generate_event_declaration(api_name):
def gen_event_send_decl(name, arg_type):
    return mcgen('''

%(api_name)s;
%(proto)s;
''',
                 api_name = api_name)
                 proto=gen_event_send_proto(name, arg_type))


def generate_event_implement(api_name, event_name, params):
    # step 1: declare any variables
    ret = mcgen("""
def gen_event_send(name, arg_type):
    ret = mcgen('''

%(api_name)s
%(proto)s
{
    QDict *qmp;
    Error *local_err = NULL;
    QMPEventFuncEmit emit;
""",
                api_name = api_name)
''',
                proto=gen_event_send_proto(name, arg_type))

    if params and params.members:
        ret += mcgen("""
    if arg_type and arg_type.members:
        ret += mcgen('''
    QmpOutputVisitor *qov;
    Visitor *v;
    QObject *obj;

""")
''')

    # step 2: check emit function, create a dict
    ret += mcgen("""
    ret += mcgen('''
    emit = qmp_event_get_func_emit();
    if (!emit) {
        return;
    }

    qmp = qmp_event_build_dict("%(event_name)s");
    qmp = qmp_event_build_dict("%(name)s");

""",
                 event_name = event_name)
''',
                 name=name)

    # step 3: visit the params if params != None
    if params and params.members:
        ret += mcgen("""
    if arg_type and arg_type.members:
        ret += mcgen('''
    qov = qmp_output_visitor_new();
    g_assert(qov);

@@ -82,45 +79,46 @@ def generate_event_implement(api_name, event_name, params):
    g_assert(v);

    /* Fake visit, as if all members are under a structure */
    visit_start_struct(v, NULL, "", "%(event_name)s", 0, &local_err);
    visit_start_struct(v, NULL, "", "%(name)s", 0, &local_err);
    if (local_err) {
        goto clean;
    }

""",
                event_name = event_name)
''',
                     name=name)

        for memb in params.members:
        for memb in arg_type.members:
            if memb.optional:
                ret += mcgen("""
    if (has_%(var)s) {
""",
                             var=c_name(memb.name))
                ret += mcgen('''
    if (has_%(c_name)s) {
''',
                             c_name=c_name(memb.name))
                push_indent()

            # Ugly: need to cast away the const
            if memb.type.name == "str":
                var_type = "(char **)"
                cast = '(char **)'
            else:
                var_type = ""
                cast = ''

            ret += mcgen("""
    visit_type_%(type)s(v, %(var_type)s&%(var)s, "%(name)s", &local_err);
            ret += mcgen('''
    visit_type_%(c_type)s(v, %(cast)s&%(c_name)s, "%(name)s", &local_err);
    if (local_err) {
        goto clean;
    }
""",
                         var_type = var_type,
                         var=c_name(memb.name),
                         type=memb.type.c_name(),
''',
                         cast=cast,
                         c_name=c_name(memb.name),
                         c_type=memb.type.c_name(),
                         name=memb.name)

            if memb.optional:
                pop_indent()
                ret += mcgen("""
                ret += mcgen('''
    }
""")
''')

        ret += mcgen("""
        ret += mcgen('''

    visit_end_struct(v, &local_err);
    if (local_err) {
@@ -131,27 +129,24 @@ def generate_event_implement(api_name, event_name, params):
    g_assert(obj != NULL);

    qdict_put_obj(qmp, "data", obj);
""")
''')

    # step 4: call qmp event api
    ret += mcgen("""
    emit(%(event_enum_value)s, qmp, &local_err);
    ret += mcgen('''
    emit(%(c_enum)s, qmp, &local_err);

""",
                 event_enum_value = c_enum_const(event_enum_name, event_name))
''',
                 c_enum=c_enum_const(event_enum_name, name))

    # step 5: clean up
    if params and params.members:
        ret += mcgen("""
    if arg_type and arg_type.members:
        ret += mcgen('''
 clean:
    qmp_output_visitor_cleanup(qov);
""")
    ret += mcgen("""
''')
    ret += mcgen('''
    error_propagate(errp, local_err);
    QDECREF(qmp);
}
""")

''')
    return ret


@@ -167,14 +162,13 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
        self._event_names = []

    def visit_end(self):
        self.decl += generate_enum(event_enum_name, self._event_names)
        self.defn += generate_enum_lookup(event_enum_name, self._event_names)
        self.decl += gen_enum(event_enum_name, self._event_names)
        self.defn += gen_enum_lookup(event_enum_name, self._event_names)
        self._event_names = None

    def visit_event(self, name, info, arg_type):
        api_name = _generate_event_api_name(name, arg_type)
        self.decl += generate_event_declaration(api_name)
        self.defn += generate_event_implement(api_name, name, arg_type)
        self.decl += gen_event_send_decl(name, arg_type)
        self.defn += gen_event_send(name, arg_type)
        self._event_names.append(name)


+44 −35
Original line number Diff line number Diff line
@@ -13,25 +13,28 @@

from qapi import *


def gen_fwd_object_or_array(name):
    return mcgen('''

typedef struct %(name)s %(name)s;
typedef struct %(c_name)s %(c_name)s;
''',
                 name=c_name(name))
                 c_name=c_name(name))


def gen_array(name, element_type):
    return mcgen('''

struct %(name)s {
struct %(c_name)s {
    union {
        %(c_type)s value;
        uint64_t padding;
    };
    struct %(name)s *next;
    %(c_name)s *next;
};
''',
                 name=c_name(name), c_type=element_type.c_type())
                 c_name=c_name(name), c_type=element_type.c_type())


def gen_struct_field(name, typ, optional):
    ret = ''
@@ -47,28 +50,31 @@ def gen_struct_field(name, typ, optional):
                 c_type=typ.c_type(), c_name=c_name(name))
    return ret

def generate_struct_fields(members):

def gen_struct_fields(members):
    ret = ''

    for memb in members:
        ret += gen_struct_field(memb.name, memb.type, memb.optional)
    return ret


def gen_struct(name, base, members):
    ret = mcgen('''

struct %(name)s {
struct %(c_name)s {
''',
                name=c_name(name))
                c_name=c_name(name))

    if base:
        ret += gen_struct_field('base', base, False)

    ret += generate_struct_fields(members)
    ret += gen_struct_fields(members)

    # Make sure that all structs have at least one field; this avoids
    # potential issues with attempting to malloc space for zero-length structs
    # in C, and also incompatibility with C++ (where an empty struct is size 1).
    # potential issues with attempting to malloc space for zero-length
    # structs in C, and also incompatibility with C++ (where an empty
    # struct is size 1).
    if not base and not members:
        ret += mcgen('''
    char qapi_dummy_field_for_empty_struct;
@@ -80,6 +86,7 @@ struct %(name)s {

    return ret


def gen_alternate_qtypes_decl(name):
    return mcgen('''

@@ -87,12 +94,13 @@ extern const int %(c_name)s_qtypes[];
''',
                 c_name=c_name(name))


def gen_alternate_qtypes(name, variants):
    ret = mcgen('''

const int %(name)s_qtypes[QTYPE_MAX] = {
const int %(c_name)s_qtypes[QTYPE_MAX] = {
''',
                name=c_name(name))
                c_name=c_name(name))

    for var in variants.variants:
        qtype = var.type.alternate_qtype()
@@ -110,28 +118,27 @@ const int %(name)s_qtypes[QTYPE_MAX] = {
''')
    return ret

def gen_union(name, base, variants):
    name = c_name(name)

def gen_union(name, base, variants):
    ret = mcgen('''

struct %(name)s {
struct %(c_name)s {
''',
                name=name)
                c_name=c_name(name))
    if base:
        ret += mcgen('''
    /* Members inherited from %(c_name)s: */
''',
                     c_name=c_name(base.name))
        ret += generate_struct_fields(base.members)
        ret += gen_struct_fields(base.members)
        ret += mcgen('''
    /* Own members: */
''')
    else:
        ret += mcgen('''
    %(discriminator_type_name)s kind;
    %(c_type)s kind;
''',
                     discriminator_type_name=c_name(variants.tag_member.type.name))
                     c_type=c_name(variants.tag_member.type.name))

    # FIXME: What purpose does data serve, besides preventing a union that
    # has a branch named 'data'? We use it in qapi-visit.py to decide
@@ -166,18 +173,20 @@ struct %(name)s {

    return ret

def generate_type_cleanup_decl(name):

def gen_type_cleanup_decl(name):
    ret = mcgen('''

void qapi_free_%(name)s(%(name)s *obj);
void qapi_free_%(c_name)s(%(c_name)s *obj);
''',
                name=c_name(name))
                c_name=c_name(name))
    return ret

def generate_type_cleanup(name):

def gen_type_cleanup(name):
    ret = mcgen('''

void qapi_free_%(name)s(%(name)s *obj)
void qapi_free_%(c_name)s(%(c_name)s *obj)
{
    QapiDeallocVisitor *md;
    Visitor *v;
@@ -188,11 +197,11 @@ void qapi_free_%(name)s(%(name)s *obj)

    md = qapi_dealloc_visitor_new();
    v = qapi_dealloc_get_visitor(md);
    visit_type_%(name)s(v, &obj, NULL, NULL);
    visit_type_%(c_name)s(v, &obj, NULL, NULL);
    qapi_dealloc_visitor_cleanup(md);
}
''',
                name=c_name(name))
                c_name=c_name(name))
    return ret


@@ -225,20 +234,20 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
        self._btin = None

    def _gen_type_cleanup(self, name):
        self.decl += generate_type_cleanup_decl(name)
        self.defn += generate_type_cleanup(name)
        self.decl += gen_type_cleanup_decl(name)
        self.defn += gen_type_cleanup(name)

    def visit_enum_type(self, name, info, values, prefix):
        self._fwdecl += generate_enum(name, values, prefix)
        self._fwdefn += generate_enum_lookup(name, values, prefix)
        self._fwdecl += gen_enum(name, values, prefix)
        self._fwdefn += gen_enum_lookup(name, values, prefix)

    def visit_array_type(self, name, info, element_type):
        if isinstance(element_type, QAPISchemaBuiltinType):
            self._btin += gen_fwd_object_or_array(name)
            self._btin += gen_array(name, element_type)
            self._btin += generate_type_cleanup_decl(name)
            self._btin += gen_type_cleanup_decl(name)
            if do_builtins:
                self.defn += generate_type_cleanup(name)
                self.defn += gen_type_cleanup(name)
        else:
            self._fwdecl += gen_fwd_object_or_array(name)
            self.decl += gen_array(name, element_type)
+69 −58

File changed.

Preview size limit exceeded, changes collapsed.

Loading