[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v6 06/16] qapi: Plumb in 'box' to qapi generator low
From: |
Eric Blake |
Subject: |
[Qemu-devel] [PATCH v6 06/16] qapi: Plumb in 'box' to qapi generator lower levels |
Date: |
Wed, 23 Dec 2015 13:55:35 -0700 |
A future patch will add support for passing a qapi union
type as the 'data' of a command. But to do that, the user
function for implementing the command, as called by the
generated marshal command, must take the corresponding C
struct as a single boxed pointer, rather than a breakdown
into one parameter per member. This patch adds the
internal plubming of a 'box' flag associated with each
command and event. For this patch, no behavior changes,
other than the testsuite outputting the value of the new
flag (always False for now).
Signed-off-by: Eric Blake <address@hidden>
---
v6: rebase to earlier changes
---
scripts/qapi-commands.py | 61 +++++++++++++++++++--------------
scripts/qapi-event.py | 34 ++++++++++--------
scripts/qapi-introspect.py | 4 +--
scripts/qapi.py | 46 +++++++++++++++----------
tests/qapi-schema/event-case.out | 1 +
tests/qapi-schema/ident-with-escape.out | 2 +-
tests/qapi-schema/indented-expr.out | 4 +--
tests/qapi-schema/qapi-schema-test.out | 19 ++++++----
tests/qapi-schema/test-qapi.py | 8 +++--
9 files changed, 106 insertions(+), 73 deletions(-)
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index 9d455c3..efdeb70 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -16,24 +16,27 @@ from qapi import *
import re
-def gen_command_decl(name, arg_type, ret_type):
+def gen_command_decl(name, arg_type, box, 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'))
+ params=gen_params(arg_type, box, 'Error **errp'))
-def gen_call(name, arg_type, ret_type):
+def gen_call(name, arg_type, box, ret_type):
ret = ''
argstr = ''
assert arg_type
- for memb in arg_type.members:
- if memb.optional:
- argstr += 'has_%s, ' % c_name(memb.name)
- argstr += '%s, ' % c_name(memb.name)
+ if box and not arg_type.is_empty():
+ assert False # not implemented
+ else:
+ 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:
@@ -54,7 +57,7 @@ def gen_call(name, arg_type, ret_type):
return ret
-def gen_marshal_vars(arg_type, ret_type):
+def gen_marshal_vars(arg_type, box, ret_type):
ret = mcgen('''
Error *err = NULL;
''')
@@ -73,18 +76,21 @@ def gen_marshal_vars(arg_type, ret_type):
Visitor *v;
''')
- for memb in arg_type.members:
- if memb.optional:
- ret += mcgen('''
+ if box:
+ assert False # not implemented
+ else:
+ 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_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())
+ c_name=c_name(memb.name),
+ c_type=memb.type.c_type(),
+ c_null=memb.type.c_null())
ret += '\n'
else:
ret += mcgen('''
@@ -95,7 +101,7 @@ def gen_marshal_vars(arg_type, ret_type):
return ret
-def gen_marshal_input_visit(arg_type, dealloc=False):
+def gen_marshal_input_visit(arg_type, box, dealloc=False):
ret = ''
if arg_type.is_empty():
@@ -112,7 +118,10 @@ def gen_marshal_input_visit(arg_type, dealloc=False):
v = qmp_input_get_visitor(qiv);
''')
- ret += gen_visit_fields(arg_type.members, skiperr=dealloc)
+ if box:
+ assert False # not implemented
+ else:
+ ret += gen_visit_fields(arg_type.members, skiperr=dealloc)
if dealloc:
ret += mcgen('''
@@ -164,7 +173,7 @@ def gen_marshal_decl(name):
proto=gen_marshal_proto(name))
-def gen_marshal(name, arg_type, ret_type):
+def gen_marshal(name, arg_type, box, ret_type):
ret = mcgen('''
%(proto)s
@@ -172,9 +181,9 @@ def gen_marshal(name, arg_type, ret_type):
''',
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)
+ ret += gen_marshal_vars(arg_type, box, ret_type)
+ ret += gen_marshal_input_visit(arg_type, box)
+ ret += gen_call(name, arg_type, box, 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
@@ -186,7 +195,7 @@ out:
ret += mcgen('''
error_propagate(errp, err);
''')
- ret += gen_marshal_input_visit(arg_type, dealloc=True)
+ ret += gen_marshal_input_visit(arg_type, box, dealloc=True)
ret += mcgen('''
}
''')
@@ -241,16 +250,16 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
self._visited_ret_types = None
def visit_command(self, name, info, arg_type, ret_type,
- gen, success_response):
+ gen, success_response, box):
if not gen:
return
- self.decl += gen_command_decl(name, arg_type, ret_type)
+ self.decl += gen_command_decl(name, arg_type, box, 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)
+ self.defn += gen_marshal(name, arg_type, box, ret_type)
if not middle_mode:
self._regy += gen_register_command(name, success_response)
diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
index e694b1b..451d077 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi-event.py
@@ -14,21 +14,21 @@
from qapi import *
-def gen_event_send_proto(name, arg_type):
+def gen_event_send_proto(name, arg_type, box):
return 'void qapi_event_send_%(c_name)s(%(param)s)' % {
'c_name': c_name(name.lower()),
- 'param': gen_params(arg_type, 'Error **errp')}
+ 'param': gen_params(arg_type, box, 'Error **errp')}
-def gen_event_send_decl(name, arg_type):
+def gen_event_send_decl(name, arg_type, box):
return mcgen('''
%(proto)s;
''',
- proto=gen_event_send_proto(name, arg_type))
+ proto=gen_event_send_proto(name, arg_type, box))
-def gen_event_send(name, arg_type):
+def gen_event_send(name, arg_type, box):
ret = mcgen('''
%(proto)s
@@ -37,7 +37,7 @@ def gen_event_send(name, arg_type):
Error *err = NULL;
QMPEventFuncEmit emit;
''',
- proto=gen_event_send_proto(name, arg_type))
+ proto=gen_event_send_proto(name, arg_type, box))
assert arg_type
if not arg_type.is_empty():
@@ -64,13 +64,19 @@ def gen_event_send(name, arg_type):
qov = qmp_output_visitor_new();
v = qmp_output_get_visitor(qov);
+''')
+
+ if box:
+ assert False # not implemented
+ else:
+ ret += mcgen('''
visit_start_struct(v, "%(name)s", NULL, 0, &err);
''',
- name=name)
- ret += gen_err_check()
- ret += gen_visit_fields(arg_type.members, need_cast=True,
- label='out_obj')
- ret += mcgen('''
+ name=name)
+ ret += gen_err_check()
+ ret += gen_visit_fields(arg_type.members, need_cast=True,
+ label='out_obj')
+ ret += mcgen('''
visit_check_struct(v, &err);
out_obj:
visit_end_struct(v);
@@ -119,9 +125,9 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
self.defn += gen_enum_lookup(event_enum_name, self._event_names)
self._event_names = None
- def visit_event(self, name, info, arg_type):
- self.decl += gen_event_send_decl(name, arg_type)
- self.defn += gen_event_send(name, arg_type)
+ def visit_event(self, name, info, arg_type, box):
+ self.decl += gen_event_send_decl(name, arg_type, box)
+ self.defn += gen_event_send(name, arg_type, box)
self._event_names.append(name)
diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index 64f2cd0..293740e 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -154,14 +154,14 @@ const char %(c_name)s[] = %(c_string)s;
for m in variants.variants]})
def visit_command(self, name, info, arg_type, ret_type,
- gen, success_response):
+ gen, success_response, box):
arg_type = arg_type or self._schema.the_empty_object_type
ret_type = ret_type or self._schema.the_empty_object_type
self._gen_json(name, 'command',
{'arg-type': self._use_type(arg_type),
'ret-type': self._use_type(ret_type)})
- def visit_event(self, name, info, arg_type):
+ def visit_event(self, name, info, arg_type, box):
arg_type = arg_type or self._schema.the_empty_object_type
self._gen_json(name, 'event', {'arg-type': self._use_type(arg_type)})
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 311bed9..b408a82 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -813,10 +813,10 @@ class QAPISchemaVisitor(object):
pass
def visit_command(self, name, info, arg_type, ret_type,
- gen, success_response):
+ gen, success_response, box):
pass
- def visit_event(self, name, info, arg_type):
+ def visit_event(self, name, info, arg_type, box):
pass
@@ -1147,7 +1147,8 @@ class QAPISchemaAlternateType(QAPISchemaType):
class QAPISchemaCommand(QAPISchemaEntity):
- def __init__(self, name, info, arg_type, ret_type, gen, success_response):
+ def __init__(self, name, info, arg_type, ret_type, gen, success_response,
+ box):
QAPISchemaEntity.__init__(self, name, info)
assert not arg_type or isinstance(arg_type, str)
assert not ret_type or isinstance(ret_type, str)
@@ -1157,12 +1158,14 @@ class QAPISchemaCommand(QAPISchemaEntity):
self.ret_type = None
self.gen = gen
self.success_response = success_response
+ self.box = box
def check(self, schema):
if self._arg_type_name:
self.arg_type = schema.lookup_type(self._arg_type_name)
assert isinstance(self.arg_type, QAPISchemaObjectType)
- assert not self.arg_type.variants # not implemented
+ if not self.box:
+ assert not self.arg_type.variants
if self._ret_type_name:
self.ret_type = schema.lookup_type(self._ret_type_name)
assert isinstance(self.ret_type, QAPISchemaType)
@@ -1170,24 +1173,26 @@ class QAPISchemaCommand(QAPISchemaEntity):
def visit(self, visitor):
visitor.visit_command(self.name, self.info,
self.arg_type, self.ret_type,
- self.gen, self.success_response)
+ self.gen, self.success_response, self.box)
class QAPISchemaEvent(QAPISchemaEntity):
- def __init__(self, name, info, arg_type):
+ def __init__(self, name, info, arg_type, box):
QAPISchemaEntity.__init__(self, name, info)
assert not arg_type or isinstance(arg_type, str)
self._arg_type_name = arg_type
self.arg_type = None
+ self.box = box
def check(self, schema):
if self._arg_type_name:
self.arg_type = schema.lookup_type(self._arg_type_name)
assert isinstance(self.arg_type, QAPISchemaObjectType)
- assert not self.arg_type.variants # not implemented
+ if not self.box:
+ assert not self.arg_type.variants
def visit(self, visitor):
- visitor.visit_event(self.name, self.info, self.arg_type)
+ visitor.visit_event(self.name, self.info, self.arg_type, self.box)
class QAPISchema(object):
@@ -1361,6 +1366,7 @@ class QAPISchema(object):
rets = expr.get('returns')
gen = expr.get('gen', True)
success_response = expr.get('success-response', True)
+ box = expr.get('box', False)
if isinstance(data, dict):
data = self._make_implicit_object_type(
name, info, 'arg', self._make_members(data, info))
@@ -1368,15 +1374,16 @@ class QAPISchema(object):
assert len(rets) == 1
rets = self._make_array_type(rets[0], info)
self._def_entity(QAPISchemaCommand(name, info, data, rets, gen,
- success_response))
+ success_response, box))
def _def_event(self, expr, info):
name = expr['event']
data = expr.get('data', {})
+ box = expr.get('box', False)
if isinstance(data, dict):
data = self._make_implicit_object_type(
name, info, 'arg', self._make_members(data, info))
- self._def_entity(QAPISchemaEvent(name, info, data))
+ self._def_entity(QAPISchemaEvent(name, info, data, box))
def _def_exprs(self):
for expr_elem in self.exprs:
@@ -1619,17 +1626,20 @@ extern const char *const %(c_name)s_lookup[];
return ret
-def gen_params(arg_type, extra):
+def gen_params(arg_type, box, extra):
assert arg_type
- assert not arg_type.variants
ret = ''
sep = ''
- for memb in arg_type.members:
- ret += sep
- sep = ', '
- if memb.optional:
- ret += 'bool has_%s, ' % c_name(memb.name)
- ret += '%s %s' % (memb.type.c_type(is_param=True), c_name(memb.name))
+ if box and not arg_type.is_empty():
+ assert False # not implemented
+ else:
+ for memb in arg_type.members:
+ ret += sep
+ sep = ', '
+ if memb.optional:
+ ret += 'bool has_%s, ' % c_name(memb.name)
+ ret += '%s %s' % (memb.type.c_type(is_param=True),
+ c_name(memb.name))
if extra:
ret += sep + extra
return ret
diff --git a/tests/qapi-schema/event-case.out b/tests/qapi-schema/event-case.out
index 18866d9..9fa846c 100644
--- a/tests/qapi-schema/event-case.out
+++ b/tests/qapi-schema/event-case.out
@@ -2,3 +2,4 @@ object :empty
enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat',
'qbool']
prefix QTYPE
event oops :empty
+ box=False
diff --git a/tests/qapi-schema/ident-with-escape.out
b/tests/qapi-schema/ident-with-escape.out
index 142cd19..1b415e7 100644
--- a/tests/qapi-schema/ident-with-escape.out
+++ b/tests/qapi-schema/ident-with-escape.out
@@ -5,4 +5,4 @@ object :obj-fooA-arg
enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat',
'qbool']
prefix QTYPE
command fooA :obj-fooA-arg -> None
- gen=True success_response=True
+ gen=True success_response=True box=False
diff --git a/tests/qapi-schema/indented-expr.out
b/tests/qapi-schema/indented-expr.out
index 5c25fcd..9f5c1e9 100644
--- a/tests/qapi-schema/indented-expr.out
+++ b/tests/qapi-schema/indented-expr.out
@@ -2,6 +2,6 @@ object :empty
enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat',
'qbool']
prefix QTYPE
command eins :empty -> None
- gen=True success_response=True
+ gen=True success_response=True box=False
command zwei :empty -> None
- gen=True success_response=True
+ gen=True success_response=True box=False
diff --git a/tests/qapi-schema/qapi-schema-test.out
b/tests/qapi-schema/qapi-schema-test.out
index 755393a..8731caa 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -100,9 +100,13 @@ alternate AltStrNum
case s: str
case n: number
event EVENT_A :empty
+ box=False
event EVENT_B :empty
+ box=False
event EVENT_C :obj-EVENT_C-arg
+ box=False
event EVENT_D :obj-EVENT_D-arg
+ box=False
object Empty1
base :empty
object Empty2
@@ -214,6 +218,7 @@ object UserDefZero
base :empty
member integer: int optional=False
event __ORG.QEMU_X-EVENT __org.qemu_x-Struct
+ box=False
alternate __org.qemu_x-Alt
tag type
case __org.qemu_x-branch: str
@@ -240,16 +245,16 @@ object __org.qemu_x-Union2
tag __org.qemu_x-member1
case __org.qemu_x-value: __org.qemu_x-Struct2
command __org.qemu_x-command :obj-__org.qemu_x-command-arg ->
__org.qemu_x-Union1
- gen=True success_response=True
+ gen=True success_response=True box=False
command guest-get-time :obj-guest-get-time-arg -> int
- gen=True success_response=True
+ gen=True success_response=True box=False
command guest-sync :obj-guest-sync-arg -> any
- gen=True success_response=True
+ gen=True success_response=True box=False
command user_def_cmd :empty -> None
- gen=True success_response=True
+ gen=True success_response=True box=False
command user_def_cmd0 Empty2 -> Empty2
- gen=True success_response=True
+ gen=True success_response=True box=False
command user_def_cmd1 :obj-user_def_cmd1-arg -> None
- gen=True success_response=True
+ gen=True success_response=True box=False
command user_def_cmd2 :obj-user_def_cmd2-arg -> UserDefTwo
- gen=True success_response=True
+ gen=True success_response=True box=False
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index bedd145..d82af59 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -36,13 +36,15 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
self._print_variants(variants)
def visit_command(self, name, info, arg_type, ret_type,
- gen, success_response):
+ gen, success_response, box):
print 'command %s %s -> %s' % \
(name, arg_type and arg_type.name, ret_type and ret_type.name)
- print ' gen=%s success_response=%s' % (gen, success_response)
+ print ' gen=%s success_response=%s box=%s' % (gen, success_response,
+ box)
- def visit_event(self, name, info, arg_type):
+ def visit_event(self, name, info, arg_type, box):
print 'event %s %s' % (name, arg_type and arg_type.name)
+ print ' box=%s' % box
@staticmethod
def _print_variants(variants):
--
2.4.3
- [Qemu-devel] [PATCH v6 00/16] qapi netdev_add introspection (post-introspection cleanups subset F), Eric Blake, 2015/12/23
- [Qemu-devel] [PATCH v6 03/16] qapi: Forbid empty unions and useless alternates, Eric Blake, 2015/12/23
- [Qemu-devel] [PATCH v6 04/16] qapi: Drop useless 'data' member of unions, Eric Blake, 2015/12/23
- [Qemu-devel] [PATCH v6 01/16] net: use Netdev instead of NetClientOptions in client init, Eric Blake, 2015/12/23
- [Qemu-devel] [PATCH v6 08/16] qapi: support implicit structs in OptsVisitor, Eric Blake, 2015/12/23
- [Qemu-devel] [PATCH v6 07/16] qapi: Implement boxed types for commands/events, Eric Blake, 2015/12/23
- [Qemu-devel] [PATCH v6 05/16] qapi: Hide tag_name data member of variants, Eric Blake, 2015/12/23
- [Qemu-devel] [PATCH v6 02/16] qapi: Avoid use of 'data' member of qapi unions, Eric Blake, 2015/12/23
- [Qemu-devel] [PATCH v6 06/16] qapi: Plumb in 'box' to qapi generator lower levels,
Eric Blake <=
- [Qemu-devel] [PATCH v6 11/16] net: Complete qapi-fication of netdev_add, Eric Blake, 2015/12/23
- [Qemu-devel] [PATCH v6 14/16] qapi: Use anonymous base in Netdev, Eric Blake, 2015/12/23
- [Qemu-devel] [PATCH v6 13/16] qapi: Use anonymous base in SchemaInfo, Eric Blake, 2015/12/23
- [Qemu-devel] [PATCH v6 15/16] qapi: Use anonymous base in CpuInfo, Eric Blake, 2015/12/23
- [Qemu-devel] [PATCH v6 10/16] net: Use correct type for bool flag, Eric Blake, 2015/12/23
- [Qemu-devel] [PATCH v6 16/16] qapi: Populate info['name'] for each entity, Eric Blake, 2015/12/23
- [Qemu-devel] [PATCH v6 12/16] qapi: Allow anonymous base for flat union, Eric Blake, 2015/12/23
- [Qemu-devel] [PATCH v6 09/16] qapi: Change Netdev into a flat union, Eric Blake, 2015/12/23
- Re: [Qemu-devel] [PATCH v6 00/16] qapi netdev_add introspection (post-introspection cleanups subset F), Eric Blake, 2015/12/23