Skip to content

Commit

Permalink
qapi-visit: Expose visit_type_FOO_members()
Browse files Browse the repository at this point in the history
Dan Berrange reported a case where he needs to work with a
QCryptoBlockOptions union type using the OptsVisitor, but only
visit one of the branches of that type (the discriminator is not
visited directly, but learned externally).  When things were
boxed, it was easy: just visit the variant directly, which took
care of both allocating the variant and visiting its members, then
store that pointer in the union type.  But now that things are
unboxed, we need a way to visit the members without allocation,
done by exposing visit_type_FOO_members() to the user.

Before the patch, we had quite a bit of code associated with
object_members_seen to make sure that a declaration of the helper
was in scope before any use of the function.  But now that the
helper is public and declared in the header, the .c file no
longer needs to worry about topological sorting (the helper is
always in scope), which leads to some nice cleanups.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1457021813-10704-4-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
  • Loading branch information
ebblake authored and Markus Armbruster committed Mar 5, 2016
1 parent c81200b commit 4d91e91
Showing 1 changed file with 7 additions and 26 deletions.
33 changes: 7 additions & 26 deletions scripts/qapi-visit.py
Expand Up @@ -15,10 +15,6 @@
from qapi import *
import re

# visit_type_FOO_members() is always emitted; track if a forward declaration
# or implementation has already been output.
object_members_seen = set()


def gen_visit_decl(name, scalar=False):
c_type = c_name(name) + ' *'
Expand All @@ -30,37 +26,23 @@ def gen_visit_decl(name, scalar=False):
c_name=c_name(name), c_type=c_type)


def gen_visit_members_decl(typ):
if typ.name in object_members_seen:
return ''
object_members_seen.add(typ.name)
def gen_visit_members_decl(name):
return mcgen('''
static void visit_type_%(c_type)s_members(Visitor *v, %(c_type)s *obj, Error **errp);
void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp);
''',
c_type=typ.c_name())
c_name=c_name(name))


def gen_visit_object_members(name, base, members, variants):
ret = ''
ret = mcgen('''
if base:
ret += gen_visit_members_decl(base)
if variants:
for var in variants.variants:
# Ugly special case for simple union TODO get rid of it
if not var.simple_union_type():
ret += gen_visit_members_decl(var.type)

object_members_seen.add(name)
ret += mcgen('''
static void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
{
Error *err = NULL;
''',
c_name=c_name(name))
c_name=c_name(name))

if base:
ret += mcgen('''
Expand Down Expand Up @@ -173,8 +155,6 @@ def gen_visit_alternate(name, variants):
for var in variants.variants:
if var.type.alternate_qtype() == 'QTYPE_QINT':
promote_int = 'false'
if isinstance(var.type, QAPISchemaObjectType):
ret += gen_visit_members_decl(var.type)

ret += mcgen('''
Expand Down Expand Up @@ -316,6 +296,7 @@ def visit_array_type(self, name, info, element_type):
self.defn += defn

def visit_object_type(self, name, info, base, members, variants):
self.decl += gen_visit_members_decl(name)
self.decl += gen_visit_decl(name)
self.defn += gen_visit_object(name, base, members, variants)

Expand Down

0 comments on commit 4d91e91

Please sign in to comment.