* [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi,
@ 2018-12-08 11:15 Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 01/27] qapi: make sure osdep.h is included in type headers Marc-André Lureau
` (28 more replies)
0 siblings, 29 replies; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau
This is the second part of the "add #if pre-processor conditions to
generated code" series, adding schema member conditions (roughly
16-38/49).
Members can be exploded as dictionnary with 'type'/'if' keys:
{ 'struct': 'TestIfStruct', 'data':
{ 'foo': 'int',
'bar': { 'type': 'int', 'if': 'defined(TEST_IF_STRUCT_BAR)'} } }
Enum values can be exploded as dictionnary with 'type'/'if' keys:
{ 'enum': 'TestIfEnum', 'data':
[ 'foo',
{ 'name' : 'bar', 'if': 'defined(TEST_IF_ENUM_BAR)' } ] }
v7:
- replaced osdep.h include by a #warning check
- renamed event_names/event_enum_members, enum_name/event_enum_ename
- move normalization after checking
- simplify make_enum_members()
- some tests changes
- rebase/conflicts tweaks
- squash documentation changes in related patches
- tweak generated documentation code & output
- modify commit comments, add rb tags
v6:
- subset of v5 series: add schema member conditions
- split "qapi: factor out check_known_keys()", error report improvements
- add a patch to "qapi: include osdep.h in type headers" to avoid
potential build configuration change issues
- rebased, on top of Markus's qapi-next branch (first 4 patches,
included for patchew testing)
Marc-André Lureau (27):
qapi: make sure osdep.h is included in type headers
qapi: do not define enumeration value explicitly
qapi: rename QAPISchemaEnumType.values to .members
qapi: change enum visitor and gen_enum* to take QAPISchemaMember
tests: print enum type members more like object type members
qapi: factor out checking for keys
qapi: improve reporting of unknown or missing keys
qapi: add a dictionary form with 'name' key for enum members
qapi: add 'if' to enum members
qapi-events: add 'if' condition to implicit event enum
qapi: pass long form enum to make_enum_members
qapi: rename allow_dict to allow_implicit
qapi: add a dictionary form for TYPE
qapi: add 'if' to implicit struct members
qapi: add an error in case a discriminator is conditional
qapi: add 'if' to union members
qapi: simplify make_enum_members()
tests/qapi: add command with condition on union argument
qapi: add 'if' to alternate members
tests/qapi: add command with condition on alternate argument
qapi: add #if conditions to generated code members
qapi: add 'If:' condition to enum values documentation
qapi: add 'If:' condition to struct members documentation
qapi: add condition to variants documentation
qapi: break long lines at 'data' member
qapi: add more conditions to SPICE
qapi: add conditions to REPLICATION type/commands on the schema
qapi/block-core.json | 26 +-
qapi/char.json | 150 ++++++-----
qapi/migration.json | 15 +-
qapi/misc.json | 7 +-
qapi/net.json | 3 +-
qapi/tpm.json | 5 +-
qapi/ui.json | 3 +-
scripts/qapi/common.py | 253 ++++++++++++------
scripts/qapi/doc.py | 30 ++-
scripts/qapi/events.py | 13 +-
scripts/qapi/introspect.py | 16 +-
scripts/qapi/types.py | 13 +-
scripts/qapi/visit.py | 8 +-
migration/colo.c | 16 +-
monitor.c | 5 -
docs/devel/qapi-code-gen.txt | 19 ++
tests/Makefile.include | 11 +-
tests/qapi-schema/alternate-base.err | 1 +
tests/qapi-schema/alternate-invalid-dict.err | 1 +
...ember.exit => alternate-invalid-dict.exit} | 0
tests/qapi-schema/alternate-invalid-dict.json | 4 +
...-member.out => alternate-invalid-dict.out} | 0
tests/qapi-schema/comments.out | 14 +-
tests/qapi-schema/doc-bad-section.out | 13 +-
tests/qapi-schema/doc-good.json | 11 +-
tests/qapi-schema/doc-good.out | 22 +-
tests/qapi-schema/doc-good.texi | 7 +-
tests/qapi-schema/double-type.err | 1 +
tests/qapi-schema/empty.out | 9 +-
tests/qapi-schema/enum-bad-member.err | 1 +
tests/qapi-schema/enum-bad-member.exit | 1 +
tests/qapi-schema/enum-bad-member.json | 2 +
tests/qapi-schema/enum-bad-member.out | 0
.../qapi-schema/enum-dict-member-unknown.err | 2 +
.../qapi-schema/enum-dict-member-unknown.exit | 1 +
.../qapi-schema/enum-dict-member-unknown.json | 2 +
.../qapi-schema/enum-dict-member-unknown.out | 0
tests/qapi-schema/enum-dict-member.err | 1 -
tests/qapi-schema/enum-dict-member.json | 2 -
tests/qapi-schema/enum-if-invalid.err | 1 +
tests/qapi-schema/enum-if-invalid.exit | 1 +
tests/qapi-schema/enum-if-invalid.json | 3 +
tests/qapi-schema/enum-if-invalid.out | 0
tests/qapi-schema/event-case.out | 9 +-
.../qapi-schema/event-member-invalid-dict.err | 1 +
.../event-member-invalid-dict.exit | 1 +
.../event-member-invalid-dict.json | 2 +
.../qapi-schema/event-member-invalid-dict.out | 0
tests/qapi-schema/event-nest-struct.json | 2 +-
.../flat-union-inline-invalid-dict.err | 1 +
.../flat-union-inline-invalid-dict.exit | 1 +
.../flat-union-inline-invalid-dict.json | 11 +
.../flat-union-inline-invalid-dict.out | 0
tests/qapi-schema/flat-union-inline.json | 2 +-
.../flat-union-invalid-if-discriminator.err | 1 +
.../flat-union-invalid-if-discriminator.exit | 1 +
.../flat-union-invalid-if-discriminator.json | 17 ++
.../flat-union-invalid-if-discriminator.out | 0
tests/qapi-schema/ident-with-escape.out | 9 +-
tests/qapi-schema/include-relpath.out | 14 +-
tests/qapi-schema/include-repetition.out | 14 +-
tests/qapi-schema/include-simple.out | 14 +-
tests/qapi-schema/indented-expr.out | 9 +-
.../nested-struct-data-invalid-dict.err | 1 +
.../nested-struct-data-invalid-dict.exit | 1 +
.../nested-struct-data-invalid-dict.json | 3 +
.../nested-struct-data-invalid-dict.out | 0
tests/qapi-schema/nested-struct-data.json | 2 +-
tests/qapi-schema/qapi-schema-test.json | 39 ++-
tests/qapi-schema/qapi-schema-test.out | 74 ++++-
.../struct-member-invalid-dict.err | 1 +
.../struct-member-invalid-dict.exit | 1 +
.../struct-member-invalid-dict.json | 3 +
.../struct-member-invalid-dict.out | 0
tests/qapi-schema/test-qapi.py | 9 +-
.../qapi-schema/union-branch-invalid-dict.err | 1 +
.../union-branch-invalid-dict.exit | 1 +
.../union-branch-invalid-dict.json | 4 +
.../qapi-schema/union-branch-invalid-dict.out | 0
tests/qapi-schema/unknown-expr-key.err | 3 +-
tests/qapi-schema/unknown-expr-key.json | 2 +-
81 files changed, 681 insertions(+), 266 deletions(-)
create mode 100644 tests/qapi-schema/alternate-invalid-dict.err
rename tests/qapi-schema/{enum-dict-member.exit => alternate-invalid-dict.exit} (100%)
create mode 100644 tests/qapi-schema/alternate-invalid-dict.json
rename tests/qapi-schema/{enum-dict-member.out => alternate-invalid-dict.out} (100%)
create mode 100644 tests/qapi-schema/enum-bad-member.err
create mode 100644 tests/qapi-schema/enum-bad-member.exit
create mode 100644 tests/qapi-schema/enum-bad-member.json
create mode 100644 tests/qapi-schema/enum-bad-member.out
create mode 100644 tests/qapi-schema/enum-dict-member-unknown.err
create mode 100644 tests/qapi-schema/enum-dict-member-unknown.exit
create mode 100644 tests/qapi-schema/enum-dict-member-unknown.json
create mode 100644 tests/qapi-schema/enum-dict-member-unknown.out
delete mode 100644 tests/qapi-schema/enum-dict-member.err
delete mode 100644 tests/qapi-schema/enum-dict-member.json
create mode 100644 tests/qapi-schema/enum-if-invalid.err
create mode 100644 tests/qapi-schema/enum-if-invalid.exit
create mode 100644 tests/qapi-schema/enum-if-invalid.json
create mode 100644 tests/qapi-schema/enum-if-invalid.out
create mode 100644 tests/qapi-schema/event-member-invalid-dict.err
create mode 100644 tests/qapi-schema/event-member-invalid-dict.exit
create mode 100644 tests/qapi-schema/event-member-invalid-dict.json
create mode 100644 tests/qapi-schema/event-member-invalid-dict.out
create mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.err
create mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.exit
create mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.json
create mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.out
create mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.err
create mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.exit
create mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.json
create mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.out
create mode 100644 tests/qapi-schema/nested-struct-data-invalid-dict.err
create mode 100644 tests/qapi-schema/nested-struct-data-invalid-dict.exit
create mode 100644 tests/qapi-schema/nested-struct-data-invalid-dict.json
create mode 100644 tests/qapi-schema/nested-struct-data-invalid-dict.out
create mode 100644 tests/qapi-schema/struct-member-invalid-dict.err
create mode 100644 tests/qapi-schema/struct-member-invalid-dict.exit
create mode 100644 tests/qapi-schema/struct-member-invalid-dict.json
create mode 100644 tests/qapi-schema/struct-member-invalid-dict.out
create mode 100644 tests/qapi-schema/union-branch-invalid-dict.err
create mode 100644 tests/qapi-schema/union-branch-invalid-dict.exit
create mode 100644 tests/qapi-schema/union-branch-invalid-dict.json
create mode 100644 tests/qapi-schema/union-branch-invalid-dict.out
--
2.20.0.rc1
^ permalink raw reply [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 01/27] qapi: make sure osdep.h is included in type headers
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
@ 2018-12-08 11:15 ` Marc-André Lureau
2018-12-10 9:52 ` Markus Armbruster
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 02/27] qapi: do not define enumeration value explicitly Marc-André Lureau
` (27 subsequent siblings)
28 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
Now that the schema can be configured, it is crucial that all types
are configured the same. Make sure config-host.h is included, by
checking osdep.h inclusion. The build-sys tracks the dependency and
rebuilds the types if the configuration changed.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
scripts/qapi/types.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index fd7808103c..3bb9cb6d47 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -201,6 +201,9 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
''',
types=types, visit=visit))
self._genh.preamble_add(mcgen('''
+#ifndef QEMU_OSDEP_H
+#error Please include osdep.h first!
+#endif
#include "qapi/qapi-builtin-types.h"
'''))
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 02/27] qapi: do not define enumeration value explicitly
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 01/27] qapi: make sure osdep.h is included in type headers Marc-André Lureau
@ 2018-12-08 11:15 ` Marc-André Lureau
2018-12-12 8:52 ` Markus Armbruster
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 03/27] qapi: rename QAPISchemaEnumType.values to .members Marc-André Lureau
` (26 subsequent siblings)
28 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
The C standard has the initial value at 0 and the subsequent values
incremented by 1. No need to set this explicitely.
This will prevent from artificial "gaps" when compiling out some enum
values and having unnecessarily large MAX values & enums arrays, or
simplifying iterating over valid enum values.
Whenever config-host.h is changed, all the enum/types are recompiled.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
scripts/qapi/common.py | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 7b62a4c7b0..7ea0cf5139 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -2045,14 +2045,11 @@ typedef enum %(c_name)s {
''',
c_name=c_name(name))
- i = 0
for value in enum_values:
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, value, prefix))
ret += mcgen('''
} %(c_name)s;
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 03/27] qapi: rename QAPISchemaEnumType.values to .members
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 01/27] qapi: make sure osdep.h is included in type headers Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 02/27] qapi: do not define enumeration value explicitly Marc-André Lureau
@ 2018-12-08 11:15 ` Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 04/27] qapi: change enum visitor and gen_enum* to take QAPISchemaMember Marc-André Lureau
` (25 subsequent siblings)
28 siblings, 0 replies; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
Rename QAPISchemaEnumType.values and related variables to members.
Makes sense ever since commit 93bda4dd4 changed .values from list of
string to list of QAPISchemaMember. Obvious no-op.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
scripts/qapi/common.py | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 7ea0cf5139..55c914ec44 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1161,22 +1161,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,7 +1186,7 @@ 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'
@@ -1403,9 +1403,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:
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 04/27] qapi: change enum visitor and gen_enum* to take QAPISchemaMember
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (2 preceding siblings ...)
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 03/27] qapi: rename QAPISchemaEnumType.values to .members Marc-André Lureau
@ 2018-12-08 11:15 ` Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 05/27] tests: print enum type members more like object type members Marc-André Lureau
` (24 subsequent siblings)
28 siblings, 0 replies; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
This will allow to add and access more properties associated with enum
values/members, like the associated 'if' condition. We may want to
have a specialized type QAPISchemaEnumMember, for now this will do.
Modify gen_enum() and gen_enum_lookup() for the same reason.
Suggested-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
scripts/qapi/common.py | 22 +++++++++++-----------
scripts/qapi/doc.py | 2 +-
scripts/qapi/events.py | 13 +++++++------
scripts/qapi/introspect.py | 5 +++--
scripts/qapi/types.py | 6 +++---
scripts/qapi/visit.py | 2 +-
tests/qapi-schema/test-qapi.py | 4 ++--
7 files changed, 28 insertions(+), 26 deletions(-)
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 55c914ec44..1fa2f79990 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1063,7 +1063,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):
@@ -1193,7 +1193,7 @@ class QAPISchemaEnumType(QAPISchemaType):
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):
@@ -2012,19 +2012,19 @@ 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:
+ 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 += mcgen('''
},
@@ -2035,9 +2035,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,11 +2045,11 @@ typedef enum %(c_name)s {
''',
c_name=c_name(name))
- for value in enum_values:
+ for m in enum_members:
ret += mcgen('''
%(c_enum)s,
''',
- c_enum=c_enum_const(name, value, prefix))
+ c_enum=c_enum_const(name, m.name, prefix))
ret += mcgen('''
} %(c_name)s;
diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
index 987fd3c943..76cb186ff9 100755
--- a/scripts/qapi/doc.py
+++ b/scripts/qapi/doc.py
@@ -206,7 +206,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,
diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
index 2ed7902424..f1b88d8786 100644
--- a/scripts/qapi/events.py
+++ b/scripts/qapi/events.py
@@ -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))
def gen_events(schema, output_dir, prefix):
diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
index 67d6106f77..417625d54b 100644
--- a/scripts/qapi/introspect.py
+++ b/scripts/qapi/introspect.py
@@ -174,8 +174,9 @@ const QLitObject %(c_name)s = %(c_string)s;
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 for m in members]}, ifcond)
def visit_array_type(self, name, info, ifcond, element_type):
element = self._use_type(element_type)
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index 3bb9cb6d47..0404710bbd 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -215,10 +215,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):
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index 460cf12989..24f85a2e85 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -310,7 +310,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))
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index cea21c773a..27f776693e 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -23,8 +23,8 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
def visit_include(self, name, info):
print('include %s' % name)
- def visit_enum_type(self, name, info, ifcond, values, prefix):
- print('enum %s %s' % (name, values))
+ def visit_enum_type(self, name, info, ifcond, members, prefix):
+ print('enum %s %s' % (name, [m.name for m in members]))
if prefix:
print(' prefix %s' % prefix)
self._print_if(ifcond)
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 05/27] tests: print enum type members more like object type members
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (3 preceding siblings ...)
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 04/27] qapi: change enum visitor and gen_enum* to take QAPISchemaMember Marc-André Lureau
@ 2018-12-08 11:15 ` Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 06/27] qapi: factor out checking for keys Marc-André Lureau
` (23 subsequent siblings)
28 siblings, 0 replies; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
Commit 93bda4dd461 changed the internal representation of enum type
members from str to QAPISchemaMember, but we still print only a
string. Has been good enough, as the name is the member's only
attribute of interest, but that's about to change. To prepare, print
them more like object type members.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
tests/qapi-schema/comments.out | 14 ++++++-
tests/qapi-schema/doc-bad-section.out | 13 +++++-
tests/qapi-schema/doc-good.out | 17 ++++++--
tests/qapi-schema/empty.out | 9 ++++-
tests/qapi-schema/event-case.out | 9 ++++-
tests/qapi-schema/ident-with-escape.out | 9 ++++-
tests/qapi-schema/include-relpath.out | 14 ++++++-
tests/qapi-schema/include-repetition.out | 14 ++++++-
tests/qapi-schema/include-simple.out | 14 ++++++-
tests/qapi-schema/indented-expr.out | 9 ++++-
tests/qapi-schema/qapi-schema-test.out | 50 +++++++++++++++++++-----
tests/qapi-schema/test-qapi.py | 4 +-
12 files changed, 149 insertions(+), 27 deletions(-)
diff --git a/tests/qapi-schema/comments.out b/tests/qapi-schema/comments.out
index 8d2f1ce8a2..d1abc4b5a1 100644
--- a/tests/qapi-schema/comments.out
+++ b/tests/qapi-schema/comments.out
@@ -1,5 +1,15 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
module comments.json
-enum Status ['good', 'bad', 'ugly']
+enum Status
+ member good
+ member bad
+ member ugly
diff --git a/tests/qapi-schema/doc-bad-section.out b/tests/qapi-schema/doc-bad-section.out
index cd28721568..db8014eed0 100644
--- a/tests/qapi-schema/doc-bad-section.out
+++ b/tests/qapi-schema/doc-bad-section.out
@@ -1,8 +1,17 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
module doc-bad-section.json
-enum Enum ['one', 'two']
+enum Enum
+ member one
+ member two
doc symbol=Enum
body=
== Produces *invalid* texinfo
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
index 35f3f1164c..c2fc5c774a 100644
--- a/tests/qapi-schema/doc-good.out
+++ b/tests/qapi-schema/doc-good.out
@@ -1,8 +1,17 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
module doc-good.json
-enum Enum ['one', 'two']
+enum Enum
+ member one
+ member two
if ['defined(IFCOND)']
object Base
member base1: Enum optional=False
@@ -18,7 +27,9 @@ object q_obj_Variant1-wrapper
member data: Variant1 optional=False
object q_obj_Variant2-wrapper
member data: Variant2 optional=False
-enum SugaredUnionKind ['one', 'two']
+enum SugaredUnionKind
+ member one
+ member two
object SugaredUnion
member type: SugaredUnionKind optional=False
tag type
diff --git a/tests/qapi-schema/empty.out b/tests/qapi-schema/empty.out
index 0ec234eec4..5483cb7bc6 100644
--- a/tests/qapi-schema/empty.out
+++ b/tests/qapi-schema/empty.out
@@ -1,3 +1,10 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
diff --git a/tests/qapi-schema/event-case.out b/tests/qapi-schema/event-case.out
index 88c0964917..f69d4ffe4e 100644
--- a/tests/qapi-schema/event-case.out
+++ b/tests/qapi-schema/event-case.out
@@ -1,6 +1,13 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
module event-case.json
event oops None
boxed=False
diff --git a/tests/qapi-schema/ident-with-escape.out b/tests/qapi-schema/ident-with-escape.out
index 24c976f473..7f891f7e90 100644
--- a/tests/qapi-schema/ident-with-escape.out
+++ b/tests/qapi-schema/ident-with-escape.out
@@ -1,6 +1,13 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
module ident-with-escape.json
object q_obj_fooA-arg
member bar1: str optional=False
diff --git a/tests/qapi-schema/include-relpath.out b/tests/qapi-schema/include-relpath.out
index ebbabd7a18..783ccfc855 100644
--- a/tests/qapi-schema/include-relpath.out
+++ b/tests/qapi-schema/include-relpath.out
@@ -1,9 +1,19 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
module include-relpath.json
include include/relpath.json
module include/relpath.json
include include-relpath-sub.json
module include-relpath-sub.json
-enum Status ['good', 'bad', 'ugly']
+enum Status
+ member good
+ member bad
+ member ugly
diff --git a/tests/qapi-schema/include-repetition.out b/tests/qapi-schema/include-repetition.out
index 7235e055bc..d45977ee56 100644
--- a/tests/qapi-schema/include-repetition.out
+++ b/tests/qapi-schema/include-repetition.out
@@ -1,10 +1,20 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
module include-repetition.json
include comments.json
module comments.json
-enum Status ['good', 'bad', 'ugly']
+enum Status
+ member good
+ member bad
+ member ugly
module include-repetition.json
include include-repetition-sub.json
module include-repetition-sub.json
diff --git a/tests/qapi-schema/include-simple.out b/tests/qapi-schema/include-simple.out
index 006f723eeb..1afe20802a 100644
--- a/tests/qapi-schema/include-simple.out
+++ b/tests/qapi-schema/include-simple.out
@@ -1,7 +1,17 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
module include-simple.json
include include-simple-sub.json
module include-simple-sub.json
-enum Status ['good', 'bad', 'ugly']
+enum Status
+ member good
+ member bad
+ member ugly
diff --git a/tests/qapi-schema/indented-expr.out b/tests/qapi-schema/indented-expr.out
index bd8a48630e..c0cf3243f3 100644
--- a/tests/qapi-schema/indented-expr.out
+++ b/tests/qapi-schema/indented-expr.out
@@ -1,6 +1,13 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
module indented-expr.json
command eins None -> None
gen=True success_response=True boxed=False oob=False preconfig=False
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 218ac7d556..39cd2b0fc3 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -1,6 +1,13 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
module qapi-schema-test.json
object TestStruct
member integer: int optional=False
@@ -11,19 +18,25 @@ object NestedEnumsOne
member enum2: EnumOne optional=True
member enum3: EnumOne optional=False
member enum4: EnumOne optional=True
-enum MyEnum []
+enum MyEnum
object Empty1
object Empty2
base Empty1
command user_def_cmd0 Empty2 -> Empty2
gen=True success_response=True boxed=False oob=False preconfig=False
-enum QEnumTwo ['value1', 'value2']
+enum QEnumTwo
prefix QENUM_TWO
+ member value1
+ member value2
object UserDefOne
base UserDefZero
member string: str optional=False
member enum1: EnumOne optional=True
-enum EnumOne ['value1', 'value2', 'value3', 'value4']
+enum EnumOne
+ member value1
+ member value2
+ member value3
+ member value4
object UserDefZero
member integer: int optional=False
object UserDefTwoDictDict
@@ -127,7 +140,21 @@ object q_obj_sizeList-wrapper
member data: sizeList optional=False
object q_obj_anyList-wrapper
member data: anyList optional=False
-enum UserDefNativeListUnionKind ['integer', 's8', 's16', 's32', 's64', 'u8', 'u16', 'u32', 'u64', 'number', 'boolean', 'string', 'sizes', 'any']
+enum UserDefNativeListUnionKind
+ member integer
+ member s8
+ member s16
+ member s32
+ member s64
+ member u8
+ member u16
+ member u32
+ member u64
+ member number
+ member boolean
+ member string
+ member sizes
+ member any
object UserDefNativeListUnion
member type: UserDefNativeListUnionKind optional=False
tag type
@@ -204,7 +231,8 @@ event EVENT_E UserDefZero
boxed=True
event EVENT_F UserDefAlternate
boxed=True
-enum __org.qemu_x-Enum ['__org.qemu_x-value']
+enum __org.qemu_x-Enum
+ member __org.qemu_x-value
object __org.qemu_x-Base
member __org.qemu_x-member1: __org.qemu_x-Enum optional=False
object __org.qemu_x-Struct
@@ -213,7 +241,8 @@ object __org.qemu_x-Struct
member wchar-t: int optional=True
object q_obj_str-wrapper
member data: str optional=False
-enum __org.qemu_x-Union1Kind ['__org.qemu_x-branch']
+enum __org.qemu_x-Union1Kind
+ member __org.qemu_x-branch
object __org.qemu_x-Union1
member type: __org.qemu_x-Union1Kind optional=False
tag type
@@ -240,11 +269,14 @@ command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Unio
object TestIfStruct
member foo: int optional=False
if ['defined(TEST_IF_STRUCT)']
-enum TestIfEnum ['foo', 'bar']
+enum TestIfEnum
+ member foo
+ member bar
if ['defined(TEST_IF_ENUM)']
object q_obj_TestStruct-wrapper
member data: TestStruct optional=False
-enum TestIfUnionKind ['foo']
+enum TestIfUnionKind
+ member foo
if ['defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)']
object TestIfUnion
member type: TestIfUnionKind optional=False
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index 27f776693e..641a18f06d 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -24,9 +24,11 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
print('include %s' % name)
def visit_enum_type(self, name, info, ifcond, members, prefix):
- print('enum %s %s' % (name, [m.name for m in members]))
+ print('enum %s' % name)
if prefix:
print(' prefix %s' % prefix)
+ for m in members:
+ print(' member %s' % m.name)
self._print_if(ifcond)
def visit_object_type(self, name, info, ifcond, base, members, variants):
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 06/27] qapi: factor out checking for keys
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (4 preceding siblings ...)
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 05/27] tests: print enum type members more like object type members Marc-André Lureau
@ 2018-12-08 11:15 ` Marc-André Lureau
2018-12-10 9:57 ` Markus Armbruster
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 07/27] qapi: improve reporting of unknown or missing keys Marc-André Lureau
` (22 subsequent siblings)
28 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
Introduce a new helper function to check if the given keys are known,
and if mandatory keys are present. The function will be reused in
other places in the following code changes.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
scripts/qapi/common.py | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 1fa2f79990..18f5872808 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -873,6 +873,17 @@ def check_struct(expr, info):
allow_metas=['struct'])
+def check_known_keys(info, source, keys, required, optional):
+ for key in keys:
+ if key not in required and key not in optional:
+ raise QAPISemError(info, "Unknown key '%s' in %s" % (key, source))
+
+ for key in required:
+ if key not in keys:
+ raise QAPISemError(info, "Key '%s' is missing from %s"
+ % (key, source))
+
+
def check_keys(expr_elem, meta, required, optional=[]):
expr = expr_elem['expr']
info = expr_elem['info']
@@ -880,10 +891,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 +905,6 @@ 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 check_exprs(exprs):
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 07/27] qapi: improve reporting of unknown or missing keys
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (5 preceding siblings ...)
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 06/27] qapi: factor out checking for keys Marc-André Lureau
@ 2018-12-08 11:15 ` Marc-André Lureau
2018-12-10 10:03 ` Markus Armbruster
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 08/27] qapi: add a dictionary form with 'name' key for enum members Marc-André Lureau
` (21 subsequent siblings)
28 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
Report the set of missing or unknown keys. And give a hint about the
accepted keys.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
scripts/qapi/common.py | 23 +++++++++++++++--------
tests/qapi-schema/alternate-base.err | 1 +
tests/qapi-schema/double-type.err | 1 +
tests/qapi-schema/unknown-expr-key.err | 3 ++-
tests/qapi-schema/unknown-expr-key.json | 2 +-
5 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 18f5872808..f205805751 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -874,14 +874,21 @@ def check_struct(expr, info):
def check_known_keys(info, source, keys, required, optional):
- for key in keys:
- if key not in required and key not in optional:
- raise QAPISemError(info, "Unknown key '%s' in %s" % (key, source))
-
- for key in required:
- if key not in keys:
- raise QAPISemError(info, "Key '%s' is missing from %s"
- % (key, source))
+
+ 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=[]):
diff --git a/tests/qapi-schema/alternate-base.err b/tests/qapi-schema/alternate-base.err
index 30d8a34373..ebe05bc898 100644
--- a/tests/qapi-schema/alternate-base.err
+++ b/tests/qapi-schema/alternate-base.err
@@ -1 +1,2 @@
tests/qapi-schema/alternate-base.json:4: Unknown key 'base' in alternate 'Alt'
+Valid keys are 'alternate', 'data', 'if'.
diff --git a/tests/qapi-schema/double-type.err b/tests/qapi-schema/double-type.err
index f9613c6d6b..799193dba1 100644
--- a/tests/qapi-schema/double-type.err
+++ b/tests/qapi-schema/double-type.err
@@ -1 +1,2 @@
tests/qapi-schema/double-type.json:2: Unknown key 'command' in struct 'bar'
+Valid keys are 'base', 'data', 'if', 'struct'.
diff --git a/tests/qapi-schema/unknown-expr-key.err b/tests/qapi-schema/unknown-expr-key.err
index 12f5ed5b43..6ff8bb99c5 100644
--- a/tests/qapi-schema/unknown-expr-key.err
+++ b/tests/qapi-schema/unknown-expr-key.err
@@ -1 +1,2 @@
-tests/qapi-schema/unknown-expr-key.json:2: Unknown key 'bogus' in struct 'bar'
+tests/qapi-schema/unknown-expr-key.json:2: Unknown keys 'bogus', 'phony' in struct 'bar'
+Valid keys are 'base', 'data', 'if', 'struct'.
diff --git a/tests/qapi-schema/unknown-expr-key.json b/tests/qapi-schema/unknown-expr-key.json
index 3b2be00cc4..13292d75ed 100644
--- a/tests/qapi-schema/unknown-expr-key.json
+++ b/tests/qapi-schema/unknown-expr-key.json
@@ -1,2 +1,2 @@
# we reject an expression with unknown top-level keys
-{ 'struct': 'bar', 'data': { 'string': 'str'}, 'bogus': { } }
+{ 'struct': 'bar', 'data': { 'string': 'str'}, 'bogus': { }, 'phony': { } }
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 08/27] qapi: add a dictionary form with 'name' key for enum members
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (6 preceding siblings ...)
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 07/27] qapi: improve reporting of unknown or missing keys Marc-André Lureau
@ 2018-12-08 11:15 ` Marc-André Lureau
2018-12-10 15:44 ` Markus Armbruster
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 09/27] qapi: add 'if' to " Marc-André Lureau
` (20 subsequent siblings)
28 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
Desugar the enum NAME form to { 'name': NAME }. This will allow to add
new enum members, such as 'if' in the following patch.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
scripts/qapi/common.py | 49 ++++++++++++++++---
tests/Makefile.include | 3 +-
tests/qapi-schema/enum-bad-member.err | 1 +
...-dict-member.exit => enum-bad-member.exit} | 0
tests/qapi-schema/enum-bad-member.json | 2 +
...um-dict-member.out => enum-bad-member.out} | 0
.../qapi-schema/enum-dict-member-unknown.err | 2 +
.../qapi-schema/enum-dict-member-unknown.exit | 1 +
.../qapi-schema/enum-dict-member-unknown.json | 2 +
.../qapi-schema/enum-dict-member-unknown.out | 0
tests/qapi-schema/enum-dict-member.err | 1 -
tests/qapi-schema/enum-dict-member.json | 2 -
12 files changed, 52 insertions(+), 11 deletions(-)
create mode 100644 tests/qapi-schema/enum-bad-member.err
rename tests/qapi-schema/{enum-dict-member.exit => enum-bad-member.exit} (100%)
create mode 100644 tests/qapi-schema/enum-bad-member.json
rename tests/qapi-schema/{enum-dict-member.out => enum-bad-member.out} (100%)
create mode 100644 tests/qapi-schema/enum-dict-member-unknown.err
create mode 100644 tests/qapi-schema/enum-dict-member-unknown.exit
create mode 100644 tests/qapi-schema/enum-dict-member-unknown.json
create mode 100644 tests/qapi-schema/enum-dict-member-unknown.out
delete mode 100644 tests/qapi-schema/enum-dict-member.err
delete mode 100644 tests/qapi-schema/enum-dict-member.json
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index f205805751..610840d2e5 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -740,6 +740,10 @@ def check_event(expr, info):
allow_metas=meta)
+def enum_get_names(expr):
+ return [e['name'] if isinstance(e, dict) else e for e in expr['data']]
+
+
def check_union(expr, info):
name = expr['union']
base = expr.get('base')
@@ -799,7 +803,7 @@ def check_union(expr, info):
# 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'"
@@ -831,7 +835,7 @@ def check_alternate(expr, info):
if qtype == 'QTYPE_QSTRING':
enum_expr = enum_types.get(value)
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
@@ -847,18 +851,32 @@ def check_alternate(expr, info):
types_seen[qt] = key
+def normalize_enum(expr):
+ members = expr['data']
+
+ # translate short member form to dict form
+ expr['data'] = [m if isinstance(m, dict) else {'name': m} for m in members]
+
+
def check_enum(expr, info):
name = expr['enum']
- members = expr.get('data')
+ members = expr['data']
prefix = expr.get('prefix')
- if not isinstance(members, list):
- raise QAPISemError(info,
- "Enum '%s' requires an array for 'data'" % name)
if prefix is not None and not isinstance(prefix, str):
raise QAPISemError(info,
"Enum '%s' requires a string for 'prefix'" % name)
+
+ if not isinstance(members, list):
+ raise QAPISemError(info,
+ "Enum '%s' requires an array for 'data'" % name)
+
for member in members:
+ if isinstance(member, dict):
+ source = "dictionary member of enum '%s'" % name
+ check_known_keys(info, source, member, ['name'], [])
+ member = member['name']
+
check_name(info, "Member of enum '%s'" % name, member,
enum_member=True)
@@ -1011,6 +1029,15 @@ def check_exprs(exprs):
return exprs
+def normalize_exprs(exprs):
+ for expr_elem in exprs:
+ expr = expr_elem['expr']
+ if 'enum' in expr:
+ normalize_enum(expr)
+
+ return exprs
+
+
#
# Schema compiler frontend
#
@@ -1567,6 +1594,7 @@ class QAPISchema(object):
f = open(fname, 'r')
parser = QAPISchemaParser(f)
exprs = check_exprs(parser.exprs)
+ exprs = normalize_exprs(exprs)
self.docs = parser.docs
self._entity_list = []
self._entity_dict = {}
@@ -1640,7 +1668,14 @@ class QAPISchema(object):
qtype_values, 'QTYPE'))
def _make_enum_members(self, values):
- return [QAPISchemaMember(v) for v in values]
+ enum = []
+ for v in values:
+ if isinstance(v, dict):
+ name = v['name']
+ else:
+ name = v
+ enum.append(QAPISchemaMember(name))
+ return enum
def _make_implicit_enum_type(self, name, info, ifcond, values):
# See also QAPISchemaObjectTypeMember._pretty_owner()
diff --git a/tests/Makefile.include b/tests/Makefile.include
index fb0b449c02..2e894c1037 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -379,10 +379,11 @@ qapi-schema += double-data.json
qapi-schema += double-type.json
qapi-schema += duplicate-key.json
qapi-schema += empty.json
+qapi-schema += enum-bad-member.json
qapi-schema += enum-bad-name.json
qapi-schema += enum-bad-prefix.json
qapi-schema += enum-clash-member.json
-qapi-schema += enum-dict-member.json
+qapi-schema += enum-dict-member-unknown.json
qapi-schema += enum-int-member.json
qapi-schema += enum-member-case.json
qapi-schema += enum-missing-data.json
diff --git a/tests/qapi-schema/enum-bad-member.err b/tests/qapi-schema/enum-bad-member.err
new file mode 100644
index 0000000000..211db9e6fc
--- /dev/null
+++ b/tests/qapi-schema/enum-bad-member.err
@@ -0,0 +1 @@
+tests/qapi-schema/enum-bad-member.json:2: Member of enum 'MyEnum' requires a string name
diff --git a/tests/qapi-schema/enum-dict-member.exit b/tests/qapi-schema/enum-bad-member.exit
similarity index 100%
rename from tests/qapi-schema/enum-dict-member.exit
rename to tests/qapi-schema/enum-bad-member.exit
diff --git a/tests/qapi-schema/enum-bad-member.json b/tests/qapi-schema/enum-bad-member.json
new file mode 100644
index 0000000000..98da6828b4
--- /dev/null
+++ b/tests/qapi-schema/enum-bad-member.json
@@ -0,0 +1,2 @@
+# we reject any enum member that is not a string
+{ 'enum': 'MyEnum', 'data': [ [ ] ] }
diff --git a/tests/qapi-schema/enum-dict-member.out b/tests/qapi-schema/enum-bad-member.out
similarity index 100%
rename from tests/qapi-schema/enum-dict-member.out
rename to tests/qapi-schema/enum-bad-member.out
diff --git a/tests/qapi-schema/enum-dict-member-unknown.err b/tests/qapi-schema/enum-dict-member-unknown.err
new file mode 100644
index 0000000000..76bd0471db
--- /dev/null
+++ b/tests/qapi-schema/enum-dict-member-unknown.err
@@ -0,0 +1,2 @@
+tests/qapi-schema/enum-dict-member-unknown.json:2: Unknown key 'bad-key' in dictionary member of enum 'MyEnum'
+Valid keys are 'name'.
diff --git a/tests/qapi-schema/enum-dict-member-unknown.exit b/tests/qapi-schema/enum-dict-member-unknown.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/enum-dict-member-unknown.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/enum-dict-member-unknown.json b/tests/qapi-schema/enum-dict-member-unknown.json
new file mode 100644
index 0000000000..6664c59201
--- /dev/null
+++ b/tests/qapi-schema/enum-dict-member-unknown.json
@@ -0,0 +1,2 @@
+# we reject any enum member that is not a string or a dict with 'name'
+{ 'enum': 'MyEnum', 'data': [ { 'name': 'foo', 'bad-key': 'str' } ] }
diff --git a/tests/qapi-schema/enum-dict-member-unknown.out b/tests/qapi-schema/enum-dict-member-unknown.out
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/qapi-schema/enum-dict-member.err b/tests/qapi-schema/enum-dict-member.err
deleted file mode 100644
index 8ca146ea59..0000000000
--- a/tests/qapi-schema/enum-dict-member.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/enum-dict-member.json:2: Member of enum 'MyEnum' requires a string name
diff --git a/tests/qapi-schema/enum-dict-member.json b/tests/qapi-schema/enum-dict-member.json
deleted file mode 100644
index 79672e0f09..0000000000
--- a/tests/qapi-schema/enum-dict-member.json
+++ /dev/null
@@ -1,2 +0,0 @@
-# we reject any enum member that is not a string
-{ 'enum': 'MyEnum', 'data': [ { 'value': 'str' } ] }
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 09/27] qapi: add 'if' to enum members
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (7 preceding siblings ...)
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 08/27] qapi: add a dictionary form with 'name' key for enum members Marc-André Lureau
@ 2018-12-08 11:15 ` Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 10/27] qapi-events: add 'if' condition to implicit event enum Marc-André Lureau
` (19 subsequent siblings)
28 siblings, 0 replies; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
QAPISchemaMember gains .ifcond for enum members: inherited classes,
such as QAPISchemaObjectTypeMember, will thus have an ifcond member
after this (those different types will also use the .ifcond to store
the condition and generate conditional code in the following patches).
The generated code remains unconditional for now. Later patches
generate the conditionals.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
scripts/qapi/common.py | 10 +++++++---
docs/devel/qapi-code-gen.txt | 9 +++++++++
tests/Makefile.include | 1 +
tests/qapi-schema/enum-dict-member-unknown.err | 2 +-
tests/qapi-schema/enum-if-invalid.err | 1 +
tests/qapi-schema/enum-if-invalid.exit | 1 +
tests/qapi-schema/enum-if-invalid.json | 3 +++
tests/qapi-schema/enum-if-invalid.out | 0
tests/qapi-schema/qapi-schema-test.json | 5 +++--
tests/qapi-schema/qapi-schema-test.out | 2 ++
tests/qapi-schema/test-qapi.py | 1 +
11 files changed, 29 insertions(+), 6 deletions(-)
create mode 100644 tests/qapi-schema/enum-if-invalid.err
create mode 100644 tests/qapi-schema/enum-if-invalid.exit
create mode 100644 tests/qapi-schema/enum-if-invalid.json
create mode 100644 tests/qapi-schema/enum-if-invalid.out
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 610840d2e5..fdc0fd69ef 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -874,7 +874,8 @@ def check_enum(expr, info):
for member in members:
if isinstance(member, dict):
source = "dictionary member of enum '%s'" % name
- check_known_keys(info, source, member, ['name'], [])
+ check_known_keys(info, source, member, ['name'], ['if'])
+ check_if(member, info)
member = member['name']
check_name(info, "Member of enum '%s'" % name, member,
@@ -1358,9 +1359,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):
@@ -1672,9 +1674,11 @@ class QAPISchema(object):
for v in values:
if isinstance(v, dict):
name = v['name']
+ ifcond = v.get('if')
else:
name = v
- enum.append(QAPISchemaMember(name))
+ ifcond = None
+ enum.append(QAPISchemaMember(name, ifcond))
return enum
def _make_implicit_enum_type(self, name, info, ifcond, values):
diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
index 53eaf01f34..08c5ef97ff 100644
--- a/docs/devel/qapi-code-gen.txt
+++ b/docs/devel/qapi-code-gen.txt
@@ -752,6 +752,15 @@ gets its generated code guarded like this:
#endif /* defined(HAVE_BAR) */
#endif /* defined(CONFIG_FOO) */
+An enum value can be replaced by a dictionary with a 'name' and a 'if'
+key.
+
+Example: a conditional 'bar' enum member.
+
+{ 'enum': 'IfEnum', 'data':
+ [ 'foo',
+ { 'name' : 'bar', 'if': 'defined(IFCOND)' } ] }
+
Please note that you are responsible to ensure that the C code will
compile with an arbitrary combination of conditions, since the
generators are unable to check it at this point.
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 2e894c1037..3c9eea27fd 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -384,6 +384,7 @@ qapi-schema += enum-bad-name.json
qapi-schema += enum-bad-prefix.json
qapi-schema += enum-clash-member.json
qapi-schema += enum-dict-member-unknown.json
+qapi-schema += enum-if-invalid.json
qapi-schema += enum-int-member.json
qapi-schema += enum-member-case.json
qapi-schema += enum-missing-data.json
diff --git a/tests/qapi-schema/enum-dict-member-unknown.err b/tests/qapi-schema/enum-dict-member-unknown.err
index 76bd0471db..2aae618be0 100644
--- a/tests/qapi-schema/enum-dict-member-unknown.err
+++ b/tests/qapi-schema/enum-dict-member-unknown.err
@@ -1,2 +1,2 @@
tests/qapi-schema/enum-dict-member-unknown.json:2: Unknown key 'bad-key' in dictionary member of enum 'MyEnum'
-Valid keys are 'name'.
+Valid keys are 'if', 'name'.
diff --git a/tests/qapi-schema/enum-if-invalid.err b/tests/qapi-schema/enum-if-invalid.err
new file mode 100644
index 0000000000..54c3cf887b
--- /dev/null
+++ b/tests/qapi-schema/enum-if-invalid.err
@@ -0,0 +1 @@
+tests/qapi-schema/enum-if-invalid.json:2: 'if' condition must be a string or a list of strings
diff --git a/tests/qapi-schema/enum-if-invalid.exit b/tests/qapi-schema/enum-if-invalid.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/enum-if-invalid.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/enum-if-invalid.json b/tests/qapi-schema/enum-if-invalid.json
new file mode 100644
index 0000000000..60bd0ef1d7
--- /dev/null
+++ b/tests/qapi-schema/enum-if-invalid.json
@@ -0,0 +1,3 @@
+# check invalid 'if' type
+{ 'enum': 'TestIfEnum', 'data':
+ [ 'foo', { 'name' : 'bar', 'if': { 'val': 'foo' } } ] }
diff --git a/tests/qapi-schema/enum-if-invalid.out b/tests/qapi-schema/enum-if-invalid.out
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index fb03163430..22d9044a89 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -204,7 +204,8 @@
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
'if': 'defined(TEST_IF_STRUCT)' }
-{ 'enum': 'TestIfEnum', 'data': [ 'foo', 'bar' ],
+{ 'enum': 'TestIfEnum', 'data':
+ [ 'foo', { 'name' : 'bar', 'if': 'defined(TEST_IF_ENUM_BAR)' } ],
'if': 'defined(TEST_IF_ENUM)' }
{ 'union': 'TestIfUnion', 'data': { 'foo': 'TestStruct' },
@@ -213,7 +214,7 @@
{ 'alternate': 'TestIfAlternate', 'data': { 'foo': 'int', 'bar': 'TestStruct' },
'if': 'defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)' }
-{ 'command': 'TestIfCmd', 'data': { 'foo': 'TestIfStruct' },
+{ 'command': 'TestIfCmd', 'data': { 'foo': 'TestIfStruct', 'bar': 'TestIfEnum' },
'returns': 'UserDefThree',
'if': ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)'] }
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 39cd2b0fc3..130199fe8f 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -272,6 +272,7 @@ object TestIfStruct
enum TestIfEnum
member foo
member bar
+ if ['defined(TEST_IF_ENUM_BAR)']
if ['defined(TEST_IF_ENUM)']
object q_obj_TestStruct-wrapper
member data: TestStruct optional=False
@@ -290,6 +291,7 @@ alternate TestIfAlternate
if ['defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)']
object q_obj_TestIfCmd-arg
member foo: TestIfStruct optional=False
+ member bar: TestIfEnum optional=False
if ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)']
command TestIfCmd q_obj_TestIfCmd-arg -> UserDefThree
gen=True success_response=True boxed=False oob=False preconfig=False
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index 641a18f06d..aadf252d9d 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -29,6 +29,7 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
print(' prefix %s' % prefix)
for m in members:
print(' member %s' % m.name)
+ self._print_if(m.ifcond, indent=8)
self._print_if(ifcond)
def visit_object_type(self, name, info, ifcond, base, members, variants):
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 10/27] qapi-events: add 'if' condition to implicit event enum
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (8 preceding siblings ...)
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 09/27] qapi: add 'if' to " Marc-André Lureau
@ 2018-12-08 11:15 ` Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 11/27] qapi: pass long form enum to make_enum_members Marc-André Lureau
` (18 subsequent siblings)
28 siblings, 0 replies; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
Add condition to QAPIEvent enum members based on the event 'if'.
The generated code remains unconditional for now. Later patches
generate the conditionals (also there is no additional coverage of
this change in qapi-schema-test.out since the event_names enum is an
implicit type created by qapi/events.py).
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
scripts/qapi/events.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
index f1b88d8786..37ee5de682 100644
--- a/scripts/qapi/events.py
+++ b/scripts/qapi/events.py
@@ -179,7 +179,7 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
self._genh.add(gen_event_send_decl(name, arg_type, boxed))
self._genc.add(gen_event_send(name, arg_type, boxed,
self._event_enum_name))
- self._event_enum_members.append(QAPISchemaMember(name))
+ self._event_enum_members.append(QAPISchemaMember(name, ifcond))
def gen_events(schema, output_dir, prefix):
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 11/27] qapi: pass long form enum to make_enum_members
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (9 preceding siblings ...)
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 10/27] qapi-events: add 'if' condition to implicit event enum Marc-André Lureau
@ 2018-12-08 11:15 ` Marc-André Lureau
2018-12-10 17:04 ` Markus Armbruster
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 12/27] qapi: rename allow_dict to allow_implicit Marc-André Lureau
` (17 subsequent siblings)
28 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
This will allow to get rid of short form handling in a following
patch.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Suggested-by: Markus Armbruster <armbru@redhat.com>
---
scripts/qapi/common.py | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index fdc0fd69ef..557b413950 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1663,9 +1663,10 @@ 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'))
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 12/27] qapi: rename allow_dict to allow_implicit
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (10 preceding siblings ...)
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 11/27] qapi: pass long form enum to make_enum_members Marc-André Lureau
@ 2018-12-08 11:15 ` Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 13/27] qapi: add a dictionary form for TYPE Marc-André Lureau
` (16 subsequent siblings)
28 siblings, 0 replies; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
This makes it a bit clearer what is the intent of the dictionnary for
the check_type() function, since there was some confusion on a
previous iteration of this series.
Suggested-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
scripts/qapi/common.py | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 557b413950..95e55b3f44 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -661,7 +661,7 @@ def check_if(expr, info):
def check_type(info, source, value, allow_array=False,
- allow_dict=False, allow_optional=False,
+ allow_implicit=False, allow_optional=False,
allow_metas=[]):
global all_names
@@ -688,7 +688,7 @@ def check_type(info, source, value, allow_array=False,
(source, all_names[value], value))
return
- if not allow_dict:
+ if not allow_implicit:
raise QAPISemError(info, "%s should be a type name" % source)
if not isinstance(value, OrderedDict):
@@ -718,7 +718,7 @@ def check_command(expr, info):
if boxed:
args_meta += ['union', 'alternate']
check_type(info, "'data' for command '%s'" % name,
- expr.get('data'), allow_dict=not boxed, allow_optional=True,
+ expr.get('data'), allow_implicit=not boxed, allow_optional=True,
allow_metas=args_meta)
returns_meta = ['union', 'struct']
if name in returns_whitelist:
@@ -736,7 +736,7 @@ def check_event(expr, info):
if boxed:
meta += ['union', 'alternate']
check_type(info, "'data' for event '%s'" % name,
- expr.get('data'), allow_dict=not boxed, allow_optional=True,
+ expr.get('data'), allow_implicit=not boxed, allow_optional=True,
allow_metas=meta)
@@ -764,7 +764,7 @@ def check_union(expr, info):
else:
# The object must have a string or dictionary 'base'.
check_type(info, "'base' for union '%s'" % name,
- base, allow_dict=True, allow_optional=True,
+ base, allow_implicit=True, allow_optional=True,
allow_metas=['struct'])
if not base:
raise QAPISemError(info, "Flat union '%s' must have a base"
@@ -887,7 +887,7 @@ def check_struct(expr, info):
members = expr['data']
check_type(info, "'data' for struct '%s'" % name, members,
- allow_dict=True, allow_optional=True)
+ allow_implicit=True, allow_optional=True)
check_type(info, "'base' for struct '%s'" % name, expr.get('base'),
allow_metas=['struct'])
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 13/27] qapi: add a dictionary form for TYPE
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (11 preceding siblings ...)
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 12/27] qapi: rename allow_dict to allow_implicit Marc-André Lureau
@ 2018-12-08 11:15 ` Marc-André Lureau
2018-12-10 17:24 ` Markus Armbruster
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 14/27] qapi: add 'if' to implicit struct members Marc-André Lureau
` (15 subsequent siblings)
28 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
Wherever a struct/union/alternate/command/event member with NAME: TYPE
form is accepted, desugar it to a NAME: { 'type': TYPE } form.
This will allow to add new member details, such as 'if' in the
following patch to introduce conditionals, or 'default' for default
values etc.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
scripts/qapi/common.py | 71 ++++++++++++++-----
tests/Makefile.include | 6 ++
tests/qapi-schema/alternate-invalid-dict.err | 1 +
tests/qapi-schema/alternate-invalid-dict.exit | 1 +
tests/qapi-schema/alternate-invalid-dict.json | 4 ++
tests/qapi-schema/alternate-invalid-dict.out | 0
.../qapi-schema/event-member-invalid-dict.err | 1 +
.../event-member-invalid-dict.exit | 1 +
.../event-member-invalid-dict.json | 2 +
.../qapi-schema/event-member-invalid-dict.out | 0
tests/qapi-schema/event-nest-struct.json | 2 +-
.../flat-union-inline-invalid-dict.err | 1 +
.../flat-union-inline-invalid-dict.exit | 1 +
.../flat-union-inline-invalid-dict.json | 11 +++
.../flat-union-inline-invalid-dict.out | 0
tests/qapi-schema/flat-union-inline.json | 2 +-
.../nested-struct-data-invalid-dict.err | 1 +
.../nested-struct-data-invalid-dict.exit | 1 +
.../nested-struct-data-invalid-dict.json | 3 +
.../nested-struct-data-invalid-dict.out | 0
tests/qapi-schema/nested-struct-data.json | 2 +-
tests/qapi-schema/qapi-schema-test.json | 10 +--
.../struct-member-invalid-dict.err | 1 +
.../struct-member-invalid-dict.exit | 1 +
.../struct-member-invalid-dict.json | 3 +
.../struct-member-invalid-dict.out | 0
.../qapi-schema/union-branch-invalid-dict.err | 1 +
.../union-branch-invalid-dict.exit | 1 +
.../union-branch-invalid-dict.json | 4 ++
.../qapi-schema/union-branch-invalid-dict.out | 0
30 files changed, 106 insertions(+), 26 deletions(-)
create mode 100644 tests/qapi-schema/alternate-invalid-dict.err
create mode 100644 tests/qapi-schema/alternate-invalid-dict.exit
create mode 100644 tests/qapi-schema/alternate-invalid-dict.json
create mode 100644 tests/qapi-schema/alternate-invalid-dict.out
create mode 100644 tests/qapi-schema/event-member-invalid-dict.err
create mode 100644 tests/qapi-schema/event-member-invalid-dict.exit
create mode 100644 tests/qapi-schema/event-member-invalid-dict.json
create mode 100644 tests/qapi-schema/event-member-invalid-dict.out
create mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.err
create mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.exit
create mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.json
create mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.out
create mode 100644 tests/qapi-schema/nested-struct-data-invalid-dict.err
create mode 100644 tests/qapi-schema/nested-struct-data-invalid-dict.exit
create mode 100644 tests/qapi-schema/nested-struct-data-invalid-dict.json
create mode 100644 tests/qapi-schema/nested-struct-data-invalid-dict.out
create mode 100644 tests/qapi-schema/struct-member-invalid-dict.err
create mode 100644 tests/qapi-schema/struct-member-invalid-dict.exit
create mode 100644 tests/qapi-schema/struct-member-invalid-dict.json
create mode 100644 tests/qapi-schema/struct-member-invalid-dict.out
create mode 100644 tests/qapi-schema/union-branch-invalid-dict.err
create mode 100644 tests/qapi-schema/union-branch-invalid-dict.exit
create mode 100644 tests/qapi-schema/union-branch-invalid-dict.json
create mode 100644 tests/qapi-schema/union-branch-invalid-dict.out
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 95e55b3f44..4b3ba53dc7 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -588,11 +588,13 @@ 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)
+ if isinstance(discriminator_value, dict):
+ discriminator_value = discriminator_value['type']
+ return enum_types.get(discriminator_value)
# Names must be letters, numbers, -, and _. They must start with letter,
@@ -660,6 +662,15 @@ def check_if(expr, info):
check_if_str(ifcond, info)
+def normalize_members(expr, field):
+ members = expr.get(field)
+ if isinstance(members, OrderedDict):
+ for key, arg in members.items():
+ if isinstance(arg, dict):
+ continue
+ members[key] = {'type': arg}
+
+
def check_type(info, source, value, allow_array=False,
allow_implicit=False, allow_optional=False,
allow_metas=[]):
@@ -704,8 +715,14 @@ 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,
+ if isinstance(arg, dict):
+ check_known_keys(info, "member '%s' of %s" % (key, source),
+ arg, ['type'], [])
+ typ = arg['type']
+ else:
+ typ = arg
+ check_type(info, "Member '%s' of %s" % (key, source),
+ typ, allow_array=True,
allow_metas=['built-in', 'union', 'alternate', 'struct',
'enum'])
@@ -776,13 +793,15 @@ 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 isinstance(discriminator_value, dict):
+ discriminator_value = discriminator_value['type']
+ enum_define = enum_types.get(discriminator_value)
allow_metas = ['struct']
# Do not allow string discriminator
if not enum_define:
@@ -795,10 +814,16 @@ def check_union(expr, info):
raise QAPISemError(info, "Union '%s' cannot have empty 'data'" % name)
for (key, value) in members.items():
check_name(info, "Member of union '%s'" % name, key)
+ if isinstance(value, dict):
+ check_known_keys(info, "member '%s' of union '%s'" % (key, name),
+ value, ['type'], [])
+ typ = value['type']
+ else:
+ typ = value
# 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)
+ typ, 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.
@@ -822,18 +847,24 @@ def check_alternate(expr, info):
"in 'data'" % name)
for (key, value) in members.items():
check_name(info, "Member of alternate '%s'" % name, key)
+ if isinstance(value, dict):
+ check_known_keys(info,
+ "member '%s' of alternate '%s'" % (key, name),
+ value, ['type'], [])
+ typ = value['type']
+ else:
+ typ = value
# 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_get_names(enum_expr):
if v in ['on', 'off']:
@@ -1035,6 +1066,10 @@ def normalize_exprs(exprs):
expr = expr_elem['expr']
if 'enum' in expr:
normalize_enum(expr)
+ elif 'union' in expr:
+ normalize_members(expr, 'base')
+ if {'union', 'alternate', 'struct', 'command', 'event'} & set(expr):
+ normalize_members(expr, 'data')
return exprs
@@ -1738,7 +1773,7 @@ class QAPISchema(object):
return QAPISchemaObjectTypeMember(name, typ, optional)
def _make_members(self, data, info):
- return [self._make_member(key, value, info)
+ return [self._make_member(key, value['type'], info)
for (key, value) in data.items()]
def _def_struct_type(self, expr, info, doc):
@@ -1774,11 +1809,11 @@ 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'])
for (key, value) in data.items()]
members = []
else:
- variants = [self._make_simple_variant(key, value, info)
+ variants = [self._make_simple_variant(key, value['type'], info)
for (key, value) in data.items()]
typ = self._make_implicit_enum_type(name, info, ifcond,
[v.name for v in variants])
@@ -1794,7 +1829,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'])
for (key, value) in data.items()]
tag_member = QAPISchemaObjectTypeMember('type', 'QType', False)
self._def_entity(
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 3c9eea27fd..ea5d1e8787 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -318,6 +318,7 @@ qapi-schema += alternate-conflict-string.json
qapi-schema += alternate-conflict-bool-string.json
qapi-schema += alternate-conflict-num-string.json
qapi-schema += alternate-empty.json
+qapi-schema += alternate-invalid-dict.json
qapi-schema += alternate-nested.json
qapi-schema += alternate-unknown.json
qapi-schema += args-alternate.json
@@ -394,6 +395,7 @@ qapi-schema += escape-too-big.json
qapi-schema += escape-too-short.json
qapi-schema += event-boxed-empty.json
qapi-schema += event-case.json
+qapi-schema += event-member-invalid-dict.json
qapi-schema += event-nest-struct.json
qapi-schema += flat-union-array-branch.json
qapi-schema += flat-union-bad-base.json
@@ -403,6 +405,7 @@ qapi-schema += flat-union-base-union.json
qapi-schema += flat-union-clash-member.json
qapi-schema += flat-union-empty.json
qapi-schema += flat-union-inline.json
+qapi-schema += flat-union-inline-invalid-dict.json
qapi-schema += flat-union-int-branch.json
qapi-schema += flat-union-invalid-branch-key.json
qapi-schema += flat-union-invalid-discriminator.json
@@ -430,6 +433,7 @@ qapi-schema += missing-comma-list.json
qapi-schema += missing-comma-object.json
qapi-schema += missing-type.json
qapi-schema += nested-struct-data.json
+qapi-schema += nested-struct-data-invalid-dict.json
qapi-schema += non-objects.json
qapi-schema += oob-test.json
qapi-schema += allow-preconfig-test.json
@@ -460,6 +464,7 @@ qapi-schema += returns-whitelist.json
qapi-schema += struct-base-clash-deep.json
qapi-schema += struct-base-clash.json
qapi-schema += struct-data-invalid.json
+qapi-schema += struct-member-invalid-dict.json
qapi-schema += struct-member-invalid.json
qapi-schema += trailing-comma-list.json
qapi-schema += trailing-comma-object.json
@@ -471,6 +476,7 @@ qapi-schema += unicode-str.json
qapi-schema += union-base-empty.json
qapi-schema += union-base-no-discriminator.json
qapi-schema += union-branch-case.json
+qapi-schema += union-branch-invalid-dict.json
qapi-schema += union-clash-branches.json
qapi-schema += union-empty.json
qapi-schema += union-invalid-base.json
diff --git a/tests/qapi-schema/alternate-invalid-dict.err b/tests/qapi-schema/alternate-invalid-dict.err
new file mode 100644
index 0000000000..631d46628e
--- /dev/null
+++ b/tests/qapi-schema/alternate-invalid-dict.err
@@ -0,0 +1 @@
+tests/qapi-schema/alternate-invalid-dict.json:2: Key 'type' is missing from member 'two' of alternate 'Alt'
diff --git a/tests/qapi-schema/alternate-invalid-dict.exit b/tests/qapi-schema/alternate-invalid-dict.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/alternate-invalid-dict.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/alternate-invalid-dict.json b/tests/qapi-schema/alternate-invalid-dict.json
new file mode 100644
index 0000000000..8e0b2ac287
--- /dev/null
+++ b/tests/qapi-schema/alternate-invalid-dict.json
@@ -0,0 +1,4 @@
+# exploded member form must have a 'type'
+{ 'alternate': 'Alt',
+ 'data': { 'one': 'str',
+ 'two': { 'if': 'foo' } } }
diff --git a/tests/qapi-schema/alternate-invalid-dict.out b/tests/qapi-schema/alternate-invalid-dict.out
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/qapi-schema/event-member-invalid-dict.err b/tests/qapi-schema/event-member-invalid-dict.err
new file mode 100644
index 0000000000..1a57fa29b0
--- /dev/null
+++ b/tests/qapi-schema/event-member-invalid-dict.err
@@ -0,0 +1 @@
+tests/qapi-schema/event-member-invalid-dict.json:1: Key 'type' is missing from member 'a' of 'data' for event 'EVENT_A'
diff --git a/tests/qapi-schema/event-member-invalid-dict.exit b/tests/qapi-schema/event-member-invalid-dict.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/event-member-invalid-dict.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/event-member-invalid-dict.json b/tests/qapi-schema/event-member-invalid-dict.json
new file mode 100644
index 0000000000..ee6f3ecb6f
--- /dev/null
+++ b/tests/qapi-schema/event-member-invalid-dict.json
@@ -0,0 +1,2 @@
+{ 'event': 'EVENT_A',
+ 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
diff --git a/tests/qapi-schema/event-member-invalid-dict.out b/tests/qapi-schema/event-member-invalid-dict.out
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/qapi-schema/event-nest-struct.json b/tests/qapi-schema/event-nest-struct.json
index ee6f3ecb6f..355ddaeff1 100644
--- a/tests/qapi-schema/event-nest-struct.json
+++ b/tests/qapi-schema/event-nest-struct.json
@@ -1,2 +1,2 @@
{ 'event': 'EVENT_A',
- 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
+ 'data': { 'a' : { 'type' : { 'integer': 'int' } }, 'b' : 'str' } }
diff --git a/tests/qapi-schema/flat-union-inline-invalid-dict.err b/tests/qapi-schema/flat-union-inline-invalid-dict.err
new file mode 100644
index 0000000000..9c4c45b7f0
--- /dev/null
+++ b/tests/qapi-schema/flat-union-inline-invalid-dict.err
@@ -0,0 +1 @@
+tests/qapi-schema/flat-union-inline-invalid-dict.json:7: Key 'type' is missing from member 'value1' of union 'TestUnion'
diff --git a/tests/qapi-schema/flat-union-inline-invalid-dict.exit b/tests/qapi-schema/flat-union-inline-invalid-dict.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/flat-union-inline-invalid-dict.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/flat-union-inline-invalid-dict.json b/tests/qapi-schema/flat-union-inline-invalid-dict.json
new file mode 100644
index 0000000000..62c7cda617
--- /dev/null
+++ b/tests/qapi-schema/flat-union-inline-invalid-dict.json
@@ -0,0 +1,11 @@
+# we require branches to be a struct name
+# TODO: should we allow anonymous inline branch types?
+{ 'enum': 'TestEnum',
+ 'data': [ 'value1', 'value2' ] }
+{ 'struct': 'Base',
+ 'data': { 'enum1': 'TestEnum', 'kind': 'str' } }
+{ 'union': 'TestUnion',
+ 'base': 'Base',
+ 'discriminator': 'enum1',
+ 'data': { 'value1': { 'string': 'str' },
+ 'value2': { 'integer': 'int' } } }
diff --git a/tests/qapi-schema/flat-union-inline-invalid-dict.out b/tests/qapi-schema/flat-union-inline-invalid-dict.out
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/qapi-schema/flat-union-inline.json b/tests/qapi-schema/flat-union-inline.json
index 62c7cda617..a9b3ce3f0d 100644
--- a/tests/qapi-schema/flat-union-inline.json
+++ b/tests/qapi-schema/flat-union-inline.json
@@ -7,5 +7,5 @@
{ 'union': 'TestUnion',
'base': 'Base',
'discriminator': 'enum1',
- 'data': { 'value1': { 'string': 'str' },
+ 'data': { 'value1': { 'type': {} },
'value2': { 'integer': 'int' } } }
diff --git a/tests/qapi-schema/nested-struct-data-invalid-dict.err b/tests/qapi-schema/nested-struct-data-invalid-dict.err
new file mode 100644
index 0000000000..5bd364e8d9
--- /dev/null
+++ b/tests/qapi-schema/nested-struct-data-invalid-dict.err
@@ -0,0 +1 @@
+tests/qapi-schema/nested-struct-data-invalid-dict.json:2: Key 'type' is missing from member 'a' of 'data' for command 'foo'
diff --git a/tests/qapi-schema/nested-struct-data-invalid-dict.exit b/tests/qapi-schema/nested-struct-data-invalid-dict.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/nested-struct-data-invalid-dict.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/nested-struct-data-invalid-dict.json b/tests/qapi-schema/nested-struct-data-invalid-dict.json
new file mode 100644
index 0000000000..efbe773ded
--- /dev/null
+++ b/tests/qapi-schema/nested-struct-data-invalid-dict.json
@@ -0,0 +1,3 @@
+# inline subtypes collide with our desired future use of defaults
+{ 'command': 'foo',
+ 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
diff --git a/tests/qapi-schema/nested-struct-data-invalid-dict.out b/tests/qapi-schema/nested-struct-data-invalid-dict.out
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/qapi-schema/nested-struct-data.json b/tests/qapi-schema/nested-struct-data.json
index efbe773ded..5b8a40cca3 100644
--- a/tests/qapi-schema/nested-struct-data.json
+++ b/tests/qapi-schema/nested-struct-data.json
@@ -1,3 +1,3 @@
# inline subtypes collide with our desired future use of defaults
{ 'command': 'foo',
- 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
+ 'data': { 'a' : { 'type': {} }, 'b' : 'str' } }
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index 22d9044a89..94570154c9 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -11,7 +11,7 @@
'guest-sync' ] } }
{ 'struct': 'TestStruct',
- 'data': { 'integer': 'int', 'boolean': 'bool', 'string': 'str' } }
+ 'data': { 'integer': {'type': 'int'}, 'boolean': 'bool', 'string': 'str' } }
# for testing enums
{ 'struct': 'NestedEnumsOne',
@@ -77,7 +77,7 @@
{ 'union': 'UserDefFlatUnion',
'base': 'UserDefUnionBase', # intentional forward reference
'discriminator': 'enum1',
- 'data': { 'value1' : 'UserDefA',
+ 'data': { 'value1' : {'type': 'UserDefA'},
'value2' : 'UserDefB',
'value3' : 'UserDefB'
# 'value4' defaults to empty
@@ -98,7 +98,7 @@
{ 'struct': 'WrapAlternate',
'data': { 'alt': 'UserDefAlternate' } }
{ 'alternate': 'UserDefAlternate',
- 'data': { 'udfu': 'UserDefFlatUnion', 'e': 'EnumOne', 'i': 'int',
+ 'data': { 'udfu': {'type': 'UserDefFlatUnion'}, 'e': 'EnumOne', 'i': 'int',
'n': 'null' } }
{ 'struct': 'UserDefC',
@@ -134,7 +134,7 @@
{ 'command': 'user_def_cmd', 'data': {} }
{ 'command': 'user_def_cmd1', 'data': {'ud1a': 'UserDefOne'} }
{ 'command': 'user_def_cmd2',
- 'data': {'ud1a': 'UserDefOne', '*ud1b': 'UserDefOne'},
+ 'data': {'ud1a': {'type': 'UserDefOne'}, '*ud1b': 'UserDefOne'},
'returns': 'UserDefTwo' }
{ 'command': 'cmd-success-response', 'data': {}, 'success-response': false }
@@ -166,7 +166,7 @@
# testing event
{ 'struct': 'EventStructOne',
- 'data': { 'struct1': 'UserDefOne', 'string': 'str', '*enum2': 'EnumOne' } }
+ 'data': { 'struct1': {'type': 'UserDefOne'}, 'string': 'str', '*enum2': 'EnumOne' } }
{ 'event': 'EVENT_A' }
{ 'event': 'EVENT_B',
diff --git a/tests/qapi-schema/struct-member-invalid-dict.err b/tests/qapi-schema/struct-member-invalid-dict.err
new file mode 100644
index 0000000000..6a765bc668
--- /dev/null
+++ b/tests/qapi-schema/struct-member-invalid-dict.err
@@ -0,0 +1 @@
+tests/qapi-schema/struct-member-invalid-dict.json:2: Key 'type' is missing from member '*a' of 'data' for struct 'foo'
diff --git a/tests/qapi-schema/struct-member-invalid-dict.exit b/tests/qapi-schema/struct-member-invalid-dict.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/struct-member-invalid-dict.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/struct-member-invalid-dict.json b/tests/qapi-schema/struct-member-invalid-dict.json
new file mode 100644
index 0000000000..9fe0d455a9
--- /dev/null
+++ b/tests/qapi-schema/struct-member-invalid-dict.json
@@ -0,0 +1,3 @@
+# Long form of member must have a value member 'type'
+{ 'struct': 'foo',
+ 'data': { '*a': { 'case': 'foo' } } }
diff --git a/tests/qapi-schema/struct-member-invalid-dict.out b/tests/qapi-schema/struct-member-invalid-dict.out
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/qapi-schema/union-branch-invalid-dict.err b/tests/qapi-schema/union-branch-invalid-dict.err
new file mode 100644
index 0000000000..89f9b36791
--- /dev/null
+++ b/tests/qapi-schema/union-branch-invalid-dict.err
@@ -0,0 +1 @@
+tests/qapi-schema/union-branch-invalid-dict.json:2: Key 'type' is missing from member 'integer' of union 'UnionInvalidBranch'
diff --git a/tests/qapi-schema/union-branch-invalid-dict.exit b/tests/qapi-schema/union-branch-invalid-dict.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/union-branch-invalid-dict.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/union-branch-invalid-dict.json b/tests/qapi-schema/union-branch-invalid-dict.json
new file mode 100644
index 0000000000..9778598dbd
--- /dev/null
+++ b/tests/qapi-schema/union-branch-invalid-dict.json
@@ -0,0 +1,4 @@
+# Long form of member must have a value member 'type'
+{ 'union': 'UnionInvalidBranch',
+ 'data': { 'integer': { 'if': 'foo'},
+ 's8': 'int8' } }
diff --git a/tests/qapi-schema/union-branch-invalid-dict.out b/tests/qapi-schema/union-branch-invalid-dict.out
new file mode 100644
index 0000000000..e69de29bb2
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 14/27] qapi: add 'if' to implicit struct members
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (12 preceding siblings ...)
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 13/27] qapi: add a dictionary form for TYPE Marc-André Lureau
@ 2018-12-08 11:15 ` Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 15/27] qapi: add an error in case a discriminator is conditional Marc-André Lureau
` (14 subsequent siblings)
28 siblings, 0 replies; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
The generated code is for now *unconditional*. Later patches generate
the conditionals.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
scripts/qapi/common.py | 14 +++++++-------
docs/devel/qapi-code-gen.txt | 10 ++++++++++
tests/qapi-schema/qapi-schema-test.json | 12 +++++++++---
tests/qapi-schema/qapi-schema-test.out | 5 +++++
tests/qapi-schema/test-qapi.py | 1 +
5 files changed, 32 insertions(+), 10 deletions(-)
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 4b3ba53dc7..aec51acb07 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -717,7 +717,7 @@ def check_type(info, source, value, allow_array=False,
# an optional argument.
if isinstance(arg, dict):
check_known_keys(info, "member '%s' of %s" % (key, source),
- arg, ['type'], [])
+ arg, ['type'], ['if'])
typ = arg['type']
else:
typ = arg
@@ -1438,8 +1438,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
@@ -1762,7 +1762,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:]
@@ -1770,10 +1770,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['type'], 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):
@@ -1794,7 +1794,7 @@ class QAPISchema(object):
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)])
+ 'wrapper', [self._make_member('data', typ, None, info)])
return QAPISchemaObjectTypeVariant(case, typ)
def _def_union_type(self, expr, info, doc):
diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
index 08c5ef97ff..e6fff32241 100644
--- a/docs/devel/qapi-code-gen.txt
+++ b/docs/devel/qapi-code-gen.txt
@@ -752,6 +752,16 @@ gets its generated code guarded like this:
#endif /* defined(HAVE_BAR) */
#endif /* defined(CONFIG_FOO) */
+Where a member can be defined with a single string value for its type,
+it is also possible to supply a dictionary instead with both 'type'
+and 'if' keys. (TODO: union and alternate)
+
+Example: a conditional 'bar' member
+
+{ 'struct': 'IfStruct', 'data':
+ { 'foo': 'int',
+ 'bar': { 'type': 'int', 'if': 'defined(IFCOND)'} } }
+
An enum value can be replaced by a dictionary with a 'name' and a 'if'
key.
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index 94570154c9..b8565a3913 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -201,7 +201,9 @@
# test 'if' condition handling
-{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
+{ 'struct': 'TestIfStruct', 'data':
+ { 'foo': 'int',
+ 'bar': { 'type': 'int', 'if': 'defined(TEST_IF_STRUCT_BAR)'} },
'if': 'defined(TEST_IF_STRUCT)' }
{ 'enum': 'TestIfEnum', 'data':
@@ -214,11 +216,15 @@
{ 'alternate': 'TestIfAlternate', 'data': { 'foo': 'int', 'bar': 'TestStruct' },
'if': 'defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)' }
-{ 'command': 'TestIfCmd', 'data': { 'foo': 'TestIfStruct', 'bar': 'TestIfEnum' },
+{ 'command': 'TestIfCmd', 'data':
+ { 'foo': 'TestIfStruct',
+ 'bar': { 'type': 'TestIfEnum', 'if': 'defined(TEST_IF_CMD_BAR)' } },
'returns': 'UserDefThree',
'if': ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)'] }
{ 'command': 'TestCmdReturnDefThree', 'returns': 'UserDefThree' }
-{ 'event': 'TestIfEvent', 'data': { 'foo': 'TestIfStruct' },
+{ 'event': 'TestIfEvent', 'data':
+ { 'foo': 'TestIfStruct',
+ 'bar': { 'type': 'TestIfEnum', 'if': 'defined(TEST_IF_EVT_BAR)' } },
'if': 'defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)' }
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 130199fe8f..23fb078b85 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -268,6 +268,8 @@ command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Unio
gen=True success_response=True boxed=False oob=False preconfig=False
object TestIfStruct
member foo: int optional=False
+ member bar: int optional=False
+ if ['defined(TEST_IF_STRUCT_BAR)']
if ['defined(TEST_IF_STRUCT)']
enum TestIfEnum
member foo
@@ -292,6 +294,7 @@ alternate TestIfAlternate
object q_obj_TestIfCmd-arg
member foo: TestIfStruct optional=False
member bar: TestIfEnum optional=False
+ if ['defined(TEST_IF_CMD_BAR)']
if ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)']
command TestIfCmd q_obj_TestIfCmd-arg -> UserDefThree
gen=True success_response=True boxed=False oob=False preconfig=False
@@ -300,6 +303,8 @@ command TestCmdReturnDefThree None -> UserDefThree
gen=True success_response=True boxed=False oob=False preconfig=False
object q_obj_TestIfEvent-arg
member foo: TestIfStruct optional=False
+ member bar: TestIfEnum optional=False
+ if ['defined(TEST_IF_EVT_BAR)']
if ['defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)']
event TestIfEvent q_obj_TestIfEvent-arg
boxed=False
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index aadf252d9d..27081cb50c 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -39,6 +39,7 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
for m in members:
print(' member %s: %s optional=%s'
% (m.name, m.type.name, m.optional))
+ self._print_if(m.ifcond, 8)
self._print_variants(variants)
self._print_if(ifcond)
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 15/27] qapi: add an error in case a discriminator is conditional
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (13 preceding siblings ...)
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 14/27] qapi: add 'if' to implicit struct members Marc-André Lureau
@ 2018-12-08 11:15 ` Marc-André Lureau
2018-12-10 17:31 ` Markus Armbruster
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 16/27] qapi: add 'if' to union members Marc-André Lureau
` (13 subsequent siblings)
28 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
Making a discriminator conditional doesn't make much sense. Instead,
the union could be made conditional.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
scripts/qapi/common.py | 8 ++++++++
tests/Makefile.include | 1 +
.../flat-union-invalid-if-discriminator.err | 1 +
.../flat-union-invalid-if-discriminator.exit | 1 +
.../flat-union-invalid-if-discriminator.json | 17 +++++++++++++++++
.../flat-union-invalid-if-discriminator.out | 0
6 files changed, 28 insertions(+)
create mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.err
create mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.exit
create mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.json
create mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.out
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index aec51acb07..f79b3fad54 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -578,6 +578,7 @@ def find_alternate_member_qtype(qapi_type):
# Return the discriminator enum define if discriminator is specified as an
# enum type, otherwise return None.
def discriminator_find_enum_define(expr):
+ name = expr['union']
base = expr.get('base')
discriminator = expr.get('discriminator')
@@ -594,6 +595,7 @@ def discriminator_find_enum_define(expr):
if isinstance(discriminator_value, dict):
discriminator_value = discriminator_value['type']
+
return enum_types.get(discriminator_value)
@@ -800,7 +802,12 @@ def check_union(expr, info):
"struct '%s'"
% (discriminator, base))
if isinstance(discriminator_value, dict):
+ if discriminator_value.get('if'):
+ raise QAPISemError(info, 'The discriminator %s.%s for union %s '
+ 'must not be conditional' %
+ (base, discriminator, name))
discriminator_value = discriminator_value['type']
+
enum_define = enum_types.get(discriminator_value)
allow_metas = ['struct']
# Do not allow string discriminator
@@ -1023,6 +1030,7 @@ def check_exprs(exprs):
if 'include' in expr:
continue
+ info = expr_elem['info']
if 'union' in expr and not discriminator_find_enum_define(expr):
name = '%sKind' % expr['union']
elif 'alternate' in expr:
diff --git a/tests/Makefile.include b/tests/Makefile.include
index ea5d1e8787..3f5a1d0c30 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -409,6 +409,7 @@ qapi-schema += flat-union-inline-invalid-dict.json
qapi-schema += flat-union-int-branch.json
qapi-schema += flat-union-invalid-branch-key.json
qapi-schema += flat-union-invalid-discriminator.json
+qapi-schema += flat-union-invalid-if-discriminator.json
qapi-schema += flat-union-no-base.json
qapi-schema += flat-union-optional-discriminator.json
qapi-schema += flat-union-string-discriminator.json
diff --git a/tests/qapi-schema/flat-union-invalid-if-discriminator.err b/tests/qapi-schema/flat-union-invalid-if-discriminator.err
new file mode 100644
index 0000000000..0c94c9860d
--- /dev/null
+++ b/tests/qapi-schema/flat-union-invalid-if-discriminator.err
@@ -0,0 +1 @@
+tests/qapi-schema/flat-union-invalid-if-discriminator.json:13: The discriminator TestBase.enum1 for union TestUnion must not be conditional
diff --git a/tests/qapi-schema/flat-union-invalid-if-discriminator.exit b/tests/qapi-schema/flat-union-invalid-if-discriminator.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/flat-union-invalid-if-discriminator.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/flat-union-invalid-if-discriminator.json b/tests/qapi-schema/flat-union-invalid-if-discriminator.json
new file mode 100644
index 0000000000..618ec36396
--- /dev/null
+++ b/tests/qapi-schema/flat-union-invalid-if-discriminator.json
@@ -0,0 +1,17 @@
+{ 'enum': 'TestEnum',
+ 'data': [ 'value1', 'value2' ] }
+
+{ 'struct': 'TestBase',
+ 'data': { 'enum1': { 'type': 'TestEnum', 'if': 'FOO' } } }
+
+{ 'struct': 'TestTypeA',
+ 'data': { 'string': 'str' } }
+
+{ 'struct': 'TestTypeB',
+ 'data': { 'integer': 'int' } }
+
+{ 'union': 'TestUnion',
+ 'base': 'TestBase',
+ 'discriminator': 'enum1',
+ 'data': { 'value1': 'TestTypeA',
+ 'value2': 'TestTypeB' } }
diff --git a/tests/qapi-schema/flat-union-invalid-if-discriminator.out b/tests/qapi-schema/flat-union-invalid-if-discriminator.out
new file mode 100644
index 0000000000..e69de29bb2
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 16/27] qapi: add 'if' to union members
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (14 preceding siblings ...)
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 15/27] qapi: add an error in case a discriminator is conditional Marc-André Lureau
@ 2018-12-08 11:15 ` Marc-André Lureau
2018-12-10 17:33 ` Markus Armbruster
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 17/27] qapi: simplify make_enum_members() Marc-André Lureau
` (12 subsequent siblings)
28 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
Add 'if' key to union members:
{ 'union': 'TestIfUnion', 'data':
'mem': { 'type': 'str', 'if': 'COND'} }
The generated code remains unconditional for now. Later patches
generate the conditionals.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
scripts/qapi/common.py | 17 +++++++++--------
docs/devel/qapi-code-gen.txt | 2 +-
tests/qapi-schema/qapi-schema-test.json | 4 +++-
tests/qapi-schema/qapi-schema-test.out | 4 ++++
tests/qapi-schema/test-qapi.py | 1 +
5 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index f79b3fad54..fd622313cb 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -823,7 +823,7 @@ def check_union(expr, info):
check_name(info, "Member of union '%s'" % name, key)
if isinstance(value, dict):
check_known_keys(info, "member '%s' of union '%s'" % (key, name),
- value, ['type'], [])
+ value, ['type'], ['if'])
typ = value['type']
else:
typ = value
@@ -1513,8 +1513,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):
@@ -1796,14 +1796,14 @@ class QAPISchema(object):
def _make_variant(self, case, typ):
return QAPISchemaObjectTypeVariant(case, typ)
- 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, None, info)])
- return QAPISchemaObjectTypeVariant(case, typ)
+ return QAPISchemaObjectTypeVariant(case, typ, ifcond)
def _def_union_type(self, expr, info, doc):
name = expr['union']
@@ -1821,10 +1821,11 @@ class QAPISchema(object):
for (key, value) in data.items()]
members = []
else:
- variants = [self._make_simple_variant(key, value['type'], 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(
diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
index e6fff32241..6f2457a2e0 100644
--- a/docs/devel/qapi-code-gen.txt
+++ b/docs/devel/qapi-code-gen.txt
@@ -754,7 +754,7 @@ gets its generated code guarded like this:
Where a member can be defined with a single string value for its type,
it is also possible to supply a dictionary instead with both 'type'
-and 'if' keys. (TODO: union and alternate)
+and 'if' keys. (TODO: alternate)
Example: a conditional 'bar' member
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index b8565a3913..6e9e4e14d9 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -210,7 +210,9 @@
[ 'foo', { 'name' : 'bar', 'if': 'defined(TEST_IF_ENUM_BAR)' } ],
'if': 'defined(TEST_IF_ENUM)' }
-{ 'union': 'TestIfUnion', 'data': { 'foo': 'TestStruct' },
+{ 'union': 'TestIfUnion', 'data':
+ { 'foo': 'TestStruct',
+ 'union_bar': { 'type': 'str', 'if': 'defined(TEST_IF_UNION_BAR)'} },
'if': 'defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)' }
{ 'alternate': 'TestIfAlternate', 'data': { 'foo': 'int', 'bar': 'TestStruct' },
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 23fb078b85..a342ecfc55 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -280,11 +280,15 @@ object q_obj_TestStruct-wrapper
member data: TestStruct optional=False
enum TestIfUnionKind
member foo
+ member union_bar
+ if ['defined(TEST_IF_UNION_BAR)']
if ['defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)']
object TestIfUnion
member type: TestIfUnionKind optional=False
tag type
case foo: q_obj_TestStruct-wrapper
+ case union_bar: q_obj_str-wrapper
+ if ['defined(TEST_IF_UNION_BAR)']
if ['defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)']
alternate TestIfAlternate
tag type
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index 27081cb50c..d592854601 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -68,6 +68,7 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
print(' tag %s' % variants.tag_member.name)
for v in variants.variants:
print(' case %s: %s' % (v.name, v.type.name))
+ QAPISchemaTestVisitor._print_if(v.ifcond, indent=8)
@staticmethod
def _print_if(ifcond, indent=4):
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 17/27] qapi: simplify make_enum_members()
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (15 preceding siblings ...)
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 16/27] qapi: add 'if' to union members Marc-André Lureau
@ 2018-12-08 11:15 ` Marc-André Lureau
2018-12-11 12:05 ` Markus Armbruster
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 18/27] tests/qapi: add command with condition on union argument Marc-André Lureau
` (11 subsequent siblings)
28 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
The function only receives the dictionary form of enum expressions
now, so we can make it shorter.
Suggested-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
scripts/qapi/common.py | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index fd622313cb..44020779dd 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1714,16 +1714,7 @@ class QAPISchema(object):
qtype_values, 'QTYPE'))
def _make_enum_members(self, values):
- enum = []
- for v in values:
- if isinstance(v, dict):
- name = v['name']
- ifcond = v.get('if')
- else:
- name = v
- ifcond = None
- enum.append(QAPISchemaMember(name, ifcond))
- return enum
+ 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()
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 18/27] tests/qapi: add command with condition on union argument
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (16 preceding siblings ...)
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 17/27] qapi: simplify make_enum_members() Marc-André Lureau
@ 2018-12-08 11:15 ` Marc-André Lureau
2018-12-11 12:09 ` Markus Armbruster
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 19/27] qapi: add 'if' to alternate members Marc-André Lureau
` (10 subsequent siblings)
28 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
For completeness.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/qapi-schema/qapi-schema-test.json | 3 +++
tests/qapi-schema/qapi-schema-test.out | 6 ++++++
2 files changed, 9 insertions(+)
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index 6e9e4e14d9..0d28475f4c 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -215,6 +215,9 @@
'union_bar': { 'type': 'str', 'if': 'defined(TEST_IF_UNION_BAR)'} },
'if': 'defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)' }
+{ 'command': 'TestIfUnionCmd', 'data': { 'union_cmd_arg': 'TestIfUnion' },
+ 'if': 'defined(TEST_IF_UNION)' }
+
{ 'alternate': 'TestIfAlternate', 'data': { 'foo': 'int', 'bar': 'TestStruct' },
'if': 'defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)' }
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index a342ecfc55..aedc668aa4 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -290,6 +290,12 @@ object TestIfUnion
case union_bar: q_obj_str-wrapper
if ['defined(TEST_IF_UNION_BAR)']
if ['defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)']
+object q_obj_TestIfUnionCmd-arg
+ member union_cmd_arg: TestIfUnion optional=False
+ if ['defined(TEST_IF_UNION)']
+command TestIfUnionCmd q_obj_TestIfUnionCmd-arg -> None
+ gen=True success_response=True boxed=False oob=False preconfig=False
+ if ['defined(TEST_IF_UNION)']
alternate TestIfAlternate
tag type
case foo: int
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 19/27] qapi: add 'if' to alternate members
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (17 preceding siblings ...)
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 18/27] tests/qapi: add command with condition on union argument Marc-André Lureau
@ 2018-12-08 11:15 ` Marc-André Lureau
2018-12-11 12:21 ` Markus Armbruster
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 20/27] tests/qapi: add command with condition on alternate argument Marc-André Lureau
` (9 subsequent siblings)
28 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
Add 'if' key to alternate members:
{ 'alternate': 'TestIfAlternate', 'data':
{ 'alt': { 'type': 'TestStruct', 'if': 'COND' } } }
Generated code is not changed by this patch but with "qapi: add #if
conditions to generated code".
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
scripts/qapi/common.py | 10 +++++-----
docs/devel/qapi-code-gen.txt | 2 +-
tests/qapi-schema/qapi-schema-test.json | 4 +++-
tests/qapi-schema/qapi-schema-test.out | 1 +
4 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 44020779dd..a70d6dec3b 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -857,7 +857,7 @@ def check_alternate(expr, info):
if isinstance(value, dict):
check_known_keys(info,
"member '%s' of alternate '%s'" % (key, name),
- value, ['type'], [])
+ value, ['type'], ['if'])
typ = value['type']
else:
typ = value
@@ -1784,8 +1784,8 @@ 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, ifcond, info):
if isinstance(typ, list):
@@ -1808,7 +1808,7 @@ class QAPISchema(object):
name, info, doc, ifcond,
'base', self._make_members(base, info))
if tag_name:
- variants = [self._make_variant(key, value['type'])
+ variants = [self._make_variant(key, value['type'], value.get('if'))
for (key, value) in data.items()]
members = []
else:
@@ -1829,7 +1829,7 @@ class QAPISchema(object):
name = expr['alternate']
data = expr['data']
ifcond = expr.get('if')
- variants = [self._make_variant(key, value['type'])
+ 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(
diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
index 6f2457a2e0..5ea62cb111 100644
--- a/docs/devel/qapi-code-gen.txt
+++ b/docs/devel/qapi-code-gen.txt
@@ -754,7 +754,7 @@ gets its generated code guarded like this:
Where a member can be defined with a single string value for its type,
it is also possible to supply a dictionary instead with both 'type'
-and 'if' keys. (TODO: alternate)
+and 'if' keys.
Example: a conditional 'bar' member
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index 0d28475f4c..d58cc49028 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -218,7 +218,9 @@
{ 'command': 'TestIfUnionCmd', 'data': { 'union_cmd_arg': 'TestIfUnion' },
'if': 'defined(TEST_IF_UNION)' }
-{ 'alternate': 'TestIfAlternate', 'data': { 'foo': 'int', 'bar': 'TestStruct' },
+{ 'alternate': 'TestIfAlternate', 'data':
+ { 'foo': 'int',
+ 'bar': { 'type': 'TestStruct', 'if': 'defined(TEST_IF_ALT_BAR)'} },
'if': 'defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)' }
{ 'command': 'TestIfCmd', 'data':
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index aedc668aa4..59d7ed17a1 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -300,6 +300,7 @@ alternate TestIfAlternate
tag type
case foo: int
case bar: TestStruct
+ if ['defined(TEST_IF_ALT_BAR)']
if ['defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)']
object q_obj_TestIfCmd-arg
member foo: TestIfStruct optional=False
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 20/27] tests/qapi: add command with condition on alternate argument
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (18 preceding siblings ...)
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 19/27] qapi: add 'if' to alternate members Marc-André Lureau
@ 2018-12-08 11:15 ` Marc-André Lureau
2018-12-11 12:20 ` Markus Armbruster
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 21/27] qapi: add #if conditions to generated code members Marc-André Lureau
` (8 subsequent siblings)
28 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:15 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
For completeness.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/qapi-schema/qapi-schema-test.json | 3 +++
tests/qapi-schema/qapi-schema-test.out | 6 ++++++
2 files changed, 9 insertions(+)
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index d58cc49028..cb0857df52 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -223,6 +223,9 @@
'bar': { 'type': 'TestStruct', 'if': 'defined(TEST_IF_ALT_BAR)'} },
'if': 'defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)' }
+{ 'command': 'TestIfAlternateCmd', 'data': { 'alt_cmd_arg': 'TestIfAlternate' },
+ 'if': 'defined(TEST_IF_ALT)' }
+
{ 'command': 'TestIfCmd', 'data':
{ 'foo': 'TestIfStruct',
'bar': { 'type': 'TestIfEnum', 'if': 'defined(TEST_IF_CMD_BAR)' } },
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 59d7ed17a1..9464101d26 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -302,6 +302,12 @@ alternate TestIfAlternate
case bar: TestStruct
if ['defined(TEST_IF_ALT_BAR)']
if ['defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)']
+object q_obj_TestIfAlternateCmd-arg
+ member alt_cmd_arg: TestIfAlternate optional=False
+ if ['defined(TEST_IF_ALT)']
+command TestIfAlternateCmd q_obj_TestIfAlternateCmd-arg -> None
+ gen=True success_response=True boxed=False oob=False preconfig=False
+ if ['defined(TEST_IF_ALT)']
object q_obj_TestIfCmd-arg
member foo: TestIfStruct optional=False
member bar: TestIfEnum optional=False
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 21/27] qapi: add #if conditions to generated code members
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (19 preceding siblings ...)
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 20/27] tests/qapi: add command with condition on alternate argument Marc-André Lureau
@ 2018-12-08 11:16 ` Marc-André Lureau
2018-12-11 13:17 ` Markus Armbruster
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 22/27] qapi: add 'If:' condition to enum values documentation Marc-André Lureau
` (7 subsequent siblings)
28 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:16 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
Wrap generated enum/struct members and code with #if/#endif, using the
.ifcond members added in the previous patches.
Some types generate both enum and struct members for example, so a
step-by-step is unnecessarily complicated to deal with (it would
easily generate invalid intermediary code).
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
scripts/qapi/common.py | 4 ++++
scripts/qapi/introspect.py | 13 +++++++++----
scripts/qapi/types.py | 4 ++++
scripts/qapi/visit.py | 6 ++++++
4 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index a70d6dec3b..3a29812ef2 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -2108,11 +2108,13 @@ const QEnumLookup %(c_name)s_lookup = {
''',
c_name=c_name(name))
for m in members:
+ ret += gen_if(m.ifcond)
index = c_enum_const(name, m.name, prefix)
ret += mcgen('''
[%(index)s] = "%(name)s",
''',
index=index, name=m.name)
+ ret += gen_endif(m.ifcond)
ret += mcgen('''
},
@@ -2134,10 +2136,12 @@ typedef enum %(c_name)s {
c_name=c_name(name))
for m in enum_members:
+ ret += gen_if(m.ifcond)
ret += mcgen('''
%(c_enum)s,
''',
c_enum=c_enum_const(name, m.name, prefix))
+ ret += gen_endif(m.ifcond)
ret += mcgen('''
} %(c_name)s;
diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
index 417625d54b..77087f629b 100644
--- a/scripts/qapi/introspect.py
+++ b/scripts/qapi/introspect.py
@@ -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,14 +171,16 @@ 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, members, prefix):
self._gen_qlit(name, 'enum',
- {'values': [m.name for m in members]}, ifcond)
+ {'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)
@@ -192,8 +196,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):
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index 0404710bbd..e2ee9f3b72 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -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;
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index 24f85a2e85..82eab72b21 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -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:
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 22/27] qapi: add 'If:' condition to enum values documentation
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (20 preceding siblings ...)
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 21/27] qapi: add #if conditions to generated code members Marc-André Lureau
@ 2018-12-08 11:16 ` Marc-André Lureau
2018-12-11 16:00 ` Markus Armbruster
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 23/27] qapi: add 'If:' condition to struct members documentation Marc-André Lureau
` (6 subsequent siblings)
28 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:16 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
Use a common function to generate the "If:..." line.
While at it, get rid of the existing \n\n (no idea why it was
there). Use a line-break in member description, this seems to look
slightly better in the plaintext version.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
scripts/qapi/doc.py | 24 +++++++++++++++---------
tests/qapi-schema/doc-good.json | 4 +++-
tests/qapi-schema/doc-good.out | 1 +
tests/qapi-schema/doc-good.texi | 2 +-
4 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
index 76cb186ff9..2133ded47e 100755
--- a/scripts/qapi/doc.py
+++ b/scripts/qapi/doc.py
@@ -126,19 +126,26 @@ 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"""
+ return '%s@b{If:} @code{%s}%s' % (
+ prefix, ', '.join(ifcond), suffix) if ifcond else ''
+
+
+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' % (
member.name, membertype,
' (optional)' if member.optional else '',
- suffix)
+ suffix, desc)
def texi_members(doc, what, base, variants, member_func):
@@ -155,7 +162,7 @@ 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)
if base:
items += '@item The members of @code{%s}\n' % base.doc_type()
if variants:
@@ -165,7 +172,7 @@ def texi_members(doc, what, base, variants, member_func):
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, suffix=when)
else:
items += '@item The members of @code{%s}%s\n' % (
v.type.doc_type(), when)
@@ -185,8 +192,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
diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json
index 984cd8ed06..c7fe08c530 100644
--- a/tests/qapi-schema/doc-good.json
+++ b/tests/qapi-schema/doc-good.json
@@ -55,7 +55,9 @@
#
# @two is undocumented
##
-{ 'enum': 'Enum', 'data': [ 'one', 'two' ], 'if': 'defined(IFCOND)' }
+{ 'enum': 'Enum', 'data':
+ [ { 'name': 'one', 'if': 'defined(IFENUM)' }, 'two' ],
+ 'if': 'defined(IFCOND)' }
##
# @Base:
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
index c2fc5c774a..a05535b69b 100644
--- a/tests/qapi-schema/doc-good.out
+++ b/tests/qapi-schema/doc-good.out
@@ -11,6 +11,7 @@ enum QType
module doc-good.json
enum Enum
member one
+ if ['defined(IFENUM)']
member two
if ['defined(IFCOND)']
object Base
diff --git a/tests/qapi-schema/doc-good.texi b/tests/qapi-schema/doc-good.texi
index e42eace474..5c0231e0e6 100644
--- a/tests/qapi-schema/doc-good.texi
+++ b/tests/qapi-schema/doc-good.texi
@@ -84,12 +84,12 @@ Examples:
@table @asis
@item @code{one}
The @emph{one} @{and only@}
+@*@b{If:} @code{defined(IFENUM)}
@item @code{two}
Not documented
@end table
@code{two} is undocumented
-
@b{If:} @code{defined(IFCOND)}
@end deftp
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 23/27] qapi: add 'If:' condition to struct members documentation
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (21 preceding siblings ...)
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 22/27] qapi: add 'If:' condition to enum values documentation Marc-André Lureau
@ 2018-12-08 11:16 ` Marc-André Lureau
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 24/27] qapi: add condition to variants documentation Marc-André Lureau
` (5 subsequent siblings)
28 siblings, 0 replies; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:16 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
scripts/qapi/doc.py | 4 ++--
tests/qapi-schema/doc-good.json | 3 ++-
tests/qapi-schema/doc-good.out | 1 +
tests/qapi-schema/doc-good.texi | 1 +
4 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
index 2133ded47e..e0cf94421c 100755
--- a/scripts/qapi/doc.py
+++ b/scripts/qapi/doc.py
@@ -142,10 +142,10 @@ 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%s' % (
+ return '@item @code{%s%s}%s%s\n%s%s' % (
member.name, membertype,
' (optional)' if member.optional else '',
- suffix, desc)
+ suffix, desc, texi_if(member.ifcond, prefix='@*'))
def texi_members(doc, what, base, variants, member_func):
diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json
index c7fe08c530..158443b1a3 100644
--- a/tests/qapi-schema/doc-good.json
+++ b/tests/qapi-schema/doc-good.json
@@ -72,7 +72,8 @@
#
# Another paragraph (but no @var: line)
##
-{ 'struct': 'Variant1', 'data': { 'var1': 'str' } }
+{ 'struct': 'Variant1',
+ 'data': { 'var1': { 'type': 'str', 'if': 'defined(IFSTR)' } } }
##
# @Variant2:
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
index a05535b69b..c310b47be2 100644
--- a/tests/qapi-schema/doc-good.out
+++ b/tests/qapi-schema/doc-good.out
@@ -18,6 +18,7 @@ object Base
member base1: Enum optional=False
object Variant1
member var1: str optional=False
+ if ['defined(IFSTR)']
object Variant2
object Object
base Base
diff --git a/tests/qapi-schema/doc-good.texi b/tests/qapi-schema/doc-good.texi
index 5c0231e0e6..0f8d69a378 100644
--- a/tests/qapi-schema/doc-good.texi
+++ b/tests/qapi-schema/doc-good.texi
@@ -119,6 +119,7 @@ Another paragraph (but no @code{var}: line)
@table @asis
@item @code{var1: string}
Not documented
+@*@b{If:} @code{defined(IFSTR)}
@end table
@end deftp
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 24/27] qapi: add condition to variants documentation
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (22 preceding siblings ...)
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 23/27] qapi: add 'If:' condition to struct members documentation Marc-André Lureau
@ 2018-12-08 11:16 ` Marc-André Lureau
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 25/27] qapi: break long lines at 'data' member Marc-André Lureau
` (4 subsequent siblings)
28 siblings, 0 replies; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:16 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Michael Roth
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
scripts/qapi/doc.py | 4 ++--
tests/qapi-schema/doc-good.json | 4 ++--
tests/qapi-schema/doc-good.out | 3 +++
tests/qapi-schema/doc-good.texi | 4 ++--
4 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
index e0cf94421c..4008054eea 100755
--- a/scripts/qapi/doc.py
+++ b/scripts/qapi/doc.py
@@ -167,8 +167,8 @@ def texi_members(doc, what, base, variants, member_func):
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:
diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json
index 158443b1a3..afe46d93f0 100644
--- a/tests/qapi-schema/doc-good.json
+++ b/tests/qapi-schema/doc-good.json
@@ -86,13 +86,13 @@
{ 'union': 'Object',
'base': 'Base',
'discriminator': 'base1',
- 'data': { 'one': 'Variant1', 'two': 'Variant2' } }
+ 'data': { 'one': 'Variant1', 'two': { 'type': 'Variant2', 'if': 'IFTWO' } } }
##
# @SugaredUnion:
##
{ 'union': 'SugaredUnion',
- 'data': { 'one': 'Variant1', 'two': 'Variant2' } }
+ 'data': { 'one': 'Variant1', 'two': { 'type': 'Variant2', 'if': 'IFTWO' } } }
##
# == Another subsection
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
index c310b47be2..ed647b82be 100644
--- a/tests/qapi-schema/doc-good.out
+++ b/tests/qapi-schema/doc-good.out
@@ -25,6 +25,7 @@ object Object
tag base1
case one: Variant1
case two: Variant2
+ if ['IFTWO']
object q_obj_Variant1-wrapper
member data: Variant1 optional=False
object q_obj_Variant2-wrapper
@@ -32,11 +33,13 @@ object q_obj_Variant2-wrapper
enum SugaredUnionKind
member one
member two
+ if ['IFTWO']
object SugaredUnion
member type: SugaredUnionKind optional=False
tag type
case one: q_obj_Variant1-wrapper
case two: q_obj_Variant2-wrapper
+ if ['IFTWO']
object q_obj_cmd-arg
member arg1: int optional=False
member arg2: str optional=True
diff --git a/tests/qapi-schema/doc-good.texi b/tests/qapi-schema/doc-good.texi
index 0f8d69a378..df08a89521 100644
--- a/tests/qapi-schema/doc-good.texi
+++ b/tests/qapi-schema/doc-good.texi
@@ -142,7 +142,7 @@ Not documented
@table @asis
@item The members of @code{Base}
@item The members of @code{Variant1} when @code{base1} is @t{"one"}
-@item The members of @code{Variant2} when @code{base1} is @t{"two"}
+@item The members of @code{Variant2} when @code{base1} is @t{"two"} (@b{If:} @code{IFTWO})
@end table
@end deftp
@@ -158,7 +158,7 @@ Not documented
@item @code{type}
One of @t{"one"}, @t{"two"}
@item @code{data: Variant1} when @code{type} is @t{"one"}
-@item @code{data: Variant2} when @code{type} is @t{"two"}
+@item @code{data: Variant2} when @code{type} is @t{"two"} (@b{If:} @code{IFTWO})
@end table
@end deftp
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 25/27] qapi: break long lines at 'data' member
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (23 preceding siblings ...)
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 24/27] qapi: add condition to variants documentation Marc-André Lureau
@ 2018-12-08 11:16 ` Marc-André Lureau
2018-12-11 16:07 ` Markus Armbruster
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 26/27] qapi: add more conditions to SPICE Marc-André Lureau
` (3 subsequent siblings)
28 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:16 UTC (permalink / raw)
To: qemu-devel
Cc: armbru, Marc-André Lureau, Eric Blake, Paolo Bonzini,
Juan Quintela, Dr. David Alan Gilbert, Jason Wang, Stefan Berger,
Gerd Hoffmann
Let's break the line before 'data'. While at it, improve a bit
indentation/spacing. (I removed some alignment which are not helping
much readability and become quickly inconsistent)
Suggested-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
qapi/block-core.json | 13 ++--
qapi/char.json | 138 +++++++++++++++++++++++++------------------
qapi/migration.json | 3 +-
qapi/misc.json | 7 ++-
qapi/net.json | 3 +-
qapi/tpm.json | 5 +-
qapi/ui.json | 3 +-
7 files changed, 101 insertions(+), 71 deletions(-)
diff --git a/qapi/block-core.json b/qapi/block-core.json
index d4fe710836..92e0205d91 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1143,8 +1143,10 @@
# This command is now obsolete and will always return an error since 2.10
#
##
-{ 'command': 'block_passwd', 'data': {'*device': 'str',
- '*node-name': 'str', 'password': 'str'} }
+{ 'command': 'block_passwd',
+ 'data': { '*device': 'str',
+ '*node-name': 'str',
+ 'password': 'str' } }
##
# @block_resize:
@@ -1171,9 +1173,10 @@
# <- { "return": {} }
#
##
-{ 'command': 'block_resize', 'data': { '*device': 'str',
- '*node-name': 'str',
- 'size': 'int' }}
+{ 'command': 'block_resize',
+ 'data': { '*device': 'str',
+ '*node-name': 'str',
+ 'size': 'int' } }
##
# @NewImageMode:
diff --git a/qapi/char.json b/qapi/char.json
index 79bac598a0..24628331ec 100644
--- a/qapi/char.json
+++ b/qapi/char.json
@@ -25,9 +25,10 @@
#
# Since: 0.14.0
##
-{ 'struct': 'ChardevInfo', 'data': {'label': 'str',
- 'filename': 'str',
- 'frontend-open': 'bool'} }
+{ 'struct': 'ChardevInfo',
+ 'data': { 'label': 'str',
+ 'filename': 'str',
+ 'frontend-open': 'bool' } }
##
# @query-chardev:
@@ -152,7 +153,8 @@
#
##
{ 'command': 'ringbuf-write',
- 'data': {'device': 'str', 'data': 'str',
+ 'data': { 'device': 'str',
+ 'data': 'str',
'*format': 'DataFormat'} }
##
@@ -202,8 +204,9 @@
#
# Since: 2.6
##
-{ 'struct': 'ChardevCommon', 'data': { '*logfile': 'str',
- '*logappend': 'bool' } }
+{ 'struct': 'ChardevCommon',
+ 'data': { '*logfile': 'str',
+ '*logappend': 'bool' } }
##
# @ChardevFile:
@@ -217,9 +220,10 @@
#
# Since: 1.4
##
-{ 'struct': 'ChardevFile', 'data': { '*in' : 'str',
- 'out' : 'str',
- '*append': 'bool' },
+{ 'struct': 'ChardevFile',
+ 'data': { '*in': 'str',
+ 'out': 'str',
+ '*append': 'bool' },
'base': 'ChardevCommon' }
##
@@ -232,7 +236,8 @@
#
# Since: 1.4
##
-{ 'struct': 'ChardevHostdev', 'data': { 'device' : 'str' },
+{ 'struct': 'ChardevHostdev',
+ 'data': { 'device': 'str' },
'base': 'ChardevCommon' }
##
@@ -260,15 +265,16 @@
#
# Since: 1.4
##
-{ 'struct': 'ChardevSocket', 'data': { 'addr' : 'SocketAddressLegacy',
- '*tls-creds' : 'str',
- '*server' : 'bool',
- '*wait' : 'bool',
- '*nodelay' : 'bool',
- '*telnet' : 'bool',
- '*tn3270' : 'bool',
- '*websocket' : 'bool',
- '*reconnect' : 'int' },
+{ 'struct': 'ChardevSocket',
+ 'data': { 'addr': 'SocketAddressLegacy',
+ '*tls-creds': 'str',
+ '*server': 'bool',
+ '*wait': 'bool',
+ '*nodelay': 'bool',
+ '*telnet': 'bool',
+ '*tn3270': 'bool',
+ '*websocket': 'bool',
+ '*reconnect': 'int' },
'base': 'ChardevCommon' }
##
@@ -281,8 +287,9 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevUdp', 'data': { 'remote' : 'SocketAddressLegacy',
- '*local' : 'SocketAddressLegacy' },
+{ 'struct': 'ChardevUdp',
+ 'data': { 'remote': 'SocketAddressLegacy',
+ '*local': 'SocketAddressLegacy' },
'base': 'ChardevCommon' }
##
@@ -294,7 +301,8 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevMux', 'data': { 'chardev' : 'str' },
+{ 'struct': 'ChardevMux',
+ 'data': { 'chardev': 'str' },
'base': 'ChardevCommon' }
##
@@ -308,7 +316,8 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevStdio', 'data': { '*signal' : 'bool' },
+{ 'struct': 'ChardevStdio',
+ 'data': { '*signal': 'bool' },
'base': 'ChardevCommon' }
@@ -321,7 +330,8 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevSpiceChannel', 'data': { 'type' : 'str' },
+{ 'struct': 'ChardevSpiceChannel',
+ 'data': { 'type': 'str' },
'base': 'ChardevCommon' }
# TODO: 'if': 'defined(CONFIG_SPICE)'
@@ -334,7 +344,8 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevSpicePort', 'data': { 'fqdn' : 'str' },
+{ 'struct': 'ChardevSpicePort',
+ 'data': { 'fqdn': 'str' },
'base': 'ChardevCommon' }
# TODO: 'if': 'defined(CONFIG_SPICE)'
@@ -350,10 +361,11 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevVC', 'data': { '*width' : 'int',
- '*height' : 'int',
- '*cols' : 'int',
- '*rows' : 'int' },
+{ 'struct': 'ChardevVC',
+ 'data': { '*width': 'int',
+ '*height': 'int',
+ '*cols': 'int',
+ '*rows': 'int' },
'base': 'ChardevCommon' }
##
@@ -365,7 +377,8 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevRingbuf', 'data': { '*size' : 'int' },
+{ 'struct': 'ChardevRingbuf',
+ 'data': { '*size': 'int' },
'base': 'ChardevCommon' }
##
@@ -375,29 +388,30 @@
#
# Since: 1.4 (testdev since 2.2, wctablet since 2.9)
##
-{ 'union': 'ChardevBackend', 'data': { 'file' : 'ChardevFile',
- 'serial' : 'ChardevHostdev',
- 'parallel': 'ChardevHostdev',
- 'pipe' : 'ChardevHostdev',
- 'socket' : 'ChardevSocket',
- 'udp' : 'ChardevUdp',
- 'pty' : 'ChardevCommon',
- 'null' : 'ChardevCommon',
- 'mux' : 'ChardevMux',
- 'msmouse': 'ChardevCommon',
- 'wctablet' : 'ChardevCommon',
- 'braille': 'ChardevCommon',
- 'testdev': 'ChardevCommon',
- 'stdio' : 'ChardevStdio',
- 'console': 'ChardevCommon',
- 'spicevmc': 'ChardevSpiceChannel',
+{ 'union': 'ChardevBackend',
+ 'data': { 'file': 'ChardevFile',
+ 'serial': 'ChardevHostdev',
+ 'parallel': 'ChardevHostdev',
+ 'pipe': 'ChardevHostdev',
+ 'socket': 'ChardevSocket',
+ 'udp': 'ChardevUdp',
+ 'pty': 'ChardevCommon',
+ 'null': 'ChardevCommon',
+ 'mux': 'ChardevMux',
+ 'msmouse': 'ChardevCommon',
+ 'wctablet': 'ChardevCommon',
+ 'braille': 'ChardevCommon',
+ 'testdev': 'ChardevCommon',
+ 'stdio': 'ChardevStdio',
+ 'console': 'ChardevCommon',
+ 'spicevmc': 'ChardevSpiceChannel',
# TODO: { 'type': 'ChardevSpiceChannel', 'if': 'defined(CONFIG_SPICE)' },
- 'spiceport': 'ChardevSpicePort',
+ 'spiceport': 'ChardevSpicePort',
# TODO: { 'type': 'ChardevSpicePort', 'if': 'defined(CONFIG_SPICE)' },
- 'vc' : 'ChardevVC',
- 'ringbuf': 'ChardevRingbuf',
- # next one is just for compatibility
- 'memory' : 'ChardevRingbuf' } }
+ 'vc': 'ChardevVC',
+ 'ringbuf': 'ChardevRingbuf',
+ # next one is just for compatibility
+ 'memory': 'ChardevRingbuf' } }
##
# @ChardevReturn:
@@ -409,7 +423,8 @@
#
# Since: 1.4
##
-{ 'struct' : 'ChardevReturn', 'data': { '*pty' : 'str' } }
+{ 'struct' : 'ChardevReturn',
+ 'data': { '*pty': 'str' } }
##
# @chardev-add:
@@ -442,8 +457,9 @@
# <- { "return": { "pty" : "/dev/pty/42" } }
#
##
-{ 'command': 'chardev-add', 'data': {'id' : 'str',
- 'backend' : 'ChardevBackend' },
+{ 'command': 'chardev-add',
+ 'data': { 'id': 'str',
+ 'backend': 'ChardevBackend' },
'returns': 'ChardevReturn' }
##
@@ -482,8 +498,9 @@
# <- {"return": {}}
#
##
-{ 'command': 'chardev-change', 'data': {'id' : 'str',
- 'backend' : 'ChardevBackend' },
+{ 'command': 'chardev-change',
+ 'data': { 'id': 'str',
+ 'backend': 'ChardevBackend' },
'returns': 'ChardevReturn' }
##
@@ -503,7 +520,8 @@
# <- { "return": {} }
#
##
-{ 'command': 'chardev-remove', 'data': {'id': 'str'} }
+{ 'command': 'chardev-remove',
+ 'data': { 'id': 'str' } }
##
# @chardev-send-break:
@@ -522,7 +540,8 @@
# <- { "return": {} }
#
##
-{ 'command': 'chardev-send-break', 'data': {'id': 'str'} }
+{ 'command': 'chardev-send-break',
+ 'data': { 'id': 'str' } }
##
# @VSERPORT_CHANGE:
@@ -543,4 +562,5 @@
#
##
{ 'event': 'VSERPORT_CHANGE',
- 'data': { 'id': 'str', 'open': 'bool' } }
+ 'data': { 'id': 'str',
+ 'open': 'bool' } }
diff --git a/qapi/migration.json b/qapi/migration.json
index 38d4c41d88..5fd33316a0 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -1356,7 +1356,8 @@
#
# Since: 3.0
##
-{ 'command': 'migrate-recover', 'data': { 'uri': 'str' },
+{ 'command': 'migrate-recover',
+ 'data': { 'uri': 'str' },
'allow-oob': true }
##
diff --git a/qapi/misc.json b/qapi/misc.json
index 6c1c5c0a37..012048a071 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -2381,7 +2381,9 @@
# <- { "return": { "fdset-id": 1, "fd": 3 } }
#
##
-{ 'command': 'add-fd', 'data': {'*fdset-id': 'int', '*opaque': 'str'},
+{ 'command': 'add-fd',
+ 'data': { '*fdset-id': 'int',
+ '*opaque': 'str' },
'returns': 'AddfdInfo' }
##
@@ -2653,7 +2655,8 @@
# }
#
##
-{'command': 'query-command-line-options', 'data': { '*option': 'str' },
+{'command': 'query-command-line-options',
+ 'data': { '*option': 'str' },
'returns': ['CommandLineOptionInfo'],
'allow-preconfig': true }
diff --git a/qapi/net.json b/qapi/net.json
index 8f99fd911d..a1a0f39f74 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -657,7 +657,8 @@
# }
#
##
-{ 'command': 'query-rx-filter', 'data': { '*name': 'str' },
+{ 'command': 'query-rx-filter',
+ 'data': { '*name': 'str' },
'returns': ['RxFilterInfo'] }
##
diff --git a/qapi/tpm.json b/qapi/tpm.json
index d50deef5e9..b30323bb6b 100644
--- a/qapi/tpm.json
+++ b/qapi/tpm.json
@@ -76,8 +76,9 @@
#
# Since: 1.5
##
-{ 'struct': 'TPMPassthroughOptions', 'data': { '*path' : 'str',
- '*cancel-path' : 'str'} }
+{ 'struct': 'TPMPassthroughOptions',
+ 'data': { '*path': 'str',
+ '*cancel-path': 'str' } }
##
# @TPMEmulatorOptions:
diff --git a/qapi/ui.json b/qapi/ui.json
index fd39acb5c3..5ad13248d5 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -598,7 +598,8 @@
# Notes: An empty password in this command will set the password to the empty
# string. Existing clients are unaffected by executing this command.
##
-{ 'command': 'change-vnc-password', 'data': {'password': 'str'},
+{ 'command': 'change-vnc-password',
+ 'data': { 'password': 'str' },
'if': 'defined(CONFIG_VNC)' }
##
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 26/27] qapi: add more conditions to SPICE
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (24 preceding siblings ...)
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 25/27] qapi: break long lines at 'data' member Marc-André Lureau
@ 2018-12-08 11:16 ` Marc-André Lureau
2018-12-11 17:11 ` Markus Armbruster
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 27/27] qapi: add conditions to REPLICATION type/commands on the schema Marc-André Lureau
` (2 subsequent siblings)
28 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:16 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, Marc-André Lureau, Eric Blake, Paolo Bonzini
Now that member can be made conditional, let's make SPICE chardev
conditional:
* spiceport, spicevmc
Before and after the patch for !CONFIG_SPICE, the error is the
same ('spiceport' is not a valid char driver name).
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
qapi/char.json | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/qapi/char.json b/qapi/char.json
index 24628331ec..77ed847972 100644
--- a/qapi/char.json
+++ b/qapi/char.json
@@ -332,8 +332,8 @@
##
{ 'struct': 'ChardevSpiceChannel',
'data': { 'type': 'str' },
- 'base': 'ChardevCommon' }
-# TODO: 'if': 'defined(CONFIG_SPICE)'
+ 'base': 'ChardevCommon',
+ 'if': 'defined(CONFIG_SPICE)' }
##
# @ChardevSpicePort:
@@ -346,8 +346,8 @@
##
{ 'struct': 'ChardevSpicePort',
'data': { 'fqdn': 'str' },
- 'base': 'ChardevCommon' }
-# TODO: 'if': 'defined(CONFIG_SPICE)'
+ 'base': 'ChardevCommon',
+ 'if': 'defined(CONFIG_SPICE)' }
##
# @ChardevVC:
@@ -404,10 +404,10 @@
'testdev': 'ChardevCommon',
'stdio': 'ChardevStdio',
'console': 'ChardevCommon',
- 'spicevmc': 'ChardevSpiceChannel',
-# TODO: { 'type': 'ChardevSpiceChannel', 'if': 'defined(CONFIG_SPICE)' },
- 'spiceport': 'ChardevSpicePort',
-# TODO: { 'type': 'ChardevSpicePort', 'if': 'defined(CONFIG_SPICE)' },
+ 'spicevmc': { 'type': 'ChardevSpiceChannel',
+ 'if': 'defined(CONFIG_SPICE)' },
+ 'spiceport': { 'type': 'ChardevSpicePort',
+ 'if': 'defined(CONFIG_SPICE)' },
'vc': 'ChardevVC',
'ringbuf': 'ChardevRingbuf',
# next one is just for compatibility
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [Qemu-devel] [PATCH for-4.0 v7 27/27] qapi: add conditions to REPLICATION type/commands on the schema
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (25 preceding siblings ...)
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 26/27] qapi: add more conditions to SPICE Marc-André Lureau
@ 2018-12-08 11:16 ` Marc-André Lureau
2018-12-11 17:15 ` Markus Armbruster
2018-12-08 11:19 ` [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
2018-12-12 17:18 ` Markus Armbruster
28 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:16 UTC (permalink / raw)
To: qemu-devel
Cc: armbru, Marc-André Lureau, zhanghailiang, Juan Quintela,
Dr. David Alan Gilbert, Eric Blake
Add #if defined(CONFIG_REPLICATION) in generated code, and adjust the
code accordingly.
Made conditional:
* xen-set-replication, query-xen-replication-status,
xen-colo-do-checkpoint
Before the patch, we first register the commands unconditionally in
generated code (requires a stub), then conditionally unregister in
qmp_unregister_commands_hack().
Afterwards, we register only when CONFIG_REPLICATION. The command
fails exactly the same, with CommandNotFound.
Improvement, because now query-qmp-schema is accurate, and we're one
step closer to killing qmp_unregister_commands_hack().
* enum BlockdevDriver value "replication" in command blockdev-add
* BlockdevOptions variant @replication
and related structures.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
qapi/block-core.json | 13 +++++++++----
qapi/migration.json | 12 ++++++++----
migration/colo.c | 16 ++++------------
monitor.c | 5 -----
4 files changed, 21 insertions(+), 25 deletions(-)
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 92e0205d91..762000f31f 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -2623,7 +2623,9 @@
'copy-on-read', 'dmg', 'file', 'ftp', 'ftps', 'gluster',
'host_cdrom', 'host_device', 'http', 'https', 'iscsi', 'luks',
'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels', 'qcow',
- 'qcow2', 'qed', 'quorum', 'raw', 'rbd', 'replication', 'sheepdog',
+ 'qcow2', 'qed', 'quorum', 'raw', 'rbd',
+ { 'name': 'replication', 'if': 'defined(CONFIG_REPLICATION)' },
+ 'sheepdog',
'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
##
@@ -3380,7 +3382,8 @@
#
# Since: 2.9
##
-{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }
+{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ],
+ 'if': 'defined(CONFIG_REPLICATION)' }
##
# @BlockdevOptionsReplication:
@@ -3398,7 +3401,8 @@
{ 'struct': 'BlockdevOptionsReplication',
'base': 'BlockdevOptionsGenericFormat',
'data': { 'mode': 'ReplicationMode',
- '*top-id': 'str' } }
+ '*top-id': 'str' },
+ 'if': 'defined(CONFIG_REPLICATION)' }
##
# @NFSTransport:
@@ -3714,7 +3718,8 @@
'quorum': 'BlockdevOptionsQuorum',
'raw': 'BlockdevOptionsRaw',
'rbd': 'BlockdevOptionsRbd',
- 'replication':'BlockdevOptionsReplication',
+ 'replication': { 'type': 'BlockdevOptionsReplication',
+ 'if': 'defined(CONFIG_REPLICATION)' },
'sheepdog': 'BlockdevOptionsSheepdog',
'ssh': 'BlockdevOptionsSsh',
'throttle': 'BlockdevOptionsThrottle',
diff --git a/qapi/migration.json b/qapi/migration.json
index 5fd33316a0..31b589ec26 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -1257,7 +1257,8 @@
# Since: 2.9
##
{ 'command': 'xen-set-replication',
- 'data': { 'enable': 'bool', 'primary': 'bool', '*failover' : 'bool' } }
+ 'data': { 'enable': 'bool', 'primary': 'bool', '*failover' : 'bool' },
+ 'if': 'defined(CONFIG_REPLICATION)' }
##
# @ReplicationStatus:
@@ -1272,7 +1273,8 @@
# Since: 2.9
##
{ 'struct': 'ReplicationStatus',
- 'data': { 'error': 'bool', '*desc': 'str' } }
+ 'data': { 'error': 'bool', '*desc': 'str' },
+ 'if': 'defined(CONFIG_REPLICATION)' }
##
# @query-xen-replication-status:
@@ -1289,7 +1291,8 @@
# Since: 2.9
##
{ 'command': 'query-xen-replication-status',
- 'returns': 'ReplicationStatus' }
+ 'returns': 'ReplicationStatus',
+ 'if': 'defined(CONFIG_REPLICATION)' }
##
# @xen-colo-do-checkpoint:
@@ -1305,7 +1308,8 @@
#
# Since: 2.9
##
-{ 'command': 'xen-colo-do-checkpoint' }
+{ 'command': 'xen-colo-do-checkpoint',
+ 'if': 'defined(CONFIG_REPLICATION)' }
##
# @COLOStatus:
diff --git a/migration/colo.c b/migration/colo.c
index fcff04c78c..398b239d1c 100644
--- a/migration/colo.c
+++ b/migration/colo.c
@@ -24,7 +24,9 @@
#include "trace.h"
#include "qemu/error-report.h"
#include "migration/failover.h"
+#ifdef CONFIG_REPLICATION
#include "replication.h"
+#endif
#include "net/colo-compare.h"
#include "net/colo.h"
#include "block/block.h"
@@ -201,11 +203,11 @@ void colo_do_failover(MigrationState *s)
}
}
+#ifdef CONFIG_REPLICATION
void qmp_xen_set_replication(bool enable, bool primary,
bool has_failover, bool failover,
Error **errp)
{
-#ifdef CONFIG_REPLICATION
ReplicationMode mode = primary ?
REPLICATION_MODE_PRIMARY :
REPLICATION_MODE_SECONDARY;
@@ -224,14 +226,10 @@ void qmp_xen_set_replication(bool enable, bool primary,
}
replication_stop_all(failover, failover ? NULL : errp);
}
-#else
- abort();
-#endif
}
ReplicationStatus *qmp_query_xen_replication_status(Error **errp)
{
-#ifdef CONFIG_REPLICATION
Error *err = NULL;
ReplicationStatus *s = g_new0(ReplicationStatus, 1);
@@ -246,19 +244,13 @@ ReplicationStatus *qmp_query_xen_replication_status(Error **errp)
error_free(err);
return s;
-#else
- abort();
-#endif
}
void qmp_xen_colo_do_checkpoint(Error **errp)
{
-#ifdef CONFIG_REPLICATION
replication_do_checkpoint_all(errp);
-#else
- abort();
-#endif
}
+#endif
COLOStatus *qmp_query_colo_status(Error **errp)
{
diff --git a/monitor.c b/monitor.c
index d39390c2f2..16a180dd50 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1146,11 +1146,6 @@ static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
*/
static void qmp_unregister_commands_hack(void)
{
-#ifndef CONFIG_REPLICATION
- qmp_unregister_command(&qmp_commands, "xen-set-replication");
- qmp_unregister_command(&qmp_commands, "query-xen-replication-status");
- qmp_unregister_command(&qmp_commands, "xen-colo-do-checkpoint");
-#endif
#ifndef TARGET_I386
qmp_unregister_command(&qmp_commands, "rtc-reset-reinjection");
qmp_unregister_command(&qmp_commands, "query-sev");
--
2.20.0.rc1
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi,
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (26 preceding siblings ...)
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 27/27] qapi: add conditions to REPLICATION type/commands on the schema Marc-André Lureau
@ 2018-12-08 11:19 ` Marc-André Lureau
2018-12-12 17:18 ` Markus Armbruster
28 siblings, 0 replies; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-08 11:19 UTC (permalink / raw)
To: qemu-devel; +Cc: Armbruster, Markus
Hi,
The cover letter title should be "qapi: add #if pre-processor
conditions to generated code (part 2)"
On Sat, Dec 8, 2018 at 3:16 PM Marc-André Lureau
<marcandre.lureau@redhat.com> wrote:
>
> This is the second part of the "add #if pre-processor conditions to
> generated code" series, adding schema member conditions (roughly
> 16-38/49).
>
> Members can be exploded as dictionnary with 'type'/'if' keys:
>
> { 'struct': 'TestIfStruct', 'data':
> { 'foo': 'int',
> 'bar': { 'type': 'int', 'if': 'defined(TEST_IF_STRUCT_BAR)'} } }
>
> Enum values can be exploded as dictionnary with 'type'/'if' keys:
>
> { 'enum': 'TestIfEnum', 'data':
> [ 'foo',
> { 'name' : 'bar', 'if': 'defined(TEST_IF_ENUM_BAR)' } ] }
>
> v7:
> - replaced osdep.h include by a #warning check
> - renamed event_names/event_enum_members, enum_name/event_enum_ename
> - move normalization after checking
> - simplify make_enum_members()
> - some tests changes
> - rebase/conflicts tweaks
> - squash documentation changes in related patches
> - tweak generated documentation code & output
> - modify commit comments, add rb tags
>
> v6:
> - subset of v5 series: add schema member conditions
> - split "qapi: factor out check_known_keys()", error report improvements
> - add a patch to "qapi: include osdep.h in type headers" to avoid
> potential build configuration change issues
> - rebased, on top of Markus's qapi-next branch (first 4 patches,
> included for patchew testing)
>
> Marc-André Lureau (27):
> qapi: make sure osdep.h is included in type headers
> qapi: do not define enumeration value explicitly
> qapi: rename QAPISchemaEnumType.values to .members
> qapi: change enum visitor and gen_enum* to take QAPISchemaMember
> tests: print enum type members more like object type members
> qapi: factor out checking for keys
> qapi: improve reporting of unknown or missing keys
> qapi: add a dictionary form with 'name' key for enum members
> qapi: add 'if' to enum members
> qapi-events: add 'if' condition to implicit event enum
> qapi: pass long form enum to make_enum_members
> qapi: rename allow_dict to allow_implicit
> qapi: add a dictionary form for TYPE
> qapi: add 'if' to implicit struct members
> qapi: add an error in case a discriminator is conditional
> qapi: add 'if' to union members
> qapi: simplify make_enum_members()
> tests/qapi: add command with condition on union argument
> qapi: add 'if' to alternate members
> tests/qapi: add command with condition on alternate argument
> qapi: add #if conditions to generated code members
> qapi: add 'If:' condition to enum values documentation
> qapi: add 'If:' condition to struct members documentation
> qapi: add condition to variants documentation
> qapi: break long lines at 'data' member
> qapi: add more conditions to SPICE
> qapi: add conditions to REPLICATION type/commands on the schema
>
> qapi/block-core.json | 26 +-
> qapi/char.json | 150 ++++++-----
> qapi/migration.json | 15 +-
> qapi/misc.json | 7 +-
> qapi/net.json | 3 +-
> qapi/tpm.json | 5 +-
> qapi/ui.json | 3 +-
> scripts/qapi/common.py | 253 ++++++++++++------
> scripts/qapi/doc.py | 30 ++-
> scripts/qapi/events.py | 13 +-
> scripts/qapi/introspect.py | 16 +-
> scripts/qapi/types.py | 13 +-
> scripts/qapi/visit.py | 8 +-
> migration/colo.c | 16 +-
> monitor.c | 5 -
> docs/devel/qapi-code-gen.txt | 19 ++
> tests/Makefile.include | 11 +-
> tests/qapi-schema/alternate-base.err | 1 +
> tests/qapi-schema/alternate-invalid-dict.err | 1 +
> ...ember.exit => alternate-invalid-dict.exit} | 0
> tests/qapi-schema/alternate-invalid-dict.json | 4 +
> ...-member.out => alternate-invalid-dict.out} | 0
> tests/qapi-schema/comments.out | 14 +-
> tests/qapi-schema/doc-bad-section.out | 13 +-
> tests/qapi-schema/doc-good.json | 11 +-
> tests/qapi-schema/doc-good.out | 22 +-
> tests/qapi-schema/doc-good.texi | 7 +-
> tests/qapi-schema/double-type.err | 1 +
> tests/qapi-schema/empty.out | 9 +-
> tests/qapi-schema/enum-bad-member.err | 1 +
> tests/qapi-schema/enum-bad-member.exit | 1 +
> tests/qapi-schema/enum-bad-member.json | 2 +
> tests/qapi-schema/enum-bad-member.out | 0
> .../qapi-schema/enum-dict-member-unknown.err | 2 +
> .../qapi-schema/enum-dict-member-unknown.exit | 1 +
> .../qapi-schema/enum-dict-member-unknown.json | 2 +
> .../qapi-schema/enum-dict-member-unknown.out | 0
> tests/qapi-schema/enum-dict-member.err | 1 -
> tests/qapi-schema/enum-dict-member.json | 2 -
> tests/qapi-schema/enum-if-invalid.err | 1 +
> tests/qapi-schema/enum-if-invalid.exit | 1 +
> tests/qapi-schema/enum-if-invalid.json | 3 +
> tests/qapi-schema/enum-if-invalid.out | 0
> tests/qapi-schema/event-case.out | 9 +-
> .../qapi-schema/event-member-invalid-dict.err | 1 +
> .../event-member-invalid-dict.exit | 1 +
> .../event-member-invalid-dict.json | 2 +
> .../qapi-schema/event-member-invalid-dict.out | 0
> tests/qapi-schema/event-nest-struct.json | 2 +-
> .../flat-union-inline-invalid-dict.err | 1 +
> .../flat-union-inline-invalid-dict.exit | 1 +
> .../flat-union-inline-invalid-dict.json | 11 +
> .../flat-union-inline-invalid-dict.out | 0
> tests/qapi-schema/flat-union-inline.json | 2 +-
> .../flat-union-invalid-if-discriminator.err | 1 +
> .../flat-union-invalid-if-discriminator.exit | 1 +
> .../flat-union-invalid-if-discriminator.json | 17 ++
> .../flat-union-invalid-if-discriminator.out | 0
> tests/qapi-schema/ident-with-escape.out | 9 +-
> tests/qapi-schema/include-relpath.out | 14 +-
> tests/qapi-schema/include-repetition.out | 14 +-
> tests/qapi-schema/include-simple.out | 14 +-
> tests/qapi-schema/indented-expr.out | 9 +-
> .../nested-struct-data-invalid-dict.err | 1 +
> .../nested-struct-data-invalid-dict.exit | 1 +
> .../nested-struct-data-invalid-dict.json | 3 +
> .../nested-struct-data-invalid-dict.out | 0
> tests/qapi-schema/nested-struct-data.json | 2 +-
> tests/qapi-schema/qapi-schema-test.json | 39 ++-
> tests/qapi-schema/qapi-schema-test.out | 74 ++++-
> .../struct-member-invalid-dict.err | 1 +
> .../struct-member-invalid-dict.exit | 1 +
> .../struct-member-invalid-dict.json | 3 +
> .../struct-member-invalid-dict.out | 0
> tests/qapi-schema/test-qapi.py | 9 +-
> .../qapi-schema/union-branch-invalid-dict.err | 1 +
> .../union-branch-invalid-dict.exit | 1 +
> .../union-branch-invalid-dict.json | 4 +
> .../qapi-schema/union-branch-invalid-dict.out | 0
> tests/qapi-schema/unknown-expr-key.err | 3 +-
> tests/qapi-schema/unknown-expr-key.json | 2 +-
> 81 files changed, 681 insertions(+), 266 deletions(-)
> create mode 100644 tests/qapi-schema/alternate-invalid-dict.err
> rename tests/qapi-schema/{enum-dict-member.exit => alternate-invalid-dict.exit} (100%)
> create mode 100644 tests/qapi-schema/alternate-invalid-dict.json
> rename tests/qapi-schema/{enum-dict-member.out => alternate-invalid-dict.out} (100%)
> create mode 100644 tests/qapi-schema/enum-bad-member.err
> create mode 100644 tests/qapi-schema/enum-bad-member.exit
> create mode 100644 tests/qapi-schema/enum-bad-member.json
> create mode 100644 tests/qapi-schema/enum-bad-member.out
> create mode 100644 tests/qapi-schema/enum-dict-member-unknown.err
> create mode 100644 tests/qapi-schema/enum-dict-member-unknown.exit
> create mode 100644 tests/qapi-schema/enum-dict-member-unknown.json
> create mode 100644 tests/qapi-schema/enum-dict-member-unknown.out
> delete mode 100644 tests/qapi-schema/enum-dict-member.err
> delete mode 100644 tests/qapi-schema/enum-dict-member.json
> create mode 100644 tests/qapi-schema/enum-if-invalid.err
> create mode 100644 tests/qapi-schema/enum-if-invalid.exit
> create mode 100644 tests/qapi-schema/enum-if-invalid.json
> create mode 100644 tests/qapi-schema/enum-if-invalid.out
> create mode 100644 tests/qapi-schema/event-member-invalid-dict.err
> create mode 100644 tests/qapi-schema/event-member-invalid-dict.exit
> create mode 100644 tests/qapi-schema/event-member-invalid-dict.json
> create mode 100644 tests/qapi-schema/event-member-invalid-dict.out
> create mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.err
> create mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.exit
> create mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.json
> create mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.out
> create mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.err
> create mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.exit
> create mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.json
> create mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.out
> create mode 100644 tests/qapi-schema/nested-struct-data-invalid-dict.err
> create mode 100644 tests/qapi-schema/nested-struct-data-invalid-dict.exit
> create mode 100644 tests/qapi-schema/nested-struct-data-invalid-dict.json
> create mode 100644 tests/qapi-schema/nested-struct-data-invalid-dict.out
> create mode 100644 tests/qapi-schema/struct-member-invalid-dict.err
> create mode 100644 tests/qapi-schema/struct-member-invalid-dict.exit
> create mode 100644 tests/qapi-schema/struct-member-invalid-dict.json
> create mode 100644 tests/qapi-schema/struct-member-invalid-dict.out
> create mode 100644 tests/qapi-schema/union-branch-invalid-dict.err
> create mode 100644 tests/qapi-schema/union-branch-invalid-dict.exit
> create mode 100644 tests/qapi-schema/union-branch-invalid-dict.json
> create mode 100644 tests/qapi-schema/union-branch-invalid-dict.out
>
> --
> 2.20.0.rc1
>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 01/27] qapi: make sure osdep.h is included in type headers
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 01/27] qapi: make sure osdep.h is included in type headers Marc-André Lureau
@ 2018-12-10 9:52 ` Markus Armbruster
2018-12-10 11:13 ` Marc-André Lureau
0 siblings, 1 reply; 69+ messages in thread
From: Markus Armbruster @ 2018-12-10 9:52 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Now that the schema can be configured, it is crucial that all types
> are configured the same. Make sure config-host.h is included, by
> checking osdep.h inclusion. The build-sys tracks the dependency and
> rebuilds the types if the configuration changed.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> scripts/qapi/types.py | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
> index fd7808103c..3bb9cb6d47 100644
> --- a/scripts/qapi/types.py
> +++ b/scripts/qapi/types.py
> @@ -201,6 +201,9 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
> ''',
> types=types, visit=visit))
> self._genh.preamble_add(mcgen('''
> +#ifndef QEMU_OSDEP_H
> +#error Please include osdep.h first!
> +#endif
> #include "qapi/qapi-builtin-types.h"
> '''))
I understand why you propose this patch. The QAPI-generated headers use
#ifdef CONFIG_FOO. The configuration header "qemu/osdep.h" must be
consistently included before the generated headers, or else you end up
with nasty bugs, such as the same enum having different values in
different .o, or the same struct having a different layout.
But this applies to *all* headers that use #ifdef. Why check it here,
but not there? What makes the QAPI-generated headers special?
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 06/27] qapi: factor out checking for keys
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 06/27] qapi: factor out checking for keys Marc-André Lureau
@ 2018-12-10 9:57 ` Markus Armbruster
0 siblings, 0 replies; 69+ messages in thread
From: Markus Armbruster @ 2018-12-10 9:57 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Introduce a new helper function to check if the given keys are known,
> and if mandatory keys are present. The function will be reused in
> other places in the following code changes.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 07/27] qapi: improve reporting of unknown or missing keys
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 07/27] qapi: improve reporting of unknown or missing keys Marc-André Lureau
@ 2018-12-10 10:03 ` Markus Armbruster
2018-12-10 11:11 ` Marc-André Lureau
0 siblings, 1 reply; 69+ messages in thread
From: Markus Armbruster @ 2018-12-10 10:03 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Report the set of missing or unknown keys. And give a hint about the
> accepted keys.
Suggest to add:
The error message for multiple meta type members (visible in
tests/qapi-schema/double-type.err) is not improved.
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 07/27] qapi: improve reporting of unknown or missing keys
2018-12-10 10:03 ` Markus Armbruster
@ 2018-12-10 11:11 ` Marc-André Lureau
0 siblings, 0 replies; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-10 11:11 UTC (permalink / raw)
To: Markus Armbruster; +Cc: QEMU, Michael Roth
On Mon, Dec 10, 2018 at 2:03 PM Markus Armbruster <armbru@redhat.com> wrote:
>
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
> > Report the set of missing or unknown keys. And give a hint about the
> > accepted keys.
>
> Suggest to add:
>
> The error message for multiple meta type members (visible in
> tests/qapi-schema/double-type.err) is not improved.
>
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
>
ack, thanks
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 01/27] qapi: make sure osdep.h is included in type headers
2018-12-10 9:52 ` Markus Armbruster
@ 2018-12-10 11:13 ` Marc-André Lureau
2018-12-10 13:28 ` Markus Armbruster
0 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-10 11:13 UTC (permalink / raw)
To: Markus Armbruster; +Cc: QEMU, Michael Roth
Hi
On Mon, Dec 10, 2018 at 1:52 PM Markus Armbruster <armbru@redhat.com> wrote:
>
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
> > Now that the schema can be configured, it is crucial that all types
> > are configured the same. Make sure config-host.h is included, by
> > checking osdep.h inclusion. The build-sys tracks the dependency and
> > rebuilds the types if the configuration changed.
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> > scripts/qapi/types.py | 3 +++
> > 1 file changed, 3 insertions(+)
> >
> > diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
> > index fd7808103c..3bb9cb6d47 100644
> > --- a/scripts/qapi/types.py
> > +++ b/scripts/qapi/types.py
> > @@ -201,6 +201,9 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
> > ''',
> > types=types, visit=visit))
> > self._genh.preamble_add(mcgen('''
> > +#ifndef QEMU_OSDEP_H
> > +#error Please include osdep.h first!
> > +#endif
> > #include "qapi/qapi-builtin-types.h"
> > '''))
>
> I understand why you propose this patch. The QAPI-generated headers use
> #ifdef CONFIG_FOO. The configuration header "qemu/osdep.h" must be
> consistently included before the generated headers, or else you end up
> with nasty bugs, such as the same enum having different values in
> different .o, or the same struct having a different layout.
>
> But this applies to *all* headers that use #ifdef. Why check it here,
> but not there? What makes the QAPI-generated headers special?
>
It's the discussion about #if in headers (and enums in particular)
that started this. We want to make sure all compilation units share
the same data structure/ABI. I proposed to include osdep.h in qapi
headers, but that was rejected.
The warning is a different approach. I agree it could apply to all
headers. Do you think I should update all headers as well?
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 01/27] qapi: make sure osdep.h is included in type headers
2018-12-10 11:13 ` Marc-André Lureau
@ 2018-12-10 13:28 ` Markus Armbruster
2018-12-11 15:47 ` Marc-André Lureau
2018-12-11 16:05 ` Daniel P. Berrangé
0 siblings, 2 replies; 69+ messages in thread
From: Markus Armbruster @ 2018-12-10 13:28 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: QEMU, Michael Roth
Marc-André Lureau <marcandre.lureau@gmail.com> writes:
> Hi
>
> On Mon, Dec 10, 2018 at 1:52 PM Markus Armbruster <armbru@redhat.com> wrote:
>>
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>
>> > Now that the schema can be configured, it is crucial that all types
>> > are configured the same. Make sure config-host.h is included, by
>> > checking osdep.h inclusion. The build-sys tracks the dependency and
>> > rebuilds the types if the configuration changed.
>> >
>> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> > ---
>> > scripts/qapi/types.py | 3 +++
>> > 1 file changed, 3 insertions(+)
>> >
>> > diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
>> > index fd7808103c..3bb9cb6d47 100644
>> > --- a/scripts/qapi/types.py
>> > +++ b/scripts/qapi/types.py
>> > @@ -201,6 +201,9 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
>> > ''',
>> > types=types, visit=visit))
>> > self._genh.preamble_add(mcgen('''
>> > +#ifndef QEMU_OSDEP_H
>> > +#error Please include osdep.h first!
>> > +#endif
>> > #include "qapi/qapi-builtin-types.h"
>> > '''))
>>
>> I understand why you propose this patch. The QAPI-generated headers use
>> #ifdef CONFIG_FOO. The configuration header "qemu/osdep.h" must be
>> consistently included before the generated headers, or else you end up
>> with nasty bugs, such as the same enum having different values in
>> different .o, or the same struct having a different layout.
>>
>> But this applies to *all* headers that use #ifdef. Why check it here,
>> but not there? What makes the QAPI-generated headers special?
>>
>
> It's the discussion about #if in headers (and enums in particular)
> that started this. We want to make sure all compilation units share
> the same data structure/ABI. I proposed to include osdep.h in qapi
> headers, but that was rejected.
> The warning is a different approach. I agree it could apply to all
> headers. Do you think I should update all headers as well?
That would replace the rule 'all .c files must include "qemu/osdep.h"
first' by 'all .h files must check "qemu/osdep.h" has been included
already', which is not an improvement.
All we have right now to help with enforcing our osdep.h rule is
scripts/clean-includes. We run it periodically to fix rule breakers.
It's manual, because we have a few .c files in the tree where the rule
doesn't apply, and the script doesn't know about them. Fixable, I
guess. Most recent run:
Subject: [PATCH] Clean up includes
Message-Id: <20181204172535.2799-1-armbru@redhat.com>
https://lists.nongnu.org/archive/html/qemu-devel/2018-12/msg00605.html
The obvious improvement would be flagging rule breakers before they get
committed.
checkpatch.pl could flag patches adding .c files that don't include
"qemu/osdep.h" first. The "first" part might be a bit annoying to code.
The "adding files" part already exists: checkpatch.pl warns when you add
a file without updating MAINTAINERS.
checkpatch.pl could also flag patches removing #include "qemu/osdep.h".
Other projects use a syntax-check make target to check sources. If we
decide we like that better than checkpatch.pl for some checks, we can do
that.
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 08/27] qapi: add a dictionary form with 'name' key for enum members
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 08/27] qapi: add a dictionary form with 'name' key for enum members Marc-André Lureau
@ 2018-12-10 15:44 ` Markus Armbruster
2018-12-10 16:05 ` Markus Armbruster
0 siblings, 1 reply; 69+ messages in thread
From: Markus Armbruster @ 2018-12-10 15:44 UTC (permalink / raw)
Cc: qemu-devel, armbru, Michael Roth
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Desugar the enum NAME form to { 'name': NAME }. This will allow to add
> new enum members, such as 'if' in the following patch.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> scripts/qapi/common.py | 49 ++++++++++++++++---
> tests/Makefile.include | 3 +-
> tests/qapi-schema/enum-bad-member.err | 1 +
> ...-dict-member.exit => enum-bad-member.exit} | 0
> tests/qapi-schema/enum-bad-member.json | 2 +
> ...um-dict-member.out => enum-bad-member.out} | 0
> .../qapi-schema/enum-dict-member-unknown.err | 2 +
> .../qapi-schema/enum-dict-member-unknown.exit | 1 +
> .../qapi-schema/enum-dict-member-unknown.json | 2 +
> .../qapi-schema/enum-dict-member-unknown.out | 0
> tests/qapi-schema/enum-dict-member.err | 1 -
> tests/qapi-schema/enum-dict-member.json | 2 -
> 12 files changed, 52 insertions(+), 11 deletions(-)
> create mode 100644 tests/qapi-schema/enum-bad-member.err
> rename tests/qapi-schema/{enum-dict-member.exit => enum-bad-member.exit} (100%)
> create mode 100644 tests/qapi-schema/enum-bad-member.json
> rename tests/qapi-schema/{enum-dict-member.out => enum-bad-member.out} (100%)
> create mode 100644 tests/qapi-schema/enum-dict-member-unknown.err
> create mode 100644 tests/qapi-schema/enum-dict-member-unknown.exit
> create mode 100644 tests/qapi-schema/enum-dict-member-unknown.json
> create mode 100644 tests/qapi-schema/enum-dict-member-unknown.out
> delete mode 100644 tests/qapi-schema/enum-dict-member.err
> delete mode 100644 tests/qapi-schema/enum-dict-member.json
>
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index f205805751..610840d2e5 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -740,6 +740,10 @@ def check_event(expr, info):
> allow_metas=meta)
>
>
> +def enum_get_names(expr):
> + return [e['name'] if isinstance(e, dict) else e for e in expr['data']]
> +
> +
Slightly more complicated than v6 because it @expr isn't normalized.
We'll revisit this at [*] below.
Another way to code this would be
members = normalized_enum_members(e['data'])
return [m['type'] for m in members]
where
def normalized_enum_members(members):
[m if isinstance(m, dict) else {'name': m} for m in members]
which then gets reused in normalize_enum()
def normalize_enum(expr)
expr['data'] = normalized_enum_members(expr['data']
Up to you. We could also change it on top.
> def check_union(expr, info):
> name = expr['union']
> base = expr.get('base')
> @@ -799,7 +803,7 @@ def check_union(expr, info):
> # 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'"
> @@ -831,7 +835,7 @@ def check_alternate(expr, info):
> if qtype == 'QTYPE_QSTRING':
> enum_expr = enum_types.get(value)
> 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
> @@ -847,18 +851,32 @@ def check_alternate(expr, info):
> types_seen[qt] = key
>
>
> +def normalize_enum(expr):
> + members = expr['data']
> +
> + # translate short member form to dict form
> + expr['data'] = [m if isinstance(m, dict) else {'name': m} for m in members]
> +
> +
> def check_enum(expr, info):
> name = expr['enum']
> - members = expr.get('data')
> + members = expr['data']
> prefix = expr.get('prefix')
>
> - if not isinstance(members, list):
> - raise QAPISemError(info,
> - "Enum '%s' requires an array for 'data'" % name)
> if prefix is not None and not isinstance(prefix, str):
> raise QAPISemError(info,
> "Enum '%s' requires a string for 'prefix'" % name)
> +
> + if not isinstance(members, list):
> + raise QAPISemError(info,
> + "Enum '%s' requires an array for 'data'" % name)
> +
Did you move this check down intentionally?
> for member in members:
> + if isinstance(member, dict):
> + source = "dictionary member of enum '%s'" % name
> + check_known_keys(info, source, member, ['name'], [])
> + member = member['name']
> +
> check_name(info, "Member of enum '%s'" % name, member,
> enum_member=True)
Again, slightly more complicated than v6 because it now runs before
normalization. We'll revisit this at [*] below.
>
> @@ -1011,6 +1029,15 @@ def check_exprs(exprs):
> return exprs
>
>
> +def normalize_exprs(exprs):
> + for expr_elem in exprs:
> + expr = expr_elem['expr']
> + if 'enum' in expr:
> + normalize_enum(expr)
> +
> + return exprs
> +
> +
> #
> # Schema compiler frontend
> #
> @@ -1567,6 +1594,7 @@ class QAPISchema(object):
> f = open(fname, 'r')
> parser = QAPISchemaParser(f)
> exprs = check_exprs(parser.exprs)
> + exprs = normalize_exprs(exprs)
> self.docs = parser.docs
> self._entity_list = []
> self._entity_dict = {}
[*] In v6, you normalized at the beginning of check_exprs(). Now, you
normalize after check_exprs(). Works, although what I suggested in my
review of v6 was to normalize later in check_exprs(), namely right after
check_keys(). I believe that would avoid the slight complications I
noted above.
> @@ -1640,7 +1668,14 @@ class QAPISchema(object):
> qtype_values, 'QTYPE'))
>
> def _make_enum_members(self, values):
> - return [QAPISchemaMember(v) for v in values]
> + enum = []
> + for v in values:
> + if isinstance(v, dict):
> + name = v['name']
> + else:
> + name = v
> + enum.append(QAPISchemaMember(name))
> + return enum
Despite normalization to the long form, we still deal with both the long
and the short form here, same as in v6. I see you addressed this in new
PATCH 11+17. What's wrong with squashing them into this patch?
>
> def _make_implicit_enum_type(self, name, info, ifcond, values):
> # See also QAPISchemaObjectTypeMember._pretty_owner()
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index fb0b449c02..2e894c1037 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -379,10 +379,11 @@ qapi-schema += double-data.json
> qapi-schema += double-type.json
> qapi-schema += duplicate-key.json
> qapi-schema += empty.json
> +qapi-schema += enum-bad-member.json
> qapi-schema += enum-bad-name.json
> qapi-schema += enum-bad-prefix.json
> qapi-schema += enum-clash-member.json
> -qapi-schema += enum-dict-member.json
> +qapi-schema += enum-dict-member-unknown.json
> qapi-schema += enum-int-member.json
> qapi-schema += enum-member-case.json
> qapi-schema += enum-missing-data.json
> diff --git a/tests/qapi-schema/enum-bad-member.err b/tests/qapi-schema/enum-bad-member.err
> new file mode 100644
> index 0000000000..211db9e6fc
> --- /dev/null
> +++ b/tests/qapi-schema/enum-bad-member.err
> @@ -0,0 +1 @@
> +tests/qapi-schema/enum-bad-member.json:2: Member of enum 'MyEnum' requires a string name
> diff --git a/tests/qapi-schema/enum-dict-member.exit b/tests/qapi-schema/enum-bad-member.exit
> similarity index 100%
> rename from tests/qapi-schema/enum-dict-member.exit
> rename to tests/qapi-schema/enum-bad-member.exit
> diff --git a/tests/qapi-schema/enum-bad-member.json b/tests/qapi-schema/enum-bad-member.json
> new file mode 100644
> index 0000000000..98da6828b4
> --- /dev/null
> +++ b/tests/qapi-schema/enum-bad-member.json
> @@ -0,0 +1,2 @@
> +# we reject any enum member that is not a string
> +{ 'enum': 'MyEnum', 'data': [ [ ] ] }
> diff --git a/tests/qapi-schema/enum-dict-member.out b/tests/qapi-schema/enum-bad-member.out
> similarity index 100%
> rename from tests/qapi-schema/enum-dict-member.out
> rename to tests/qapi-schema/enum-bad-member.out
> diff --git a/tests/qapi-schema/enum-dict-member-unknown.err b/tests/qapi-schema/enum-dict-member-unknown.err
> new file mode 100644
> index 0000000000..76bd0471db
> --- /dev/null
> +++ b/tests/qapi-schema/enum-dict-member-unknown.err
> @@ -0,0 +1,2 @@
> +tests/qapi-schema/enum-dict-member-unknown.json:2: Unknown key 'bad-key' in dictionary member of enum 'MyEnum'
> +Valid keys are 'name'.
> diff --git a/tests/qapi-schema/enum-dict-member-unknown.exit b/tests/qapi-schema/enum-dict-member-unknown.exit
> new file mode 100644
> index 0000000000..d00491fd7e
> --- /dev/null
> +++ b/tests/qapi-schema/enum-dict-member-unknown.exit
> @@ -0,0 +1 @@
> +1
> diff --git a/tests/qapi-schema/enum-dict-member-unknown.json b/tests/qapi-schema/enum-dict-member-unknown.json
> new file mode 100644
> index 0000000000..6664c59201
> --- /dev/null
> +++ b/tests/qapi-schema/enum-dict-member-unknown.json
> @@ -0,0 +1,2 @@
> +# we reject any enum member that is not a string or a dict with 'name'
> +{ 'enum': 'MyEnum', 'data': [ { 'name': 'foo', 'bad-key': 'str' } ] }
> diff --git a/tests/qapi-schema/enum-dict-member-unknown.out b/tests/qapi-schema/enum-dict-member-unknown.out
> new file mode 100644
> index 0000000000..e69de29bb2
> diff --git a/tests/qapi-schema/enum-dict-member.err b/tests/qapi-schema/enum-dict-member.err
> deleted file mode 100644
> index 8ca146ea59..0000000000
> --- a/tests/qapi-schema/enum-dict-member.err
> +++ /dev/null
> @@ -1 +0,0 @@
> -tests/qapi-schema/enum-dict-member.json:2: Member of enum 'MyEnum' requires a string name
> diff --git a/tests/qapi-schema/enum-dict-member.json b/tests/qapi-schema/enum-dict-member.json
> deleted file mode 100644
> index 79672e0f09..0000000000
> --- a/tests/qapi-schema/enum-dict-member.json
> +++ /dev/null
> @@ -1,2 +0,0 @@
> -# we reject any enum member that is not a string
> -{ 'enum': 'MyEnum', 'data': [ { 'value': 'str' } ] }
I think we still need this one to cover "key 'name' is required in the
long form".
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 08/27] qapi: add a dictionary form with 'name' key for enum members
2018-12-10 15:44 ` Markus Armbruster
@ 2018-12-10 16:05 ` Markus Armbruster
0 siblings, 0 replies; 69+ messages in thread
From: Markus Armbruster @ 2018-12-10 16:05 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth
One more thing...
Markus Armbruster <armbru@redhat.com> writes:
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
>> Desugar the enum NAME form to { 'name': NAME }. This will allow to add
>> new enum members, such as 'if' in the following patch.
>>
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> ---
>> scripts/qapi/common.py | 49 ++++++++++++++++---
>> tests/Makefile.include | 3 +-
>> tests/qapi-schema/enum-bad-member.err | 1 +
>> ...-dict-member.exit => enum-bad-member.exit} | 0
>> tests/qapi-schema/enum-bad-member.json | 2 +
>> ...um-dict-member.out => enum-bad-member.out} | 0
>> .../qapi-schema/enum-dict-member-unknown.err | 2 +
>> .../qapi-schema/enum-dict-member-unknown.exit | 1 +
>> .../qapi-schema/enum-dict-member-unknown.json | 2 +
>> .../qapi-schema/enum-dict-member-unknown.out | 0
>> tests/qapi-schema/enum-dict-member.err | 1 -
>> tests/qapi-schema/enum-dict-member.json | 2 -
>> 12 files changed, 52 insertions(+), 11 deletions(-)
>> create mode 100644 tests/qapi-schema/enum-bad-member.err
>> rename tests/qapi-schema/{enum-dict-member.exit => enum-bad-member.exit} (100%)
>> create mode 100644 tests/qapi-schema/enum-bad-member.json
>> rename tests/qapi-schema/{enum-dict-member.out => enum-bad-member.out} (100%)
>> create mode 100644 tests/qapi-schema/enum-dict-member-unknown.err
>> create mode 100644 tests/qapi-schema/enum-dict-member-unknown.exit
>> create mode 100644 tests/qapi-schema/enum-dict-member-unknown.json
>> create mode 100644 tests/qapi-schema/enum-dict-member-unknown.out
>> delete mode 100644 tests/qapi-schema/enum-dict-member.err
>> delete mode 100644 tests/qapi-schema/enum-dict-member.json
>>
>> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
[...]
>> @@ -847,18 +851,32 @@ def check_alternate(expr, info):
>> types_seen[qt] = key
>>
>>
>> +def normalize_enum(expr):
>> + members = expr['data']
>> +
>> + # translate short member form to dict form
>> + expr['data'] = [m if isinstance(m, dict) else {'name': m} for m in members]
>> +
>> +
>> def check_enum(expr, info):
>> name = expr['enum']
>> - members = expr.get('data')
>> + members = expr['data']
>> prefix = expr.get('prefix')
>>
>> - if not isinstance(members, list):
>> - raise QAPISemError(info,
>> - "Enum '%s' requires an array for 'data'" % name)
>> if prefix is not None and not isinstance(prefix, str):
>> raise QAPISemError(info,
>> "Enum '%s' requires a string for 'prefix'" % name)
>> +
>> + if not isinstance(members, list):
>> + raise QAPISemError(info,
>> + "Enum '%s' requires an array for 'data'" % name)
>> +
>
> Did you move this check down intentionally?
>
>> for member in members:
>> + if isinstance(member, dict):
>> + source = "dictionary member of enum '%s'" % name
>> + check_known_keys(info, source, member, ['name'], [])
>> + member = member['name']
>> +
>> check_name(info, "Member of enum '%s'" % name, member,
>> enum_member=True)
>
> Again, slightly more complicated than v6 because it now runs before
> normalization. We'll revisit this at [*] below.
If we keep it this way, then let's at least avoid assigning to the loop
control variable:
member_name = member['name']
else:
member_name = member
check_name(info, "Member of enum '%s'" % name, member_name,
enum_member=True)
[...]
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 11/27] qapi: pass long form enum to make_enum_members
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 11/27] qapi: pass long form enum to make_enum_members Marc-André Lureau
@ 2018-12-10 17:04 ` Markus Armbruster
0 siblings, 0 replies; 69+ messages in thread
From: Markus Armbruster @ 2018-12-10 17:04 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> This will allow to get rid of short form handling in a following
> patch.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> Suggested-by: Markus Armbruster <armbru@redhat.com>
> ---
> scripts/qapi/common.py | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index fdc0fd69ef..557b413950 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -1663,9 +1663,10 @@ 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']
Long line.
> + qtype_values = self._make_enum_members([{'name': n} for n in qtypes])
> +
> self._def_entity(QAPISchemaEnumType('QType', None, None, None,
> qtype_values, 'QTYPE'))
We may want to squash this one into PATCH 08 as mentioned in that
patch's review.
In case we don't:
Reviewed-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 13/27] qapi: add a dictionary form for TYPE
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 13/27] qapi: add a dictionary form for TYPE Marc-André Lureau
@ 2018-12-10 17:24 ` Markus Armbruster
2018-12-11 12:11 ` Marc-André Lureau
2018-12-11 15:18 ` Markus Armbruster
0 siblings, 2 replies; 69+ messages in thread
From: Markus Armbruster @ 2018-12-10 17:24 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Wherever a struct/union/alternate/command/event member with NAME: TYPE
> form is accepted, desugar it to a NAME: { 'type': TYPE } form.
>
> This will allow to add new member details, such as 'if' in the
> following patch to introduce conditionals, or 'default' for default
> values etc.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> scripts/qapi/common.py | 71 ++++++++++++++-----
> tests/Makefile.include | 6 ++
> tests/qapi-schema/alternate-invalid-dict.err | 1 +
> tests/qapi-schema/alternate-invalid-dict.exit | 1 +
> tests/qapi-schema/alternate-invalid-dict.json | 4 ++
> tests/qapi-schema/alternate-invalid-dict.out | 0
> .../qapi-schema/event-member-invalid-dict.err | 1 +
> .../event-member-invalid-dict.exit | 1 +
> .../event-member-invalid-dict.json | 2 +
> .../qapi-schema/event-member-invalid-dict.out | 0
> tests/qapi-schema/event-nest-struct.json | 2 +-
> .../flat-union-inline-invalid-dict.err | 1 +
> .../flat-union-inline-invalid-dict.exit | 1 +
> .../flat-union-inline-invalid-dict.json | 11 +++
> .../flat-union-inline-invalid-dict.out | 0
> tests/qapi-schema/flat-union-inline.json | 2 +-
> .../nested-struct-data-invalid-dict.err | 1 +
> .../nested-struct-data-invalid-dict.exit | 1 +
> .../nested-struct-data-invalid-dict.json | 3 +
> .../nested-struct-data-invalid-dict.out | 0
> tests/qapi-schema/nested-struct-data.json | 2 +-
> tests/qapi-schema/qapi-schema-test.json | 10 +--
> .../struct-member-invalid-dict.err | 1 +
> .../struct-member-invalid-dict.exit | 1 +
> .../struct-member-invalid-dict.json | 3 +
> .../struct-member-invalid-dict.out | 0
> .../qapi-schema/union-branch-invalid-dict.err | 1 +
> .../union-branch-invalid-dict.exit | 1 +
> .../union-branch-invalid-dict.json | 4 ++
> .../qapi-schema/union-branch-invalid-dict.out | 0
> 30 files changed, 106 insertions(+), 26 deletions(-)
> create mode 100644 tests/qapi-schema/alternate-invalid-dict.err
> create mode 100644 tests/qapi-schema/alternate-invalid-dict.exit
> create mode 100644 tests/qapi-schema/alternate-invalid-dict.json
> create mode 100644 tests/qapi-schema/alternate-invalid-dict.out
> create mode 100644 tests/qapi-schema/event-member-invalid-dict.err
> create mode 100644 tests/qapi-schema/event-member-invalid-dict.exit
> create mode 100644 tests/qapi-schema/event-member-invalid-dict.json
> create mode 100644 tests/qapi-schema/event-member-invalid-dict.out
> create mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.err
> create mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.exit
> create mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.json
> create mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.out
> create mode 100644 tests/qapi-schema/nested-struct-data-invalid-dict.err
> create mode 100644 tests/qapi-schema/nested-struct-data-invalid-dict.exit
> create mode 100644 tests/qapi-schema/nested-struct-data-invalid-dict.json
> create mode 100644 tests/qapi-schema/nested-struct-data-invalid-dict.out
> create mode 100644 tests/qapi-schema/struct-member-invalid-dict.err
> create mode 100644 tests/qapi-schema/struct-member-invalid-dict.exit
> create mode 100644 tests/qapi-schema/struct-member-invalid-dict.json
> create mode 100644 tests/qapi-schema/struct-member-invalid-dict.out
> create mode 100644 tests/qapi-schema/union-branch-invalid-dict.err
> create mode 100644 tests/qapi-schema/union-branch-invalid-dict.exit
> create mode 100644 tests/qapi-schema/union-branch-invalid-dict.json
> create mode 100644 tests/qapi-schema/union-branch-invalid-dict.out
>
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index 95e55b3f44..4b3ba53dc7 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -588,11 +588,13 @@ 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)
> + if isinstance(discriminator_value, dict):
> + discriminator_value = discriminator_value['type']
> + return enum_types.get(discriminator_value)
As in PATCH 08, this is slightly more complicated than v6 because @expr
isn't normalized. I can't say offhand whether normalizing in the place
I suggested in my review of v6 would avoid this complication.
>
>
> # Names must be letters, numbers, -, and _. They must start with letter,
> @@ -660,6 +662,15 @@ def check_if(expr, info):
> check_if_str(ifcond, info)
>
>
> +def normalize_members(expr, field):
> + members = expr.get(field)
> + if isinstance(members, OrderedDict):
> + for key, arg in members.items():
> + if isinstance(arg, dict):
> + continue
> + members[key] = {'type': arg}
> +
> +
> def check_type(info, source, value, allow_array=False,
> allow_implicit=False, allow_optional=False,
> allow_metas=[]):
> @@ -704,8 +715,14 @@ 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,
> + if isinstance(arg, dict):
> + check_known_keys(info, "member '%s' of %s" % (key, source),
> + arg, ['type'], [])
> + typ = arg['type']
> + else:
> + typ = arg
> + check_type(info, "Member '%s' of %s" % (key, source),
> + typ, allow_array=True,
> allow_metas=['built-in', 'union', 'alternate', 'struct',
> 'enum'])
>
Slightly more complicated than v6, this time because members of the
implicit struct type aren't normalized, yet.
> @@ -776,13 +793,15 @@ 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 isinstance(discriminator_value, dict):
> + discriminator_value = discriminator_value['type']
> + enum_define = enum_types.get(discriminator_value)
> allow_metas = ['struct']
> # Do not allow string discriminator
> if not enum_define:
> @@ -795,10 +814,16 @@ def check_union(expr, info):
> raise QAPISemError(info, "Union '%s' cannot have empty 'data'" % name)
> for (key, value) in members.items():
> check_name(info, "Member of union '%s'" % name, key)
> + if isinstance(value, dict):
> + check_known_keys(info, "member '%s' of union '%s'" % (key, name),
> + value, ['type'], [])
> + typ = value['type']
> + else:
> + typ = value
Likewise.
>
> # 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)
> + typ, 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.
> @@ -822,18 +847,24 @@ def check_alternate(expr, info):
> "in 'data'" % name)
> for (key, value) in members.items():
> check_name(info, "Member of alternate '%s'" % name, key)
> + if isinstance(value, dict):
> + check_known_keys(info,
> + "member '%s' of alternate '%s'" % (key, name),
> + value, ['type'], [])
> + typ = value['type']
> + else:
> + typ = value
Likewise.
>
> # 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_get_names(enum_expr):
> if v in ['on', 'off']:
> @@ -1035,6 +1066,10 @@ def normalize_exprs(exprs):
> expr = expr_elem['expr']
> if 'enum' in expr:
> normalize_enum(expr)
> + elif 'union' in expr:
> + normalize_members(expr, 'base')
> + if {'union', 'alternate', 'struct', 'command', 'event'} & set(expr):
> + normalize_members(expr, 'data')
>
> return exprs
>
> @@ -1738,7 +1773,7 @@ class QAPISchema(object):
> return QAPISchemaObjectTypeMember(name, typ, optional)
>
> def _make_members(self, data, info):
> - return [self._make_member(key, value, info)
> + return [self._make_member(key, value['type'], info)
> for (key, value) in data.items()]
>
> def _def_struct_type(self, expr, info, doc):
> @@ -1774,11 +1809,11 @@ 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'])
> for (key, value) in data.items()]
> members = []
> else:
> - variants = [self._make_simple_variant(key, value, info)
> + variants = [self._make_simple_variant(key, value['type'], info)
> for (key, value) in data.items()]
> typ = self._make_implicit_enum_type(name, info, ifcond,
> [v.name for v in variants])
> @@ -1794,7 +1829,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'])
> for (key, value) in data.items()]
> tag_member = QAPISchemaObjectTypeMember('type', 'QType', False)
> self._def_entity(
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index 3c9eea27fd..ea5d1e8787 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -318,6 +318,7 @@ qapi-schema += alternate-conflict-string.json
> qapi-schema += alternate-conflict-bool-string.json
> qapi-schema += alternate-conflict-num-string.json
> qapi-schema += alternate-empty.json
> +qapi-schema += alternate-invalid-dict.json
> qapi-schema += alternate-nested.json
> qapi-schema += alternate-unknown.json
> qapi-schema += args-alternate.json
> @@ -394,6 +395,7 @@ qapi-schema += escape-too-big.json
> qapi-schema += escape-too-short.json
> qapi-schema += event-boxed-empty.json
> qapi-schema += event-case.json
> +qapi-schema += event-member-invalid-dict.json
> qapi-schema += event-nest-struct.json
> qapi-schema += flat-union-array-branch.json
> qapi-schema += flat-union-bad-base.json
> @@ -403,6 +405,7 @@ qapi-schema += flat-union-base-union.json
> qapi-schema += flat-union-clash-member.json
> qapi-schema += flat-union-empty.json
> qapi-schema += flat-union-inline.json
> +qapi-schema += flat-union-inline-invalid-dict.json
> qapi-schema += flat-union-int-branch.json
> qapi-schema += flat-union-invalid-branch-key.json
> qapi-schema += flat-union-invalid-discriminator.json
> @@ -430,6 +433,7 @@ qapi-schema += missing-comma-list.json
> qapi-schema += missing-comma-object.json
> qapi-schema += missing-type.json
> qapi-schema += nested-struct-data.json
> +qapi-schema += nested-struct-data-invalid-dict.json
> qapi-schema += non-objects.json
> qapi-schema += oob-test.json
> qapi-schema += allow-preconfig-test.json
> @@ -460,6 +464,7 @@ qapi-schema += returns-whitelist.json
> qapi-schema += struct-base-clash-deep.json
> qapi-schema += struct-base-clash.json
> qapi-schema += struct-data-invalid.json
> +qapi-schema += struct-member-invalid-dict.json
> qapi-schema += struct-member-invalid.json
> qapi-schema += trailing-comma-list.json
> qapi-schema += trailing-comma-object.json
> @@ -471,6 +476,7 @@ qapi-schema += unicode-str.json
> qapi-schema += union-base-empty.json
> qapi-schema += union-base-no-discriminator.json
> qapi-schema += union-branch-case.json
> +qapi-schema += union-branch-invalid-dict.json
> qapi-schema += union-clash-branches.json
> qapi-schema += union-empty.json
> qapi-schema += union-invalid-base.json
> diff --git a/tests/qapi-schema/alternate-invalid-dict.err b/tests/qapi-schema/alternate-invalid-dict.err
> new file mode 100644
> index 0000000000..631d46628e
> --- /dev/null
> +++ b/tests/qapi-schema/alternate-invalid-dict.err
> @@ -0,0 +1 @@
> +tests/qapi-schema/alternate-invalid-dict.json:2: Key 'type' is missing from member 'two' of alternate 'Alt'
> diff --git a/tests/qapi-schema/alternate-invalid-dict.exit b/tests/qapi-schema/alternate-invalid-dict.exit
> new file mode 100644
> index 0000000000..d00491fd7e
> --- /dev/null
> +++ b/tests/qapi-schema/alternate-invalid-dict.exit
> @@ -0,0 +1 @@
> +1
> diff --git a/tests/qapi-schema/alternate-invalid-dict.json b/tests/qapi-schema/alternate-invalid-dict.json
> new file mode 100644
> index 0000000000..8e0b2ac287
> --- /dev/null
> +++ b/tests/qapi-schema/alternate-invalid-dict.json
> @@ -0,0 +1,4 @@
> +# exploded member form must have a 'type'
> +{ 'alternate': 'Alt',
> + 'data': { 'one': 'str',
> + 'two': { 'if': 'foo' } } }
> diff --git a/tests/qapi-schema/alternate-invalid-dict.out b/tests/qapi-schema/alternate-invalid-dict.out
> new file mode 100644
> index 0000000000..e69de29bb2
> diff --git a/tests/qapi-schema/event-member-invalid-dict.err b/tests/qapi-schema/event-member-invalid-dict.err
> new file mode 100644
> index 0000000000..1a57fa29b0
> --- /dev/null
> +++ b/tests/qapi-schema/event-member-invalid-dict.err
> @@ -0,0 +1 @@
> +tests/qapi-schema/event-member-invalid-dict.json:1: Key 'type' is missing from member 'a' of 'data' for event 'EVENT_A'
> diff --git a/tests/qapi-schema/event-member-invalid-dict.exit b/tests/qapi-schema/event-member-invalid-dict.exit
> new file mode 100644
> index 0000000000..d00491fd7e
> --- /dev/null
> +++ b/tests/qapi-schema/event-member-invalid-dict.exit
> @@ -0,0 +1 @@
> +1
> diff --git a/tests/qapi-schema/event-member-invalid-dict.json b/tests/qapi-schema/event-member-invalid-dict.json
> new file mode 100644
> index 0000000000..ee6f3ecb6f
> --- /dev/null
> +++ b/tests/qapi-schema/event-member-invalid-dict.json
> @@ -0,0 +1,2 @@
> +{ 'event': 'EVENT_A',
> + 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
> diff --git a/tests/qapi-schema/event-member-invalid-dict.out b/tests/qapi-schema/event-member-invalid-dict.out
> new file mode 100644
> index 0000000000..e69de29bb2
> diff --git a/tests/qapi-schema/event-nest-struct.json b/tests/qapi-schema/event-nest-struct.json
> index ee6f3ecb6f..355ddaeff1 100644
> --- a/tests/qapi-schema/event-nest-struct.json
> +++ b/tests/qapi-schema/event-nest-struct.json
> @@ -1,2 +1,2 @@
> { 'event': 'EVENT_A',
> - 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
> + 'data': { 'a' : { 'type' : { 'integer': 'int' } }, 'b' : 'str' } }
> diff --git a/tests/qapi-schema/flat-union-inline-invalid-dict.err b/tests/qapi-schema/flat-union-inline-invalid-dict.err
> new file mode 100644
> index 0000000000..9c4c45b7f0
> --- /dev/null
> +++ b/tests/qapi-schema/flat-union-inline-invalid-dict.err
> @@ -0,0 +1 @@
> +tests/qapi-schema/flat-union-inline-invalid-dict.json:7: Key 'type' is missing from member 'value1' of union 'TestUnion'
> diff --git a/tests/qapi-schema/flat-union-inline-invalid-dict.exit b/tests/qapi-schema/flat-union-inline-invalid-dict.exit
> new file mode 100644
> index 0000000000..d00491fd7e
> --- /dev/null
> +++ b/tests/qapi-schema/flat-union-inline-invalid-dict.exit
> @@ -0,0 +1 @@
> +1
> diff --git a/tests/qapi-schema/flat-union-inline-invalid-dict.json b/tests/qapi-schema/flat-union-inline-invalid-dict.json
> new file mode 100644
> index 0000000000..62c7cda617
> --- /dev/null
> +++ b/tests/qapi-schema/flat-union-inline-invalid-dict.json
> @@ -0,0 +1,11 @@
> +# we require branches to be a struct name
> +# TODO: should we allow anonymous inline branch types?
> +{ 'enum': 'TestEnum',
> + 'data': [ 'value1', 'value2' ] }
> +{ 'struct': 'Base',
> + 'data': { 'enum1': 'TestEnum', 'kind': 'str' } }
> +{ 'union': 'TestUnion',
> + 'base': 'Base',
> + 'discriminator': 'enum1',
> + 'data': { 'value1': { 'string': 'str' },
> + 'value2': { 'integer': 'int' } } }
> diff --git a/tests/qapi-schema/flat-union-inline-invalid-dict.out b/tests/qapi-schema/flat-union-inline-invalid-dict.out
> new file mode 100644
> index 0000000000..e69de29bb2
> diff --git a/tests/qapi-schema/flat-union-inline.json b/tests/qapi-schema/flat-union-inline.json
> index 62c7cda617..a9b3ce3f0d 100644
> --- a/tests/qapi-schema/flat-union-inline.json
> +++ b/tests/qapi-schema/flat-union-inline.json
> @@ -7,5 +7,5 @@
> { 'union': 'TestUnion',
> 'base': 'Base',
> 'discriminator': 'enum1',
> - 'data': { 'value1': { 'string': 'str' },
> + 'data': { 'value1': { 'type': {} },
> 'value2': { 'integer': 'int' } } }
> diff --git a/tests/qapi-schema/nested-struct-data-invalid-dict.err b/tests/qapi-schema/nested-struct-data-invalid-dict.err
> new file mode 100644
> index 0000000000..5bd364e8d9
> --- /dev/null
> +++ b/tests/qapi-schema/nested-struct-data-invalid-dict.err
> @@ -0,0 +1 @@
> +tests/qapi-schema/nested-struct-data-invalid-dict.json:2: Key 'type' is missing from member 'a' of 'data' for command 'foo'
> diff --git a/tests/qapi-schema/nested-struct-data-invalid-dict.exit b/tests/qapi-schema/nested-struct-data-invalid-dict.exit
> new file mode 100644
> index 0000000000..d00491fd7e
> --- /dev/null
> +++ b/tests/qapi-schema/nested-struct-data-invalid-dict.exit
> @@ -0,0 +1 @@
> +1
> diff --git a/tests/qapi-schema/nested-struct-data-invalid-dict.json b/tests/qapi-schema/nested-struct-data-invalid-dict.json
> new file mode 100644
> index 0000000000..efbe773ded
> --- /dev/null
> +++ b/tests/qapi-schema/nested-struct-data-invalid-dict.json
> @@ -0,0 +1,3 @@
> +# inline subtypes collide with our desired future use of defaults
> +{ 'command': 'foo',
> + 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
> diff --git a/tests/qapi-schema/nested-struct-data-invalid-dict.out b/tests/qapi-schema/nested-struct-data-invalid-dict.out
> new file mode 100644
> index 0000000000..e69de29bb2
> diff --git a/tests/qapi-schema/nested-struct-data.json b/tests/qapi-schema/nested-struct-data.json
> index efbe773ded..5b8a40cca3 100644
> --- a/tests/qapi-schema/nested-struct-data.json
> +++ b/tests/qapi-schema/nested-struct-data.json
> @@ -1,3 +1,3 @@
> # inline subtypes collide with our desired future use of defaults
> { 'command': 'foo',
> - 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
> + 'data': { 'a' : { 'type': {} }, 'b' : 'str' } }
> diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
> index 22d9044a89..94570154c9 100644
> --- a/tests/qapi-schema/qapi-schema-test.json
> +++ b/tests/qapi-schema/qapi-schema-test.json
> @@ -11,7 +11,7 @@
> 'guest-sync' ] } }
>
> { 'struct': 'TestStruct',
> - 'data': { 'integer': 'int', 'boolean': 'bool', 'string': 'str' } }
> + 'data': { 'integer': {'type': 'int'}, 'boolean': 'bool', 'string': 'str' } }
>
> # for testing enums
> { 'struct': 'NestedEnumsOne',
> @@ -77,7 +77,7 @@
> { 'union': 'UserDefFlatUnion',
> 'base': 'UserDefUnionBase', # intentional forward reference
> 'discriminator': 'enum1',
> - 'data': { 'value1' : 'UserDefA',
> + 'data': { 'value1' : {'type': 'UserDefA'},
> 'value2' : 'UserDefB',
> 'value3' : 'UserDefB'
> # 'value4' defaults to empty
> @@ -98,7 +98,7 @@
> { 'struct': 'WrapAlternate',
> 'data': { 'alt': 'UserDefAlternate' } }
> { 'alternate': 'UserDefAlternate',
> - 'data': { 'udfu': 'UserDefFlatUnion', 'e': 'EnumOne', 'i': 'int',
> + 'data': { 'udfu': {'type': 'UserDefFlatUnion'}, 'e': 'EnumOne', 'i': 'int',
> 'n': 'null' } }
>
> { 'struct': 'UserDefC',
> @@ -134,7 +134,7 @@
> { 'command': 'user_def_cmd', 'data': {} }
> { 'command': 'user_def_cmd1', 'data': {'ud1a': 'UserDefOne'} }
> { 'command': 'user_def_cmd2',
> - 'data': {'ud1a': 'UserDefOne', '*ud1b': 'UserDefOne'},
> + 'data': {'ud1a': {'type': 'UserDefOne'}, '*ud1b': 'UserDefOne'},
> 'returns': 'UserDefTwo' }
>
> { 'command': 'cmd-success-response', 'data': {}, 'success-response': false }
> @@ -166,7 +166,7 @@
>
> # testing event
> { 'struct': 'EventStructOne',
> - 'data': { 'struct1': 'UserDefOne', 'string': 'str', '*enum2': 'EnumOne' } }
> + 'data': { 'struct1': {'type': 'UserDefOne'}, 'string': 'str', '*enum2': 'EnumOne' } }
>
> { 'event': 'EVENT_A' }
> { 'event': 'EVENT_B',
> diff --git a/tests/qapi-schema/struct-member-invalid-dict.err b/tests/qapi-schema/struct-member-invalid-dict.err
> new file mode 100644
> index 0000000000..6a765bc668
> --- /dev/null
> +++ b/tests/qapi-schema/struct-member-invalid-dict.err
> @@ -0,0 +1 @@
> +tests/qapi-schema/struct-member-invalid-dict.json:2: Key 'type' is missing from member '*a' of 'data' for struct 'foo'
> diff --git a/tests/qapi-schema/struct-member-invalid-dict.exit b/tests/qapi-schema/struct-member-invalid-dict.exit
> new file mode 100644
> index 0000000000..d00491fd7e
> --- /dev/null
> +++ b/tests/qapi-schema/struct-member-invalid-dict.exit
> @@ -0,0 +1 @@
> +1
> diff --git a/tests/qapi-schema/struct-member-invalid-dict.json b/tests/qapi-schema/struct-member-invalid-dict.json
> new file mode 100644
> index 0000000000..9fe0d455a9
> --- /dev/null
> +++ b/tests/qapi-schema/struct-member-invalid-dict.json
> @@ -0,0 +1,3 @@
> +# Long form of member must have a value member 'type'
> +{ 'struct': 'foo',
> + 'data': { '*a': { 'case': 'foo' } } }
> diff --git a/tests/qapi-schema/struct-member-invalid-dict.out b/tests/qapi-schema/struct-member-invalid-dict.out
> new file mode 100644
> index 0000000000..e69de29bb2
> diff --git a/tests/qapi-schema/union-branch-invalid-dict.err b/tests/qapi-schema/union-branch-invalid-dict.err
> new file mode 100644
> index 0000000000..89f9b36791
> --- /dev/null
> +++ b/tests/qapi-schema/union-branch-invalid-dict.err
> @@ -0,0 +1 @@
> +tests/qapi-schema/union-branch-invalid-dict.json:2: Key 'type' is missing from member 'integer' of union 'UnionInvalidBranch'
> diff --git a/tests/qapi-schema/union-branch-invalid-dict.exit b/tests/qapi-schema/union-branch-invalid-dict.exit
> new file mode 100644
> index 0000000000..d00491fd7e
> --- /dev/null
> +++ b/tests/qapi-schema/union-branch-invalid-dict.exit
> @@ -0,0 +1 @@
> +1
> diff --git a/tests/qapi-schema/union-branch-invalid-dict.json b/tests/qapi-schema/union-branch-invalid-dict.json
> new file mode 100644
> index 0000000000..9778598dbd
> --- /dev/null
> +++ b/tests/qapi-schema/union-branch-invalid-dict.json
> @@ -0,0 +1,4 @@
> +# Long form of member must have a value member 'type'
> +{ 'union': 'UnionInvalidBranch',
> + 'data': { 'integer': { 'if': 'foo'},
> + 's8': 'int8' } }
> diff --git a/tests/qapi-schema/union-branch-invalid-dict.out b/tests/qapi-schema/union-branch-invalid-dict.out
> new file mode 100644
> index 0000000000..e69de29bb2
Looks good, but I'd like to investigate whether my suggested placement
of the normalization would simplify things before I give my R-by.
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 15/27] qapi: add an error in case a discriminator is conditional
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 15/27] qapi: add an error in case a discriminator is conditional Marc-André Lureau
@ 2018-12-10 17:31 ` Markus Armbruster
2018-12-11 15:23 ` Markus Armbruster
0 siblings, 1 reply; 69+ messages in thread
From: Markus Armbruster @ 2018-12-10 17:31 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Making a discriminator conditional doesn't make much sense.
Good point (so easy to overlook!), but why first add the 'if' feature
broken that way in PATCH 13, then fix it up in PATCH 15?
> Instead,
> the union could be made conditional.
What do you mean by that?
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> scripts/qapi/common.py | 8 ++++++++
> tests/Makefile.include | 1 +
> .../flat-union-invalid-if-discriminator.err | 1 +
> .../flat-union-invalid-if-discriminator.exit | 1 +
> .../flat-union-invalid-if-discriminator.json | 17 +++++++++++++++++
> .../flat-union-invalid-if-discriminator.out | 0
> 6 files changed, 28 insertions(+)
> create mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.err
> create mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.exit
> create mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.json
> create mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.out
>
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index aec51acb07..f79b3fad54 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -578,6 +578,7 @@ def find_alternate_member_qtype(qapi_type):
> # Return the discriminator enum define if discriminator is specified as an
> # enum type, otherwise return None.
> def discriminator_find_enum_define(expr):
> + name = expr['union']
> base = expr.get('base')
> discriminator = expr.get('discriminator')
>
> @@ -594,6 +595,7 @@ def discriminator_find_enum_define(expr):
>
> if isinstance(discriminator_value, dict):
> discriminator_value = discriminator_value['type']
> +
> return enum_types.get(discriminator_value)
>
>
These two hunks are leftovers, please drop.
> @@ -800,7 +802,12 @@ def check_union(expr, info):
> "struct '%s'"
> % (discriminator, base))
> if isinstance(discriminator_value, dict):
> + if discriminator_value.get('if'):
> + raise QAPISemError(info, 'The discriminator %s.%s for union %s '
> + 'must not be conditional' %
> + (base, discriminator, name))
> discriminator_value = discriminator_value['type']
> +
> enum_define = enum_types.get(discriminator_value)
> allow_metas = ['struct']
> # Do not allow string discriminator
> @@ -1023,6 +1030,7 @@ def check_exprs(exprs):
>
> if 'include' in expr:
> continue
> + info = expr_elem['info']
> if 'union' in expr and not discriminator_find_enum_define(expr):
> name = '%sKind' % expr['union']
> elif 'alternate' in expr:
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index ea5d1e8787..3f5a1d0c30 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -409,6 +409,7 @@ qapi-schema += flat-union-inline-invalid-dict.json
> qapi-schema += flat-union-int-branch.json
> qapi-schema += flat-union-invalid-branch-key.json
> qapi-schema += flat-union-invalid-discriminator.json
> +qapi-schema += flat-union-invalid-if-discriminator.json
> qapi-schema += flat-union-no-base.json
> qapi-schema += flat-union-optional-discriminator.json
> qapi-schema += flat-union-string-discriminator.json
> diff --git a/tests/qapi-schema/flat-union-invalid-if-discriminator.err b/tests/qapi-schema/flat-union-invalid-if-discriminator.err
> new file mode 100644
> index 0000000000..0c94c9860d
> --- /dev/null
> +++ b/tests/qapi-schema/flat-union-invalid-if-discriminator.err
> @@ -0,0 +1 @@
> +tests/qapi-schema/flat-union-invalid-if-discriminator.json:13: The discriminator TestBase.enum1 for union TestUnion must not be conditional
> diff --git a/tests/qapi-schema/flat-union-invalid-if-discriminator.exit b/tests/qapi-schema/flat-union-invalid-if-discriminator.exit
> new file mode 100644
> index 0000000000..d00491fd7e
> --- /dev/null
> +++ b/tests/qapi-schema/flat-union-invalid-if-discriminator.exit
> @@ -0,0 +1 @@
> +1
> diff --git a/tests/qapi-schema/flat-union-invalid-if-discriminator.json b/tests/qapi-schema/flat-union-invalid-if-discriminator.json
> new file mode 100644
> index 0000000000..618ec36396
> --- /dev/null
> +++ b/tests/qapi-schema/flat-union-invalid-if-discriminator.json
> @@ -0,0 +1,17 @@
> +{ 'enum': 'TestEnum',
> + 'data': [ 'value1', 'value2' ] }
> +
> +{ 'struct': 'TestBase',
> + 'data': { 'enum1': { 'type': 'TestEnum', 'if': 'FOO' } } }
> +
> +{ 'struct': 'TestTypeA',
> + 'data': { 'string': 'str' } }
> +
> +{ 'struct': 'TestTypeB',
> + 'data': { 'integer': 'int' } }
> +
> +{ 'union': 'TestUnion',
> + 'base': 'TestBase',
> + 'discriminator': 'enum1',
> + 'data': { 'value1': 'TestTypeA',
> + 'value2': 'TestTypeB' } }
> diff --git a/tests/qapi-schema/flat-union-invalid-if-discriminator.out b/tests/qapi-schema/flat-union-invalid-if-discriminator.out
> new file mode 100644
> index 0000000000..e69de29bb2
Patch looks good otherwise.
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 16/27] qapi: add 'if' to union members
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 16/27] qapi: add 'if' to union members Marc-André Lureau
@ 2018-12-10 17:33 ` Markus Armbruster
0 siblings, 0 replies; 69+ messages in thread
From: Markus Armbruster @ 2018-12-10 17:33 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Add 'if' key to union members:
>
> { 'union': 'TestIfUnion', 'data':
> 'mem': { 'type': 'str', 'if': 'COND'} }
>
> The generated code remains unconditional for now. Later patches
> generate the conditionals.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 17/27] qapi: simplify make_enum_members()
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 17/27] qapi: simplify make_enum_members() Marc-André Lureau
@ 2018-12-11 12:05 ` Markus Armbruster
2018-12-11 12:08 ` Marc-André Lureau
0 siblings, 1 reply; 69+ messages in thread
From: Markus Armbruster @ 2018-12-11 12:05 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> The function only receives the dictionary form of enum expressions
> now, so we can make it shorter.
>
> Suggested-by: Markus Armbruster <armbru@redhat.com>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> scripts/qapi/common.py | 11 +----------
> 1 file changed, 1 insertion(+), 10 deletions(-)
>
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index fd622313cb..44020779dd 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -1714,16 +1714,7 @@ class QAPISchema(object):
> qtype_values, 'QTYPE'))
>
> def _make_enum_members(self, values):
> - enum = []
> - for v in values:
> - if isinstance(v, dict):
> - name = v['name']
> - ifcond = v.get('if')
> - else:
> - name = v
> - ifcond = None
> - enum.append(QAPISchemaMember(name, ifcond))
> - return enum
> + 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()
We may want to squash this one into PATCH 08 as mentioned in that
patch's review.
In case we don't:
Reviewed-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 17/27] qapi: simplify make_enum_members()
2018-12-11 12:05 ` Markus Armbruster
@ 2018-12-11 12:08 ` Marc-André Lureau
0 siblings, 0 replies; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-11 12:08 UTC (permalink / raw)
To: Markus Armbruster; +Cc: QEMU, Michael Roth
Hi
On Tue, Dec 11, 2018 at 4:06 PM Markus Armbruster <armbru@redhat.com> wrote:
>
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
> > The function only receives the dictionary form of enum expressions
> > now, so we can make it shorter.
> >
> > Suggested-by: Markus Armbruster <armbru@redhat.com>
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> > scripts/qapi/common.py | 11 +----------
> > 1 file changed, 1 insertion(+), 10 deletions(-)
> >
> > diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> > index fd622313cb..44020779dd 100644
> > --- a/scripts/qapi/common.py
> > +++ b/scripts/qapi/common.py
> > @@ -1714,16 +1714,7 @@ class QAPISchema(object):
> > qtype_values, 'QTYPE'))
> >
> > def _make_enum_members(self, values):
> > - enum = []
> > - for v in values:
> > - if isinstance(v, dict):
> > - name = v['name']
> > - ifcond = v.get('if')
> > - else:
> > - name = v
> > - ifcond = None
> > - enum.append(QAPISchemaMember(name, ifcond))
> > - return enum
> > + 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()
>
> We may want to squash this one into PATCH 08 as mentioned in that
> patch's review.
>
> In case we don't:
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
>
Feel free to squash on commit, thanks
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 18/27] tests/qapi: add command with condition on union argument
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 18/27] tests/qapi: add command with condition on union argument Marc-André Lureau
@ 2018-12-11 12:09 ` Markus Armbruster
2018-12-11 12:13 ` Marc-André Lureau
0 siblings, 1 reply; 69+ messages in thread
From: Markus Armbruster @ 2018-12-11 12:09 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> For completeness.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Let's say "Forgotten in commit 967c885108f."
Reviewed-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 13/27] qapi: add a dictionary form for TYPE
2018-12-10 17:24 ` Markus Armbruster
@ 2018-12-11 12:11 ` Marc-André Lureau
2018-12-11 15:35 ` Markus Armbruster
2018-12-11 15:18 ` Markus Armbruster
1 sibling, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-11 12:11 UTC (permalink / raw)
To: Markus Armbruster; +Cc: QEMU, Michael Roth
Hi
On Mon, Dec 10, 2018 at 9:26 PM Markus Armbruster <armbru@redhat.com> wrote:
>
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
> > Wherever a struct/union/alternate/command/event member with NAME: TYPE
> > form is accepted, desugar it to a NAME: { 'type': TYPE } form.
> >
> > This will allow to add new member details, such as 'if' in the
> > following patch to introduce conditionals, or 'default' for default
> > values etc.
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> > scripts/qapi/common.py | 71 ++++++++++++++-----
> > tests/Makefile.include | 6 ++
> > tests/qapi-schema/alternate-invalid-dict.err | 1 +
> > tests/qapi-schema/alternate-invalid-dict.exit | 1 +
> > tests/qapi-schema/alternate-invalid-dict.json | 4 ++
> > tests/qapi-schema/alternate-invalid-dict.out | 0
> > .../qapi-schema/event-member-invalid-dict.err | 1 +
> > .../event-member-invalid-dict.exit | 1 +
> > .../event-member-invalid-dict.json | 2 +
> > .../qapi-schema/event-member-invalid-dict.out | 0
> > tests/qapi-schema/event-nest-struct.json | 2 +-
> > .../flat-union-inline-invalid-dict.err | 1 +
> > .../flat-union-inline-invalid-dict.exit | 1 +
> > .../flat-union-inline-invalid-dict.json | 11 +++
> > .../flat-union-inline-invalid-dict.out | 0
> > tests/qapi-schema/flat-union-inline.json | 2 +-
> > .../nested-struct-data-invalid-dict.err | 1 +
> > .../nested-struct-data-invalid-dict.exit | 1 +
> > .../nested-struct-data-invalid-dict.json | 3 +
> > .../nested-struct-data-invalid-dict.out | 0
> > tests/qapi-schema/nested-struct-data.json | 2 +-
> > tests/qapi-schema/qapi-schema-test.json | 10 +--
> > .../struct-member-invalid-dict.err | 1 +
> > .../struct-member-invalid-dict.exit | 1 +
> > .../struct-member-invalid-dict.json | 3 +
> > .../struct-member-invalid-dict.out | 0
> > .../qapi-schema/union-branch-invalid-dict.err | 1 +
> > .../union-branch-invalid-dict.exit | 1 +
> > .../union-branch-invalid-dict.json | 4 ++
> > .../qapi-schema/union-branch-invalid-dict.out | 0
> > 30 files changed, 106 insertions(+), 26 deletions(-)
> > create mode 100644 tests/qapi-schema/alternate-invalid-dict.err
> > create mode 100644 tests/qapi-schema/alternate-invalid-dict.exit
> > create mode 100644 tests/qapi-schema/alternate-invalid-dict.json
> > create mode 100644 tests/qapi-schema/alternate-invalid-dict.out
> > create mode 100644 tests/qapi-schema/event-member-invalid-dict.err
> > create mode 100644 tests/qapi-schema/event-member-invalid-dict.exit
> > create mode 100644 tests/qapi-schema/event-member-invalid-dict.json
> > create mode 100644 tests/qapi-schema/event-member-invalid-dict.out
> > create mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.err
> > create mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.exit
> > create mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.json
> > create mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.out
> > create mode 100644 tests/qapi-schema/nested-struct-data-invalid-dict.err
> > create mode 100644 tests/qapi-schema/nested-struct-data-invalid-dict.exit
> > create mode 100644 tests/qapi-schema/nested-struct-data-invalid-dict.json
> > create mode 100644 tests/qapi-schema/nested-struct-data-invalid-dict.out
> > create mode 100644 tests/qapi-schema/struct-member-invalid-dict.err
> > create mode 100644 tests/qapi-schema/struct-member-invalid-dict.exit
> > create mode 100644 tests/qapi-schema/struct-member-invalid-dict.json
> > create mode 100644 tests/qapi-schema/struct-member-invalid-dict.out
> > create mode 100644 tests/qapi-schema/union-branch-invalid-dict.err
> > create mode 100644 tests/qapi-schema/union-branch-invalid-dict.exit
> > create mode 100644 tests/qapi-schema/union-branch-invalid-dict.json
> > create mode 100644 tests/qapi-schema/union-branch-invalid-dict.out
> >
> > diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> > index 95e55b3f44..4b3ba53dc7 100644
> > --- a/scripts/qapi/common.py
> > +++ b/scripts/qapi/common.py
> > @@ -588,11 +588,13 @@ 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)
> > + if isinstance(discriminator_value, dict):
> > + discriminator_value = discriminator_value['type']
> > + return enum_types.get(discriminator_value)
>
> As in PATCH 08, this is slightly more complicated than v6 because @expr
> isn't normalized. I can't say offhand whether normalizing in the place
> I suggested in my review of v6 would avoid this complication.
>
> >
> >
> > # Names must be letters, numbers, -, and _. They must start with letter,
> > @@ -660,6 +662,15 @@ def check_if(expr, info):
> > check_if_str(ifcond, info)
> >
> >
> > +def normalize_members(expr, field):
> > + members = expr.get(field)
> > + if isinstance(members, OrderedDict):
> > + for key, arg in members.items():
> > + if isinstance(arg, dict):
> > + continue
> > + members[key] = {'type': arg}
> > +
> > +
> > def check_type(info, source, value, allow_array=False,
> > allow_implicit=False, allow_optional=False,
> > allow_metas=[]):
> > @@ -704,8 +715,14 @@ 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,
> > + if isinstance(arg, dict):
> > + check_known_keys(info, "member '%s' of %s" % (key, source),
> > + arg, ['type'], [])
> > + typ = arg['type']
> > + else:
> > + typ = arg
> > + check_type(info, "Member '%s' of %s" % (key, source),
> > + typ, allow_array=True,
> > allow_metas=['built-in', 'union', 'alternate', 'struct',
> > 'enum'])
> >
>
> Slightly more complicated than v6, this time because members of the
> implicit struct type aren't normalized, yet.
>
> > @@ -776,13 +793,15 @@ 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 isinstance(discriminator_value, dict):
> > + discriminator_value = discriminator_value['type']
> > + enum_define = enum_types.get(discriminator_value)
> > allow_metas = ['struct']
> > # Do not allow string discriminator
> > if not enum_define:
> > @@ -795,10 +814,16 @@ def check_union(expr, info):
> > raise QAPISemError(info, "Union '%s' cannot have empty 'data'" % name)
> > for (key, value) in members.items():
> > check_name(info, "Member of union '%s'" % name, key)
> > + if isinstance(value, dict):
> > + check_known_keys(info, "member '%s' of union '%s'" % (key, name),
> > + value, ['type'], [])
> > + typ = value['type']
> > + else:
> > + typ = value
>
> Likewise.
>
> >
> > # 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)
> > + typ, 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.
> > @@ -822,18 +847,24 @@ def check_alternate(expr, info):
> > "in 'data'" % name)
> > for (key, value) in members.items():
> > check_name(info, "Member of alternate '%s'" % name, key)
> > + if isinstance(value, dict):
> > + check_known_keys(info,
> > + "member '%s' of alternate '%s'" % (key, name),
> > + value, ['type'], [])
> > + typ = value['type']
> > + else:
> > + typ = value
>
> Likewise.
>
> >
> > # 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_get_names(enum_expr):
> > if v in ['on', 'off']:
> > @@ -1035,6 +1066,10 @@ def normalize_exprs(exprs):
> > expr = expr_elem['expr']
> > if 'enum' in expr:
> > normalize_enum(expr)
> > + elif 'union' in expr:
> > + normalize_members(expr, 'base')
> > + if {'union', 'alternate', 'struct', 'command', 'event'} & set(expr):
> > + normalize_members(expr, 'data')
> >
> > return exprs
> >
> > @@ -1738,7 +1773,7 @@ class QAPISchema(object):
> > return QAPISchemaObjectTypeMember(name, typ, optional)
> >
> > def _make_members(self, data, info):
> > - return [self._make_member(key, value, info)
> > + return [self._make_member(key, value['type'], info)
> > for (key, value) in data.items()]
> >
> > def _def_struct_type(self, expr, info, doc):
> > @@ -1774,11 +1809,11 @@ 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'])
> > for (key, value) in data.items()]
> > members = []
> > else:
> > - variants = [self._make_simple_variant(key, value, info)
> > + variants = [self._make_simple_variant(key, value['type'], info)
> > for (key, value) in data.items()]
> > typ = self._make_implicit_enum_type(name, info, ifcond,
> > [v.name for v in variants])
> > @@ -1794,7 +1829,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'])
> > for (key, value) in data.items()]
> > tag_member = QAPISchemaObjectTypeMember('type', 'QType', False)
> > self._def_entity(
> > diff --git a/tests/Makefile.include b/tests/Makefile.include
> > index 3c9eea27fd..ea5d1e8787 100644
> > --- a/tests/Makefile.include
> > +++ b/tests/Makefile.include
> > @@ -318,6 +318,7 @@ qapi-schema += alternate-conflict-string.json
> > qapi-schema += alternate-conflict-bool-string.json
> > qapi-schema += alternate-conflict-num-string.json
> > qapi-schema += alternate-empty.json
> > +qapi-schema += alternate-invalid-dict.json
> > qapi-schema += alternate-nested.json
> > qapi-schema += alternate-unknown.json
> > qapi-schema += args-alternate.json
> > @@ -394,6 +395,7 @@ qapi-schema += escape-too-big.json
> > qapi-schema += escape-too-short.json
> > qapi-schema += event-boxed-empty.json
> > qapi-schema += event-case.json
> > +qapi-schema += event-member-invalid-dict.json
> > qapi-schema += event-nest-struct.json
> > qapi-schema += flat-union-array-branch.json
> > qapi-schema += flat-union-bad-base.json
> > @@ -403,6 +405,7 @@ qapi-schema += flat-union-base-union.json
> > qapi-schema += flat-union-clash-member.json
> > qapi-schema += flat-union-empty.json
> > qapi-schema += flat-union-inline.json
> > +qapi-schema += flat-union-inline-invalid-dict.json
> > qapi-schema += flat-union-int-branch.json
> > qapi-schema += flat-union-invalid-branch-key.json
> > qapi-schema += flat-union-invalid-discriminator.json
> > @@ -430,6 +433,7 @@ qapi-schema += missing-comma-list.json
> > qapi-schema += missing-comma-object.json
> > qapi-schema += missing-type.json
> > qapi-schema += nested-struct-data.json
> > +qapi-schema += nested-struct-data-invalid-dict.json
> > qapi-schema += non-objects.json
> > qapi-schema += oob-test.json
> > qapi-schema += allow-preconfig-test.json
> > @@ -460,6 +464,7 @@ qapi-schema += returns-whitelist.json
> > qapi-schema += struct-base-clash-deep.json
> > qapi-schema += struct-base-clash.json
> > qapi-schema += struct-data-invalid.json
> > +qapi-schema += struct-member-invalid-dict.json
> > qapi-schema += struct-member-invalid.json
> > qapi-schema += trailing-comma-list.json
> > qapi-schema += trailing-comma-object.json
> > @@ -471,6 +476,7 @@ qapi-schema += unicode-str.json
> > qapi-schema += union-base-empty.json
> > qapi-schema += union-base-no-discriminator.json
> > qapi-schema += union-branch-case.json
> > +qapi-schema += union-branch-invalid-dict.json
> > qapi-schema += union-clash-branches.json
> > qapi-schema += union-empty.json
> > qapi-schema += union-invalid-base.json
> > diff --git a/tests/qapi-schema/alternate-invalid-dict.err b/tests/qapi-schema/alternate-invalid-dict.err
> > new file mode 100644
> > index 0000000000..631d46628e
> > --- /dev/null
> > +++ b/tests/qapi-schema/alternate-invalid-dict.err
> > @@ -0,0 +1 @@
> > +tests/qapi-schema/alternate-invalid-dict.json:2: Key 'type' is missing from member 'two' of alternate 'Alt'
> > diff --git a/tests/qapi-schema/alternate-invalid-dict.exit b/tests/qapi-schema/alternate-invalid-dict.exit
> > new file mode 100644
> > index 0000000000..d00491fd7e
> > --- /dev/null
> > +++ b/tests/qapi-schema/alternate-invalid-dict.exit
> > @@ -0,0 +1 @@
> > +1
> > diff --git a/tests/qapi-schema/alternate-invalid-dict.json b/tests/qapi-schema/alternate-invalid-dict.json
> > new file mode 100644
> > index 0000000000..8e0b2ac287
> > --- /dev/null
> > +++ b/tests/qapi-schema/alternate-invalid-dict.json
> > @@ -0,0 +1,4 @@
> > +# exploded member form must have a 'type'
> > +{ 'alternate': 'Alt',
> > + 'data': { 'one': 'str',
> > + 'two': { 'if': 'foo' } } }
> > diff --git a/tests/qapi-schema/alternate-invalid-dict.out b/tests/qapi-schema/alternate-invalid-dict.out
> > new file mode 100644
> > index 0000000000..e69de29bb2
> > diff --git a/tests/qapi-schema/event-member-invalid-dict.err b/tests/qapi-schema/event-member-invalid-dict.err
> > new file mode 100644
> > index 0000000000..1a57fa29b0
> > --- /dev/null
> > +++ b/tests/qapi-schema/event-member-invalid-dict.err
> > @@ -0,0 +1 @@
> > +tests/qapi-schema/event-member-invalid-dict.json:1: Key 'type' is missing from member 'a' of 'data' for event 'EVENT_A'
> > diff --git a/tests/qapi-schema/event-member-invalid-dict.exit b/tests/qapi-schema/event-member-invalid-dict.exit
> > new file mode 100644
> > index 0000000000..d00491fd7e
> > --- /dev/null
> > +++ b/tests/qapi-schema/event-member-invalid-dict.exit
> > @@ -0,0 +1 @@
> > +1
> > diff --git a/tests/qapi-schema/event-member-invalid-dict.json b/tests/qapi-schema/event-member-invalid-dict.json
> > new file mode 100644
> > index 0000000000..ee6f3ecb6f
> > --- /dev/null
> > +++ b/tests/qapi-schema/event-member-invalid-dict.json
> > @@ -0,0 +1,2 @@
> > +{ 'event': 'EVENT_A',
> > + 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
> > diff --git a/tests/qapi-schema/event-member-invalid-dict.out b/tests/qapi-schema/event-member-invalid-dict.out
> > new file mode 100644
> > index 0000000000..e69de29bb2
> > diff --git a/tests/qapi-schema/event-nest-struct.json b/tests/qapi-schema/event-nest-struct.json
> > index ee6f3ecb6f..355ddaeff1 100644
> > --- a/tests/qapi-schema/event-nest-struct.json
> > +++ b/tests/qapi-schema/event-nest-struct.json
> > @@ -1,2 +1,2 @@
> > { 'event': 'EVENT_A',
> > - 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
> > + 'data': { 'a' : { 'type' : { 'integer': 'int' } }, 'b' : 'str' } }
> > diff --git a/tests/qapi-schema/flat-union-inline-invalid-dict.err b/tests/qapi-schema/flat-union-inline-invalid-dict.err
> > new file mode 100644
> > index 0000000000..9c4c45b7f0
> > --- /dev/null
> > +++ b/tests/qapi-schema/flat-union-inline-invalid-dict.err
> > @@ -0,0 +1 @@
> > +tests/qapi-schema/flat-union-inline-invalid-dict.json:7: Key 'type' is missing from member 'value1' of union 'TestUnion'
> > diff --git a/tests/qapi-schema/flat-union-inline-invalid-dict.exit b/tests/qapi-schema/flat-union-inline-invalid-dict.exit
> > new file mode 100644
> > index 0000000000..d00491fd7e
> > --- /dev/null
> > +++ b/tests/qapi-schema/flat-union-inline-invalid-dict.exit
> > @@ -0,0 +1 @@
> > +1
> > diff --git a/tests/qapi-schema/flat-union-inline-invalid-dict.json b/tests/qapi-schema/flat-union-inline-invalid-dict.json
> > new file mode 100644
> > index 0000000000..62c7cda617
> > --- /dev/null
> > +++ b/tests/qapi-schema/flat-union-inline-invalid-dict.json
> > @@ -0,0 +1,11 @@
> > +# we require branches to be a struct name
> > +# TODO: should we allow anonymous inline branch types?
> > +{ 'enum': 'TestEnum',
> > + 'data': [ 'value1', 'value2' ] }
> > +{ 'struct': 'Base',
> > + 'data': { 'enum1': 'TestEnum', 'kind': 'str' } }
> > +{ 'union': 'TestUnion',
> > + 'base': 'Base',
> > + 'discriminator': 'enum1',
> > + 'data': { 'value1': { 'string': 'str' },
> > + 'value2': { 'integer': 'int' } } }
> > diff --git a/tests/qapi-schema/flat-union-inline-invalid-dict.out b/tests/qapi-schema/flat-union-inline-invalid-dict.out
> > new file mode 100644
> > index 0000000000..e69de29bb2
> > diff --git a/tests/qapi-schema/flat-union-inline.json b/tests/qapi-schema/flat-union-inline.json
> > index 62c7cda617..a9b3ce3f0d 100644
> > --- a/tests/qapi-schema/flat-union-inline.json
> > +++ b/tests/qapi-schema/flat-union-inline.json
> > @@ -7,5 +7,5 @@
> > { 'union': 'TestUnion',
> > 'base': 'Base',
> > 'discriminator': 'enum1',
> > - 'data': { 'value1': { 'string': 'str' },
> > + 'data': { 'value1': { 'type': {} },
> > 'value2': { 'integer': 'int' } } }
> > diff --git a/tests/qapi-schema/nested-struct-data-invalid-dict.err b/tests/qapi-schema/nested-struct-data-invalid-dict.err
> > new file mode 100644
> > index 0000000000..5bd364e8d9
> > --- /dev/null
> > +++ b/tests/qapi-schema/nested-struct-data-invalid-dict.err
> > @@ -0,0 +1 @@
> > +tests/qapi-schema/nested-struct-data-invalid-dict.json:2: Key 'type' is missing from member 'a' of 'data' for command 'foo'
> > diff --git a/tests/qapi-schema/nested-struct-data-invalid-dict.exit b/tests/qapi-schema/nested-struct-data-invalid-dict.exit
> > new file mode 100644
> > index 0000000000..d00491fd7e
> > --- /dev/null
> > +++ b/tests/qapi-schema/nested-struct-data-invalid-dict.exit
> > @@ -0,0 +1 @@
> > +1
> > diff --git a/tests/qapi-schema/nested-struct-data-invalid-dict.json b/tests/qapi-schema/nested-struct-data-invalid-dict.json
> > new file mode 100644
> > index 0000000000..efbe773ded
> > --- /dev/null
> > +++ b/tests/qapi-schema/nested-struct-data-invalid-dict.json
> > @@ -0,0 +1,3 @@
> > +# inline subtypes collide with our desired future use of defaults
> > +{ 'command': 'foo',
> > + 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
> > diff --git a/tests/qapi-schema/nested-struct-data-invalid-dict.out b/tests/qapi-schema/nested-struct-data-invalid-dict.out
> > new file mode 100644
> > index 0000000000..e69de29bb2
> > diff --git a/tests/qapi-schema/nested-struct-data.json b/tests/qapi-schema/nested-struct-data.json
> > index efbe773ded..5b8a40cca3 100644
> > --- a/tests/qapi-schema/nested-struct-data.json
> > +++ b/tests/qapi-schema/nested-struct-data.json
> > @@ -1,3 +1,3 @@
> > # inline subtypes collide with our desired future use of defaults
> > { 'command': 'foo',
> > - 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
> > + 'data': { 'a' : { 'type': {} }, 'b' : 'str' } }
> > diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
> > index 22d9044a89..94570154c9 100644
> > --- a/tests/qapi-schema/qapi-schema-test.json
> > +++ b/tests/qapi-schema/qapi-schema-test.json
> > @@ -11,7 +11,7 @@
> > 'guest-sync' ] } }
> >
> > { 'struct': 'TestStruct',
> > - 'data': { 'integer': 'int', 'boolean': 'bool', 'string': 'str' } }
> > + 'data': { 'integer': {'type': 'int'}, 'boolean': 'bool', 'string': 'str' } }
> >
> > # for testing enums
> > { 'struct': 'NestedEnumsOne',
> > @@ -77,7 +77,7 @@
> > { 'union': 'UserDefFlatUnion',
> > 'base': 'UserDefUnionBase', # intentional forward reference
> > 'discriminator': 'enum1',
> > - 'data': { 'value1' : 'UserDefA',
> > + 'data': { 'value1' : {'type': 'UserDefA'},
> > 'value2' : 'UserDefB',
> > 'value3' : 'UserDefB'
> > # 'value4' defaults to empty
> > @@ -98,7 +98,7 @@
> > { 'struct': 'WrapAlternate',
> > 'data': { 'alt': 'UserDefAlternate' } }
> > { 'alternate': 'UserDefAlternate',
> > - 'data': { 'udfu': 'UserDefFlatUnion', 'e': 'EnumOne', 'i': 'int',
> > + 'data': { 'udfu': {'type': 'UserDefFlatUnion'}, 'e': 'EnumOne', 'i': 'int',
> > 'n': 'null' } }
> >
> > { 'struct': 'UserDefC',
> > @@ -134,7 +134,7 @@
> > { 'command': 'user_def_cmd', 'data': {} }
> > { 'command': 'user_def_cmd1', 'data': {'ud1a': 'UserDefOne'} }
> > { 'command': 'user_def_cmd2',
> > - 'data': {'ud1a': 'UserDefOne', '*ud1b': 'UserDefOne'},
> > + 'data': {'ud1a': {'type': 'UserDefOne'}, '*ud1b': 'UserDefOne'},
> > 'returns': 'UserDefTwo' }
> >
> > { 'command': 'cmd-success-response', 'data': {}, 'success-response': false }
> > @@ -166,7 +166,7 @@
> >
> > # testing event
> > { 'struct': 'EventStructOne',
> > - 'data': { 'struct1': 'UserDefOne', 'string': 'str', '*enum2': 'EnumOne' } }
> > + 'data': { 'struct1': {'type': 'UserDefOne'}, 'string': 'str', '*enum2': 'EnumOne' } }
> >
> > { 'event': 'EVENT_A' }
> > { 'event': 'EVENT_B',
> > diff --git a/tests/qapi-schema/struct-member-invalid-dict.err b/tests/qapi-schema/struct-member-invalid-dict.err
> > new file mode 100644
> > index 0000000000..6a765bc668
> > --- /dev/null
> > +++ b/tests/qapi-schema/struct-member-invalid-dict.err
> > @@ -0,0 +1 @@
> > +tests/qapi-schema/struct-member-invalid-dict.json:2: Key 'type' is missing from member '*a' of 'data' for struct 'foo'
> > diff --git a/tests/qapi-schema/struct-member-invalid-dict.exit b/tests/qapi-schema/struct-member-invalid-dict.exit
> > new file mode 100644
> > index 0000000000..d00491fd7e
> > --- /dev/null
> > +++ b/tests/qapi-schema/struct-member-invalid-dict.exit
> > @@ -0,0 +1 @@
> > +1
> > diff --git a/tests/qapi-schema/struct-member-invalid-dict.json b/tests/qapi-schema/struct-member-invalid-dict.json
> > new file mode 100644
> > index 0000000000..9fe0d455a9
> > --- /dev/null
> > +++ b/tests/qapi-schema/struct-member-invalid-dict.json
> > @@ -0,0 +1,3 @@
> > +# Long form of member must have a value member 'type'
> > +{ 'struct': 'foo',
> > + 'data': { '*a': { 'case': 'foo' } } }
> > diff --git a/tests/qapi-schema/struct-member-invalid-dict.out b/tests/qapi-schema/struct-member-invalid-dict.out
> > new file mode 100644
> > index 0000000000..e69de29bb2
> > diff --git a/tests/qapi-schema/union-branch-invalid-dict.err b/tests/qapi-schema/union-branch-invalid-dict.err
> > new file mode 100644
> > index 0000000000..89f9b36791
> > --- /dev/null
> > +++ b/tests/qapi-schema/union-branch-invalid-dict.err
> > @@ -0,0 +1 @@
> > +tests/qapi-schema/union-branch-invalid-dict.json:2: Key 'type' is missing from member 'integer' of union 'UnionInvalidBranch'
> > diff --git a/tests/qapi-schema/union-branch-invalid-dict.exit b/tests/qapi-schema/union-branch-invalid-dict.exit
> > new file mode 100644
> > index 0000000000..d00491fd7e
> > --- /dev/null
> > +++ b/tests/qapi-schema/union-branch-invalid-dict.exit
> > @@ -0,0 +1 @@
> > +1
> > diff --git a/tests/qapi-schema/union-branch-invalid-dict.json b/tests/qapi-schema/union-branch-invalid-dict.json
> > new file mode 100644
> > index 0000000000..9778598dbd
> > --- /dev/null
> > +++ b/tests/qapi-schema/union-branch-invalid-dict.json
> > @@ -0,0 +1,4 @@
> > +# Long form of member must have a value member 'type'
> > +{ 'union': 'UnionInvalidBranch',
> > + 'data': { 'integer': { 'if': 'foo'},
> > + 's8': 'int8' } }
> > diff --git a/tests/qapi-schema/union-branch-invalid-dict.out b/tests/qapi-schema/union-branch-invalid-dict.out
> > new file mode 100644
> > index 0000000000..e69de29bb2
>
> Looks good, but I'd like to investigate whether my suggested placement
> of the normalization would simplify things before I give my R-by.
>
I am not sure I follow, you suggest to have normalization before
check? Then how can we produce an error that reflects the input
accurately? Should we carry additional information (original form etc)
on the source during normalization?
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 18/27] tests/qapi: add command with condition on union argument
2018-12-11 12:09 ` Markus Armbruster
@ 2018-12-11 12:13 ` Marc-André Lureau
0 siblings, 0 replies; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-11 12:13 UTC (permalink / raw)
To: Markus Armbruster; +Cc: QEMU, Michael Roth
On Tue, Dec 11, 2018 at 4:09 PM Markus Armbruster <armbru@redhat.com> wrote:
>
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
> > For completeness.
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> Let's say "Forgotten in commit 967c885108f."
>
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
ack, thanks
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 20/27] tests/qapi: add command with condition on alternate argument
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 20/27] tests/qapi: add command with condition on alternate argument Marc-André Lureau
@ 2018-12-11 12:20 ` Markus Armbruster
0 siblings, 0 replies; 69+ messages in thread
From: Markus Armbruster @ 2018-12-11 12:20 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, armbru, Michael Roth
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> For completeness.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Let's say "Forgotten in commit 967c885108f."
We could squash PATCH 18 and this one together. In case we don't:
Reviewed-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 19/27] qapi: add 'if' to alternate members
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 19/27] qapi: add 'if' to alternate members Marc-André Lureau
@ 2018-12-11 12:21 ` Markus Armbruster
0 siblings, 0 replies; 69+ messages in thread
From: Markus Armbruster @ 2018-12-11 12:21 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Add 'if' key to alternate members:
>
> { 'alternate': 'TestIfAlternate', 'data':
> { 'alt': { 'type': 'TestStruct', 'if': 'COND' } } }
>
> Generated code is not changed by this patch but with "qapi: add #if
> conditions to generated code".
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 21/27] qapi: add #if conditions to generated code members
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 21/27] qapi: add #if conditions to generated code members Marc-André Lureau
@ 2018-12-11 13:17 ` Markus Armbruster
0 siblings, 0 replies; 69+ messages in thread
From: Markus Armbruster @ 2018-12-11 13:17 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Wrap generated enum/struct members and code with #if/#endif, using the
> .ifcond members added in the previous patches.
>
> Some types generate both enum and struct members for example, so a
> step-by-step is unnecessarily complicated to deal with (it would
> easily generate invalid intermediary code).
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
We've since agreed to tweak the commit message:
qapi: Add #if conditions to generated code members
Wrap generated enum and struct members and their supporting code with
#if/#endif, using the .ifcond members added in the previous patches.
We do enum and struct in a single patch because union tag enum and the
associated variants tie them together, and dealing with that to split
the patch doesn't seem worthwhile.
> ---
> scripts/qapi/common.py | 4 ++++
> scripts/qapi/introspect.py | 13 +++++++++----
> scripts/qapi/types.py | 4 ++++
> scripts/qapi/visit.py | 6 ++++++
> 4 files changed, 23 insertions(+), 4 deletions(-)
>
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index a70d6dec3b..3a29812ef2 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -2108,11 +2108,13 @@ const QEnumLookup %(c_name)s_lookup = {
> ''',
> c_name=c_name(name))
> for m in members:
> + ret += gen_if(m.ifcond)
> index = c_enum_const(name, m.name, prefix)
> ret += mcgen('''
> [%(index)s] = "%(name)s",
> ''',
> index=index, name=m.name)
> + ret += gen_endif(m.ifcond)
>
> ret += mcgen('''
> },
> @@ -2134,10 +2136,12 @@ typedef enum %(c_name)s {
> c_name=c_name(name))
>
> for m in enum_members:
> + ret += gen_if(m.ifcond)
> ret += mcgen('''
> %(c_enum)s,
> ''',
> c_enum=c_enum_const(name, m.name, prefix))
> + ret += gen_endif(m.ifcond)
>
> ret += mcgen('''
> } %(c_name)s;
> diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
> index 417625d54b..77087f629b 100644
> --- a/scripts/qapi/introspect.py
> +++ b/scripts/qapi/introspect.py
> @@ -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,14 +171,16 @@ 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, members, prefix):
> self._gen_qlit(name, 'enum',
> - {'values': [m.name for m in members]}, ifcond)
> + {'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)
> @@ -192,8 +196,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})
Long line. I'll feed the series to pycodestyle and pylint.
> + 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):
> diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
> index 0404710bbd..e2ee9f3b72 100644
> --- a/scripts/qapi/types.py
> +++ b/scripts/qapi/types.py
> @@ -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;
> diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
> index 24f85a2e85..82eab72b21 100644
> --- a/scripts/qapi/visit.py
> +++ b/scripts/qapi/visit.py
> @@ -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:
With the tweaked commit message:
Reviewed-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 13/27] qapi: add a dictionary form for TYPE
2018-12-10 17:24 ` Markus Armbruster
2018-12-11 12:11 ` Marc-André Lureau
@ 2018-12-11 15:18 ` Markus Armbruster
1 sibling, 0 replies; 69+ messages in thread
From: Markus Armbruster @ 2018-12-11 15:18 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth
New pylint gripes:
scripts/qapi/common.py:674:0: R0912: Too many branches (13/12) (too-many-branches)
scripts/qapi/common.py:764:0: R0912: Too many branches (13/12) (too-many-branches)
scripts/qapi/common.py:838:0: R0912: Too many branches (13/12) (too-many-branches)
That's check_type(), check_union(), check_alternate(). Let's ignore
these for now.
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 15/27] qapi: add an error in case a discriminator is conditional
2018-12-10 17:31 ` Markus Armbruster
@ 2018-12-11 15:23 ` Markus Armbruster
0 siblings, 0 replies; 69+ messages in thread
From: Markus Armbruster @ 2018-12-11 15:23 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth
Two more nits...
Markus Armbruster <armbru@redhat.com> writes:
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
>> Making a discriminator conditional doesn't make much sense.
>
> Good point (so easy to overlook!), but why first add the 'if' feature
> broken that way in PATCH 13, then fix it up in PATCH 15?
>
>> Instead,
>> the union could be made conditional.
>
> What do you mean by that?
>
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> ---
>> scripts/qapi/common.py | 8 ++++++++
>> tests/Makefile.include | 1 +
>> .../flat-union-invalid-if-discriminator.err | 1 +
>> .../flat-union-invalid-if-discriminator.exit | 1 +
>> .../flat-union-invalid-if-discriminator.json | 17 +++++++++++++++++
>> .../flat-union-invalid-if-discriminator.out | 0
>> 6 files changed, 28 insertions(+)
>> create mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.err
>> create mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.exit
>> create mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.json
>> create mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.out
>>
>> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
>> index aec51acb07..f79b3fad54 100644
>> --- a/scripts/qapi/common.py
>> +++ b/scripts/qapi/common.py
>> @@ -578,6 +578,7 @@ def find_alternate_member_qtype(qapi_type):
>> # Return the discriminator enum define if discriminator is specified as an
>> # enum type, otherwise return None.
>> def discriminator_find_enum_define(expr):
>> + name = expr['union']
Dead assignment.
>> base = expr.get('base')
>> discriminator = expr.get('discriminator')
>>
>> @@ -594,6 +595,7 @@ def discriminator_find_enum_define(expr):
>>
>> if isinstance(discriminator_value, dict):
>> discriminator_value = discriminator_value['type']
>> +
>> return enum_types.get(discriminator_value)
>>
>>
>
> These two hunks are leftovers, please drop.
>
>> @@ -800,7 +802,12 @@ def check_union(expr, info):
>> "struct '%s'"
>> % (discriminator, base))
>> if isinstance(discriminator_value, dict):
>> + if discriminator_value.get('if'):
>> + raise QAPISemError(info, 'The discriminator %s.%s for union %s '
pycodestyle complains
scripts/qapi/common.py:806:80: E501 line too long (80 > 79 characters)
>> + 'must not be conditional' %
>> + (base, discriminator, name))
>> discriminator_value = discriminator_value['type']
>> +
>> enum_define = enum_types.get(discriminator_value)
>> allow_metas = ['struct']
>> # Do not allow string discriminator
>> @@ -1023,6 +1030,7 @@ def check_exprs(exprs):
>>
>> if 'include' in expr:
>> continue
>> + info = expr_elem['info']
>> if 'union' in expr and not discriminator_find_enum_define(expr):
>> name = '%sKind' % expr['union']
>> elif 'alternate' in expr:
>> diff --git a/tests/Makefile.include b/tests/Makefile.include
>> index ea5d1e8787..3f5a1d0c30 100644
>> --- a/tests/Makefile.include
>> +++ b/tests/Makefile.include
>> @@ -409,6 +409,7 @@ qapi-schema += flat-union-inline-invalid-dict.json
>> qapi-schema += flat-union-int-branch.json
>> qapi-schema += flat-union-invalid-branch-key.json
>> qapi-schema += flat-union-invalid-discriminator.json
>> +qapi-schema += flat-union-invalid-if-discriminator.json
>> qapi-schema += flat-union-no-base.json
>> qapi-schema += flat-union-optional-discriminator.json
>> qapi-schema += flat-union-string-discriminator.json
>> diff --git a/tests/qapi-schema/flat-union-invalid-if-discriminator.err b/tests/qapi-schema/flat-union-invalid-if-discriminator.err
>> new file mode 100644
>> index 0000000000..0c94c9860d
>> --- /dev/null
>> +++ b/tests/qapi-schema/flat-union-invalid-if-discriminator.err
>> @@ -0,0 +1 @@
>> +tests/qapi-schema/flat-union-invalid-if-discriminator.json:13: The discriminator TestBase.enum1 for union TestUnion must not be conditional
>> diff --git a/tests/qapi-schema/flat-union-invalid-if-discriminator.exit b/tests/qapi-schema/flat-union-invalid-if-discriminator.exit
>> new file mode 100644
>> index 0000000000..d00491fd7e
>> --- /dev/null
>> +++ b/tests/qapi-schema/flat-union-invalid-if-discriminator.exit
>> @@ -0,0 +1 @@
>> +1
>> diff --git a/tests/qapi-schema/flat-union-invalid-if-discriminator.json b/tests/qapi-schema/flat-union-invalid-if-discriminator.json
>> new file mode 100644
>> index 0000000000..618ec36396
>> --- /dev/null
>> +++ b/tests/qapi-schema/flat-union-invalid-if-discriminator.json
>> @@ -0,0 +1,17 @@
>> +{ 'enum': 'TestEnum',
>> + 'data': [ 'value1', 'value2' ] }
>> +
>> +{ 'struct': 'TestBase',
>> + 'data': { 'enum1': { 'type': 'TestEnum', 'if': 'FOO' } } }
>> +
>> +{ 'struct': 'TestTypeA',
>> + 'data': { 'string': 'str' } }
>> +
>> +{ 'struct': 'TestTypeB',
>> + 'data': { 'integer': 'int' } }
>> +
>> +{ 'union': 'TestUnion',
>> + 'base': 'TestBase',
>> + 'discriminator': 'enum1',
>> + 'data': { 'value1': 'TestTypeA',
>> + 'value2': 'TestTypeB' } }
>> diff --git a/tests/qapi-schema/flat-union-invalid-if-discriminator.out b/tests/qapi-schema/flat-union-invalid-if-discriminator.out
>> new file mode 100644
>> index 0000000000..e69de29bb2
>
> Patch looks good otherwise.
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 13/27] qapi: add a dictionary form for TYPE
2018-12-11 12:11 ` Marc-André Lureau
@ 2018-12-11 15:35 ` Markus Armbruster
0 siblings, 0 replies; 69+ messages in thread
From: Markus Armbruster @ 2018-12-11 15:35 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: QEMU, Michael Roth
Marc-André Lureau <marcandre.lureau@gmail.com> writes:
> Hi
>
> On Mon, Dec 10, 2018 at 9:26 PM Markus Armbruster <armbru@redhat.com> wrote:
[...]
>> Looks good, but I'd like to investigate whether my suggested placement
>> of the normalization would simplify things before I give my R-by.
>>
>
> I am not sure I follow, you suggest to have normalization before
> check? Then how can we produce an error that reflects the input
> accurately? Should we carry additional information (original form etc)
> on the source during normalization?
Let me play with it. If my idea works out, showing it to you will be
easier than explaining it. If it doesn't, ditching it quietly will also
be easier than explaining it :)
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 01/27] qapi: make sure osdep.h is included in type headers
2018-12-10 13:28 ` Markus Armbruster
@ 2018-12-11 15:47 ` Marc-André Lureau
2018-12-12 6:47 ` Markus Armbruster
2018-12-11 16:05 ` Daniel P. Berrangé
1 sibling, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-11 15:47 UTC (permalink / raw)
To: Markus Armbruster; +Cc: QEMU, Michael Roth
Hi
On Mon, Dec 10, 2018 at 5:28 PM Markus Armbruster <armbru@redhat.com> wrote:
>
> Marc-André Lureau <marcandre.lureau@gmail.com> writes:
>
> > Hi
> >
> > On Mon, Dec 10, 2018 at 1:52 PM Markus Armbruster <armbru@redhat.com> wrote:
> >>
> >> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> >>
> >> > Now that the schema can be configured, it is crucial that all types
> >> > are configured the same. Make sure config-host.h is included, by
> >> > checking osdep.h inclusion. The build-sys tracks the dependency and
> >> > rebuilds the types if the configuration changed.
> >> >
> >> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> >> > ---
> >> > scripts/qapi/types.py | 3 +++
> >> > 1 file changed, 3 insertions(+)
> >> >
> >> > diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
> >> > index fd7808103c..3bb9cb6d47 100644
> >> > --- a/scripts/qapi/types.py
> >> > +++ b/scripts/qapi/types.py
> >> > @@ -201,6 +201,9 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
> >> > ''',
> >> > types=types, visit=visit))
> >> > self._genh.preamble_add(mcgen('''
> >> > +#ifndef QEMU_OSDEP_H
> >> > +#error Please include osdep.h first!
> >> > +#endif
> >> > #include "qapi/qapi-builtin-types.h"
> >> > '''))
> >>
> >> I understand why you propose this patch. The QAPI-generated headers use
> >> #ifdef CONFIG_FOO. The configuration header "qemu/osdep.h" must be
> >> consistently included before the generated headers, or else you end up
> >> with nasty bugs, such as the same enum having different values in
> >> different .o, or the same struct having a different layout.
> >>
> >> But this applies to *all* headers that use #ifdef. Why check it here,
> >> but not there? What makes the QAPI-generated headers special?
> >>
> >
> > It's the discussion about #if in headers (and enums in particular)
> > that started this. We want to make sure all compilation units share
> > the same data structure/ABI. I proposed to include osdep.h in qapi
> > headers, but that was rejected.
> > The warning is a different approach. I agree it could apply to all
> > headers. Do you think I should update all headers as well?
>
> That would replace the rule 'all .c files must include "qemu/osdep.h"
> first' by 'all .h files must check "qemu/osdep.h" has been included
> already', which is not an improvement.
That would be an improvement since headers may also be impacted by osdep.h
Alternatively, why not use -include ?
>
> All we have right now to help with enforcing our osdep.h rule is
> scripts/clean-includes. We run it periodically to fix rule breakers.
> It's manual, because we have a few .c files in the tree where the rule
> doesn't apply, and the script doesn't know about them. Fixable, I
> guess. Most recent run:
>
> Subject: [PATCH] Clean up includes
> Message-Id: <20181204172535.2799-1-armbru@redhat.com>
> https://lists.nongnu.org/archive/html/qemu-devel/2018-12/msg00605.html
>
> The obvious improvement would be flagging rule breakers before they get
> committed.
>
> checkpatch.pl could flag patches adding .c files that don't include
> "qemu/osdep.h" first. The "first" part might be a bit annoying to code.
> The "adding files" part already exists: checkpatch.pl warns when you add
> a file without updating MAINTAINERS.
>
> checkpatch.pl could also flag patches removing #include "qemu/osdep.h".
>
> Other projects use a syntax-check make target to check sources. If we
> decide we like that better than checkpatch.pl for some checks, we can do
> that.
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 22/27] qapi: add 'If:' condition to enum values documentation
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 22/27] qapi: add 'If:' condition to enum values documentation Marc-André Lureau
@ 2018-12-11 16:00 ` Markus Armbruster
2018-12-11 16:07 ` Marc-André Lureau
0 siblings, 1 reply; 69+ messages in thread
From: Markus Armbruster @ 2018-12-11 16:00 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Use a common function to generate the "If:..." line.
>
> While at it, get rid of the existing \n\n (no idea why it was
> there). Use a line-break in member description, this seems to look
> slightly better in the plaintext version.
Where exactly in the patch is this done?
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> scripts/qapi/doc.py | 24 +++++++++++++++---------
> tests/qapi-schema/doc-good.json | 4 +++-
> tests/qapi-schema/doc-good.out | 1 +
> tests/qapi-schema/doc-good.texi | 2 +-
> 4 files changed, 20 insertions(+), 11 deletions(-)
>
> diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
> index 76cb186ff9..2133ded47e 100755
> --- a/scripts/qapi/doc.py
> +++ b/scripts/qapi/doc.py
> @@ -126,19 +126,26 @@ 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"""
> + return '%s@b{If:} @code{%s}%s' % (
> + prefix, ', '.join(ifcond), suffix) if ifcond else ''
I like the ternary operator, but I nevertheless think this function is
easier to read as
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='@*'))
Do you ignore suffix intentionally?
>
>
> -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' % (
> member.name, membertype,
> ' (optional)' if member.optional else '',
> - suffix)
> + suffix, desc)
>
>
> def texi_members(doc, what, base, variants, member_func):
> @@ -155,7 +162,7 @@ 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)
Here, you pass a @desc argument, but no @suffix.
@member_func is either texi_enum_value() or texi_member(). Works.
> if base:
> items += '@item The members of @code{%s}\n' % base.doc_type()
> if variants:
> @@ -165,7 +172,7 @@ def texi_members(doc, what, base, variants, member_func):
> 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, suffix=when)
Here, you pass a @suffix argument, but no @desc.
texi_enum_value() would choke on that, but it can't occur here, because
enums have no variants.
Still, I'd prefer texi_enum_value() and texi_member() to have the exact
same signature.
> else:
> items += '@item The members of @code{%s}%s\n' % (
> v.type.doc_type(), when)
> @@ -185,8 +192,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
>
>
> diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json
> index 984cd8ed06..c7fe08c530 100644
> --- a/tests/qapi-schema/doc-good.json
> +++ b/tests/qapi-schema/doc-good.json
> @@ -55,7 +55,9 @@
> #
> # @two is undocumented
> ##
> -{ 'enum': 'Enum', 'data': [ 'one', 'two' ], 'if': 'defined(IFCOND)' }
> +{ 'enum': 'Enum', 'data':
> + [ { 'name': 'one', 'if': 'defined(IFENUM)' }, 'two' ],
> + 'if': 'defined(IFCOND)' }
IFCOND applies to the enum, and IFENUM applies to one of its values.
Awkward. Let's rename IFENUM to IFONE.
>
> ##
> # @Base:
> diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
> index c2fc5c774a..a05535b69b 100644
> --- a/tests/qapi-schema/doc-good.out
> +++ b/tests/qapi-schema/doc-good.out
> @@ -11,6 +11,7 @@ enum QType
> module doc-good.json
> enum Enum
> member one
> + if ['defined(IFENUM)']
> member two
> if ['defined(IFCOND)']
> object Base
> diff --git a/tests/qapi-schema/doc-good.texi b/tests/qapi-schema/doc-good.texi
> index e42eace474..5c0231e0e6 100644
> --- a/tests/qapi-schema/doc-good.texi
> +++ b/tests/qapi-schema/doc-good.texi
> @@ -84,12 +84,12 @@ Examples:
> @table @asis
> @item @code{one}
> The @emph{one} @{and only@}
> +@*@b{If:} @code{defined(IFENUM)}
@* forces a line break. Putting it at the end of the previous line
would be tidier, but let's ignore that for now.
> @item @code{two}
> Not documented
> @end table
> @code{two} is undocumented
>
> -
> @b{If:} @code{defined(IFCOND)}
> @end deftp
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 01/27] qapi: make sure osdep.h is included in type headers
2018-12-10 13:28 ` Markus Armbruster
2018-12-11 15:47 ` Marc-André Lureau
@ 2018-12-11 16:05 ` Daniel P. Berrangé
2018-12-12 6:48 ` Markus Armbruster
1 sibling, 1 reply; 69+ messages in thread
From: Daniel P. Berrangé @ 2018-12-11 16:05 UTC (permalink / raw)
To: Markus Armbruster; +Cc: Marc-André Lureau, QEMU, Michael Roth
On Mon, Dec 10, 2018 at 02:28:26PM +0100, Markus Armbruster wrote:
> Marc-André Lureau <marcandre.lureau@gmail.com> writes:
>
> > Hi
> >
> > On Mon, Dec 10, 2018 at 1:52 PM Markus Armbruster <armbru@redhat.com> wrote:
> >>
> >> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> >>
> >> > Now that the schema can be configured, it is crucial that all types
> >> > are configured the same. Make sure config-host.h is included, by
> >> > checking osdep.h inclusion. The build-sys tracks the dependency and
> >> > rebuilds the types if the configuration changed.
> >> >
> >> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> >> > ---
> >> > scripts/qapi/types.py | 3 +++
> >> > 1 file changed, 3 insertions(+)
> >> >
> >> > diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
> >> > index fd7808103c..3bb9cb6d47 100644
> >> > --- a/scripts/qapi/types.py
> >> > +++ b/scripts/qapi/types.py
> >> > @@ -201,6 +201,9 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
> >> > ''',
> >> > types=types, visit=visit))
> >> > self._genh.preamble_add(mcgen('''
> >> > +#ifndef QEMU_OSDEP_H
> >> > +#error Please include osdep.h first!
> >> > +#endif
> >> > #include "qapi/qapi-builtin-types.h"
> >> > '''))
> >>
> >> I understand why you propose this patch. The QAPI-generated headers use
> >> #ifdef CONFIG_FOO. The configuration header "qemu/osdep.h" must be
> >> consistently included before the generated headers, or else you end up
> >> with nasty bugs, such as the same enum having different values in
> >> different .o, or the same struct having a different layout.
> >>
> >> But this applies to *all* headers that use #ifdef. Why check it here,
> >> but not there? What makes the QAPI-generated headers special?
> >>
> >
> > It's the discussion about #if in headers (and enums in particular)
> > that started this. We want to make sure all compilation units share
> > the same data structure/ABI. I proposed to include osdep.h in qapi
> > headers, but that was rejected.
> > The warning is a different approach. I agree it could apply to all
> > headers. Do you think I should update all headers as well?
>
> That would replace the rule 'all .c files must include "qemu/osdep.h"
> first' by 'all .h files must check "qemu/osdep.h" has been included
> already', which is not an improvement.
>
> All we have right now to help with enforcing our osdep.h rule is
> scripts/clean-includes. We run it periodically to fix rule breakers.
> It's manual, because we have a few .c files in the tree where the rule
> doesn't apply, and the script doesn't know about them. Fixable, I
> guess. Most recent run:
>
> Subject: [PATCH] Clean up includes
> Message-Id: <20181204172535.2799-1-armbru@redhat.com>
> https://lists.nongnu.org/archive/html/qemu-devel/2018-12/msg00605.html
>
> The obvious improvement would be flagging rule breakers before they get
> committed.
>
> checkpatch.pl could flag patches adding .c files that don't include
> "qemu/osdep.h" first. The "first" part might be a bit annoying to code.
You can get this logic from GNULIBs syntax-check make rules. It uses
this perl code to check that config.h is included first:
while (<>) {
if (/^# *include\b/) {
if (not m{^# *include <config\.h>}) {
print "$ARGV\n";
$$ret = 1;
}
close ARGV;
}
}
Regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 25/27] qapi: break long lines at 'data' member
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 25/27] qapi: break long lines at 'data' member Marc-André Lureau
@ 2018-12-11 16:07 ` Markus Armbruster
2018-12-11 16:08 ` Marc-André Lureau
0 siblings, 1 reply; 69+ messages in thread
From: Markus Armbruster @ 2018-12-11 16:07 UTC (permalink / raw)
To: Marc-André Lureau
Cc: qemu-devel, Juan Quintela, Jason Wang, Dr. David Alan Gilbert,
Gerd Hoffmann, Paolo Bonzini, Stefan Berger
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Let's break the line before 'data'. While at it, improve a bit
> indentation/spacing. (I removed some alignment which are not helping
> much readability and become quickly inconsistent)
>
> Suggested-by: Markus Armbruster <armbru@redhat.com>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
I can cherry-pick this one into my next pull request to reduce the
likelihood of conflicts.
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 22/27] qapi: add 'If:' condition to enum values documentation
2018-12-11 16:00 ` Markus Armbruster
@ 2018-12-11 16:07 ` Marc-André Lureau
2018-12-13 13:59 ` Markus Armbruster
0 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-11 16:07 UTC (permalink / raw)
To: Armbruster, Markus; +Cc: qemu-devel, Michael Roth
Hi
On Tue, Dec 11, 2018 at 8:00 PM Markus Armbruster <armbru@redhat.com> wrote:
>
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
> > Use a common function to generate the "If:..." line.
> >
> > While at it, get rid of the existing \n\n (no idea why it was
> > there). Use a line-break in member description, this seems to look
> > slightly better in the plaintext version.
>
> Where exactly in the patch is this done?
- if ifcond:
- body += '\n\n@b{If:} @code{%s}' % ", ".join(ifcond)
+ body += texi_if(ifcond, suffix='')
See also doc-good.texi output
>
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> > scripts/qapi/doc.py | 24 +++++++++++++++---------
> > tests/qapi-schema/doc-good.json | 4 +++-
> > tests/qapi-schema/doc-good.out | 1 +
> > tests/qapi-schema/doc-good.texi | 2 +-
> > 4 files changed, 20 insertions(+), 11 deletions(-)
> >
> > diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
> > index 76cb186ff9..2133ded47e 100755
> > --- a/scripts/qapi/doc.py
> > +++ b/scripts/qapi/doc.py
> > @@ -126,19 +126,26 @@ 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"""
> > + return '%s@b{If:} @code{%s}%s' % (
> > + prefix, ', '.join(ifcond), suffix) if ifcond else ''
>
> I like the ternary operator, but I nevertheless think this function is
> easier to read as
>
> if not ifcond:
> return ''
> return '%s@b{If:} @code{%s}%s' % (prefix, ', '.join(ifcond), suffix)
>
No difference to me, sure
> > +
> > +
> > +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='@*'))
>
> Do you ignore suffix intentionally?
yes
>
> >
> >
> > -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' % (
> > member.name, membertype,
> > ' (optional)' if member.optional else '',
> > - suffix)
> > + suffix, desc)
> >
> >
> > def texi_members(doc, what, base, variants, member_func):
> > @@ -155,7 +162,7 @@ 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)
>
> Here, you pass a @desc argument, but no @suffix.
>
> @member_func is either texi_enum_value() or texi_member(). Works.
>
> > if base:
> > items += '@item The members of @code{%s}\n' % base.doc_type()
> > if variants:
> > @@ -165,7 +172,7 @@ def texi_members(doc, what, base, variants, member_func):
> > 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, suffix=when)
>
> Here, you pass a @suffix argument, but no @desc.
>
> texi_enum_value() would choke on that, but it can't occur here, because
> enums have no variants.
>
> Still, I'd prefer texi_enum_value() and texi_member() to have the exact
> same signature.
OK (not sure what is the more pythonic way)
>
> > else:
> > items += '@item The members of @code{%s}%s\n' % (
> > v.type.doc_type(), when)
> > @@ -185,8 +192,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
> >
> >
> > diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json
> > index 984cd8ed06..c7fe08c530 100644
> > --- a/tests/qapi-schema/doc-good.json
> > +++ b/tests/qapi-schema/doc-good.json
> > @@ -55,7 +55,9 @@
> > #
> > # @two is undocumented
> > ##
> > -{ 'enum': 'Enum', 'data': [ 'one', 'two' ], 'if': 'defined(IFCOND)' }
> > +{ 'enum': 'Enum', 'data':
> > + [ { 'name': 'one', 'if': 'defined(IFENUM)' }, 'two' ],
> > + 'if': 'defined(IFCOND)' }
>
> IFCOND applies to the enum, and IFENUM applies to one of its values.
> Awkward. Let's rename IFENUM to IFONE.
ok
>
> >
> > ##
> > # @Base:
> > diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
> > index c2fc5c774a..a05535b69b 100644
> > --- a/tests/qapi-schema/doc-good.out
> > +++ b/tests/qapi-schema/doc-good.out
> > @@ -11,6 +11,7 @@ enum QType
> > module doc-good.json
> > enum Enum
> > member one
> > + if ['defined(IFENUM)']
> > member two
> > if ['defined(IFCOND)']
> > object Base
> > diff --git a/tests/qapi-schema/doc-good.texi b/tests/qapi-schema/doc-good.texi
> > index e42eace474..5c0231e0e6 100644
> > --- a/tests/qapi-schema/doc-good.texi
> > +++ b/tests/qapi-schema/doc-good.texi
> > @@ -84,12 +84,12 @@ Examples:
> > @table @asis
> > @item @code{one}
> > The @emph{one} @{and only@}
> > +@*@b{If:} @code{defined(IFENUM)}
>
> @* forces a line break. Putting it at the end of the previous line
> would be tidier, but let's ignore that for now.
For consistency and easier reading, I think it's better to keep it as
a seperate line in the end for the corresponding section
>
> > @item @code{two}
> > Not documented
> > @end table
> > @code{two} is undocumented
> >
> > -
> > @b{If:} @code{defined(IFCOND)}
> > @end deftp
thanks
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 25/27] qapi: break long lines at 'data' member
2018-12-11 16:07 ` Markus Armbruster
@ 2018-12-11 16:08 ` Marc-André Lureau
0 siblings, 0 replies; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-11 16:08 UTC (permalink / raw)
To: Armbruster, Markus
Cc: qemu-devel, Juan Quintela, Jason Wang, Dr. David Alan Gilbert,
Hoffmann, Gerd, Bonzini, Paolo, stefanb
Hi
On Tue, Dec 11, 2018 at 8:07 PM Markus Armbruster <armbru@redhat.com> wrote:
>
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
> > Let's break the line before 'data'. While at it, improve a bit
> > indentation/spacing. (I removed some alignment which are not helping
> > much readability and become quickly inconsistent)
> >
> > Suggested-by: Markus Armbruster <armbru@redhat.com>
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
>
> I can cherry-pick this one into my next pull request to reduce the
> likelihood of conflicts.
Ideally, you take as much patches as you can in your -next tree, so I
don't have to carry them and resend them all the time. Up to you, you
are the maintainer.
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 26/27] qapi: add more conditions to SPICE
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 26/27] qapi: add more conditions to SPICE Marc-André Lureau
@ 2018-12-11 17:11 ` Markus Armbruster
0 siblings, 0 replies; 69+ messages in thread
From: Markus Armbruster @ 2018-12-11 17:11 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, Paolo Bonzini
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Now that member can be made conditional, let's make SPICE chardev
> conditional:
>
> * spiceport, spicevmc
>
> Before and after the patch for !CONFIG_SPICE, the error is the
> same ('spiceport' is not a valid char driver name).
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> qapi/char.json | 16 ++++++++--------
> 1 file changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/qapi/char.json b/qapi/char.json
> index 24628331ec..77ed847972 100644
> --- a/qapi/char.json
> +++ b/qapi/char.json
> @@ -332,8 +332,8 @@
> ##
> { 'struct': 'ChardevSpiceChannel',
> 'data': { 'type': 'str' },
> - 'base': 'ChardevCommon' }
> -# TODO: 'if': 'defined(CONFIG_SPICE)'
> + 'base': 'ChardevCommon',
> + 'if': 'defined(CONFIG_SPICE)' }
>
> ##
> # @ChardevSpicePort:
> @@ -346,8 +346,8 @@
> ##
> { 'struct': 'ChardevSpicePort',
> 'data': { 'fqdn': 'str' },
> - 'base': 'ChardevCommon' }
> -# TODO: 'if': 'defined(CONFIG_SPICE)'
> + 'base': 'ChardevCommon',
> + 'if': 'defined(CONFIG_SPICE)' }
>
> ##
> # @ChardevVC:
> @@ -404,10 +404,10 @@
> 'testdev': 'ChardevCommon',
> 'stdio': 'ChardevStdio',
> 'console': 'ChardevCommon',
> - 'spicevmc': 'ChardevSpiceChannel',
> -# TODO: { 'type': 'ChardevSpiceChannel', 'if': 'defined(CONFIG_SPICE)' },
> - 'spiceport': 'ChardevSpicePort',
> -# TODO: { 'type': 'ChardevSpicePort', 'if': 'defined(CONFIG_SPICE)' },
> + 'spicevmc': { 'type': 'ChardevSpiceChannel',
> + 'if': 'defined(CONFIG_SPICE)' },
> + 'spiceport': { 'type': 'ChardevSpicePort',
> + 'if': 'defined(CONFIG_SPICE)' },
> 'vc': 'ChardevVC',
> 'ringbuf': 'ChardevRingbuf',
> # next one is just for compatibility
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Reviewing this patch's effect on generated files led me to a few things.
None of them need to be addressed to get this series accepted. I
actually recommend not to address them in this series, because that
could lead to further delays.
There's an opportunity for minor output beautification: back-to-back
#endif / #if like
#endif /* defined(CONFIG_SPICE) */
#if defined(CONFIG_SPICE)
in generated C could be omitted.
The generated documentation shows conditionals as
If: 'defined(CONFIG_SPICE)'
We should at least explain this notation in the introduction. Other
notation, too. Predates this series.
Should we *strip* documentation for disabled stuff instead?
Complication: disabled everywhere, or just for a target? We build the
documentation only once, and that's a feature. We can therefore only
strip documentation for stuff that's disabled target-independently.
That's a bit more involved.
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 27/27] qapi: add conditions to REPLICATION type/commands on the schema
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 27/27] qapi: add conditions to REPLICATION type/commands on the schema Marc-André Lureau
@ 2018-12-11 17:15 ` Markus Armbruster
2018-12-11 17:17 ` Marc-André Lureau
0 siblings, 1 reply; 69+ messages in thread
From: Markus Armbruster @ 2018-12-11 17:15 UTC (permalink / raw)
To: Marc-André Lureau
Cc: qemu-devel, zhanghailiang, Juan Quintela, Dr. David Alan Gilbert
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Add #if defined(CONFIG_REPLICATION) in generated code, and adjust the
> code accordingly.
>
> Made conditional:
>
> * xen-set-replication, query-xen-replication-status,
> xen-colo-do-checkpoint
>
> Before the patch, we first register the commands unconditionally in
> generated code (requires a stub), then conditionally unregister in
> qmp_unregister_commands_hack().
>
> Afterwards, we register only when CONFIG_REPLICATION. The command
> fails exactly the same, with CommandNotFound.
>
> Improvement, because now query-qmp-schema is accurate, and we're one
> step closer to killing qmp_unregister_commands_hack().
>
> * enum BlockdevDriver value "replication" in command blockdev-add
>
> * BlockdevOptions variant @replication
>
> and related structures.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
> ---
> qapi/block-core.json | 13 +++++++++----
> qapi/migration.json | 12 ++++++++----
> migration/colo.c | 16 ++++------------
> monitor.c | 5 -----
> 4 files changed, 21 insertions(+), 25 deletions(-)
>
> diff --git a/qapi/block-core.json b/qapi/block-core.json
> index 92e0205d91..762000f31f 100644
> --- a/qapi/block-core.json
> +++ b/qapi/block-core.json
> @@ -2623,7 +2623,9 @@
> 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps', 'gluster',
> 'host_cdrom', 'host_device', 'http', 'https', 'iscsi', 'luks',
> 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels', 'qcow',
> - 'qcow2', 'qed', 'quorum', 'raw', 'rbd', 'replication', 'sheepdog',
> + 'qcow2', 'qed', 'quorum', 'raw', 'rbd',
> + { 'name': 'replication', 'if': 'defined(CONFIG_REPLICATION)' },
> + 'sheepdog',
> 'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
>
> ##
> @@ -3380,7 +3382,8 @@
> #
> # Since: 2.9
> ##
> -{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }
> +{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ],
> + 'if': 'defined(CONFIG_REPLICATION)' }
>
> ##
> # @BlockdevOptionsReplication:
> @@ -3398,7 +3401,8 @@
> { 'struct': 'BlockdevOptionsReplication',
> 'base': 'BlockdevOptionsGenericFormat',
> 'data': { 'mode': 'ReplicationMode',
> - '*top-id': 'str' } }
> + '*top-id': 'str' },
> + 'if': 'defined(CONFIG_REPLICATION)' }
>
> ##
> # @NFSTransport:
> @@ -3714,7 +3718,8 @@
> 'quorum': 'BlockdevOptionsQuorum',
> 'raw': 'BlockdevOptionsRaw',
> 'rbd': 'BlockdevOptionsRbd',
> - 'replication':'BlockdevOptionsReplication',
> + 'replication': { 'type': 'BlockdevOptionsReplication',
> + 'if': 'defined(CONFIG_REPLICATION)' },
> 'sheepdog': 'BlockdevOptionsSheepdog',
> 'ssh': 'BlockdevOptionsSsh',
> 'throttle': 'BlockdevOptionsThrottle',
> diff --git a/qapi/migration.json b/qapi/migration.json
> index 5fd33316a0..31b589ec26 100644
> --- a/qapi/migration.json
> +++ b/qapi/migration.json
> @@ -1257,7 +1257,8 @@
> # Since: 2.9
> ##
> { 'command': 'xen-set-replication',
> - 'data': { 'enable': 'bool', 'primary': 'bool', '*failover' : 'bool' } }
> + 'data': { 'enable': 'bool', 'primary': 'bool', '*failover' : 'bool' },
> + 'if': 'defined(CONFIG_REPLICATION)' }
>
> ##
> # @ReplicationStatus:
> @@ -1272,7 +1273,8 @@
> # Since: 2.9
> ##
> { 'struct': 'ReplicationStatus',
> - 'data': { 'error': 'bool', '*desc': 'str' } }
> + 'data': { 'error': 'bool', '*desc': 'str' },
> + 'if': 'defined(CONFIG_REPLICATION)' }
>
> ##
> # @query-xen-replication-status:
> @@ -1289,7 +1291,8 @@
> # Since: 2.9
> ##
> { 'command': 'query-xen-replication-status',
> - 'returns': 'ReplicationStatus' }
> + 'returns': 'ReplicationStatus',
> + 'if': 'defined(CONFIG_REPLICATION)' }
>
> ##
> # @xen-colo-do-checkpoint:
> @@ -1305,7 +1308,8 @@
> #
> # Since: 2.9
> ##
> -{ 'command': 'xen-colo-do-checkpoint' }
> +{ 'command': 'xen-colo-do-checkpoint',
> + 'if': 'defined(CONFIG_REPLICATION)' }
>
> ##
> # @COLOStatus:
> diff --git a/migration/colo.c b/migration/colo.c
> index fcff04c78c..398b239d1c 100644
> --- a/migration/colo.c
> +++ b/migration/colo.c
> @@ -24,7 +24,9 @@
> #include "trace.h"
> #include "qemu/error-report.h"
> #include "migration/failover.h"
> +#ifdef CONFIG_REPLICATION
> #include "replication.h"
> +#endif
> #include "net/colo-compare.h"
> #include "net/colo.h"
> #include "block/block.h"
> @@ -201,11 +203,11 @@ void colo_do_failover(MigrationState *s)
> }
> }
>
> +#ifdef CONFIG_REPLICATION
> void qmp_xen_set_replication(bool enable, bool primary,
> bool has_failover, bool failover,
> Error **errp)
> {
> -#ifdef CONFIG_REPLICATION
> ReplicationMode mode = primary ?
> REPLICATION_MODE_PRIMARY :
> REPLICATION_MODE_SECONDARY;
> @@ -224,14 +226,10 @@ void qmp_xen_set_replication(bool enable, bool primary,
> }
> replication_stop_all(failover, failover ? NULL : errp);
> }
> -#else
> - abort();
> -#endif
> }
>
> ReplicationStatus *qmp_query_xen_replication_status(Error **errp)
> {
> -#ifdef CONFIG_REPLICATION
> Error *err = NULL;
> ReplicationStatus *s = g_new0(ReplicationStatus, 1);
>
> @@ -246,19 +244,13 @@ ReplicationStatus *qmp_query_xen_replication_status(Error **errp)
>
> error_free(err);
> return s;
> -#else
> - abort();
> -#endif
> }
>
> void qmp_xen_colo_do_checkpoint(Error **errp)
> {
> -#ifdef CONFIG_REPLICATION
> replication_do_checkpoint_all(errp);
> -#else
> - abort();
> -#endif
> }
> +#endif
/* CONFIG_REPLICATION */ after the endif wouldn't hurt.
>
> COLOStatus *qmp_query_colo_status(Error **errp)
> {
> diff --git a/monitor.c b/monitor.c
> index d39390c2f2..16a180dd50 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -1146,11 +1146,6 @@ static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
> */
> static void qmp_unregister_commands_hack(void)
> {
> -#ifndef CONFIG_REPLICATION
> - qmp_unregister_command(&qmp_commands, "xen-set-replication");
> - qmp_unregister_command(&qmp_commands, "query-xen-replication-status");
> - qmp_unregister_command(&qmp_commands, "xen-colo-do-checkpoint");
> -#endif
> #ifndef TARGET_I386
> qmp_unregister_command(&qmp_commands, "rtc-reset-reinjection");
> qmp_unregister_command(&qmp_commands, "query-sev");
Only TARGET conditionals left here. Good.
Reviewed-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 27/27] qapi: add conditions to REPLICATION type/commands on the schema
2018-12-11 17:15 ` Markus Armbruster
@ 2018-12-11 17:17 ` Marc-André Lureau
0 siblings, 0 replies; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-11 17:17 UTC (permalink / raw)
To: Armbruster, Markus
Cc: qemu-devel, zhanghailiang, Juan Quintela, Dr. David Alan Gilbert
Hi
On Tue, Dec 11, 2018 at 9:15 PM Markus Armbruster <armbru@redhat.com> wrote:
>
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
> > Add #if defined(CONFIG_REPLICATION) in generated code, and adjust the
> > code accordingly.
> >
> > Made conditional:
> >
> > * xen-set-replication, query-xen-replication-status,
> > xen-colo-do-checkpoint
> >
> > Before the patch, we first register the commands unconditionally in
> > generated code (requires a stub), then conditionally unregister in
> > qmp_unregister_commands_hack().
> >
> > Afterwards, we register only when CONFIG_REPLICATION. The command
> > fails exactly the same, with CommandNotFound.
> >
> > Improvement, because now query-qmp-schema is accurate, and we're one
> > step closer to killing qmp_unregister_commands_hack().
> >
> > * enum BlockdevDriver value "replication" in command blockdev-add
> >
> > * BlockdevOptions variant @replication
> >
> > and related structures.
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > Reviewed-by: Markus Armbruster <armbru@redhat.com>
> > ---
> > qapi/block-core.json | 13 +++++++++----
> > qapi/migration.json | 12 ++++++++----
> > migration/colo.c | 16 ++++------------
> > monitor.c | 5 -----
> > 4 files changed, 21 insertions(+), 25 deletions(-)
> >
> > diff --git a/qapi/block-core.json b/qapi/block-core.json
> > index 92e0205d91..762000f31f 100644
> > --- a/qapi/block-core.json
> > +++ b/qapi/block-core.json
> > @@ -2623,7 +2623,9 @@
> > 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps', 'gluster',
> > 'host_cdrom', 'host_device', 'http', 'https', 'iscsi', 'luks',
> > 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels', 'qcow',
> > - 'qcow2', 'qed', 'quorum', 'raw', 'rbd', 'replication', 'sheepdog',
> > + 'qcow2', 'qed', 'quorum', 'raw', 'rbd',
> > + { 'name': 'replication', 'if': 'defined(CONFIG_REPLICATION)' },
> > + 'sheepdog',
> > 'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
> >
> > ##
> > @@ -3380,7 +3382,8 @@
> > #
> > # Since: 2.9
> > ##
> > -{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }
> > +{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ],
> > + 'if': 'defined(CONFIG_REPLICATION)' }
> >
> > ##
> > # @BlockdevOptionsReplication:
> > @@ -3398,7 +3401,8 @@
> > { 'struct': 'BlockdevOptionsReplication',
> > 'base': 'BlockdevOptionsGenericFormat',
> > 'data': { 'mode': 'ReplicationMode',
> > - '*top-id': 'str' } }
> > + '*top-id': 'str' },
> > + 'if': 'defined(CONFIG_REPLICATION)' }
> >
> > ##
> > # @NFSTransport:
> > @@ -3714,7 +3718,8 @@
> > 'quorum': 'BlockdevOptionsQuorum',
> > 'raw': 'BlockdevOptionsRaw',
> > 'rbd': 'BlockdevOptionsRbd',
> > - 'replication':'BlockdevOptionsReplication',
> > + 'replication': { 'type': 'BlockdevOptionsReplication',
> > + 'if': 'defined(CONFIG_REPLICATION)' },
> > 'sheepdog': 'BlockdevOptionsSheepdog',
> > 'ssh': 'BlockdevOptionsSsh',
> > 'throttle': 'BlockdevOptionsThrottle',
> > diff --git a/qapi/migration.json b/qapi/migration.json
> > index 5fd33316a0..31b589ec26 100644
> > --- a/qapi/migration.json
> > +++ b/qapi/migration.json
> > @@ -1257,7 +1257,8 @@
> > # Since: 2.9
> > ##
> > { 'command': 'xen-set-replication',
> > - 'data': { 'enable': 'bool', 'primary': 'bool', '*failover' : 'bool' } }
> > + 'data': { 'enable': 'bool', 'primary': 'bool', '*failover' : 'bool' },
> > + 'if': 'defined(CONFIG_REPLICATION)' }
> >
> > ##
> > # @ReplicationStatus:
> > @@ -1272,7 +1273,8 @@
> > # Since: 2.9
> > ##
> > { 'struct': 'ReplicationStatus',
> > - 'data': { 'error': 'bool', '*desc': 'str' } }
> > + 'data': { 'error': 'bool', '*desc': 'str' },
> > + 'if': 'defined(CONFIG_REPLICATION)' }
> >
> > ##
> > # @query-xen-replication-status:
> > @@ -1289,7 +1291,8 @@
> > # Since: 2.9
> > ##
> > { 'command': 'query-xen-replication-status',
> > - 'returns': 'ReplicationStatus' }
> > + 'returns': 'ReplicationStatus',
> > + 'if': 'defined(CONFIG_REPLICATION)' }
> >
> > ##
> > # @xen-colo-do-checkpoint:
> > @@ -1305,7 +1308,8 @@
> > #
> > # Since: 2.9
> > ##
> > -{ 'command': 'xen-colo-do-checkpoint' }
> > +{ 'command': 'xen-colo-do-checkpoint',
> > + 'if': 'defined(CONFIG_REPLICATION)' }
> >
> > ##
> > # @COLOStatus:
> > diff --git a/migration/colo.c b/migration/colo.c
> > index fcff04c78c..398b239d1c 100644
> > --- a/migration/colo.c
> > +++ b/migration/colo.c
> > @@ -24,7 +24,9 @@
> > #include "trace.h"
> > #include "qemu/error-report.h"
> > #include "migration/failover.h"
> > +#ifdef CONFIG_REPLICATION
> > #include "replication.h"
> > +#endif
> > #include "net/colo-compare.h"
> > #include "net/colo.h"
> > #include "block/block.h"
> > @@ -201,11 +203,11 @@ void colo_do_failover(MigrationState *s)
> > }
> > }
> >
> > +#ifdef CONFIG_REPLICATION
> > void qmp_xen_set_replication(bool enable, bool primary,
> > bool has_failover, bool failover,
> > Error **errp)
> > {
> > -#ifdef CONFIG_REPLICATION
> > ReplicationMode mode = primary ?
> > REPLICATION_MODE_PRIMARY :
> > REPLICATION_MODE_SECONDARY;
> > @@ -224,14 +226,10 @@ void qmp_xen_set_replication(bool enable, bool primary,
> > }
> > replication_stop_all(failover, failover ? NULL : errp);
> > }
> > -#else
> > - abort();
> > -#endif
> > }
> >
> > ReplicationStatus *qmp_query_xen_replication_status(Error **errp)
> > {
> > -#ifdef CONFIG_REPLICATION
> > Error *err = NULL;
> > ReplicationStatus *s = g_new0(ReplicationStatus, 1);
> >
> > @@ -246,19 +244,13 @@ ReplicationStatus *qmp_query_xen_replication_status(Error **errp)
> >
> > error_free(err);
> > return s;
> > -#else
> > - abort();
> > -#endif
> > }
> >
> > void qmp_xen_colo_do_checkpoint(Error **errp)
> > {
> > -#ifdef CONFIG_REPLICATION
> > replication_do_checkpoint_all(errp);
> > -#else
> > - abort();
> > -#endif
> > }
> > +#endif
>
> /* CONFIG_REPLICATION */ after the endif wouldn't hurt.
>
> >
> > COLOStatus *qmp_query_colo_status(Error **errp)
> > {
> > diff --git a/monitor.c b/monitor.c
> > index d39390c2f2..16a180dd50 100644
> > --- a/monitor.c
> > +++ b/monitor.c
> > @@ -1146,11 +1146,6 @@ static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
> > */
> > static void qmp_unregister_commands_hack(void)
> > {
> > -#ifndef CONFIG_REPLICATION
> > - qmp_unregister_command(&qmp_commands, "xen-set-replication");
> > - qmp_unregister_command(&qmp_commands, "query-xen-replication-status");
> > - qmp_unregister_command(&qmp_commands, "xen-colo-do-checkpoint");
> > -#endif
> > #ifndef TARGET_I386
> > qmp_unregister_command(&qmp_commands, "rtc-reset-reinjection");
> > qmp_unregister_command(&qmp_commands, "query-sev");
>
> Only TARGET conditionals left here. Good.
IIRC, they are removed in part 3.
>
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 01/27] qapi: make sure osdep.h is included in type headers
2018-12-11 15:47 ` Marc-André Lureau
@ 2018-12-12 6:47 ` Markus Armbruster
0 siblings, 0 replies; 69+ messages in thread
From: Markus Armbruster @ 2018-12-12 6:47 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: QEMU, Michael Roth
Marc-André Lureau <marcandre.lureau@gmail.com> writes:
> Hi
>
> On Mon, Dec 10, 2018 at 5:28 PM Markus Armbruster <armbru@redhat.com> wrote:
>>
>> Marc-André Lureau <marcandre.lureau@gmail.com> writes:
>>
>> > Hi
>> >
>> > On Mon, Dec 10, 2018 at 1:52 PM Markus Armbruster <armbru@redhat.com> wrote:
>> >>
>> >> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>> >>
>> >> > Now that the schema can be configured, it is crucial that all types
>> >> > are configured the same. Make sure config-host.h is included, by
>> >> > checking osdep.h inclusion. The build-sys tracks the dependency and
>> >> > rebuilds the types if the configuration changed.
>> >> >
>> >> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> >> > ---
>> >> > scripts/qapi/types.py | 3 +++
>> >> > 1 file changed, 3 insertions(+)
>> >> >
>> >> > diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
>> >> > index fd7808103c..3bb9cb6d47 100644
>> >> > --- a/scripts/qapi/types.py
>> >> > +++ b/scripts/qapi/types.py
>> >> > @@ -201,6 +201,9 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
>> >> > ''',
>> >> > types=types, visit=visit))
>> >> > self._genh.preamble_add(mcgen('''
>> >> > +#ifndef QEMU_OSDEP_H
>> >> > +#error Please include osdep.h first!
>> >> > +#endif
>> >> > #include "qapi/qapi-builtin-types.h"
>> >> > '''))
>> >>
>> >> I understand why you propose this patch. The QAPI-generated headers use
>> >> #ifdef CONFIG_FOO. The configuration header "qemu/osdep.h" must be
>> >> consistently included before the generated headers, or else you end up
>> >> with nasty bugs, such as the same enum having different values in
>> >> different .o, or the same struct having a different layout.
>> >>
>> >> But this applies to *all* headers that use #ifdef. Why check it here,
>> >> but not there? What makes the QAPI-generated headers special?
>> >>
>> >
>> > It's the discussion about #if in headers (and enums in particular)
>> > that started this. We want to make sure all compilation units share
>> > the same data structure/ABI. I proposed to include osdep.h in qapi
>> > headers, but that was rejected.
>> > The warning is a different approach. I agree it could apply to all
>> > headers. Do you think I should update all headers as well?
>>
>> That would replace the rule 'all .c files must include "qemu/osdep.h"
>> first' by 'all .h files must check "qemu/osdep.h" has been included
>> already', which is not an improvement.
>
> That would be an improvement since headers may also be impacted by osdep.h
>
> Alternatively, why not use -include ?
Requiring .c to include the configuration header first follows
established Autoconf practice. The "first" part covers all headers.
I've seen plenty of autoconfiscated code, yet none where the headers
double-check the configuration header has been included already. Such a
check is neither sufficient nor really necessary. Checking the .c is
both.
I have no strong feelings about using -include instead. I'd prefer to
avoid the difference to what other projects do, though.
Circling back to the issue that made you propose this patch.
I think I'm (belatedly) coming around to your initial view that the use
of conditionals in generated QAPI code is safe enough.
I shouldn't be worried about #if defined(CONFIG_HOST_THING) where
CONFIG_HOST_THING belongs to config-host.h. That's always pulled in via
qemu/osdep.h.
I also shouldn't be worried about #if defined(CONFIG_TARGET_THING) where
CONFIG_TARGET_THING belongs to config-target.h. qemu/osdep.h pulls in
either that or exec/poison.h.
I even shouldn't be worried about #if defined(RANDOM_MACRO) as long as
qemu/osdep.h pulls in its owner or poisons it. I might legitimately be
worried about the "as long as" part.
We could perhaps extract the ifconds and look for macros that belong
neither to config-host.h nor config-target.h. But I'm not sure it's
worth the bother.
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 01/27] qapi: make sure osdep.h is included in type headers
2018-12-11 16:05 ` Daniel P. Berrangé
@ 2018-12-12 6:48 ` Markus Armbruster
0 siblings, 0 replies; 69+ messages in thread
From: Markus Armbruster @ 2018-12-12 6:48 UTC (permalink / raw)
To: Daniel P. Berrangé; +Cc: Marc-André Lureau, QEMU, Michael Roth
Daniel P. Berrangé <berrange@redhat.com> writes:
> On Mon, Dec 10, 2018 at 02:28:26PM +0100, Markus Armbruster wrote:
[...]
>> checkpatch.pl could flag patches adding .c files that don't include
>> "qemu/osdep.h" first. The "first" part might be a bit annoying to code.
>
> You can get this logic from GNULIBs syntax-check make rules. It uses
> this perl code to check that config.h is included first:
>
> while (<>) {
> if (/^# *include\b/) {
> if (not m{^# *include <config\.h>}) {
> print "$ARGV\n";
> $$ret = 1;
> }
> close ARGV;
> }
> }
Thanks!
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 02/27] qapi: do not define enumeration value explicitly
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 02/27] qapi: do not define enumeration value explicitly Marc-André Lureau
@ 2018-12-12 8:52 ` Markus Armbruster
2018-12-12 9:05 ` Marc-André Lureau
0 siblings, 1 reply; 69+ messages in thread
From: Markus Armbruster @ 2018-12-12 8:52 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> The C standard has the initial value at 0 and the subsequent values
> incremented by 1. No need to set this explicitely.
>
> This will prevent from artificial "gaps" when compiling out some enum
> values and having unnecessarily large MAX values & enums arrays, or
> simplifying iterating over valid enum values.
Should mention that compiling out will only become possible later in
this series.
> Whenever config-host.h is changed, all the enum/types are recompiled.
This soundness argument is incomplete. Yes, our coding conventions
ensure everything gets recompiled when config-host.h changes. But
nothing stops people from using 'if' conditions that depend on more than
just config-host.h.
What about this:
qapi: Do not define enumeration value explicitly
The generated C enumeration types explicitly set the enumeration
constants to 0, 1, 2, ... That's exactly what you get when you don't
supply values.
Drop the explicit values. No change now, but it will avoid gaps in
the values when we later add support for 'if' conditions. Avoiding
such gaps will save us the trouble of changing the ENUM_lookup[]
tables to work without a sentinel.
We'll have to take care to ensure the headers required by the 'if'
conditions get always included before the generated QAPI code.
Fortunately, our convention to include "qemu/osdep.h" first in any .c
ensures that's the case for our CONFIG_FOO macros.
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
With an improved commit message:
Reviewed-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 02/27] qapi: do not define enumeration value explicitly
2018-12-12 8:52 ` Markus Armbruster
@ 2018-12-12 9:05 ` Marc-André Lureau
0 siblings, 0 replies; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-12 9:05 UTC (permalink / raw)
To: Armbruster, Markus; +Cc: qemu-devel, Michael Roth
Hi
On Wed, Dec 12, 2018 at 12:52 PM Markus Armbruster <armbru@redhat.com> wrote:
>
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
> > The C standard has the initial value at 0 and the subsequent values
> > incremented by 1. No need to set this explicitely.
> >
> > This will prevent from artificial "gaps" when compiling out some enum
> > values and having unnecessarily large MAX values & enums arrays, or
> > simplifying iterating over valid enum values.
>
> Should mention that compiling out will only become possible later in
> this series.
>
> > Whenever config-host.h is changed, all the enum/types are recompiled.
>
> This soundness argument is incomplete. Yes, our coding conventions
> ensure everything gets recompiled when config-host.h changes. But
> nothing stops people from using 'if' conditions that depend on more than
> just config-host.h.
>
> What about this:
>
> qapi: Do not define enumeration value explicitly
>
> The generated C enumeration types explicitly set the enumeration
> constants to 0, 1, 2, ... That's exactly what you get when you don't
> supply values.
>
> Drop the explicit values. No change now, but it will avoid gaps in
> the values when we later add support for 'if' conditions. Avoiding
> such gaps will save us the trouble of changing the ENUM_lookup[]
> tables to work without a sentinel.
>
> We'll have to take care to ensure the headers required by the 'if'
> conditions get always included before the generated QAPI code.
> Fortunately, our convention to include "qemu/osdep.h" first in any .c
> ensures that's the case for our CONFIG_FOO macros.
>
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> With an improved commit message:
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
ack, thanks!
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi,
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
` (27 preceding siblings ...)
2018-12-08 11:19 ` [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
@ 2018-12-12 17:18 ` Markus Armbruster
2018-12-12 18:13 ` Marc-André Lureau
28 siblings, 1 reply; 69+ messages in thread
From: Markus Armbruster @ 2018-12-12 17:18 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> This is the second part of the "add #if pre-processor conditions to
> generated code" series, adding schema member conditions (roughly
> 16-38/49).
>
> Members can be exploded as dictionnary with 'type'/'if' keys:
>
> { 'struct': 'TestIfStruct', 'data':
> { 'foo': 'int',
> 'bar': { 'type': 'int', 'if': 'defined(TEST_IF_STRUCT_BAR)'} } }
>
> Enum values can be exploded as dictionnary with 'type'/'if' keys:
>
> { 'enum': 'TestIfEnum', 'data':
> [ 'foo',
> { 'name' : 'bar', 'if': 'defined(TEST_IF_ENUM_BAR)' } ] }
PATCH 03,18,20,25 are only losely related to this second part. They are
also ready. Queued on branch qapi-next in my public repository, with
PATCH 18 and 20 squashed together.
I took the liberty to implement the the idea on normalization I
mentioned in review of PATCH 08. I also squashed a few patches that are
essentially fixups into the patches they fix. I did not address any
other review comments. Result is on branch qapi-if-2. Please have a
look.
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi,
2018-12-12 17:18 ` Markus Armbruster
@ 2018-12-12 18:13 ` Marc-André Lureau
2018-12-13 5:11 ` Markus Armbruster
0 siblings, 1 reply; 69+ messages in thread
From: Marc-André Lureau @ 2018-12-12 18:13 UTC (permalink / raw)
To: Markus Armbruster; +Cc: QEMU
Hi
On Wed, Dec 12, 2018 at 9:18 PM Markus Armbruster <armbru@redhat.com> wrote:
>
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
> > This is the second part of the "add #if pre-processor conditions to
> > generated code" series, adding schema member conditions (roughly
> > 16-38/49).
> >
> > Members can be exploded as dictionnary with 'type'/'if' keys:
> >
> > { 'struct': 'TestIfStruct', 'data':
> > { 'foo': 'int',
> > 'bar': { 'type': 'int', 'if': 'defined(TEST_IF_STRUCT_BAR)'} } }
> >
> > Enum values can be exploded as dictionnary with 'type'/'if' keys:
> >
> > { 'enum': 'TestIfEnum', 'data':
> > [ 'foo',
> > { 'name' : 'bar', 'if': 'defined(TEST_IF_ENUM_BAR)' } ] }
>
> PATCH 03,18,20,25 are only losely related to this second part. They are
> also ready. Queued on branch qapi-next in my public repository, with
> PATCH 18 and 20 squashed together.
>
> I took the liberty to implement the the idea on normalization I
> mentioned in review of PATCH 08. I also squashed a few patches that are
> essentially fixups into the patches they fix. I did not address any
> other review comments. Result is on branch qapi-if-2. Please have a
> look.
>
Looks good to me. Is there something left to rework from this branch
or it is good to go?
thanks
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi,
2018-12-12 18:13 ` Marc-André Lureau
@ 2018-12-13 5:11 ` Markus Armbruster
0 siblings, 0 replies; 69+ messages in thread
From: Markus Armbruster @ 2018-12-13 5:11 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: Markus Armbruster, QEMU
Marc-André Lureau <marcandre.lureau@gmail.com> writes:
> Hi
>
> On Wed, Dec 12, 2018 at 9:18 PM Markus Armbruster <armbru@redhat.com> wrote:
>>
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>
>> > This is the second part of the "add #if pre-processor conditions to
>> > generated code" series, adding schema member conditions (roughly
>> > 16-38/49).
>> >
>> > Members can be exploded as dictionnary with 'type'/'if' keys:
>> >
>> > { 'struct': 'TestIfStruct', 'data':
>> > { 'foo': 'int',
>> > 'bar': { 'type': 'int', 'if': 'defined(TEST_IF_STRUCT_BAR)'} } }
>> >
>> > Enum values can be exploded as dictionnary with 'type'/'if' keys:
>> >
>> > { 'enum': 'TestIfEnum', 'data':
>> > [ 'foo',
>> > { 'name' : 'bar', 'if': 'defined(TEST_IF_ENUM_BAR)' } ] }
>>
>> PATCH 03,18,20,25 are only losely related to this second part. They are
>> also ready. Queued on branch qapi-next in my public repository, with
>> PATCH 18 and 20 squashed together.
>>
>> I took the liberty to implement the the idea on normalization I
>> mentioned in review of PATCH 08. I also squashed a few patches that are
>> essentially fixups into the patches they fix. I did not address any
>> other review comments. Result is on branch qapi-if-2. Please have a
>> look.
>>
>
> Looks good to me. Is there something left to rework from this branch
> or it is good to go?
> thanks
I adressed only the one review comment that was hard to explain, plus
some patch squashing. The other review comments still need to be
considered and worked in.
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [Qemu-devel] [PATCH for-4.0 v7 22/27] qapi: add 'If:' condition to enum values documentation
2018-12-11 16:07 ` Marc-André Lureau
@ 2018-12-13 13:59 ` Markus Armbruster
0 siblings, 0 replies; 69+ messages in thread
From: Markus Armbruster @ 2018-12-13 13:59 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: Armbruster, Markus, qemu-devel, Michael Roth
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Hi
>
> On Tue, Dec 11, 2018 at 8:00 PM Markus Armbruster <armbru@redhat.com> wrote:
>>
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>
>> > Use a common function to generate the "If:..." line.
>> >
>> > While at it, get rid of the existing \n\n (no idea why it was
>> > there). Use a line-break in member description, this seems to look
>> > slightly better in the plaintext version.
>>
>> Where exactly in the patch is this done?
>
> - if ifcond:
> - body += '\n\n@b{If:} @code{%s}' % ", ".join(ifcond)
> + body += texi_if(ifcond, suffix='')
Thanks. I suspected that much, but wasn't sure.
> See also doc-good.texi output
>
>>
>> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> > ---
>> > scripts/qapi/doc.py | 24 +++++++++++++++---------
>> > tests/qapi-schema/doc-good.json | 4 +++-
>> > tests/qapi-schema/doc-good.out | 1 +
>> > tests/qapi-schema/doc-good.texi | 2 +-
>> > 4 files changed, 20 insertions(+), 11 deletions(-)
>> >
>> > diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
>> > index 76cb186ff9..2133ded47e 100755
>> > --- a/scripts/qapi/doc.py
>> > +++ b/scripts/qapi/doc.py
>> > @@ -126,19 +126,26 @@ 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"""
>> > + return '%s@b{If:} @code{%s}%s' % (
>> > + prefix, ', '.join(ifcond), suffix) if ifcond else ''
>>
>> I like the ternary operator, but I nevertheless think this function is
>> easier to read as
>>
>> if not ifcond:
>> return ''
>> return '%s@b{If:} @code{%s}%s' % (prefix, ', '.join(ifcond), suffix)
>>
>
> No difference to me, sure
>
>> > +
>> > +
>> > +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='@*'))
>>
>> Do you ignore suffix intentionally?
>
> yes
That's kind of surprising, until you pry open the abstraction and
realize that we reach this one only from the first call of member_func()
below, which ...
>>
>> >
>> >
>> > -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' % (
>> > member.name, membertype,
>> > ' (optional)' if member.optional else '',
>> > - suffix)
>> > + suffix, desc)
>> >
>> >
>> > def texi_members(doc, what, base, variants, member_func):
>> > @@ -155,7 +162,7 @@ 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)
>>
>> Here, you pass a @desc argument, but no @suffix.
>>
>> @member_func is either texi_enum_value() or texi_member(). Works.
... doesn't pass @suffix. So @suffix is empty when we ignore it.
>> > if base:
>> > items += '@item The members of @code{%s}\n' % base.doc_type()
>> > if variants:
>> > @@ -165,7 +172,7 @@ def texi_members(doc, what, base, variants, member_func):
>> > 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, suffix=when)
>>
>> Here, you pass a @suffix argument, but no @desc.
>>
>> texi_enum_value() would choke on that, but it can't occur here, because
>> enums have no variants.
>>
>> Still, I'd prefer texi_enum_value() and texi_member() to have the exact
>> same signature.
>
> OK (not sure what is the more pythonic way)
I suspect there's a clean solution struggling to get out. But I can't
grasp it yet.
>>
>> > else:
>> > items += '@item The members of @code{%s}%s\n' % (
>> > v.type.doc_type(), when)
>> > @@ -185,8 +192,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
>> >
>> >
[...]
^ permalink raw reply [flat|nested] 69+ messages in thread
end of thread, other threads:[~2018-12-13 13:59 UTC | newest]
Thread overview: 69+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-08 11:15 [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 01/27] qapi: make sure osdep.h is included in type headers Marc-André Lureau
2018-12-10 9:52 ` Markus Armbruster
2018-12-10 11:13 ` Marc-André Lureau
2018-12-10 13:28 ` Markus Armbruster
2018-12-11 15:47 ` Marc-André Lureau
2018-12-12 6:47 ` Markus Armbruster
2018-12-11 16:05 ` Daniel P. Berrangé
2018-12-12 6:48 ` Markus Armbruster
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 02/27] qapi: do not define enumeration value explicitly Marc-André Lureau
2018-12-12 8:52 ` Markus Armbruster
2018-12-12 9:05 ` Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 03/27] qapi: rename QAPISchemaEnumType.values to .members Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 04/27] qapi: change enum visitor and gen_enum* to take QAPISchemaMember Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 05/27] tests: print enum type members more like object type members Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 06/27] qapi: factor out checking for keys Marc-André Lureau
2018-12-10 9:57 ` Markus Armbruster
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 07/27] qapi: improve reporting of unknown or missing keys Marc-André Lureau
2018-12-10 10:03 ` Markus Armbruster
2018-12-10 11:11 ` Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 08/27] qapi: add a dictionary form with 'name' key for enum members Marc-André Lureau
2018-12-10 15:44 ` Markus Armbruster
2018-12-10 16:05 ` Markus Armbruster
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 09/27] qapi: add 'if' to " Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 10/27] qapi-events: add 'if' condition to implicit event enum Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 11/27] qapi: pass long form enum to make_enum_members Marc-André Lureau
2018-12-10 17:04 ` Markus Armbruster
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 12/27] qapi: rename allow_dict to allow_implicit Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 13/27] qapi: add a dictionary form for TYPE Marc-André Lureau
2018-12-10 17:24 ` Markus Armbruster
2018-12-11 12:11 ` Marc-André Lureau
2018-12-11 15:35 ` Markus Armbruster
2018-12-11 15:18 ` Markus Armbruster
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 14/27] qapi: add 'if' to implicit struct members Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 15/27] qapi: add an error in case a discriminator is conditional Marc-André Lureau
2018-12-10 17:31 ` Markus Armbruster
2018-12-11 15:23 ` Markus Armbruster
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 16/27] qapi: add 'if' to union members Marc-André Lureau
2018-12-10 17:33 ` Markus Armbruster
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 17/27] qapi: simplify make_enum_members() Marc-André Lureau
2018-12-11 12:05 ` Markus Armbruster
2018-12-11 12:08 ` Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 18/27] tests/qapi: add command with condition on union argument Marc-André Lureau
2018-12-11 12:09 ` Markus Armbruster
2018-12-11 12:13 ` Marc-André Lureau
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 19/27] qapi: add 'if' to alternate members Marc-André Lureau
2018-12-11 12:21 ` Markus Armbruster
2018-12-08 11:15 ` [Qemu-devel] [PATCH for-4.0 v7 20/27] tests/qapi: add command with condition on alternate argument Marc-André Lureau
2018-12-11 12:20 ` Markus Armbruster
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 21/27] qapi: add #if conditions to generated code members Marc-André Lureau
2018-12-11 13:17 ` Markus Armbruster
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 22/27] qapi: add 'If:' condition to enum values documentation Marc-André Lureau
2018-12-11 16:00 ` Markus Armbruster
2018-12-11 16:07 ` Marc-André Lureau
2018-12-13 13:59 ` Markus Armbruster
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 23/27] qapi: add 'If:' condition to struct members documentation Marc-André Lureau
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 24/27] qapi: add condition to variants documentation Marc-André Lureau
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 25/27] qapi: break long lines at 'data' member Marc-André Lureau
2018-12-11 16:07 ` Markus Armbruster
2018-12-11 16:08 ` Marc-André Lureau
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 26/27] qapi: add more conditions to SPICE Marc-André Lureau
2018-12-11 17:11 ` Markus Armbruster
2018-12-08 11:16 ` [Qemu-devel] [PATCH for-4.0 v7 27/27] qapi: add conditions to REPLICATION type/commands on the schema Marc-André Lureau
2018-12-11 17:15 ` Markus Armbruster
2018-12-11 17:17 ` Marc-André Lureau
2018-12-08 11:19 ` [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi, Marc-André Lureau
2018-12-12 17:18 ` Markus Armbruster
2018-12-12 18:13 ` Marc-André Lureau
2018-12-13 5:11 ` Markus Armbruster
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.