qapi: Plumb in 'boxed' to qapi generator lower levels

The next 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.  Even without a union, being able to use
a C struct rather than a list of parameters can make it much
easier to handle coding with QAPI.

This patch adds the internal plumbing of a 'boxed' flag
associated with each command and event.  In several cases,
this means adding indentation, with one new dead branch and
the remaining branch being the original code more deeply
nested; this was done so that the new implementation in the
next patch is easier to review without also being mixed with
indentation changes.

For this patch, no behavior or generated output changes, other
than the testsuite outputting the value of the new flag
(always False for now).

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-9-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Identifier box renamed to boxed in two places]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
This commit is contained in:
Eric Blake 2016-07-13 21:50:19 -06:00 committed by Markus Armbruster
parent 4d0b268fdb
commit 48825ca419
9 changed files with 70 additions and 49 deletions

View file

@ -16,20 +16,22 @@ from qapi import *
import re
def gen_command_decl(name, arg_type, ret_type):
def gen_command_decl(name, arg_type, boxed, 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, boxed, 'Error **errp'))
def gen_call(name, arg_type, ret_type):
def gen_call(name, arg_type, boxed, ret_type):
ret = ''
argstr = ''
if arg_type:
if boxed:
assert False # not implemented
elif arg_type:
assert not arg_type.variants
for memb in arg_type.members:
if memb.optional:
@ -94,7 +96,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, boxed, ret_type):
ret = mcgen('''
%(proto)s
@ -136,7 +138,7 @@ def gen_marshal(name, arg_type, ret_type):
(void)args;
''')
ret += gen_call(name, arg_type, ret_type)
ret += gen_call(name, arg_type, boxed, ret_type)
# 'goto out' produced above for arg_type, and by gen_call() for ret_type
if (arg_type and not arg_type.is_empty()) or ret_type:
@ -212,16 +214,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, boxed):
if not gen:
return
self.decl += gen_command_decl(name, arg_type, ret_type)
self.decl += gen_command_decl(name, arg_type, boxed, 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, boxed, ret_type)
if not middle_mode:
self._regy += gen_register_command(name, success_response)