2015-08-21 07:04:50 +00:00
|
|
|
#
|
|
|
|
# QAPI visitor generator
|
|
|
|
#
|
|
|
|
# Copyright IBM, Corp. 2011
|
2018-02-19 18:08:37 +00:00
|
|
|
# Copyright (C) 2014-2015 Red Hat, Inc.
|
2015-08-21 07:04:50 +00:00
|
|
|
#
|
|
|
|
# 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
|
|
|
|
|
2018-02-19 21:17:35 +00:00
|
|
|
implicit_structs_seen = set()
|
2018-02-19 21:16:17 +00:00
|
|
|
struct_fields_seen = set()
|
2015-08-21 07:04:50 +00:00
|
|
|
|
2018-02-19 22:37:07 +00:00
|
|
|
def gen_visit_decl(name, scalar=False):
|
|
|
|
c_type = c_name(name) + ' *'
|
|
|
|
if not scalar:
|
|
|
|
c_type += '*'
|
|
|
|
return mcgen('''
|
2018-02-19 23:20:03 +00:00
|
|
|
void visit_type_%(c_name)s(Visitor *v, %(c_type)sobj, const char *name, Error **errp);
|
2018-02-19 22:37:07 +00:00
|
|
|
''',
|
|
|
|
c_name=c_name(name), c_type=c_type)
|
|
|
|
|
|
|
|
|
2018-02-19 22:33:32 +00:00
|
|
|
def gen_visit_implicit_struct(typ):
|
|
|
|
if typ in implicit_structs_seen:
|
2015-08-21 07:04:50 +00:00
|
|
|
return ''
|
2018-02-19 22:33:32 +00:00
|
|
|
implicit_structs_seen.add(typ)
|
|
|
|
|
2018-02-19 21:16:17 +00:00
|
|
|
ret = ''
|
2018-02-19 22:33:32 +00:00
|
|
|
if typ.name not in struct_fields_seen:
|
2018-02-19 21:16:17 +00:00
|
|
|
# Need a forward declaration
|
|
|
|
ret += mcgen('''
|
|
|
|
|
2018-02-19 23:20:03 +00:00
|
|
|
static void visit_type_%(c_type)s_fields(Visitor *v, %(c_type)s **obj, Error **errp);
|
2018-02-19 21:16:17 +00:00
|
|
|
''',
|
2018-02-19 22:33:32 +00:00
|
|
|
c_type=typ.c_name())
|
2018-02-19 21:16:17 +00:00
|
|
|
|
|
|
|
ret += mcgen('''
|
2015-08-21 07:04:50 +00:00
|
|
|
|
2018-02-19 23:20:03 +00:00
|
|
|
static void visit_type_implicit_%(c_type)s(Visitor *v, %(c_type)s **obj, Error **errp)
|
2015-08-21 07:04:50 +00:00
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
|
2018-02-19 23:20:03 +00:00
|
|
|
visit_start_implicit_struct(v, (void **)obj, sizeof(%(c_type)s), &err);
|
2015-08-21 07:04:50 +00:00
|
|
|
if (!err) {
|
2018-02-19 23:20:03 +00:00
|
|
|
visit_type_%(c_type)s_fields(v, obj, errp);
|
|
|
|
visit_end_implicit_struct(v);
|
2015-08-21 07:04:50 +00:00
|
|
|
}
|
|
|
|
error_propagate(errp, err);
|
|
|
|
}
|
|
|
|
''',
|
2018-02-19 22:33:32 +00:00
|
|
|
c_type=typ.c_name())
|
2018-02-19 21:16:17 +00:00
|
|
|
return ret
|
2015-08-21 07:04:50 +00:00
|
|
|
|
2018-02-19 22:33:32 +00:00
|
|
|
def gen_visit_struct_fields(name, base, members):
|
2018-02-19 21:16:17 +00:00
|
|
|
struct_fields_seen.add(name)
|
|
|
|
|
2015-08-21 07:04:50 +00:00
|
|
|
ret = ''
|
|
|
|
|
|
|
|
if base:
|
2018-02-19 22:33:32 +00:00
|
|
|
ret += gen_visit_implicit_struct(base)
|
2015-08-21 07:04:50 +00:00
|
|
|
|
|
|
|
ret += mcgen('''
|
|
|
|
|
2018-02-19 23:20:03 +00:00
|
|
|
static void visit_type_%(c_name)s_fields(Visitor *v, %(c_name)s **obj, Error **errp)
|
2015-08-21 07:04:50 +00:00
|
|
|
{
|
|
|
|
Error *err = NULL;
|
2018-02-19 21:29:11 +00:00
|
|
|
|
2015-08-21 07:04:50 +00:00
|
|
|
''',
|
2018-02-19 22:33:32 +00:00
|
|
|
c_name=c_name(name))
|
2015-08-21 07:04:50 +00:00
|
|
|
|
|
|
|
if base:
|
|
|
|
ret += mcgen('''
|
2018-02-19 23:27:47 +00:00
|
|
|
visit_type_implicit_%(c_type)s(v, &(*obj)->%(c_name)s, &err);
|
2015-08-21 07:04:50 +00:00
|
|
|
''',
|
2018-02-19 22:33:32 +00:00
|
|
|
c_type=base.c_name(), c_name=c_name('base'))
|
2018-02-19 23:27:47 +00:00
|
|
|
ret += gen_err_check()
|
2015-08-21 07:04:50 +00:00
|
|
|
|
qapi: Share gen_visit_fields()
Consolidate the code between visit, command marshalling, and
event generation that iterates over the members of a struct.
It reduces code duplication in the generator, so that a future
patch can reduce the size of generated code while touching only
one instead of three locations.
There are no changes to the generated marshal code.
The visitor code becomes slightly more verbose, but remains
semantically equivalent, and is actually easier to read as
it follows a more common idiom:
| visit_optional(v, &(*obj)->has_device, "device", &err);
|- if (!err && (*obj)->has_device) {
|- visit_type_str(v, &(*obj)->device, "device", &err);
|- }
| if (err) {
| goto out;
| }
|+ if ((*obj)->has_device) {
|+ visit_type_str(v, &(*obj)->device, "device", &err);
|+ if (err) {
|+ goto out;
|+ }
|+ }
The event code becomes slightly more verbose, but this is
arguably a bug fix: although the visitors are not well
documented, use of an optional member should not be attempted
unless guarded by a prior call to visit_optional(). Works only
because the output qmp visitor has a no-op visit_optional():
|+ visit_optional(v, &has_offset, "offset", &err);
|+ if (err) {
|+ goto out;
|+ }
| if (has_offset) {
| visit_type_int(v, &offset, "offset", &err);
Backports commit 82ca8e469666b169ccf818a0e36136aee97d7db0 from qemu
2018-02-19 23:41:37 +00:00
|
|
|
ret += gen_visit_fields(members, prefix='(*obj)->')
|
2015-08-21 07:04:50 +00:00
|
|
|
|
2018-02-19 22:33:32 +00:00
|
|
|
if re.search('^ *goto out;', ret, re.MULTILINE):
|
2015-08-21 07:04:50 +00:00
|
|
|
ret += mcgen('''
|
|
|
|
|
|
|
|
out:
|
|
|
|
''')
|
|
|
|
ret += mcgen('''
|
|
|
|
error_propagate(errp, err);
|
|
|
|
}
|
|
|
|
''')
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
2018-02-19 22:37:07 +00:00
|
|
|
def gen_visit_struct(name, base, members):
|
|
|
|
ret = gen_visit_struct_fields(name, base, members)
|
|
|
|
|
|
|
|
# FIXME: if *obj is NULL on entry, and visit_start_struct() assigns to
|
|
|
|
# *obj, but then visit_type_FOO_fields() fails, we should clean up *obj
|
|
|
|
# rather than leaving it non-NULL. As currently written, the caller must
|
|
|
|
# call qapi_free_FOO() to avoid a memory leak of the partial FOO.
|
|
|
|
ret += mcgen('''
|
|
|
|
|
2018-02-19 23:20:03 +00:00
|
|
|
void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error **errp)
|
2018-02-19 22:37:07 +00:00
|
|
|
{
|
2015-08-21 07:04:50 +00:00
|
|
|
Error *err = NULL;
|
|
|
|
|
2018-02-19 23:20:03 +00:00
|
|
|
visit_start_struct(v, (void **)obj, "%(name)s", name, sizeof(%(c_name)s), &err);
|
2015-08-21 07:04:50 +00:00
|
|
|
|
|
|
|
if (!err) {
|
|
|
|
if (*obj) {
|
2018-02-19 23:20:03 +00:00
|
|
|
visit_type_%(c_name)s_fields(v, obj, errp);
|
2015-08-21 07:04:50 +00:00
|
|
|
}
|
2018-02-19 23:20:03 +00:00
|
|
|
visit_end_struct(v, &err);
|
2015-08-21 07:04:50 +00:00
|
|
|
}
|
|
|
|
error_propagate(errp, err);
|
|
|
|
}
|
2018-02-19 22:37:07 +00:00
|
|
|
''',
|
|
|
|
name=name, c_name=c_name(name))
|
2015-08-21 07:04:50 +00:00
|
|
|
return ret
|
|
|
|
|
2018-02-19 22:33:32 +00:00
|
|
|
|
qapi-visit: Convert to QAPISchemaVisitor, fixing bugs
Fixes flat unions to visit the base's base members (the previous
commit merely added them to the struct). Same test case.
Patch's effect on visit_type_UserDefFlatUnion():
static void visit_type_UserDefFlatUnion_fields(Visitor *m, UserDefFlatUnion **obj, Error **errp)
{
Error *err = NULL;
+ visit_type_int(m, &(*obj)->integer, "integer", &err);
+ if (err) {
+ goto out;
+ }
visit_type_str(m, &(*obj)->string, "string", &err);
if (err) {
goto out;
Test cases updated for the bug fix.
Fixes alternates to generate a visitor for their implicit enumeration
type. None of them are currently used, obviously. Example:
block-core.json's BlockdevRef now generates
visit_type_BlockdevRefKind().
Code is generated in a different order now, and therefore has got a
few new forward declarations. Doesn't matter.
The guard QAPI_VISIT_BUILTIN_VISITOR_DECL is renamed to
QAPI_VISIT_BUILTIN.
The previous commit's two ugly special cases exist here, too. Mark
both TODO.
Backports commit 441cbac0c7e641780decbc674a9a68c6a5200f71 from qemu
2018-02-19 22:04:55 +00:00
|
|
|
def gen_visit_list(name, element_type):
|
2015-08-21 07:04:50 +00:00
|
|
|
return mcgen('''
|
|
|
|
|
2018-02-19 23:20:03 +00:00
|
|
|
void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error **errp)
|
2015-08-21 07:04:50 +00:00
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
GenericList *i, **prev;
|
|
|
|
|
2018-02-19 23:20:03 +00:00
|
|
|
visit_start_list(v, name, &err);
|
2015-08-21 07:04:50 +00:00
|
|
|
if (err) {
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (prev = (GenericList **)obj;
|
2018-02-19 23:20:03 +00:00
|
|
|
!err && (i = visit_next_list(v, prev)) != NULL;
|
2015-08-21 07:04:50 +00:00
|
|
|
prev = &i) {
|
2018-02-19 22:33:32 +00:00
|
|
|
%(c_name)s *native_i = (%(c_name)s *)i;
|
2018-02-19 23:20:03 +00:00
|
|
|
visit_type_%(c_elt_type)s(v, &native_i->value, NULL, &err);
|
2015-08-21 07:04:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
error_propagate(errp, err);
|
|
|
|
err = NULL;
|
2018-02-19 23:20:03 +00:00
|
|
|
visit_end_list(v);
|
2015-08-21 07:04:50 +00:00
|
|
|
out:
|
|
|
|
error_propagate(errp, err);
|
|
|
|
}
|
|
|
|
''',
|
2018-02-19 22:33:32 +00:00
|
|
|
c_name=c_name(name), c_elt_type=element_type.c_name())
|
|
|
|
|
2015-08-21 07:04:50 +00:00
|
|
|
|
2018-02-19 22:33:32 +00:00
|
|
|
def gen_visit_enum(name):
|
2015-08-21 07:04:50 +00:00
|
|
|
return mcgen('''
|
|
|
|
|
2018-02-19 23:20:03 +00:00
|
|
|
void visit_type_%(c_name)s(Visitor *v, %(c_name)s *obj, const char *name, Error **errp)
|
2015-08-21 07:04:50 +00:00
|
|
|
{
|
2018-02-19 23:20:03 +00:00
|
|
|
visit_type_enum(v, (int *)obj, %(c_name)s_lookup, "%(name)s", name, errp);
|
2015-08-21 07:04:50 +00:00
|
|
|
}
|
|
|
|
''',
|
2018-02-19 21:20:07 +00:00
|
|
|
c_name=c_name(name), name=name)
|
2015-08-21 07:04:50 +00:00
|
|
|
|
2018-02-19 22:33:32 +00:00
|
|
|
|
qapi-visit: Convert to QAPISchemaVisitor, fixing bugs
Fixes flat unions to visit the base's base members (the previous
commit merely added them to the struct). Same test case.
Patch's effect on visit_type_UserDefFlatUnion():
static void visit_type_UserDefFlatUnion_fields(Visitor *m, UserDefFlatUnion **obj, Error **errp)
{
Error *err = NULL;
+ visit_type_int(m, &(*obj)->integer, "integer", &err);
+ if (err) {
+ goto out;
+ }
visit_type_str(m, &(*obj)->string, "string", &err);
if (err) {
goto out;
Test cases updated for the bug fix.
Fixes alternates to generate a visitor for their implicit enumeration
type. None of them are currently used, obviously. Example:
block-core.json's BlockdevRef now generates
visit_type_BlockdevRefKind().
Code is generated in a different order now, and therefore has got a
few new forward declarations. Doesn't matter.
The guard QAPI_VISIT_BUILTIN_VISITOR_DECL is renamed to
QAPI_VISIT_BUILTIN.
The previous commit's two ugly special cases exist here, too. Mark
both TODO.
Backports commit 441cbac0c7e641780decbc674a9a68c6a5200f71 from qemu
2018-02-19 22:04:55 +00:00
|
|
|
def gen_visit_alternate(name, variants):
|
2015-08-21 07:04:50 +00:00
|
|
|
ret = mcgen('''
|
|
|
|
|
2018-02-19 23:20:03 +00:00
|
|
|
void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error **errp)
|
2015-08-21 07:04:50 +00:00
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
|
2018-02-19 23:20:03 +00:00
|
|
|
visit_start_implicit_struct(v, (void**) obj, sizeof(%(c_name)s), &err);
|
2015-08-21 07:04:50 +00:00
|
|
|
if (err) {
|
|
|
|
goto out;
|
|
|
|
}
|
2018-02-19 23:20:03 +00:00
|
|
|
visit_get_next_type(v, (int*) &(*obj)->kind, %(c_name)s_qtypes, name, &err);
|
2015-08-21 07:04:50 +00:00
|
|
|
if (err) {
|
2018-02-19 23:23:12 +00:00
|
|
|
goto out_obj;
|
2015-08-21 07:04:50 +00:00
|
|
|
}
|
|
|
|
switch ((*obj)->kind) {
|
|
|
|
''',
|
2018-02-19 22:33:32 +00:00
|
|
|
c_name=c_name(name))
|
2015-08-21 07:04:50 +00:00
|
|
|
|
qapi-visit: Convert to QAPISchemaVisitor, fixing bugs
Fixes flat unions to visit the base's base members (the previous
commit merely added them to the struct). Same test case.
Patch's effect on visit_type_UserDefFlatUnion():
static void visit_type_UserDefFlatUnion_fields(Visitor *m, UserDefFlatUnion **obj, Error **errp)
{
Error *err = NULL;
+ visit_type_int(m, &(*obj)->integer, "integer", &err);
+ if (err) {
+ goto out;
+ }
visit_type_str(m, &(*obj)->string, "string", &err);
if (err) {
goto out;
Test cases updated for the bug fix.
Fixes alternates to generate a visitor for their implicit enumeration
type. None of them are currently used, obviously. Example:
block-core.json's BlockdevRef now generates
visit_type_BlockdevRefKind().
Code is generated in a different order now, and therefore has got a
few new forward declarations. Doesn't matter.
The guard QAPI_VISIT_BUILTIN_VISITOR_DECL is renamed to
QAPI_VISIT_BUILTIN.
The previous commit's two ugly special cases exist here, too. Mark
both TODO.
Backports commit 441cbac0c7e641780decbc674a9a68c6a5200f71 from qemu
2018-02-19 22:04:55 +00:00
|
|
|
for var in variants.variants:
|
2015-08-21 07:04:50 +00:00
|
|
|
ret += mcgen('''
|
2018-02-19 22:33:32 +00:00
|
|
|
case %(case)s:
|
2018-02-19 23:20:03 +00:00
|
|
|
visit_type_%(c_type)s(v, &(*obj)->%(c_name)s, name, &err);
|
2015-08-21 07:04:50 +00:00
|
|
|
break;
|
|
|
|
''',
|
2018-02-19 22:33:32 +00:00
|
|
|
case=c_enum_const(variants.tag_member.type.name,
|
|
|
|
var.name),
|
|
|
|
c_type=var.type.c_name(),
|
|
|
|
c_name=c_name(var.name))
|
2015-08-21 07:04:50 +00:00
|
|
|
|
|
|
|
ret += mcgen('''
|
|
|
|
default:
|
|
|
|
abort();
|
|
|
|
}
|
2018-02-19 23:23:12 +00:00
|
|
|
out_obj:
|
2015-08-21 07:04:50 +00:00
|
|
|
error_propagate(errp, err);
|
|
|
|
err = NULL;
|
2018-02-19 23:20:03 +00:00
|
|
|
visit_end_implicit_struct(v);
|
2015-08-21 07:04:50 +00:00
|
|
|
out:
|
|
|
|
error_propagate(errp, err);
|
|
|
|
}
|
|
|
|
''')
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
2018-02-19 22:33:32 +00:00
|
|
|
|
qapi-visit: Convert to QAPISchemaVisitor, fixing bugs
Fixes flat unions to visit the base's base members (the previous
commit merely added them to the struct). Same test case.
Patch's effect on visit_type_UserDefFlatUnion():
static void visit_type_UserDefFlatUnion_fields(Visitor *m, UserDefFlatUnion **obj, Error **errp)
{
Error *err = NULL;
+ visit_type_int(m, &(*obj)->integer, "integer", &err);
+ if (err) {
+ goto out;
+ }
visit_type_str(m, &(*obj)->string, "string", &err);
if (err) {
goto out;
Test cases updated for the bug fix.
Fixes alternates to generate a visitor for their implicit enumeration
type. None of them are currently used, obviously. Example:
block-core.json's BlockdevRef now generates
visit_type_BlockdevRefKind().
Code is generated in a different order now, and therefore has got a
few new forward declarations. Doesn't matter.
The guard QAPI_VISIT_BUILTIN_VISITOR_DECL is renamed to
QAPI_VISIT_BUILTIN.
The previous commit's two ugly special cases exist here, too. Mark
both TODO.
Backports commit 441cbac0c7e641780decbc674a9a68c6a5200f71 from qemu
2018-02-19 22:04:55 +00:00
|
|
|
def gen_visit_union(name, base, variants):
|
|
|
|
ret = ''
|
2015-08-21 07:04:50 +00:00
|
|
|
|
|
|
|
if base:
|
qapi-visit: Convert to QAPISchemaVisitor, fixing bugs
Fixes flat unions to visit the base's base members (the previous
commit merely added them to the struct). Same test case.
Patch's effect on visit_type_UserDefFlatUnion():
static void visit_type_UserDefFlatUnion_fields(Visitor *m, UserDefFlatUnion **obj, Error **errp)
{
Error *err = NULL;
+ visit_type_int(m, &(*obj)->integer, "integer", &err);
+ if (err) {
+ goto out;
+ }
visit_type_str(m, &(*obj)->string, "string", &err);
if (err) {
goto out;
Test cases updated for the bug fix.
Fixes alternates to generate a visitor for their implicit enumeration
type. None of them are currently used, obviously. Example:
block-core.json's BlockdevRef now generates
visit_type_BlockdevRefKind().
Code is generated in a different order now, and therefore has got a
few new forward declarations. Doesn't matter.
The guard QAPI_VISIT_BUILTIN_VISITOR_DECL is renamed to
QAPI_VISIT_BUILTIN.
The previous commit's two ugly special cases exist here, too. Mark
both TODO.
Backports commit 441cbac0c7e641780decbc674a9a68c6a5200f71 from qemu
2018-02-19 22:04:55 +00:00
|
|
|
members = [m for m in base.members if m != variants.tag_member]
|
2018-02-19 22:33:32 +00:00
|
|
|
ret += gen_visit_struct_fields(name, None, members)
|
2015-08-21 07:04:50 +00:00
|
|
|
|
qapi-visit: Convert to QAPISchemaVisitor, fixing bugs
Fixes flat unions to visit the base's base members (the previous
commit merely added them to the struct). Same test case.
Patch's effect on visit_type_UserDefFlatUnion():
static void visit_type_UserDefFlatUnion_fields(Visitor *m, UserDefFlatUnion **obj, Error **errp)
{
Error *err = NULL;
+ visit_type_int(m, &(*obj)->integer, "integer", &err);
+ if (err) {
+ goto out;
+ }
visit_type_str(m, &(*obj)->string, "string", &err);
if (err) {
goto out;
Test cases updated for the bug fix.
Fixes alternates to generate a visitor for their implicit enumeration
type. None of them are currently used, obviously. Example:
block-core.json's BlockdevRef now generates
visit_type_BlockdevRefKind().
Code is generated in a different order now, and therefore has got a
few new forward declarations. Doesn't matter.
The guard QAPI_VISIT_BUILTIN_VISITOR_DECL is renamed to
QAPI_VISIT_BUILTIN.
The previous commit's two ugly special cases exist here, too. Mark
both TODO.
Backports commit 441cbac0c7e641780decbc674a9a68c6a5200f71 from qemu
2018-02-19 22:04:55 +00:00
|
|
|
for var in variants.variants:
|
|
|
|
# Ugly special case for simple union TODO get rid of it
|
|
|
|
if not var.simple_union_type():
|
2018-02-19 22:33:32 +00:00
|
|
|
ret += gen_visit_implicit_struct(var.type)
|
2015-08-21 07:04:50 +00:00
|
|
|
|
|
|
|
ret += mcgen('''
|
|
|
|
|
2018-02-19 23:20:03 +00:00
|
|
|
void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error **errp)
|
2015-08-21 07:04:50 +00:00
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
|
2018-02-19 23:20:03 +00:00
|
|
|
visit_start_struct(v, (void **)obj, "%(name)s", name, sizeof(%(c_name)s), &err);
|
2015-08-21 07:04:50 +00:00
|
|
|
if (err) {
|
|
|
|
goto out;
|
|
|
|
}
|
2018-02-19 23:26:12 +00:00
|
|
|
if (!*obj) {
|
|
|
|
goto out_obj;
|
|
|
|
}
|
2015-08-21 07:04:50 +00:00
|
|
|
''',
|
2018-02-19 21:20:07 +00:00
|
|
|
c_name=c_name(name), name=name)
|
2015-08-21 07:04:50 +00:00
|
|
|
|
|
|
|
if base:
|
|
|
|
ret += mcgen('''
|
2018-02-19 23:26:12 +00:00
|
|
|
visit_type_%(c_name)s_fields(v, obj, &err);
|
2015-08-21 07:04:50 +00:00
|
|
|
''',
|
2018-02-19 22:33:32 +00:00
|
|
|
c_name=c_name(name))
|
2018-02-19 23:27:47 +00:00
|
|
|
ret += gen_err_check(label='out_obj')
|
2015-08-21 07:04:50 +00:00
|
|
|
|
2018-02-19 22:33:32 +00:00
|
|
|
tag_key = variants.tag_member.name
|
qapi-visit: Convert to QAPISchemaVisitor, fixing bugs
Fixes flat unions to visit the base's base members (the previous
commit merely added them to the struct). Same test case.
Patch's effect on visit_type_UserDefFlatUnion():
static void visit_type_UserDefFlatUnion_fields(Visitor *m, UserDefFlatUnion **obj, Error **errp)
{
Error *err = NULL;
+ visit_type_int(m, &(*obj)->integer, "integer", &err);
+ if (err) {
+ goto out;
+ }
visit_type_str(m, &(*obj)->string, "string", &err);
if (err) {
goto out;
Test cases updated for the bug fix.
Fixes alternates to generate a visitor for their implicit enumeration
type. None of them are currently used, obviously. Example:
block-core.json's BlockdevRef now generates
visit_type_BlockdevRefKind().
Code is generated in a different order now, and therefore has got a
few new forward declarations. Doesn't matter.
The guard QAPI_VISIT_BUILTIN_VISITOR_DECL is renamed to
QAPI_VISIT_BUILTIN.
The previous commit's two ugly special cases exist here, too. Mark
both TODO.
Backports commit 441cbac0c7e641780decbc674a9a68c6a5200f71 from qemu
2018-02-19 22:04:55 +00:00
|
|
|
if not variants.tag_name:
|
|
|
|
# we pointlessly use a different key for simple unions
|
2018-02-19 22:33:32 +00:00
|
|
|
tag_key = 'type'
|
2015-08-21 07:04:50 +00:00
|
|
|
ret += mcgen('''
|
2018-02-19 23:26:12 +00:00
|
|
|
visit_type_%(c_type)s(v, &(*obj)->%(c_name)s, "%(name)s", &err);
|
|
|
|
if (err) {
|
|
|
|
goto out_obj;
|
|
|
|
}
|
|
|
|
if (!visit_start_union(v, !!(*obj)->data, &err) || err) {
|
|
|
|
goto out_obj;
|
|
|
|
}
|
|
|
|
switch ((*obj)->%(c_name)s) {
|
2015-08-21 07:04:50 +00:00
|
|
|
''',
|
2018-02-19 22:33:32 +00:00
|
|
|
c_type=variants.tag_member.type.c_name(),
|
qapi-visit: Convert to QAPISchemaVisitor, fixing bugs
Fixes flat unions to visit the base's base members (the previous
commit merely added them to the struct). Same test case.
Patch's effect on visit_type_UserDefFlatUnion():
static void visit_type_UserDefFlatUnion_fields(Visitor *m, UserDefFlatUnion **obj, Error **errp)
{
Error *err = NULL;
+ visit_type_int(m, &(*obj)->integer, "integer", &err);
+ if (err) {
+ goto out;
+ }
visit_type_str(m, &(*obj)->string, "string", &err);
if (err) {
goto out;
Test cases updated for the bug fix.
Fixes alternates to generate a visitor for their implicit enumeration
type. None of them are currently used, obviously. Example:
block-core.json's BlockdevRef now generates
visit_type_BlockdevRefKind().
Code is generated in a different order now, and therefore has got a
few new forward declarations. Doesn't matter.
The guard QAPI_VISIT_BUILTIN_VISITOR_DECL is renamed to
QAPI_VISIT_BUILTIN.
The previous commit's two ugly special cases exist here, too. Mark
both TODO.
Backports commit 441cbac0c7e641780decbc674a9a68c6a5200f71 from qemu
2018-02-19 22:04:55 +00:00
|
|
|
# TODO ugly special case for simple union
|
|
|
|
# Use same tag name in C as on the wire to get rid of
|
|
|
|
# it, then: c_name=c_name(variants.tag_member.name)
|
|
|
|
c_name=c_name(variants.tag_name or 'kind'),
|
2018-02-19 22:33:32 +00:00
|
|
|
name=tag_key)
|
2015-08-21 07:04:50 +00:00
|
|
|
|
qapi-visit: Convert to QAPISchemaVisitor, fixing bugs
Fixes flat unions to visit the base's base members (the previous
commit merely added them to the struct). Same test case.
Patch's effect on visit_type_UserDefFlatUnion():
static void visit_type_UserDefFlatUnion_fields(Visitor *m, UserDefFlatUnion **obj, Error **errp)
{
Error *err = NULL;
+ visit_type_int(m, &(*obj)->integer, "integer", &err);
+ if (err) {
+ goto out;
+ }
visit_type_str(m, &(*obj)->string, "string", &err);
if (err) {
goto out;
Test cases updated for the bug fix.
Fixes alternates to generate a visitor for their implicit enumeration
type. None of them are currently used, obviously. Example:
block-core.json's BlockdevRef now generates
visit_type_BlockdevRefKind().
Code is generated in a different order now, and therefore has got a
few new forward declarations. Doesn't matter.
The guard QAPI_VISIT_BUILTIN_VISITOR_DECL is renamed to
QAPI_VISIT_BUILTIN.
The previous commit's two ugly special cases exist here, too. Mark
both TODO.
Backports commit 441cbac0c7e641780decbc674a9a68c6a5200f71 from qemu
2018-02-19 22:04:55 +00:00
|
|
|
for var in variants.variants:
|
|
|
|
# TODO ugly special case for simple union
|
|
|
|
simple_union_type = var.simple_union_type()
|
2018-02-19 22:33:32 +00:00
|
|
|
ret += mcgen('''
|
2018-02-19 23:26:12 +00:00
|
|
|
case %(case)s:
|
2018-02-19 22:33:32 +00:00
|
|
|
''',
|
|
|
|
case=c_enum_const(variants.tag_member.type.name,
|
|
|
|
var.name))
|
qapi-visit: Convert to QAPISchemaVisitor, fixing bugs
Fixes flat unions to visit the base's base members (the previous
commit merely added them to the struct). Same test case.
Patch's effect on visit_type_UserDefFlatUnion():
static void visit_type_UserDefFlatUnion_fields(Visitor *m, UserDefFlatUnion **obj, Error **errp)
{
Error *err = NULL;
+ visit_type_int(m, &(*obj)->integer, "integer", &err);
+ if (err) {
+ goto out;
+ }
visit_type_str(m, &(*obj)->string, "string", &err);
if (err) {
goto out;
Test cases updated for the bug fix.
Fixes alternates to generate a visitor for their implicit enumeration
type. None of them are currently used, obviously. Example:
block-core.json's BlockdevRef now generates
visit_type_BlockdevRefKind().
Code is generated in a different order now, and therefore has got a
few new forward declarations. Doesn't matter.
The guard QAPI_VISIT_BUILTIN_VISITOR_DECL is renamed to
QAPI_VISIT_BUILTIN.
The previous commit's two ugly special cases exist here, too. Mark
both TODO.
Backports commit 441cbac0c7e641780decbc674a9a68c6a5200f71 from qemu
2018-02-19 22:04:55 +00:00
|
|
|
if simple_union_type:
|
2018-02-19 22:33:32 +00:00
|
|
|
ret += mcgen('''
|
2018-02-19 23:26:12 +00:00
|
|
|
visit_type_%(c_type)s(v, &(*obj)->%(c_name)s, "data", &err);
|
2018-02-19 22:33:32 +00:00
|
|
|
''',
|
|
|
|
c_type=simple_union_type.c_name(),
|
|
|
|
c_name=c_name(var.name))
|
2015-08-21 07:04:50 +00:00
|
|
|
else:
|
2018-02-19 22:33:32 +00:00
|
|
|
ret += mcgen('''
|
2018-02-19 23:26:12 +00:00
|
|
|
visit_type_implicit_%(c_type)s(v, &(*obj)->%(c_name)s, &err);
|
2018-02-19 22:33:32 +00:00
|
|
|
''',
|
|
|
|
c_type=var.type.c_name(),
|
|
|
|
c_name=c_name(var.name))
|
2015-08-21 07:04:50 +00:00
|
|
|
|
|
|
|
ret += mcgen('''
|
2018-02-19 23:26:12 +00:00
|
|
|
break;
|
2018-02-19 22:33:32 +00:00
|
|
|
''')
|
2015-08-21 07:04:50 +00:00
|
|
|
|
|
|
|
ret += mcgen('''
|
2018-02-19 23:26:12 +00:00
|
|
|
default:
|
|
|
|
abort();
|
2015-08-21 07:04:50 +00:00
|
|
|
}
|
2018-02-19 23:26:12 +00:00
|
|
|
out_obj:
|
|
|
|
error_propagate(errp, err);
|
|
|
|
err = NULL;
|
|
|
|
visit_end_union(v, !!(*obj)->data, &err);
|
|
|
|
error_propagate(errp, err);
|
|
|
|
err = NULL;
|
2018-02-19 23:20:03 +00:00
|
|
|
visit_end_struct(v, &err);
|
2015-08-21 07:04:50 +00:00
|
|
|
out:
|
|
|
|
error_propagate(errp, err);
|
|
|
|
}
|
|
|
|
''')
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
2018-02-19 22:33:32 +00:00
|
|
|
|
qapi-visit: Convert to QAPISchemaVisitor, fixing bugs
Fixes flat unions to visit the base's base members (the previous
commit merely added them to the struct). Same test case.
Patch's effect on visit_type_UserDefFlatUnion():
static void visit_type_UserDefFlatUnion_fields(Visitor *m, UserDefFlatUnion **obj, Error **errp)
{
Error *err = NULL;
+ visit_type_int(m, &(*obj)->integer, "integer", &err);
+ if (err) {
+ goto out;
+ }
visit_type_str(m, &(*obj)->string, "string", &err);
if (err) {
goto out;
Test cases updated for the bug fix.
Fixes alternates to generate a visitor for their implicit enumeration
type. None of them are currently used, obviously. Example:
block-core.json's BlockdevRef now generates
visit_type_BlockdevRefKind().
Code is generated in a different order now, and therefore has got a
few new forward declarations. Doesn't matter.
The guard QAPI_VISIT_BUILTIN_VISITOR_DECL is renamed to
QAPI_VISIT_BUILTIN.
The previous commit's two ugly special cases exist here, too. Mark
both TODO.
Backports commit 441cbac0c7e641780decbc674a9a68c6a5200f71 from qemu
2018-02-19 22:04:55 +00:00
|
|
|
class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
|
|
|
|
def __init__(self):
|
|
|
|
self.decl = None
|
|
|
|
self.defn = None
|
|
|
|
self._btin = None
|
|
|
|
|
|
|
|
def visit_begin(self, schema):
|
|
|
|
self.decl = ''
|
|
|
|
self.defn = ''
|
|
|
|
self._btin = guardstart('QAPI_VISIT_BUILTIN')
|
|
|
|
|
|
|
|
def visit_end(self):
|
|
|
|
# To avoid header dependency hell, we always generate
|
|
|
|
# declarations for built-in types in our header files and
|
|
|
|
# simply guard them. See also do_builtins (command line
|
|
|
|
# option -b).
|
|
|
|
self._btin += guardend('QAPI_VISIT_BUILTIN')
|
|
|
|
self.decl = self._btin + self.decl
|
|
|
|
self._btin = None
|
|
|
|
|
2018-02-19 23:49:02 +00:00
|
|
|
def visit_needed(self, entity):
|
|
|
|
# Visit everything except implicit objects
|
2018-02-19 23:53:03 +00:00
|
|
|
return not (entity.is_implicit() and
|
|
|
|
isinstance(entity, QAPISchemaObjectType))
|
2018-02-19 23:49:02 +00:00
|
|
|
|
qapi-visit: Convert to QAPISchemaVisitor, fixing bugs
Fixes flat unions to visit the base's base members (the previous
commit merely added them to the struct). Same test case.
Patch's effect on visit_type_UserDefFlatUnion():
static void visit_type_UserDefFlatUnion_fields(Visitor *m, UserDefFlatUnion **obj, Error **errp)
{
Error *err = NULL;
+ visit_type_int(m, &(*obj)->integer, "integer", &err);
+ if (err) {
+ goto out;
+ }
visit_type_str(m, &(*obj)->string, "string", &err);
if (err) {
goto out;
Test cases updated for the bug fix.
Fixes alternates to generate a visitor for their implicit enumeration
type. None of them are currently used, obviously. Example:
block-core.json's BlockdevRef now generates
visit_type_BlockdevRefKind().
Code is generated in a different order now, and therefore has got a
few new forward declarations. Doesn't matter.
The guard QAPI_VISIT_BUILTIN_VISITOR_DECL is renamed to
QAPI_VISIT_BUILTIN.
The previous commit's two ugly special cases exist here, too. Mark
both TODO.
Backports commit 441cbac0c7e641780decbc674a9a68c6a5200f71 from qemu
2018-02-19 22:04:55 +00:00
|
|
|
def visit_enum_type(self, name, info, values, prefix):
|
|
|
|
self.decl += gen_visit_decl(name, scalar=True)
|
2018-02-19 22:33:32 +00:00
|
|
|
self.defn += gen_visit_enum(name)
|
qapi-visit: Convert to QAPISchemaVisitor, fixing bugs
Fixes flat unions to visit the base's base members (the previous
commit merely added them to the struct). Same test case.
Patch's effect on visit_type_UserDefFlatUnion():
static void visit_type_UserDefFlatUnion_fields(Visitor *m, UserDefFlatUnion **obj, Error **errp)
{
Error *err = NULL;
+ visit_type_int(m, &(*obj)->integer, "integer", &err);
+ if (err) {
+ goto out;
+ }
visit_type_str(m, &(*obj)->string, "string", &err);
if (err) {
goto out;
Test cases updated for the bug fix.
Fixes alternates to generate a visitor for their implicit enumeration
type. None of them are currently used, obviously. Example:
block-core.json's BlockdevRef now generates
visit_type_BlockdevRefKind().
Code is generated in a different order now, and therefore has got a
few new forward declarations. Doesn't matter.
The guard QAPI_VISIT_BUILTIN_VISITOR_DECL is renamed to
QAPI_VISIT_BUILTIN.
The previous commit's two ugly special cases exist here, too. Mark
both TODO.
Backports commit 441cbac0c7e641780decbc674a9a68c6a5200f71 from qemu
2018-02-19 22:04:55 +00:00
|
|
|
|
|
|
|
def visit_array_type(self, name, info, element_type):
|
|
|
|
decl = gen_visit_decl(name)
|
|
|
|
defn = gen_visit_list(name, element_type)
|
|
|
|
if isinstance(element_type, QAPISchemaBuiltinType):
|
|
|
|
self._btin += decl
|
|
|
|
if do_builtins:
|
|
|
|
self.defn += defn
|
|
|
|
else:
|
|
|
|
self.decl += decl
|
|
|
|
self.defn += defn
|
|
|
|
|
|
|
|
def visit_object_type(self, name, info, base, members, variants):
|
2018-02-19 23:49:02 +00:00
|
|
|
self.decl += gen_visit_decl(name)
|
|
|
|
if variants:
|
|
|
|
assert not members # not implemented
|
|
|
|
self.defn += gen_visit_union(name, base, variants)
|
|
|
|
else:
|
|
|
|
self.defn += gen_visit_struct(name, base, members)
|
qapi-visit: Convert to QAPISchemaVisitor, fixing bugs
Fixes flat unions to visit the base's base members (the previous
commit merely added them to the struct). Same test case.
Patch's effect on visit_type_UserDefFlatUnion():
static void visit_type_UserDefFlatUnion_fields(Visitor *m, UserDefFlatUnion **obj, Error **errp)
{
Error *err = NULL;
+ visit_type_int(m, &(*obj)->integer, "integer", &err);
+ if (err) {
+ goto out;
+ }
visit_type_str(m, &(*obj)->string, "string", &err);
if (err) {
goto out;
Test cases updated for the bug fix.
Fixes alternates to generate a visitor for their implicit enumeration
type. None of them are currently used, obviously. Example:
block-core.json's BlockdevRef now generates
visit_type_BlockdevRefKind().
Code is generated in a different order now, and therefore has got a
few new forward declarations. Doesn't matter.
The guard QAPI_VISIT_BUILTIN_VISITOR_DECL is renamed to
QAPI_VISIT_BUILTIN.
The previous commit's two ugly special cases exist here, too. Mark
both TODO.
Backports commit 441cbac0c7e641780decbc674a9a68c6a5200f71 from qemu
2018-02-19 22:04:55 +00:00
|
|
|
|
|
|
|
def visit_alternate_type(self, name, info, variants):
|
|
|
|
self.decl += gen_visit_decl(name)
|
|
|
|
self.defn += gen_visit_alternate(name, variants)
|
|
|
|
|
|
|
|
# If you link code generated from multiple schemata, you want only one
|
|
|
|
# instance of the code for built-in types. Generate it only when
|
|
|
|
# do_builtins, enabled by command line option -b. See also
|
|
|
|
# QAPISchemaGenVisitVisitor.visit_end().
|
2015-08-21 07:04:50 +00:00
|
|
|
do_builtins = False
|
|
|
|
|
2018-02-19 20:19:07 +00:00
|
|
|
(input_file, output_dir, do_c, do_h, prefix, opts) = \
|
|
|
|
parse_command_line("b", ["builtins"])
|
|
|
|
|
2015-08-21 07:04:50 +00:00
|
|
|
for o, a in opts:
|
2018-02-19 20:19:07 +00:00
|
|
|
if o in ("-b", "--builtins"):
|
2015-08-21 07:04:50 +00:00
|
|
|
do_builtins = True
|
|
|
|
|
2018-02-19 20:31:47 +00:00
|
|
|
c_comment = '''
|
2015-08-21 07:04:50 +00:00
|
|
|
/*
|
|
|
|
* schema-defined QAPI visitor functions
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
2018-02-19 20:31:47 +00:00
|
|
|
'''
|
|
|
|
h_comment = '''
|
2015-08-21 07:04:50 +00:00
|
|
|
/*
|
|
|
|
* schema-defined QAPI visitor functions
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
2018-02-19 20:31:47 +00:00
|
|
|
'''
|
2015-08-21 07:04:50 +00:00
|
|
|
|
2018-02-19 20:31:47 +00:00
|
|
|
(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
|
|
|
|
'qapi-visit.c', 'qapi-visit.h',
|
|
|
|
c_comment, h_comment)
|
2015-08-21 07:04:50 +00:00
|
|
|
|
2018-02-19 20:31:47 +00:00
|
|
|
fdef.write(mcgen('''
|
|
|
|
#include "qemu-common.h"
|
|
|
|
#include "%(prefix)sqapi-visit.h"
|
|
|
|
''',
|
2018-02-19 22:33:32 +00:00
|
|
|
prefix=prefix))
|
2018-02-19 20:31:47 +00:00
|
|
|
|
|
|
|
fdecl.write(mcgen('''
|
2015-08-21 07:04:50 +00:00
|
|
|
#include "qapi/visitor.h"
|
|
|
|
#include "%(prefix)sqapi-types.h"
|
|
|
|
|
|
|
|
''',
|
2018-02-19 20:31:47 +00:00
|
|
|
prefix=prefix))
|
2015-08-21 07:04:50 +00:00
|
|
|
|
qapi-visit: Convert to QAPISchemaVisitor, fixing bugs
Fixes flat unions to visit the base's base members (the previous
commit merely added them to the struct). Same test case.
Patch's effect on visit_type_UserDefFlatUnion():
static void visit_type_UserDefFlatUnion_fields(Visitor *m, UserDefFlatUnion **obj, Error **errp)
{
Error *err = NULL;
+ visit_type_int(m, &(*obj)->integer, "integer", &err);
+ if (err) {
+ goto out;
+ }
visit_type_str(m, &(*obj)->string, "string", &err);
if (err) {
goto out;
Test cases updated for the bug fix.
Fixes alternates to generate a visitor for their implicit enumeration
type. None of them are currently used, obviously. Example:
block-core.json's BlockdevRef now generates
visit_type_BlockdevRefKind().
Code is generated in a different order now, and therefore has got a
few new forward declarations. Doesn't matter.
The guard QAPI_VISIT_BUILTIN_VISITOR_DECL is renamed to
QAPI_VISIT_BUILTIN.
The previous commit's two ugly special cases exist here, too. Mark
both TODO.
Backports commit 441cbac0c7e641780decbc674a9a68c6a5200f71 from qemu
2018-02-19 22:04:55 +00:00
|
|
|
schema = QAPISchema(input_file)
|
|
|
|
gen = QAPISchemaGenVisitVisitor()
|
|
|
|
schema.visit(gen)
|
|
|
|
fdef.write(gen.defn)
|
|
|
|
fdecl.write(gen.decl)
|
2015-08-21 07:04:50 +00:00
|
|
|
|
2018-02-19 20:31:47 +00:00
|
|
|
close_output(fdef, fdecl)
|