mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2018-07-03' into staging
QAPI patches for 2018-07-03 # gpg: Signature made Tue 03 Jul 2018 21:52:55 BST # 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-07-03: qapi: add conditions to SPICE type/commands/events on the schema qapi: add conditions to VNC type/commands/events on the schema qapi: add 'If:' section to generated documentation qapi-types: add #if conditions to types & visitors qapi/events: add #if conditions to events qapi/commands: add #if conditions to commands qapi-introspect: add preprocessor conditions to generated QLit qapi-introspect: modify to_qlit() to append ',' on level > 0 qapi: add #if/#endif helpers qapi: mcgen() shouldn't indent # lines qapi: add 'ifcond' to visitor methods qapi: leave the ifcond attribute undefined until check() qapi: pass 'if' condition into QAPISchemaEntity objects qapi: add 'if' to top-level expressions Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -239,7 +239,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
|
||||
QAPISchemaModularCVisitor.__init__(
|
||||
self, prefix, 'qapi-commands',
|
||||
' * Schema-defined QAPI/QMP commands', __doc__)
|
||||
self._regy = ''
|
||||
self._regy = QAPIGenCCode()
|
||||
self._visited_ret_types = {}
|
||||
|
||||
def _begin_module(self, name):
|
||||
@@ -275,20 +275,28 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
|
||||
void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
|
||||
''',
|
||||
c_prefix=c_name(self._prefix, protect=False)))
|
||||
genc.add(gen_registry(self._regy, self._prefix))
|
||||
genc.add(gen_registry(self._regy.get_content(), self._prefix))
|
||||
|
||||
def visit_command(self, name, info, arg_type, ret_type, gen,
|
||||
def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
|
||||
success_response, boxed, allow_oob, allow_preconfig):
|
||||
if not gen:
|
||||
return
|
||||
self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type))
|
||||
# FIXME: If T is a user-defined type, the user is responsible
|
||||
# for making this work, i.e. to make T's condition the
|
||||
# conjunction of the T-returning commands' conditions. If T
|
||||
# is a built-in type, this isn't possible: the
|
||||
# qmp_marshal_output_T() will be generated unconditionally.
|
||||
if ret_type and ret_type not in self._visited_ret_types[self._genc]:
|
||||
self._visited_ret_types[self._genc].add(ret_type)
|
||||
self._genc.add(gen_marshal_output(ret_type))
|
||||
self._genh.add(gen_marshal_decl(name))
|
||||
self._genc.add(gen_marshal(name, arg_type, boxed, ret_type))
|
||||
self._regy += gen_register_command(name, success_response, allow_oob,
|
||||
allow_preconfig)
|
||||
with ifcontext(ret_type.ifcond,
|
||||
self._genh, self._genc, self._regy):
|
||||
self._genc.add(gen_marshal_output(ret_type))
|
||||
with ifcontext(ifcond, self._genh, self._genc, self._regy):
|
||||
self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type))
|
||||
self._genh.add(gen_marshal_decl(name))
|
||||
self._genc.add(gen_marshal(name, arg_type, boxed, ret_type))
|
||||
self._regy.add(gen_register_command(name, success_response,
|
||||
allow_oob, allow_preconfig))
|
||||
|
||||
|
||||
def gen_commands(schema, output_dir, prefix):
|
||||
|
||||
+221
-59
File diff suppressed because it is too large
Load Diff
Regular → Executable
+17
-15
@@ -174,7 +174,7 @@ def texi_members(doc, what, base, variants, member_func):
|
||||
return '\n@b{%s:}\n@table @asis\n%s@end table\n' % (what, items)
|
||||
|
||||
|
||||
def texi_sections(doc):
|
||||
def texi_sections(doc, ifcond):
|
||||
"""Format additional sections following arguments"""
|
||||
body = ''
|
||||
for section in doc.sections:
|
||||
@@ -185,14 +185,16 @@ def texi_sections(doc):
|
||||
body += texi_example(section.text)
|
||||
else:
|
||||
body += texi_format(section.text)
|
||||
if ifcond:
|
||||
body += '\n\n@b{If:} @code{%s}' % ", ".join(ifcond)
|
||||
return body
|
||||
|
||||
|
||||
def texi_entity(doc, what, base=None, variants=None,
|
||||
def texi_entity(doc, what, ifcond, base=None, variants=None,
|
||||
member_func=texi_member):
|
||||
return (texi_body(doc)
|
||||
+ texi_members(doc, what, base, variants, member_func)
|
||||
+ texi_sections(doc))
|
||||
+ texi_sections(doc, ifcond))
|
||||
|
||||
|
||||
class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
|
||||
@@ -204,47 +206,47 @@ 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, values, prefix):
|
||||
def visit_enum_type(self, name, info, ifcond, values, prefix):
|
||||
doc = self.cur_doc
|
||||
self._gen.add(TYPE_FMT(type='Enum',
|
||||
name=doc.symbol,
|
||||
body=texi_entity(doc, 'Values',
|
||||
body=texi_entity(doc, 'Values', ifcond,
|
||||
member_func=texi_enum_value)))
|
||||
|
||||
def visit_object_type(self, name, info, base, members, variants):
|
||||
def visit_object_type(self, name, info, ifcond, base, members, variants):
|
||||
doc = self.cur_doc
|
||||
if base and base.is_implicit():
|
||||
base = None
|
||||
self._gen.add(TYPE_FMT(type='Object',
|
||||
name=doc.symbol,
|
||||
body=texi_entity(doc, 'Members',
|
||||
body=texi_entity(doc, 'Members', ifcond,
|
||||
base, variants)))
|
||||
|
||||
def visit_alternate_type(self, name, info, variants):
|
||||
def visit_alternate_type(self, name, info, ifcond, variants):
|
||||
doc = self.cur_doc
|
||||
self._gen.add(TYPE_FMT(type='Alternate',
|
||||
name=doc.symbol,
|
||||
body=texi_entity(doc, 'Members')))
|
||||
body=texi_entity(doc, 'Members', ifcond)))
|
||||
|
||||
def visit_command(self, name, info, arg_type, ret_type, gen,
|
||||
def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
|
||||
success_response, boxed, allow_oob, allow_preconfig):
|
||||
doc = self.cur_doc
|
||||
if boxed:
|
||||
body = texi_body(doc)
|
||||
body += ('\n@b{Arguments:} the members of @code{%s}\n'
|
||||
% arg_type.name)
|
||||
body += texi_sections(doc)
|
||||
body += texi_sections(doc, ifcond)
|
||||
else:
|
||||
body = texi_entity(doc, 'Arguments')
|
||||
body = texi_entity(doc, 'Arguments', ifcond)
|
||||
self._gen.add(MSG_FMT(type='Command',
|
||||
name=doc.symbol,
|
||||
body=body))
|
||||
|
||||
def visit_event(self, name, info, arg_type, boxed):
|
||||
def visit_event(self, name, info, ifcond, arg_type, boxed):
|
||||
doc = self.cur_doc
|
||||
self._gen.add(MSG_FMT(type='Event',
|
||||
name=doc.symbol,
|
||||
body=texi_entity(doc, 'Arguments')))
|
||||
body=texi_entity(doc, 'Arguments', ifcond)))
|
||||
|
||||
def symbol(self, doc, entity):
|
||||
if self._gen._body:
|
||||
@@ -257,7 +259,7 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
|
||||
assert not doc.args
|
||||
if self._gen._body:
|
||||
self._gen.add('\n')
|
||||
self._gen.add(texi_body(doc) + texi_sections(doc))
|
||||
self._gen.add(texi_body(doc) + texi_sections(doc, None))
|
||||
|
||||
|
||||
def gen_doc(schema, output_dir, prefix):
|
||||
|
||||
@@ -184,9 +184,11 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
|
||||
genh.add(gen_enum(self._enum_name, self._event_names))
|
||||
genc.add(gen_enum_lookup(self._enum_name, self._event_names))
|
||||
|
||||
def visit_event(self, name, info, arg_type, boxed):
|
||||
self._genh.add(gen_event_send_decl(name, arg_type, boxed))
|
||||
self._genc.add(gen_event_send(name, arg_type, boxed, self._enum_name))
|
||||
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)
|
||||
|
||||
|
||||
|
||||
+30
-17
@@ -18,6 +18,15 @@ def to_qlit(obj, level=0, suppress_first_indent=False):
|
||||
def indent(level):
|
||||
return level * 4 * ' '
|
||||
|
||||
if isinstance(obj, tuple):
|
||||
ifobj, ifcond = obj
|
||||
ret = gen_if(ifcond)
|
||||
ret += to_qlit(ifobj, level)
|
||||
endif = gen_endif(ifcond)
|
||||
if endif:
|
||||
ret += '\n' + endif
|
||||
return ret
|
||||
|
||||
ret = ''
|
||||
if not suppress_first_indent:
|
||||
ret += indent(level)
|
||||
@@ -26,11 +35,11 @@ def to_qlit(obj, level=0, suppress_first_indent=False):
|
||||
elif isinstance(obj, str):
|
||||
ret += 'QLIT_QSTR(' + to_c_string(obj) + ')'
|
||||
elif isinstance(obj, list):
|
||||
elts = [to_qlit(elt, level + 1)
|
||||
elts = [to_qlit(elt, level + 1).strip('\n')
|
||||
for elt in obj]
|
||||
elts.append(indent(level + 1) + "{}")
|
||||
ret += 'QLIT_QLIST(((QLitObject[]) {\n'
|
||||
ret += ',\n'.join(elts) + '\n'
|
||||
ret += '\n'.join(elts) + '\n'
|
||||
ret += indent(level) + '}))'
|
||||
elif isinstance(obj, dict):
|
||||
elts = []
|
||||
@@ -45,6 +54,8 @@ def to_qlit(obj, level=0, suppress_first_indent=False):
|
||||
ret += 'QLIT_QBOOL(%s)' % ('true' if obj else 'false')
|
||||
else:
|
||||
assert False # not implemented
|
||||
if level > 0:
|
||||
ret += ','
|
||||
return ret
|
||||
|
||||
|
||||
@@ -126,12 +137,12 @@ const QLitObject %(c_name)s = %(c_string)s;
|
||||
return '[' + self._use_type(typ.element_type) + ']'
|
||||
return self._name(typ.name)
|
||||
|
||||
def _gen_qlit(self, name, mtype, obj):
|
||||
def _gen_qlit(self, name, mtype, obj, ifcond):
|
||||
if mtype not in ('command', 'event', 'builtin', 'array'):
|
||||
name = self._name(name)
|
||||
obj['name'] = name
|
||||
obj['meta-type'] = mtype
|
||||
self._qlits.append(obj)
|
||||
self._qlits.append((obj, ifcond))
|
||||
|
||||
def _gen_member(self, member):
|
||||
ret = {'name': member.name, 'type': self._use_type(member.type)}
|
||||
@@ -147,28 +158,29 @@ const QLitObject %(c_name)s = %(c_string)s;
|
||||
return {'case': variant.name, 'type': self._use_type(variant.type)}
|
||||
|
||||
def visit_builtin_type(self, name, info, json_type):
|
||||
self._gen_qlit(name, 'builtin', {'json-type': json_type})
|
||||
self._gen_qlit(name, 'builtin', {'json-type': json_type}, [])
|
||||
|
||||
def visit_enum_type(self, name, info, values, prefix):
|
||||
self._gen_qlit(name, 'enum', {'values': values})
|
||||
def visit_enum_type(self, name, info, ifcond, values, prefix):
|
||||
self._gen_qlit(name, 'enum', {'values': values}, ifcond)
|
||||
|
||||
def visit_array_type(self, name, info, element_type):
|
||||
def visit_array_type(self, name, info, ifcond, element_type):
|
||||
element = self._use_type(element_type)
|
||||
self._gen_qlit('[' + element + ']', 'array', {'element-type': element})
|
||||
self._gen_qlit('[' + element + ']', 'array', {'element-type': element},
|
||||
ifcond)
|
||||
|
||||
def visit_object_type_flat(self, name, info, members, variants):
|
||||
def visit_object_type_flat(self, name, info, ifcond, members, variants):
|
||||
obj = {'members': [self._gen_member(m) for m in members]}
|
||||
if variants:
|
||||
obj.update(self._gen_variants(variants.tag_member.name,
|
||||
variants.variants))
|
||||
self._gen_qlit(name, 'object', obj)
|
||||
self._gen_qlit(name, 'object', obj, ifcond)
|
||||
|
||||
def visit_alternate_type(self, name, info, variants):
|
||||
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]})
|
||||
for m in variants.variants]}, ifcond)
|
||||
|
||||
def visit_command(self, name, info, arg_type, ret_type, gen,
|
||||
def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
|
||||
success_response, boxed, allow_oob, allow_preconfig):
|
||||
arg_type = arg_type or self._schema.the_empty_object_type
|
||||
ret_type = ret_type or self._schema.the_empty_object_type
|
||||
@@ -176,11 +188,12 @@ const QLitObject %(c_name)s = %(c_string)s;
|
||||
{'arg-type': self._use_type(arg_type),
|
||||
'ret-type': self._use_type(ret_type),
|
||||
'allow-oob': allow_oob,
|
||||
'allow-preconfig': allow_preconfig})
|
||||
'allow-preconfig': allow_preconfig}, ifcond)
|
||||
|
||||
def visit_event(self, name, info, arg_type, boxed):
|
||||
def visit_event(self, name, info, ifcond, arg_type, boxed):
|
||||
arg_type = arg_type or self._schema.the_empty_object_type
|
||||
self._gen_qlit(name, 'event', {'arg-type': self._use_type(arg_type)})
|
||||
self._gen_qlit(name, 'event', {'arg-type': self._use_type(arg_type)},
|
||||
ifcond)
|
||||
|
||||
|
||||
def gen_introspect(schema, output_dir, prefix, opt_unmask):
|
||||
|
||||
+33
-23
@@ -55,7 +55,7 @@ def gen_struct_members(members):
|
||||
return ret
|
||||
|
||||
|
||||
def gen_object(name, base, members, variants):
|
||||
def gen_object(name, ifcond, base, members, variants):
|
||||
if name in objects_seen:
|
||||
return ''
|
||||
objects_seen.add(name)
|
||||
@@ -64,11 +64,14 @@ def gen_object(name, base, members, variants):
|
||||
if variants:
|
||||
for v in variants.variants:
|
||||
if isinstance(v.type, QAPISchemaObjectType):
|
||||
ret += gen_object(v.type.name, v.type.base,
|
||||
ret += gen_object(v.type.name, v.type.ifcond, v.type.base,
|
||||
v.type.local_members, v.type.variants)
|
||||
|
||||
ret += mcgen('''
|
||||
|
||||
''')
|
||||
ret += gen_if(ifcond)
|
||||
ret += mcgen('''
|
||||
struct %(c_name)s {
|
||||
''',
|
||||
c_name=c_name(name))
|
||||
@@ -101,6 +104,7 @@ struct %(c_name)s {
|
||||
ret += mcgen('''
|
||||
};
|
||||
''')
|
||||
ret += gen_endif(ifcond)
|
||||
|
||||
return ret
|
||||
|
||||
@@ -208,34 +212,40 @@ 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, values, prefix):
|
||||
self._genh.preamble_add(gen_enum(name, values, prefix))
|
||||
self._genc.add(gen_enum_lookup(name, values, prefix))
|
||||
def visit_enum_type(self, name, info, ifcond, values, 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))
|
||||
|
||||
def visit_array_type(self, name, info, element_type):
|
||||
self._genh.preamble_add(gen_fwd_object_or_array(name))
|
||||
self._genh.add(gen_array(name, element_type))
|
||||
self._gen_type_cleanup(name)
|
||||
def visit_array_type(self, name, info, ifcond, element_type):
|
||||
with ifcontext(ifcond, self._genh, self._genc):
|
||||
self._genh.preamble_add(gen_fwd_object_or_array(name))
|
||||
self._genh.add(gen_array(name, element_type))
|
||||
self._gen_type_cleanup(name)
|
||||
|
||||
def visit_object_type(self, name, info, base, members, variants):
|
||||
def visit_object_type(self, name, info, ifcond, base, members, variants):
|
||||
# Nothing to do for the special empty builtin
|
||||
if name == 'q_empty':
|
||||
return
|
||||
self._genh.preamble_add(gen_fwd_object_or_array(name))
|
||||
self._genh.add(gen_object(name, base, members, variants))
|
||||
if base and not base.is_implicit():
|
||||
self._genh.add(gen_upcast(name, base))
|
||||
# TODO Worth changing the visitor signature, so we could
|
||||
# directly use rather than repeat type.is_implicit()?
|
||||
if not name.startswith('q_'):
|
||||
# implicit types won't be directly allocated/freed
|
||||
self._gen_type_cleanup(name)
|
||||
with ifcontext(ifcond, self._genh):
|
||||
self._genh.preamble_add(gen_fwd_object_or_array(name))
|
||||
self._genh.add(gen_object(name, ifcond, base, members, variants))
|
||||
with ifcontext(ifcond, self._genh, self._genc):
|
||||
if base and not base.is_implicit():
|
||||
self._genh.add(gen_upcast(name, base))
|
||||
# TODO Worth changing the visitor signature, so we could
|
||||
# directly use rather than repeat type.is_implicit()?
|
||||
if not name.startswith('q_'):
|
||||
# implicit types won't be directly allocated/freed
|
||||
self._gen_type_cleanup(name)
|
||||
|
||||
def visit_alternate_type(self, name, info, variants):
|
||||
self._genh.preamble_add(gen_fwd_object_or_array(name))
|
||||
self._genh.add(gen_object(name, None,
|
||||
def visit_alternate_type(self, name, info, ifcond, variants):
|
||||
with ifcontext(ifcond, self._genh):
|
||||
self._genh.preamble_add(gen_fwd_object_or_array(name))
|
||||
self._genh.add(gen_object(name, ifcond, None,
|
||||
[variants.tag_member], variants))
|
||||
self._gen_type_cleanup(name)
|
||||
with ifcontext(ifcond, self._genh, self._genc):
|
||||
self._gen_type_cleanup(name)
|
||||
|
||||
|
||||
def gen_types(schema, output_dir, prefix, opt_builtins):
|
||||
|
||||
+23
-18
@@ -310,30 +310,35 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
|
||||
''',
|
||||
types=types))
|
||||
|
||||
def visit_enum_type(self, name, info, values, prefix):
|
||||
self._genh.add(gen_visit_decl(name, scalar=True))
|
||||
self._genc.add(gen_visit_enum(name))
|
||||
def visit_enum_type(self, name, info, ifcond, values, prefix):
|
||||
with ifcontext(ifcond, self._genh, self._genc):
|
||||
self._genh.add(gen_visit_decl(name, scalar=True))
|
||||
self._genc.add(gen_visit_enum(name))
|
||||
|
||||
def visit_array_type(self, name, info, element_type):
|
||||
self._genh.add(gen_visit_decl(name))
|
||||
self._genc.add(gen_visit_list(name, element_type))
|
||||
def visit_array_type(self, name, info, ifcond, element_type):
|
||||
with ifcontext(ifcond, self._genh, self._genc):
|
||||
self._genh.add(gen_visit_decl(name))
|
||||
self._genc.add(gen_visit_list(name, element_type))
|
||||
|
||||
def visit_object_type(self, name, info, base, members, variants):
|
||||
def visit_object_type(self, name, info, ifcond, base, members, variants):
|
||||
# Nothing to do for the special empty builtin
|
||||
if name == 'q_empty':
|
||||
return
|
||||
self._genh.add(gen_visit_members_decl(name))
|
||||
self._genc.add(gen_visit_object_members(name, base, members, variants))
|
||||
# TODO Worth changing the visitor signature, so we could
|
||||
# directly use rather than repeat type.is_implicit()?
|
||||
if not name.startswith('q_'):
|
||||
# only explicit types need an allocating visit
|
||||
self._genh.add(gen_visit_decl(name))
|
||||
self._genc.add(gen_visit_object(name, base, members, variants))
|
||||
with ifcontext(ifcond, self._genh, self._genc):
|
||||
self._genh.add(gen_visit_members_decl(name))
|
||||
self._genc.add(gen_visit_object_members(name, base,
|
||||
members, variants))
|
||||
# TODO Worth changing the visitor signature, so we could
|
||||
# directly use rather than repeat type.is_implicit()?
|
||||
if not name.startswith('q_'):
|
||||
# only explicit types need an allocating visit
|
||||
self._genh.add(gen_visit_decl(name))
|
||||
self._genc.add(gen_visit_object(name, base, members, variants))
|
||||
|
||||
def visit_alternate_type(self, name, info, variants):
|
||||
self._genh.add(gen_visit_decl(name))
|
||||
self._genc.add(gen_visit_alternate(name, variants))
|
||||
def visit_alternate_type(self, name, info, ifcond, variants):
|
||||
with ifcontext(ifcond, self._genh, self._genc):
|
||||
self._genh.add(gen_visit_decl(name))
|
||||
self._genc.add(gen_visit_alternate(name, variants))
|
||||
|
||||
|
||||
def gen_visit(schema, output_dir, prefix, opt_builtins):
|
||||
|
||||
Reference in New Issue
Block a user