QAPI patches for 2018-12-13

-----BEGIN PGP SIGNATURE-----
 
 iQIcBAABAgAGBQJcE0VvAAoJEDhwtADrkYZTLCkP/RvRR9iTcoM98kcFNjqBZRQa
 rUbSNBavxwzutPiT40WcNhg7hc0Uaptve8oMkGcfyyTh9UyhdOe8WNPxTos96vYt
 GtUhNhknGlvP4A7Zjs6KIIhl084MtPkpuPERkXZL4lgNrIw8BrFoj5hkZ3UIvItf
 14oA1o6Zf9UxN1Yt12lZnG9N8t4ld5IKhkXh/FQ6OJNHz9GrhPq4A7vd4ipBRBjt
 PjvXVOYCEkiHRfJ3Qv5Thk2C1xzLRFusA5ff1rju324KGPoM8oZ+xGSUVqD0hhMe
 Kpzv4a6HV7SuM1fqJoZrF87VOhAO9bpxzIHUp83FhpKGDH4xqppDWYno/+9imPDA
 DAHUaOeaKpX6O4ttB96jRwTEOAbq3TzPqtYiyRaXhbtCc0dKi0HxHmIpwS4KNkHK
 Y3VuoTavarMfuLl2gDO+9PJhHxol8g0oYiaxXddW0svgnSM3xBTz/hGE2duStHTb
 DSWDVB/oVIOyR8eWSglUnc+OOJrxSkiaJelSU730Uc6kIk7hiY8PFQiwqebsI6uq
 IOABDG1/W0FkSRNl5QwXnGlD0eUzl1ySm2zvsgvJrC8ooAhzjjWdkcwtEdEYxlUj
 KqH+8ZFP+mOckrW9boqYPVqOL4GzNMnK23vEoidurhyShsmiCTyk+jckiJrl/IMy
 OlwA850MKVJ3W3+knR0I
 =bymN
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2018-12-13-v2' into staging

QAPI patches for 2018-12-13

# gpg: Signature made Fri 14 Dec 2018 05:53:51 GMT
# gpg:                using RSA key 3870B400EB918653
# gpg: Good signature from "Markus Armbruster <armbru@redhat.com>"
# gpg:                 aka "Markus Armbruster <armbru@pond.sub.org>"
# Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867  4E5F 3870 B400 EB91 8653

* remotes/armbru/tags/pull-qapi-2018-12-13-v2: (32 commits)
  qapi: add conditions to REPLICATION type/commands on the schema
  qapi: add more conditions to SPICE
  qapi: add condition to variants documentation
  qapi: add 'If:' condition to struct members documentation
  qapi: add 'If:' condition to enum values documentation
  qapi: Add #if conditions to generated code members
  qapi: add 'if' to alternate members
  qapi: add 'if' to union members
  qapi: Add 'if' to implicit struct members
  qapi: add a dictionary form for TYPE
  qapi-events: add 'if' condition to implicit event enum
  qapi: add 'if' to enum members
  qapi: add a dictionary form with 'name' key for enum members
  qapi: improve reporting of unknown or missing keys
  qapi: factor out checking for keys
  tests: print enum type members more like object type members
  qapi: change enum visitor and gen_enum* to take QAPISchemaMember
  qapi: Do not define enumeration value explicitly
  qapi: break long lines at 'data' member
  qapi: rename QAPISchemaEnumType.values to .members
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2018-12-15 21:19:06 +00:00
commit 81781be3c9
91 changed files with 1166 additions and 510 deletions

View file

@ -588,11 +588,11 @@ def discriminator_find_enum_define(expr):
if not base_members:
return None
discriminator_type = base_members.get(discriminator)
if not discriminator_type:
discriminator_value = base_members.get(discriminator)
if not discriminator_value:
return None
return enum_types.get(discriminator_type)
return enum_types.get(discriminator_value['type'])
# Names must be letters, numbers, -, and _. They must start with letter,
@ -704,8 +704,10 @@ def check_type(info, source, value, allow_array=False,
% (source, key))
# Todo: allow dictionaries to represent default values of
# an optional argument.
check_type(info, "Member '%s' of %s" % (key, source), arg,
allow_array=True,
check_known_keys(info, "member '%s' of %s" % (key, source),
arg, ['type'], ['if'])
check_type(info, "Member '%s' of %s" % (key, source),
arg['type'], allow_array=True,
allow_metas=['built-in', 'union', 'alternate', 'struct',
'enum'])
@ -740,6 +742,10 @@ def check_event(expr, info):
allow_metas=meta)
def enum_get_names(expr):
return [e['name'] for e in expr['data']]
def check_union(expr, info):
name = expr['union']
base = expr.get('base')
@ -772,13 +778,17 @@ def check_union(expr, info):
# member of the base struct.
check_name(info, "Discriminator of flat union '%s'" % name,
discriminator)
discriminator_type = base_members.get(discriminator)
if not discriminator_type:
discriminator_value = base_members.get(discriminator)
if not discriminator_value:
raise QAPISemError(info,
"Discriminator '%s' is not a member of base "
"struct '%s'"
% (discriminator, base))
enum_define = enum_types.get(discriminator_type)
if discriminator_value.get('if'):
raise QAPISemError(info, 'The discriminator %s.%s for union %s '
'must not be conditional' %
(base, discriminator, name))
enum_define = enum_types.get(discriminator_value['type'])
allow_metas = ['struct']
# Do not allow string discriminator
if not enum_define:
@ -792,14 +802,17 @@ def check_union(expr, info):
for (key, value) in members.items():
check_name(info, "Member of union '%s'" % name, key)
check_known_keys(info, "member '%s' of union '%s'" % (key, name),
value, ['type'], ['if'])
# Each value must name a known type
check_type(info, "Member '%s' of union '%s'" % (key, name),
value, allow_array=not base, allow_metas=allow_metas)
value['type'],
allow_array=not base, allow_metas=allow_metas)
# If the discriminator names an enum type, then all members
# of 'data' must also be members of the enum type.
if enum_define:
if key not in enum_define['data']:
if key not in enum_get_names(enum_define):
raise QAPISemError(info,
"Discriminator value '%s' is not found in "
"enum '%s'"
@ -818,20 +831,23 @@ def check_alternate(expr, info):
"in 'data'" % name)
for (key, value) in members.items():
check_name(info, "Member of alternate '%s'" % name, key)
check_known_keys(info,
"member '%s' of alternate '%s'" % (key, name),
value, ['type'], ['if'])
typ = value['type']
# Ensure alternates have no type conflicts.
check_type(info, "Member '%s' of alternate '%s'" % (key, name),
value,
check_type(info, "Member '%s' of alternate '%s'" % (key, name), typ,
allow_metas=['built-in', 'union', 'struct', 'enum'])
qtype = find_alternate_member_qtype(value)
qtype = find_alternate_member_qtype(typ)
if not qtype:
raise QAPISemError(info, "Alternate '%s' member '%s' cannot use "
"type '%s'" % (name, key, value))
"type '%s'" % (name, key, typ))
conflicting = set([qtype])
if qtype == 'QTYPE_QSTRING':
enum_expr = enum_types.get(value)
enum_expr = enum_types.get(typ)
if enum_expr:
for v in enum_expr['data']:
for v in enum_get_names(enum_expr):
if v in ['on', 'off']:
conflicting.add('QTYPE_QBOOL')
if re.match(r'[-+0-9.]', v): # lazy, could be tightened
@ -849,7 +865,7 @@ def check_alternate(expr, info):
def check_enum(expr, info):
name = expr['enum']
members = expr.get('data')
members = expr['data']
prefix = expr.get('prefix')
if not isinstance(members, list):
@ -858,8 +874,12 @@ def check_enum(expr, info):
if prefix is not None and not isinstance(prefix, str):
raise QAPISemError(info,
"Enum '%s' requires a string for 'prefix'" % name)
for member in members:
check_name(info, "Member of enum '%s'" % name, member,
source = "dictionary member of enum '%s'" % name
check_known_keys(info, source, member, ['name'], ['if'])
check_if(member, info)
check_name(info, "Member of enum '%s'" % name, member['name'],
enum_member=True)
@ -873,6 +893,24 @@ def check_struct(expr, info):
allow_metas=['struct'])
def check_known_keys(info, source, keys, required, optional):
def pprint(elems):
return ', '.join("'" + e + "'" for e in sorted(elems))
missing = set(required) - set(keys)
if missing:
raise QAPISemError(info, "Key%s %s %s missing from %s"
% ('s' if len(missing) > 1 else '', pprint(missing),
'are' if len(missing) > 1 else 'is', source))
allowed = set(required + optional)
unknown = set(keys) - allowed
if unknown:
raise QAPISemError(info, "Unknown key%s %s in %s\nValid keys are %s."
% ('s' if len(unknown) > 1 else '', pprint(unknown),
source, pprint(allowed)))
def check_keys(expr_elem, meta, required, optional=[]):
expr = expr_elem['expr']
info = expr_elem['info']
@ -880,10 +918,9 @@ def check_keys(expr_elem, meta, required, optional=[]):
if not isinstance(name, str):
raise QAPISemError(info, "'%s' key must have a string value" % meta)
required = required + [meta]
source = "%s '%s'" % (meta, name)
check_known_keys(info, source, expr.keys(), required, optional)
for (key, value) in expr.items():
if key not in required and key not in optional:
raise QAPISemError(info, "Unknown key '%s' in %s '%s'"
% (key, meta, name))
if key in ['gen', 'success-response'] and value is not False:
raise QAPISemError(info,
"'%s' of %s '%s' should only use false value"
@ -895,10 +932,20 @@ def check_keys(expr_elem, meta, required, optional=[]):
% (key, meta, name))
if key == 'if':
check_if(expr, info)
for key in required:
if key not in expr:
raise QAPISemError(info, "Key '%s' is missing from %s '%s'"
% (key, meta, name))
def normalize_enum(expr):
if isinstance(expr['data'], list):
expr['data'] = [m if isinstance(m, dict) else {'name': m}
for m in expr['data']]
def normalize_members(members):
if isinstance(members, OrderedDict):
for key, arg in members.items():
if isinstance(arg, dict):
continue
members[key] = {'type': arg}
def check_exprs(exprs):
@ -924,27 +971,34 @@ def check_exprs(exprs):
if 'enum' in expr:
meta = 'enum'
check_keys(expr_elem, 'enum', ['data'], ['if', 'prefix'])
normalize_enum(expr)
enum_types[expr[meta]] = expr
elif 'union' in expr:
meta = 'union'
check_keys(expr_elem, 'union', ['data'],
['base', 'discriminator', 'if'])
normalize_members(expr.get('base'))
normalize_members(expr['data'])
union_types[expr[meta]] = expr
elif 'alternate' in expr:
meta = 'alternate'
check_keys(expr_elem, 'alternate', ['data'], ['if'])
normalize_members(expr['data'])
elif 'struct' in expr:
meta = 'struct'
check_keys(expr_elem, 'struct', ['data'], ['base', 'if'])
normalize_members(expr['data'])
struct_types[expr[meta]] = expr
elif 'command' in expr:
meta = 'command'
check_keys(expr_elem, 'command', [],
['data', 'returns', 'gen', 'success-response',
'boxed', 'allow-oob', 'allow-preconfig', 'if'])
normalize_members(expr.get('data'))
elif 'event' in expr:
meta = 'event'
check_keys(expr_elem, 'event', [], ['data', 'boxed', 'if'])
normalize_members(expr.get('data'))
else:
raise QAPISemError(expr_elem['info'],
"Expression is missing metatype")
@ -1063,7 +1117,7 @@ class QAPISchemaVisitor(object):
def visit_builtin_type(self, name, info, json_type):
pass
def visit_enum_type(self, name, info, ifcond, values, prefix):
def visit_enum_type(self, name, info, ifcond, members, prefix):
pass
def visit_array_type(self, name, info, ifcond, element_type):
@ -1161,22 +1215,22 @@ class QAPISchemaBuiltinType(QAPISchemaType):
class QAPISchemaEnumType(QAPISchemaType):
def __init__(self, name, info, doc, ifcond, values, prefix):
def __init__(self, name, info, doc, ifcond, members, prefix):
QAPISchemaType.__init__(self, name, info, doc, ifcond)
for v in values:
assert isinstance(v, QAPISchemaMember)
v.set_owner(name)
for m in members:
assert isinstance(m, QAPISchemaMember)
m.set_owner(name)
assert prefix is None or isinstance(prefix, str)
self.values = values
self.members = members
self.prefix = prefix
def check(self, schema):
QAPISchemaType.check(self, schema)
seen = {}
for v in self.values:
v.check_clash(self.info, seen)
for m in self.members:
m.check_clash(self.info, seen)
if self.doc:
self.doc.connect_member(v)
self.doc.connect_member(m)
def is_implicit(self):
# See QAPISchema._make_implicit_enum_type() and ._def_predefineds()
@ -1186,14 +1240,14 @@ class QAPISchemaEnumType(QAPISchemaType):
return c_name(self.name)
def member_names(self):
return [v.name for v in self.values]
return [m.name for m in self.members]
def json_type(self):
return 'string'
def visit(self, visitor):
visitor.visit_enum_type(self.name, self.info, self.ifcond,
self.member_names(), self.prefix)
self.members, self.prefix)
class QAPISchemaArrayType(QAPISchemaType):
@ -1318,9 +1372,10 @@ class QAPISchemaObjectType(QAPISchemaType):
class QAPISchemaMember(object):
role = 'member'
def __init__(self, name):
def __init__(self, name, ifcond=None):
assert isinstance(name, str)
self.name = name
self.ifcond = listify_cond(ifcond)
self.owner = None
def set_owner(self, name):
@ -1361,8 +1416,8 @@ class QAPISchemaMember(object):
class QAPISchemaObjectTypeMember(QAPISchemaMember):
def __init__(self, name, typ, optional):
QAPISchemaMember.__init__(self, name)
def __init__(self, name, typ, optional, ifcond=None):
QAPISchemaMember.__init__(self, name, ifcond)
assert isinstance(typ, str)
assert isinstance(optional, bool)
self._type_name = typ
@ -1403,9 +1458,9 @@ class QAPISchemaObjectTypeVariants(object):
if self._tag_name: # flat union
# branches that are not explicitly covered get an empty type
cases = set([v.name for v in self.variants])
for val in self.tag_member.type.values:
if val.name not in cases:
v = QAPISchemaObjectTypeVariant(val.name, 'q_empty')
for m in self.tag_member.type.members:
if m.name not in cases:
v = QAPISchemaObjectTypeVariant(m.name, 'q_empty')
v.set_owner(self.tag_member.owner)
self.variants.append(v)
for v in self.variants:
@ -1428,8 +1483,8 @@ class QAPISchemaObjectTypeVariants(object):
class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
role = 'branch'
def __init__(self, name, typ):
QAPISchemaObjectTypeMember.__init__(self, name, typ, False)
def __init__(self, name, typ, ifcond=None):
QAPISchemaObjectTypeMember.__init__(self, name, typ, False, ifcond)
class QAPISchemaAlternateType(QAPISchemaType):
@ -1620,14 +1675,16 @@ class QAPISchema(object):
self.the_empty_object_type = QAPISchemaObjectType(
'q_empty', None, None, None, None, [], None)
self._def_entity(self.the_empty_object_type)
qtype_values = self._make_enum_members(['none', 'qnull', 'qnum',
'qstring', 'qdict', 'qlist',
'qbool'])
qtypes = ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist',
'qbool']
qtype_values = self._make_enum_members([{'name': n} for n in qtypes])
self._def_entity(QAPISchemaEnumType('QType', None, None, None,
qtype_values, 'QTYPE'))
def _make_enum_members(self, values):
return [QAPISchemaMember(v) for v in values]
return [QAPISchemaMember(v['name'], v.get('if')) for v in values]
def _make_implicit_enum_type(self, name, info, ifcond, values):
# See also QAPISchemaObjectTypeMember._pretty_owner()
@ -1674,7 +1731,7 @@ class QAPISchema(object):
name, info, doc, ifcond,
self._make_enum_members(data), prefix))
def _make_member(self, name, typ, info):
def _make_member(self, name, typ, ifcond, info):
optional = False
if name.startswith('*'):
name = name[1:]
@ -1682,10 +1739,10 @@ class QAPISchema(object):
if isinstance(typ, list):
assert len(typ) == 1
typ = self._make_array_type(typ[0], info)
return QAPISchemaObjectTypeMember(name, typ, optional)
return QAPISchemaObjectTypeMember(name, typ, optional, ifcond)
def _make_members(self, data, info):
return [self._make_member(key, value, info)
return [self._make_member(key, value['type'], value.get('if'), info)
for (key, value) in data.items()]
def _def_struct_type(self, expr, info, doc):
@ -1697,17 +1754,17 @@ class QAPISchema(object):
self._make_members(data, info),
None))
def _make_variant(self, case, typ):
return QAPISchemaObjectTypeVariant(case, typ)
def _make_variant(self, case, typ, ifcond):
return QAPISchemaObjectTypeVariant(case, typ, ifcond)
def _make_simple_variant(self, case, typ, info):
def _make_simple_variant(self, case, typ, ifcond, info):
if isinstance(typ, list):
assert len(typ) == 1
typ = self._make_array_type(typ[0], info)
typ = self._make_implicit_object_type(
typ, info, None, self.lookup_type(typ),
'wrapper', [self._make_member('data', typ, info)])
return QAPISchemaObjectTypeVariant(case, typ)
'wrapper', [self._make_member('data', typ, None, info)])
return QAPISchemaObjectTypeVariant(case, typ, ifcond)
def _def_union_type(self, expr, info, doc):
name = expr['union']
@ -1721,14 +1778,15 @@ class QAPISchema(object):
name, info, doc, ifcond,
'base', self._make_members(base, info))
if tag_name:
variants = [self._make_variant(key, value)
variants = [self._make_variant(key, value['type'], value.get('if'))
for (key, value) in data.items()]
members = []
else:
variants = [self._make_simple_variant(key, value, info)
variants = [self._make_simple_variant(key, value['type'],
value.get('if'), info)
for (key, value) in data.items()]
typ = self._make_implicit_enum_type(name, info, ifcond,
[v.name for v in variants])
enum = [{'name': v.name, 'if': v.ifcond} for v in variants]
typ = self._make_implicit_enum_type(name, info, ifcond, enum)
tag_member = QAPISchemaObjectTypeMember('type', typ, False)
members = [tag_member]
self._def_entity(
@ -1741,7 +1799,7 @@ class QAPISchema(object):
name = expr['alternate']
data = expr['data']
ifcond = expr.get('if')
variants = [self._make_variant(key, value)
variants = [self._make_variant(key, value['type'], value.get('if'))
for (key, value) in data.items()]
tag_member = QAPISchemaObjectTypeMember('type', 'QType', False)
self._def_entity(
@ -2012,19 +2070,21 @@ def _wrap_ifcond(ifcond, before, after):
return out
def gen_enum_lookup(name, values, prefix=None):
def gen_enum_lookup(name, members, prefix=None):
ret = mcgen('''
const QEnumLookup %(c_name)s_lookup = {
.array = (const char *const[]) {
''',
c_name=c_name(name))
for value in values:
index = c_enum_const(name, value, prefix)
for m in members:
ret += gen_if(m.ifcond)
index = c_enum_const(name, m.name, prefix)
ret += mcgen('''
[%(index)s] = "%(value)s",
[%(index)s] = "%(name)s",
''',
index=index, value=value)
index=index, name=m.name)
ret += gen_endif(m.ifcond)
ret += mcgen('''
},
@ -2035,9 +2095,9 @@ const QEnumLookup %(c_name)s_lookup = {
return ret
def gen_enum(name, values, prefix=None):
def gen_enum(name, members, prefix=None):
# append automatically generated _MAX value
enum_values = values + ['_MAX']
enum_members = members + [QAPISchemaMember('_MAX')]
ret = mcgen('''
@ -2045,14 +2105,13 @@ typedef enum %(c_name)s {
''',
c_name=c_name(name))
i = 0
for value in enum_values:
for m in enum_members:
ret += gen_if(m.ifcond)
ret += mcgen('''
%(c_enum)s = %(i)d,
%(c_enum)s,
''',
c_enum=c_enum_const(name, value, prefix),
i=i)
i += 1
c_enum=c_enum_const(name, m.name, prefix))
ret += gen_endif(m.ifcond)
ret += mcgen('''
} %(c_name)s;

View file

@ -126,19 +126,27 @@ def texi_body(doc):
return texi_format(doc.body.text)
def texi_enum_value(value):
def texi_if(ifcond, prefix='\n', suffix='\n'):
"""Format the #if condition"""
if not ifcond:
return ''
return '%s@b{If:} @code{%s}%s' % (prefix, ', '.join(ifcond), suffix)
def texi_enum_value(value, desc, suffix):
"""Format a table of members item for an enumeration value"""
return '@item @code{%s}\n' % value.name
return '@item @code{%s}\n%s%s' % (
value.name, desc, texi_if(value.ifcond, prefix='@*'))
def texi_member(member, suffix=''):
def texi_member(member, desc, suffix):
"""Format a table of members item for an object type member"""
typ = member.type.doc_type()
membertype = ': ' + typ if typ else ''
return '@item @code{%s%s}%s%s\n' % (
return '@item @code{%s%s}%s%s\n%s%s' % (
member.name, membertype,
' (optional)' if member.optional else '',
suffix)
suffix, desc, texi_if(member.ifcond, prefix='@*'))
def texi_members(doc, what, base, variants, member_func):
@ -155,17 +163,17 @@ def texi_members(doc, what, base, variants, member_func):
desc = 'One of ' + members_text + '\n'
else:
desc = 'Not documented\n'
items += member_func(section.member) + desc
items += member_func(section.member, desc, suffix='')
if base:
items += '@item The members of @code{%s}\n' % base.doc_type()
if variants:
for v in variants.variants:
when = ' when @code{%s} is @t{"%s"}' % (
variants.tag_member.name, v.name)
when = ' when @code{%s} is @t{"%s"}%s' % (
variants.tag_member.name, v.name, texi_if(v.ifcond, " (", ")"))
if v.type.is_implicit():
assert not v.type.base and not v.type.variants
for m in v.type.local_members:
items += member_func(m, when)
items += member_func(m, desc='', suffix=when)
else:
items += '@item The members of @code{%s}%s\n' % (
v.type.doc_type(), when)
@ -185,8 +193,7 @@ def texi_sections(doc, ifcond):
body += texi_example(section.text)
else:
body += texi_format(section.text)
if ifcond:
body += '\n\n@b{If:} @code{%s}' % ", ".join(ifcond)
body += texi_if(ifcond, suffix='')
return body
@ -206,7 +213,7 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
def write(self, output_dir):
self._gen.write(output_dir, self._prefix + 'qapi-doc.texi')
def visit_enum_type(self, name, info, ifcond, values, prefix):
def visit_enum_type(self, name, info, ifcond, members, prefix):
doc = self.cur_doc
self._gen.add(TYPE_FMT(type='Enum',
name=doc.symbol,

View file

@ -143,8 +143,8 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
QAPISchemaModularCVisitor.__init__(
self, prefix, 'qapi-events',
' * Schema-defined QAPI/QMP events', __doc__)
self._enum_name = c_name(prefix + 'QAPIEvent', protect=False)
self._event_names = []
self._event_enum_name = c_name(prefix + 'QAPIEvent', protect=False)
self._event_enum_members = []
def _begin_module(self, name):
types = self._module_basename('qapi-types', name)
@ -170,15 +170,16 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
def visit_end(self):
(genc, genh) = self._module[self._main_module]
genh.add(gen_enum(self._enum_name, self._event_names))
genc.add(gen_enum_lookup(self._enum_name, self._event_names))
genh.add(gen_enum(self._event_enum_name, self._event_enum_members))
genc.add(gen_enum_lookup(self._event_enum_name,
self._event_enum_members))
def visit_event(self, name, info, ifcond, arg_type, boxed):
with ifcontext(ifcond, self._genh, self._genc):
self._genh.add(gen_event_send_decl(name, arg_type, boxed))
self._genc.add(gen_event_send(name, arg_type, boxed,
self._enum_name))
self._event_names.append(name)
self._event_enum_name))
self._event_enum_members.append(QAPISchemaMember(name, ifcond))
def gen_events(schema, output_dir, prefix):

View file

@ -162,6 +162,8 @@ const QLitObject %(c_name)s = %(c_string)s;
ret = {'name': member.name, 'type': self._use_type(member.type)}
if member.optional:
ret['default'] = None
if member.ifcond:
ret = (ret, {'if': member.ifcond})
return ret
def _gen_variants(self, tag_name, variants):
@ -169,13 +171,17 @@ const QLitObject %(c_name)s = %(c_string)s;
'variants': [self._gen_variant(v) for v in variants]}
def _gen_variant(self, variant):
return {'case': variant.name, 'type': self._use_type(variant.type)}
return ({'case': variant.name, 'type': self._use_type(variant.type)},
{'if': variant.ifcond})
def visit_builtin_type(self, name, info, json_type):
self._gen_qlit(name, 'builtin', {'json-type': json_type}, [])
def visit_enum_type(self, name, info, ifcond, values, prefix):
self._gen_qlit(name, 'enum', {'values': values}, ifcond)
def visit_enum_type(self, name, info, ifcond, members, prefix):
self._gen_qlit(name, 'enum',
{'values':
[(m.name, {'if': m.ifcond}) for m in members]},
ifcond)
def visit_array_type(self, name, info, ifcond, element_type):
element = self._use_type(element_type)
@ -191,8 +197,9 @@ const QLitObject %(c_name)s = %(c_string)s;
def visit_alternate_type(self, name, info, ifcond, variants):
self._gen_qlit(name, 'alternate',
{'members': [{'type': self._use_type(m.type)}
for m in variants.variants]}, ifcond)
{'members': [
({'type': self._use_type(m.type)}, {'if': m.ifcond})
for m in variants.variants]}, ifcond)
def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
success_response, boxed, allow_oob, allow_preconfig):

View file

@ -43,6 +43,7 @@ struct %(c_name)s {
def gen_struct_members(members):
ret = ''
for memb in members:
ret += gen_if(memb.ifcond)
if memb.optional:
ret += mcgen('''
bool has_%(c_name)s;
@ -52,6 +53,7 @@ def gen_struct_members(members):
%(c_type)s %(c_name)s;
''',
c_type=memb.type.c_type(), c_name=c_name(memb.name))
ret += gen_endif(memb.ifcond)
return ret
@ -131,11 +133,13 @@ def gen_variants(variants):
for var in variants.variants:
if var.type.name == 'q_empty':
continue
ret += gen_if(var.ifcond)
ret += mcgen('''
%(c_type)s %(c_name)s;
''',
c_type=var.type.c_unboxed_type(),
c_name=c_name(var.name))
ret += gen_endif(var.ifcond)
ret += mcgen('''
} u;
@ -212,10 +216,10 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
self._genh.add(gen_type_cleanup_decl(name))
self._genc.add(gen_type_cleanup(name))
def visit_enum_type(self, name, info, ifcond, values, prefix):
def visit_enum_type(self, name, info, ifcond, members, prefix):
with ifcontext(ifcond, self._genh, self._genc):
self._genh.preamble_add(gen_enum(name, values, prefix))
self._genc.add(gen_enum_lookup(name, values, prefix))
self._genh.preamble_add(gen_enum(name, members, prefix))
self._genc.add(gen_enum_lookup(name, members, prefix))
def visit_array_type(self, name, info, ifcond, element_type):
with ifcontext(ifcond, self._genh, self._genc):

View file

@ -54,6 +54,7 @@ void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
c_type=base.c_name())
for memb in members:
ret += gen_if(memb.ifcond)
if memb.optional:
ret += mcgen('''
if (visit_optional(v, "%(name)s", &obj->has_%(c_name)s)) {
@ -73,6 +74,7 @@ void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
ret += mcgen('''
}
''')
ret += gen_endif(memb.ifcond)
if variants:
ret += mcgen('''
@ -84,6 +86,7 @@ void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
case_str = c_enum_const(variants.tag_member.type.name,
var.name,
variants.tag_member.type.prefix)
ret += gen_if(var.ifcond)
if var.type.name == 'q_empty':
# valid variant and nothing to do
ret += mcgen('''
@ -100,6 +103,7 @@ void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
case=case_str,
c_type=var.type.c_name(), c_name=c_name(var.name))
ret += gen_endif(var.ifcond)
ret += mcgen('''
default:
abort();
@ -190,6 +194,7 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
c_name=c_name(name))
for var in variants.variants:
ret += gen_if(var.ifcond)
ret += mcgen('''
case %(case)s:
''',
@ -217,6 +222,7 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
ret += mcgen('''
break;
''')
ret += gen_endif(var.ifcond)
ret += mcgen('''
case QTYPE_NONE:
@ -310,7 +316,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
''',
types=types))
def visit_enum_type(self, name, info, ifcond, values, prefix):
def visit_enum_type(self, name, info, ifcond, members, prefix):
with ifcontext(ifcond, self._genh, self._genc):
self._genh.add(gen_visit_decl(name, scalar=True))
self._genc.add(gen_visit_enum(name))