All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code
@ 2018-03-21 11:51 Marc-André Lureau
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 01/49] qapi/visit: remove useless prefix argument Marc-André Lureau
                   ` (53 more replies)
  0 siblings, 54 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Hi,

In order to clean-up some hacks in qapi (having to unregister commands
at runtime), I proposed a "[PATCH v5 02/20] qapi.py: add a simple #ifdef condition"

(see http://lists.gnu.org/archive/html/qemu-devel/2016-08/msg03106.html).

However, we decided to drop that patch from the series and solve the
problem later. The main issues were:
- the syntax was awkward to the JSON schema and documentation
- the evaluation of the condition was done in the qapi scripts, with
  very limited capability
- each target/config would need different generated files.

Instead, it could defer the #if evaluation to the C-preprocessor.

With this series, top-level qapi JSON entity can take 'if' keys:

{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
  'if': 'defined(TEST_IF_STRUCT)' }

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)' } ] }

A benefit from having conditional schema is that introspection will
reflect more accurately the capability of the server. Another benefit
is that it may help to remove some dead code when disabling a
functionality.

Starting from patch "qapi: add conditions to VNC type/commands/events
on the schema", the series demonstrates adding conditions.

The schema is splitted in common and per-target parts starting from
"RFC: qapi: learn to split schema by 'top-unit'" patch. This allows a
target schema to use target-poisoned defines as conditions (such as
TARGET_I386).

There are a lot more things one can make conditional in the QAPI
schema, like pci/kvm/xen/numa/vde/slirp/posix/win32/vsock/lzo etc etc,
however I am still evaluating the implication of such changes both
externally and internally, for those interested, I can share my wip
branch.

Comments welcome,

v5:
- adapt to the new 'modular' / single generator design, making
  splitting schema a bit more complicated than before, when it was
  only at build-sys level. See "RFC: qapi: learn to split schema by
  'top-unit'" for the new apporach at splitting common and target
  parts.
- replace the #if-wrapper decorator with a @contextmanager (if necessary,
  this could be replaced by explicit begin/end calls instead now)
- better split of target events, introducing seperate limiter/emitter
- add a 'RFC: make RTC_CHANGE per-target' to show how conditional
  could be used and exercice the 'per-unit' event limiter
- +painful rebase
- add some r-b tags

v4:
- added "qlit: use QType instead of int" patch
- use a "default:" case in qobject_from_qlit()
- added a test for invalid 'if': ['']
- listify ifcond in constructors
- added "qapi: leave the ifcond attribute undefined until check()"
  patch (could be squashed)
- use a negative lookahead in "qapi: mcgen() shouldn't indent # lines"
- fix extra empty line in "qapi-introspect: add preprocessor
  conditions to generated QLit"
- added desugar/normalization passes, such as NAME -> { 'name': NAME }
- splitted "qapi: change enum visitor to take QAPISchemaMember"
- prettify test-qapi.py members output
- added missing #if wrapping for enum members in generated introspection
- clarified some error messages
- added "qapi: rename allow_dict to allow_implicit" patch for clarity
- added a seperate patch for "qapi: add a dictionnary form" for enum
  names
- added a seperate patch for "qapi: add a dictionnary form" for struct
  members
- squashed the patches adding #if to generated code (some types
  generate both enum and struct members for example, so a step-by-step
  is unnecessarily complicated to deal with)
- squashed some tests with related patch
- added "qapi: add an error in case a discriminator is conditionnal"
- add back VNC-specific crypto 'des-rfb' when VNC is disabled
- change the way unit filtering is done (so no -u means no filtering)
- made target.json the top-level documentation schema
- removed some blank lines in generated code output
- improve documentation, add various tests
- commit message improvements
- misc pycodestyle/pep8 fixes
- add r-b tags

v3:
- rebased (qlit is now merged upstream)
- solve the per-target #ifdef problem by using a target.json
  and new qapi generated target files
- update some commit messages based on Markus review
- more schema error reporting
- move the ifcond argument closer to info/doc
- use mcgen() in gen_if()/gen_endif()
- simplify "modify to_qlit() to take an optional suffix"
- fix generated qlit indentation
- fix temporary build break by merging #if types & visitors patch
- fix some redundant condtionals generation
- change enum visitor to take QAPISchemaMember
- reject unknown dictionnary keys in { .., 'if': ..}
- split qapi test visitor print() with trailing ',' trick

v2: after Markus review
 - "qboject: add literal qobject type", splitted & many updates
 - "qapi: generate a literal qobject for introspection", fixed leak
 - "visitor: pass size of strings array to enum visitor", rewrote as a
  series of patches to change char*[] to struct { int n, char *[] }.
 - split the "if" patches in parsing, tests, generation
 - added a docs/devel/qapi-code-gen.txt patch
 - added a patch to remove enum value assignment, to avoid "holes"
   with #if values
 - update #if VNC patch, compile out "info vnc", compile out des-rfb
 - dropped "qobject: replace dump_qobject() by qobject_to_string()" patch
 - dropped qapi.mk patch
 - other smaller changes

Marc-André Lureau (49):
  qapi/visit: remove useless prefix argument
  qapi/events: generate event enum in main module
  qapi: add 'if' to top-level expressions
  qapi: pass 'if' condition into QAPISchemaEntity objects
  qapi: leave the ifcond attribute undefined until check()
  qapi: add 'ifcond' to visitor methods
  qapi: mcgen() shouldn't indent # lines
  qapi: add #if/#endif helpers
  qapi-introspect: modify to_qlit() to append ',' on level > 0
  qapi-introspect: add preprocessor conditions to generated QLit
  qapi/commands: add #if conditions to commands
  qapi/events: add #if conditions to events
  qapi-types: refactor variants handling
  qapi-types: add #if conditions to types & visitors
  qapi: do not define enumeration value explicitely
  qapi: rename QAPISchemaEnumType.values to .members
  qapi: change enum visitor to take QAPISchemaMember
  tests: modify visit_enum_type() in test-qapi to print members
  qapi: factor out check_known_keys()
  qapi: add a dictionnary form with 'name' key for enum members
  qapi: add 'if' to enum members
  qapi-event: add 'if' condition to implicit event enum
  qapi: rename allow_dict to allow_implicit
  qapi: add a dictionary form with 'type' key for members
  qapi: add 'if' to implicit struct members
  qapi: add an error in case a discriminator is conditionnal
  qapi: add 'if' on union members
  qapi: add 'if' to alternate members
  qapi: add #if conditions to generated code members
  docs: document schema configuration
  qapi2texi: add 'If:' section to generated documentation
  qapi2texi: add 'If:' condition to enum values
  qapi2texi: add 'If:' condition to struct members
  qapi2texi: add condition to variants
  qapi: add conditions to VNC type/commands/events on the schema
  qapi: add conditions to SPICE type/commands/events on the schema
  qapi: add conditions to REPLICATION type/commands on the schema
  build-sys: move qmp-introspect per target
  qapi-commands: don't initialize command list in qmp_init_marshall()
  RFC: qapi: learn to split schema by 'top-unit'
  qapi: add a top-unit 'target' schema
  qapi: make rtc-reset-reinjection and SEV depend on TARGET_I386
  qapi: make s390 commands depend on TARGET_S390X
  target.json: add a note about query-cpu* not being s390x-specific
  qapi: make query-gic-capabilities depend on TARGET_ARM
  qapi: make query-cpu-model-expansion depend on s390 or x86
  qapi: make query-cpu-definitions depend on specific targets
  qapi: remove qmp_unregister_command()
  RFC: make RTC_CHANGE per-target

 qapi/block-core.json                          |  13 +-
 qapi/char.json                                |  10 +-
 qapi/migration.json                           |  12 +-
 qapi/misc.json                                | 380 -----------
 qapi/qapi-schema.json                         |   1 +
 qapi/target.json                              | 415 ++++++++++++
 qapi/ui.json                                  |  75 ++-
 scripts/qapi/commands.py                      |  43 +-
 scripts/qapi/common.py                        | 599 +++++++++++++-----
 scripts/qapi/doc.py                           |  46 +-
 scripts/qapi/events.py                        |  45 +-
 scripts/qapi/introspect.py                    |  57 +-
 scripts/qapi/types.py                         |  98 +--
 scripts/qapi/visit.py                         |  59 +-
 include/qapi/qmp-event.h                      |   4 +
 include/qapi/qmp/dispatch.h                   |   1 -
 include/sysemu/arch_init.h                    |  11 -
 target/i386/sev_i386.h                        |   2 +-
 ui/vnc.h                                      |   2 +
 hmp.c                                         |   9 +-
 hw/ppc/spapr_rtc.c                            |   2 +-
 hw/s390x/s390-skeys.c                         |   2 +-
 hw/timer/mc146818rtc.c                        |   4 +-
 migration/colo.c                              |  16 +-
 monitor.c                                     | 297 +++++----
 qapi/qmp-event.c                              |  11 +
 qapi/qmp-registry.c                           |   8 -
 qga/main.c                                    |   1 +
 qmp.c                                         |  72 +--
 stubs/arch-query-cpu-def.c                    |  11 -
 stubs/arch-query-cpu-model-baseline.c         |  13 -
 stubs/arch-query-cpu-model-comparison.c       |  13 -
 stubs/arch-query-cpu-model-expansion.c        |  13 -
 target/arm/helper.c                           |   3 +-
 target/arm/monitor.c                          |   2 +-
 target/i386/cpu.c                             |   6 +-
 target/ppc/translate_init.c                   |   3 +-
 target/s390x/cpu_models.c                     |   9 +-
 tests/test-qmp-cmds.c                         |   7 +
 tests/test-qobject-input-visitor.c            |   1 -
 Makefile                                      |   1 +
 Makefile.objs                                 |   2 -
 Makefile.target                               |   4 +
 docs/devel/qapi-code-gen.txt                  |  38 ++
 hmp-commands-info.hx                          |   2 +
 stubs/Makefile.objs                           |   4 -
 tests/Makefile.include                        |  14 +-
 tests/qapi-schema/alternate-base.err          |   2 +-
 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/bad-if-empty-list.err       |   1 +
 tests/qapi-schema/bad-if-empty-list.exit      |   1 +
 tests/qapi-schema/bad-if-empty-list.json      |   3 +
 tests/qapi-schema/bad-if-empty-list.out       |   0
 tests/qapi-schema/bad-if-empty.err            |   1 +
 tests/qapi-schema/bad-if-empty.exit           |   1 +
 tests/qapi-schema/bad-if-empty.json           |   3 +
 tests/qapi-schema/bad-if-empty.out            |   0
 tests/qapi-schema/bad-if-list.err             |   1 +
 tests/qapi-schema/bad-if-list.exit            |   1 +
 tests/qapi-schema/bad-if-list.json            |   3 +
 tests/qapi-schema/bad-if-list.out             |   0
 tests/qapi-schema/bad-if.err                  |   1 +
 tests/qapi-schema/bad-if.exit                 |   1 +
 tests/qapi-schema/bad-if.json                 |   3 +
 tests/qapi-schema/bad-if.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                |  23 +-
 tests/qapi-schema/doc-good.texi               |  10 +-
 tests/qapi-schema/double-type.err             |   2 +-
 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  |   1 +
 .../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/enum-missing-data.err       |   2 +-
 tests/qapi-schema/event-case.out              |   9 +-
 tests/qapi-schema/event-nest-struct.err       |   2 +-
 tests/qapi-schema/flat-union-inline.err       |   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 +-
 tests/qapi-schema/nested-struct-data.err      |   2 +-
 tests/qapi-schema/qapi-schema-test.json       |  46 +-
 tests/qapi-schema/qapi-schema-test.out        | 100 ++-
 .../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                |  39 +-
 .../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        |   2 +-
 tests/qapi-schema/unknown-expr-key.json       |   2 +-
 116 files changed, 1768 insertions(+), 1094 deletions(-)
 create mode 100644 qapi/target.json
 mode change 100644 => 100755 scripts/qapi/doc.py
 delete mode 100644 stubs/arch-query-cpu-def.c
 delete mode 100644 stubs/arch-query-cpu-model-baseline.c
 delete mode 100644 stubs/arch-query-cpu-model-comparison.c
 delete mode 100644 stubs/arch-query-cpu-model-expansion.c
 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/bad-if-empty-list.err
 create mode 100644 tests/qapi-schema/bad-if-empty-list.exit
 create mode 100644 tests/qapi-schema/bad-if-empty-list.json
 create mode 100644 tests/qapi-schema/bad-if-empty-list.out
 create mode 100644 tests/qapi-schema/bad-if-empty.err
 create mode 100644 tests/qapi-schema/bad-if-empty.exit
 create mode 100644 tests/qapi-schema/bad-if-empty.json
 create mode 100644 tests/qapi-schema/bad-if-empty.out
 create mode 100644 tests/qapi-schema/bad-if-list.err
 create mode 100644 tests/qapi-schema/bad-if-list.exit
 create mode 100644 tests/qapi-schema/bad-if-list.json
 create mode 100644 tests/qapi-schema/bad-if-list.out
 create mode 100644 tests/qapi-schema/bad-if.err
 create mode 100644 tests/qapi-schema/bad-if.exit
 create mode 100644 tests/qapi-schema/bad-if.json
 create mode 100644 tests/qapi-schema/bad-if.out
 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/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/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.16.2.521.g9aa15f885a

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 01/49] qapi/visit: remove useless prefix argument
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-18 14:29   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 02/49] qapi/events: generate event enum in main module Marc-André Lureau
                   ` (52 subsequent siblings)
  53 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/visit.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index 5d72d8936c..3c5ea1289e 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -293,7 +293,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
 #include "qapi/qmp/qerror.h"
 #include "%(visit)s.h"
 ''',
-                                      visit=visit, prefix=self._prefix))
+                                      visit=visit))
         self._genh.preamble_add(mcgen('''
 #include "qapi/qapi-builtin-visit.h"
 #include "%(types)s.h"
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 02/49] qapi/events: generate event enum in main module
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 01/49] qapi/visit: remove useless prefix argument Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-18 14:33   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 03/49] qapi: add 'if' to top-level expressions Marc-André Lureau
                   ` (51 subsequent siblings)
  53 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

The event generator produces an enum, and put it in the last visited
module. It fits better in the main module, since it's the set of all
visited events, from all modules.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/events.py | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
index 3dc523cf39..3e448ae523 100644
--- a/scripts/qapi/events.py
+++ b/scripts/qapi/events.py
@@ -180,8 +180,9 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
                              types=types))
 
     def visit_end(self):
-        self._genh.add(gen_enum(self._enum_name, self._event_names))
-        self._genc.add(gen_enum_lookup(self._enum_name, self._event_names))
+        (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))
 
     def visit_event(self, name, info, arg_type, boxed):
         self._genh.add(gen_event_send_decl(name, arg_type, boxed))
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 03/49] qapi: add 'if' to top-level expressions
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 01/49] qapi/visit: remove useless prefix argument Marc-André Lureau
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 02/49] qapi/events: generate event enum in main module Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-19  7:57   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 04/49] qapi: pass 'if' condition into QAPISchemaEntity objects Marc-André Lureau
                   ` (50 subsequent siblings)
  53 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Accept 'if' key in top-level elements, accepted as string or list of
string type. The following patches will modify the test visitor to
check the value is correctly saved, and generate #if/#endif code (as a
single #if/endif line or a series for a list).

Example of 'if' key:
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
  'if': 'defined(TEST_IF_STRUCT)' }

The generated code is for now *unconditional*. Later patches generate
the conditionals.

A following patch for qapi-code-gen.txt will provide more complete
documentation for 'if' usage.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
 scripts/qapi/common.py                   | 35 ++++++++++++++++++++----
 tests/test-qmp-cmds.c                    |  6 ++++
 tests/Makefile.include                   |  6 ++++
 tests/qapi-schema/bad-if-empty-list.err  |  1 +
 tests/qapi-schema/bad-if-empty-list.exit |  1 +
 tests/qapi-schema/bad-if-empty-list.json |  3 ++
 tests/qapi-schema/bad-if-empty-list.out  |  0
 tests/qapi-schema/bad-if-empty.err       |  1 +
 tests/qapi-schema/bad-if-empty.exit      |  1 +
 tests/qapi-schema/bad-if-empty.json      |  3 ++
 tests/qapi-schema/bad-if-empty.out       |  0
 tests/qapi-schema/bad-if-list.err        |  1 +
 tests/qapi-schema/bad-if-list.exit       |  1 +
 tests/qapi-schema/bad-if-list.json       |  3 ++
 tests/qapi-schema/bad-if-list.out        |  0
 tests/qapi-schema/bad-if.err             |  1 +
 tests/qapi-schema/bad-if.exit            |  1 +
 tests/qapi-schema/bad-if.json            |  3 ++
 tests/qapi-schema/bad-if.out             |  0
 tests/qapi-schema/qapi-schema-test.json  | 20 ++++++++++++++
 tests/qapi-schema/qapi-schema-test.out   | 22 +++++++++++++++
 21 files changed, 103 insertions(+), 6 deletions(-)
 create mode 100644 tests/qapi-schema/bad-if-empty-list.err
 create mode 100644 tests/qapi-schema/bad-if-empty-list.exit
 create mode 100644 tests/qapi-schema/bad-if-empty-list.json
 create mode 100644 tests/qapi-schema/bad-if-empty-list.out
 create mode 100644 tests/qapi-schema/bad-if-empty.err
 create mode 100644 tests/qapi-schema/bad-if-empty.exit
 create mode 100644 tests/qapi-schema/bad-if-empty.json
 create mode 100644 tests/qapi-schema/bad-if-empty.out
 create mode 100644 tests/qapi-schema/bad-if-list.err
 create mode 100644 tests/qapi-schema/bad-if-list.exit
 create mode 100644 tests/qapi-schema/bad-if-list.json
 create mode 100644 tests/qapi-schema/bad-if-list.out
 create mode 100644 tests/qapi-schema/bad-if.err
 create mode 100644 tests/qapi-schema/bad-if.exit
 create mode 100644 tests/qapi-schema/bad-if.json
 create mode 100644 tests/qapi-schema/bad-if.out

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 2c05e3c284..4f9e02b0b4 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -637,6 +637,27 @@ def add_name(name, info, meta, implicit=False):
     all_names[name] = meta
 
 
+def check_if(expr, info):
+
+    def check_if_str(ifcond, info):
+        if not isinstance(ifcond, str):
+            raise QAPISemError(
+                info, "'if' condition must be a string or a list of strings")
+        if ifcond == '':
+            raise QAPISemError(info, "'if' condition '' makes no sense")
+
+    ifcond = expr.get('if')
+    if ifcond is None:
+        return
+    if isinstance(ifcond, list):
+        if ifcond == []:
+            raise QAPISemError(info, "'if' condition [] is useless")
+        for elt in ifcond:
+            check_if_str(elt, info)
+    else:
+        check_if_str(ifcond, info)
+
+
 def check_type(info, source, value, allow_array=False,
                allow_dict=False, allow_optional=False,
                allow_metas=[]):
@@ -876,6 +897,8 @@ def check_keys(expr_elem, meta, required, optional=[]):
             raise QAPISemError(info,
                                "'%s' of %s '%s' should only use true value"
                                % (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'"
@@ -904,28 +927,28 @@ def check_exprs(exprs):
 
         if 'enum' in expr:
             meta = 'enum'
-            check_keys(expr_elem, 'enum', ['data'], ['prefix'])
+            check_keys(expr_elem, 'enum', ['data'], ['if', 'prefix'])
             enum_types[expr[meta]] = expr
         elif 'union' in expr:
             meta = 'union'
             check_keys(expr_elem, 'union', ['data'],
-                       ['base', 'discriminator'])
+                       ['base', 'discriminator', 'if'])
             union_types[expr[meta]] = expr
         elif 'alternate' in expr:
             meta = 'alternate'
-            check_keys(expr_elem, 'alternate', ['data'])
+            check_keys(expr_elem, 'alternate', ['data'], ['if'])
         elif 'struct' in expr:
             meta = 'struct'
-            check_keys(expr_elem, 'struct', ['data'], ['base'])
+            check_keys(expr_elem, 'struct', ['data'], ['base', 'if'])
             struct_types[expr[meta]] = expr
         elif 'command' in expr:
             meta = 'command'
             check_keys(expr_elem, 'command', [],
                        ['data', 'returns', 'gen', 'success-response',
-                        'boxed', 'allow-oob'])
+                        'boxed', 'allow-oob', 'if'])
         elif 'event' in expr:
             meta = 'event'
-            check_keys(expr_elem, 'event', [], ['data', 'boxed'])
+            check_keys(expr_elem, 'event', [], ['data', 'boxed', 'if'])
         else:
             raise QAPISemError(expr_elem['info'],
                                "Expression is missing metatype")
diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c
index 93fbbb1b73..c25fc2100a 100644
--- a/tests/test-qmp-cmds.c
+++ b/tests/test-qmp-cmds.c
@@ -12,6 +12,12 @@
 
 static QmpCommandList qmp_commands;
 
+/* #if defined(TEST_IF_STRUCT) && defined(TEST_IF_CMD) */
+void qmp_TestIfCmd(TestIfStruct *foo, Error **errp)
+{
+}
+/* #endif */
+
 void qmp_user_def_cmd(Error **errp)
 {
 }
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 0b277036df..f77ad2ba3b 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -436,6 +436,10 @@ qapi-schema += args-unknown.json
 qapi-schema += bad-base.json
 qapi-schema += bad-data.json
 qapi-schema += bad-ident.json
+qapi-schema += bad-if.json
+qapi-schema += bad-if-empty.json
+qapi-schema += bad-if-empty-list.json
+qapi-schema += bad-if-list.json
 qapi-schema += bad-type-bool.json
 qapi-schema += bad-type-dict.json
 qapi-schema += bad-type-int.json
@@ -933,6 +937,8 @@ $(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json
 		"TEST","$*.out")
 	@# Sanitize error messages (make them independent of build directory)
 	@perl -p -e 's|\Q$(SRC_PATH)\E/||g' $*.test.err | diff -u $(SRC_PATH)/$*.err -
+	@if test "$(QAPI_REGENERATE)" == 1 ; then cp $*.test.out $(SRC_PATH)/$*.out ; fi
+	@if test "$(QAPI_REGENERATE)" == 1 ; then cp $*.test.err $(SRC_PATH)/$*.err ; fi
 	@diff -u $(SRC_PATH)/$*.out $*.test.out
 	@diff -u $(SRC_PATH)/$*.exit $*.test.exit
 
diff --git a/tests/qapi-schema/bad-if-empty-list.err b/tests/qapi-schema/bad-if-empty-list.err
new file mode 100644
index 0000000000..75fe6497bc
--- /dev/null
+++ b/tests/qapi-schema/bad-if-empty-list.err
@@ -0,0 +1 @@
+tests/qapi-schema/bad-if-empty-list.json:2: 'if' condition [] is useless
diff --git a/tests/qapi-schema/bad-if-empty-list.exit b/tests/qapi-schema/bad-if-empty-list.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/bad-if-empty-list.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/bad-if-empty-list.json b/tests/qapi-schema/bad-if-empty-list.json
new file mode 100644
index 0000000000..94f2eb8670
--- /dev/null
+++ b/tests/qapi-schema/bad-if-empty-list.json
@@ -0,0 +1,3 @@
+# check empty 'if' list
+{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
+  'if': [] }
diff --git a/tests/qapi-schema/bad-if-empty-list.out b/tests/qapi-schema/bad-if-empty-list.out
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/qapi-schema/bad-if-empty.err b/tests/qapi-schema/bad-if-empty.err
new file mode 100644
index 0000000000..358bdc3e51
--- /dev/null
+++ b/tests/qapi-schema/bad-if-empty.err
@@ -0,0 +1 @@
+tests/qapi-schema/bad-if-empty.json:2: 'if' condition '' makes no sense
diff --git a/tests/qapi-schema/bad-if-empty.exit b/tests/qapi-schema/bad-if-empty.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/bad-if-empty.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/bad-if-empty.json b/tests/qapi-schema/bad-if-empty.json
new file mode 100644
index 0000000000..fe1dd4eca6
--- /dev/null
+++ b/tests/qapi-schema/bad-if-empty.json
@@ -0,0 +1,3 @@
+# check empty 'if'
+{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
+  'if': '' }
diff --git a/tests/qapi-schema/bad-if-empty.out b/tests/qapi-schema/bad-if-empty.out
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/qapi-schema/bad-if-list.err b/tests/qapi-schema/bad-if-list.err
new file mode 100644
index 0000000000..0af6316f78
--- /dev/null
+++ b/tests/qapi-schema/bad-if-list.err
@@ -0,0 +1 @@
+tests/qapi-schema/bad-if-list.json:2: 'if' condition '' makes no sense
diff --git a/tests/qapi-schema/bad-if-list.exit b/tests/qapi-schema/bad-if-list.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/bad-if-list.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/bad-if-list.json b/tests/qapi-schema/bad-if-list.json
new file mode 100644
index 0000000000..49ced9b9ca
--- /dev/null
+++ b/tests/qapi-schema/bad-if-list.json
@@ -0,0 +1,3 @@
+# check invalid 'if' content
+{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
+  'if': ['foo', ''] }
diff --git a/tests/qapi-schema/bad-if-list.out b/tests/qapi-schema/bad-if-list.out
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/qapi-schema/bad-if.err b/tests/qapi-schema/bad-if.err
new file mode 100644
index 0000000000..c2e3f5f44c
--- /dev/null
+++ b/tests/qapi-schema/bad-if.err
@@ -0,0 +1 @@
+tests/qapi-schema/bad-if.json:2: 'if' condition must be a string or a list of strings
diff --git a/tests/qapi-schema/bad-if.exit b/tests/qapi-schema/bad-if.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/bad-if.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/bad-if.json b/tests/qapi-schema/bad-if.json
new file mode 100644
index 0000000000..3edd1a0bf2
--- /dev/null
+++ b/tests/qapi-schema/bad-if.json
@@ -0,0 +1,3 @@
+# check invalid 'if' type
+{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
+  'if': { 'value': 'defined(TEST_IF_STRUCT)' } }
diff --git a/tests/qapi-schema/bad-if.out b/tests/qapi-schema/bad-if.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 c72dbd8050..b997b2d43d 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -188,3 +188,23 @@
   'data': { 'a': ['__org.qemu_x-Enum'], 'b': ['__org.qemu_x-Struct'],
             'c': '__org.qemu_x-Union2', 'd': '__org.qemu_x-Alt' },
   'returns': '__org.qemu_x-Union1' }
+
+# test 'if' condition handling
+
+{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
+  'if': 'defined(TEST_IF_STRUCT)' }
+
+{ 'enum': 'TestIfEnum', 'data': [ 'foo', 'bar' ],
+  'if': 'defined(TEST_IF_ENUM)' }
+
+{ 'union': 'TestIfUnion', 'data': { 'foo': 'TestStruct' },
+  'if': 'defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)' }
+
+{ 'alternate': 'TestIfAlternate', 'data': { 'foo': 'int', 'bar': 'TestStruct' },
+  'if': 'defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)' }
+
+{ 'command': 'TestIfCmd', 'data': { 'foo': 'TestIfStruct' },
+  'if': ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)'] }
+
+{ 'event': 'TestIfEvent', 'data': { 'foo': 'TestIfStruct' },
+  '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 012e7fc06a..b11682314c 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -230,3 +230,25 @@ object q_obj___org.qemu_x-command-arg
     member d: __org.qemu_x-Alt optional=False
 command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Union1
    gen=True success_response=True boxed=False
+object TestIfStruct
+    member foo: int optional=False
+enum TestIfEnum ['foo', 'bar']
+object q_obj_TestStruct-wrapper
+    member data: TestStruct optional=False
+enum TestIfUnionKind ['foo']
+object TestIfUnion
+    member type: TestIfUnionKind optional=False
+    tag type
+    case foo: q_obj_TestStruct-wrapper
+alternate TestIfAlternate
+    tag type
+    case foo: int
+    case bar: TestStruct
+object q_obj_TestIfCmd-arg
+    member foo: TestIfStruct optional=False
+command TestIfCmd q_obj_TestIfCmd-arg -> None
+   gen=True success_response=True boxed=False
+object q_obj_TestIfEvent-arg
+    member foo: TestIfStruct optional=False
+event TestIfEvent q_obj_TestIfEvent-arg
+   boxed=False
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 04/49] qapi: pass 'if' condition into QAPISchemaEntity objects
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (2 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 03/49] qapi: add 'if' to top-level expressions Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-19  8:09   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 05/49] qapi: leave the ifcond attribute undefined until check() Marc-André Lureau
                   ` (49 subsequent siblings)
  53 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Built-in objects remain unconditional.  Explicitly defined objects
use the condition specified in the schema.  Implicitly defined
objects inherit their condition from their users.  For most of them,
there is exactly one user, so the condition to use is obvious.  The
exception is the wrapped type's generated for simple union variants,
which can be shared by any number of simple unions.  The tight
condition would be the disjunction of the conditions of these simple
unions.  For now, use wrapped type's condition instead.  Much
simpler and good enough for now.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
 scripts/qapi/common.py | 97 ++++++++++++++++++++++++++++--------------
 1 file changed, 65 insertions(+), 32 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 4f9e02b0b4..d8ab3d8f7f 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1006,8 +1006,16 @@ def check_exprs(exprs):
 # Schema compiler frontend
 #
 
+def listify_cond(ifcond):
+    if not ifcond:
+        return []
+    if not isinstance(ifcond, list):
+        return [ifcond]
+    return ifcond
+
+
 class QAPISchemaEntity(object):
-    def __init__(self, name, info, doc):
+    def __init__(self, name, info, doc, ifcond=None):
         assert name is None or isinstance(name, str)
         self.name = name
         self.module = None
@@ -1018,6 +1026,7 @@ class QAPISchemaEntity(object):
         # such place).
         self.info = info
         self.doc = doc
+        self.ifcond = listify_cond(ifcond)
 
     def c_name(self):
         return c_name(self.name)
@@ -1150,8 +1159,8 @@ class QAPISchemaBuiltinType(QAPISchemaType):
 
 
 class QAPISchemaEnumType(QAPISchemaType):
-    def __init__(self, name, info, doc, values, prefix):
-        QAPISchemaType.__init__(self, name, info, doc)
+    def __init__(self, name, info, doc, ifcond, values, prefix):
+        QAPISchemaType.__init__(self, name, info, doc, ifcond)
         for v in values:
             assert isinstance(v, QAPISchemaMember)
             v.set_owner(name)
@@ -1186,7 +1195,7 @@ class QAPISchemaEnumType(QAPISchemaType):
 
 class QAPISchemaArrayType(QAPISchemaType):
     def __init__(self, name, info, element_type):
-        QAPISchemaType.__init__(self, name, info, None)
+        QAPISchemaType.__init__(self, name, info, None, None)
         assert isinstance(element_type, str)
         self._element_type_name = element_type
         self.element_type = None
@@ -1194,6 +1203,7 @@ class QAPISchemaArrayType(QAPISchemaType):
     def check(self, schema):
         self.element_type = schema.lookup_type(self._element_type_name)
         assert self.element_type
+        self.ifcond = self.element_type.ifcond
 
     def is_implicit(self):
         return True
@@ -1215,11 +1225,12 @@ class QAPISchemaArrayType(QAPISchemaType):
 
 
 class QAPISchemaObjectType(QAPISchemaType):
-    def __init__(self, name, info, doc, base, local_members, variants):
+    def __init__(self, name, info, doc, ifcond,
+                 base, local_members, variants):
         # struct has local_members, optional base, and no variants
         # flat union has base, variants, and no local_members
         # simple union has local_members, variants, and no base
-        QAPISchemaType.__init__(self, name, info, doc)
+        QAPISchemaType.__init__(self, name, info, doc, ifcond)
         assert base is None or isinstance(base, str)
         for m in local_members:
             assert isinstance(m, QAPISchemaObjectTypeMember)
@@ -1407,8 +1418,8 @@ class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
 
 
 class QAPISchemaAlternateType(QAPISchemaType):
-    def __init__(self, name, info, doc, variants):
-        QAPISchemaType.__init__(self, name, info, doc)
+    def __init__(self, name, info, doc, ifcond, variants):
+        QAPISchemaType.__init__(self, name, info, doc, ifcond)
         assert isinstance(variants, QAPISchemaObjectTypeVariants)
         assert variants.tag_member
         variants.set_owner(name)
@@ -1444,9 +1455,9 @@ class QAPISchemaAlternateType(QAPISchemaType):
 
 
 class QAPISchemaCommand(QAPISchemaEntity):
-    def __init__(self, name, info, doc, arg_type, ret_type,
+    def __init__(self, name, info, doc, ifcond, arg_type, ret_type,
                  gen, success_response, boxed, allow_oob):
-        QAPISchemaEntity.__init__(self, name, info, doc)
+        QAPISchemaEntity.__init__(self, name, info, doc, ifcond)
         assert not arg_type or isinstance(arg_type, str)
         assert not ret_type or isinstance(ret_type, str)
         self._arg_type_name = arg_type
@@ -1485,8 +1496,8 @@ class QAPISchemaCommand(QAPISchemaEntity):
 
 
 class QAPISchemaEvent(QAPISchemaEntity):
-    def __init__(self, name, info, doc, arg_type, boxed):
-        QAPISchemaEntity.__init__(self, name, info, doc)
+    def __init__(self, name, info, doc, ifcond, arg_type, boxed):
+        QAPISchemaEntity.__init__(self, name, info, doc, ifcond)
         assert not arg_type or isinstance(arg_type, str)
         self._arg_type_name = arg_type
         self.arg_type = None
@@ -1581,22 +1592,22 @@ class QAPISchema(object):
                   ('null',   'null',    'QNull' + pointer_suffix)]:
             self._def_builtin_type(*t)
         self.the_empty_object_type = QAPISchemaObjectType(
-            'q_empty', None, None, None, [], None)
+            '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'])
-        self._def_entity(QAPISchemaEnumType('QType', None, None,
+        self._def_entity(QAPISchemaEnumType('QType', None, None, None,
                                             qtype_values, 'QTYPE'))
 
     def _make_enum_members(self, values):
         return [QAPISchemaMember(v) for v in values]
 
-    def _make_implicit_enum_type(self, name, info, values):
+    def _make_implicit_enum_type(self, name, info, ifcond, values):
         # See also QAPISchemaObjectTypeMember._pretty_owner()
         name = name + 'Kind'   # Use namespace reserved by add_name()
         self._def_entity(QAPISchemaEnumType(
-            name, info, None, self._make_enum_members(values), None))
+            name, info, None, ifcond, self._make_enum_members(values), None))
         return name
 
     def _make_array_type(self, element_type, info):
@@ -1605,22 +1616,37 @@ class QAPISchema(object):
             self._def_entity(QAPISchemaArrayType(name, info, element_type))
         return name
 
-    def _make_implicit_object_type(self, name, info, doc, role, members):
+    def _make_implicit_object_type(self, name, info, doc, ifcond,
+                                   role, members):
         if not members:
             return None
         # See also QAPISchemaObjectTypeMember._pretty_owner()
         name = 'q_obj_%s-%s' % (name, role)
-        if not self.lookup_entity(name, QAPISchemaObjectType):
-            self._def_entity(QAPISchemaObjectType(name, info, doc, None,
-                                                  members, None))
+        typ = self.lookup_entity(name, QAPISchemaObjectType)
+        if typ:
+            # The implicit object type has multiple users.  This can
+            # happen only for simple unions' implicit wrapper types.
+            # Its ifcond should be the disjunction of its user's
+            # ifconds.  Not implemented.  Instead, we always pass the
+            # wrapped type's ifcond, which is trivially the same for all
+            # users.  It's also necessary for the wrapper to compile.
+            # But it's not tight: the disjunction need not imply it.  We
+            # may end up compiling useless wrapper types.
+            # TODO kill simple unions or implement the disjunction
+            assert ifcond == typ.ifcond
+        else:
+            self._def_entity(QAPISchemaObjectType(name, info, doc, ifcond,
+                                                  None, members, None))
         return name
 
     def _def_enum_type(self, expr, info, doc):
         name = expr['enum']
         data = expr['data']
         prefix = expr.get('prefix')
+        ifcond = expr.get('if')
         self._def_entity(QAPISchemaEnumType(
-            name, info, doc, self._make_enum_members(data), prefix))
+            name, info, doc, ifcond,
+            self._make_enum_members(data), prefix))
 
     def _make_member(self, name, typ, info):
         optional = False
@@ -1640,7 +1666,8 @@ class QAPISchema(object):
         name = expr['struct']
         base = expr.get('base')
         data = expr['data']
-        self._def_entity(QAPISchemaObjectType(name, info, doc, base,
+        ifcond = expr.get('if')
+        self._def_entity(QAPISchemaObjectType(name, info, doc, ifcond, base,
                                               self._make_members(data, info),
                                               None))
 
@@ -1652,18 +1679,21 @@ class QAPISchema(object):
             assert len(typ) == 1
             typ = self._make_array_type(typ[0], info)
         typ = self._make_implicit_object_type(
-            typ, info, None, 'wrapper', [self._make_member('data', typ, info)])
+            typ, info, None, self.lookup_type(typ).ifcond,
+            'wrapper', [self._make_member('data', typ, info)])
         return QAPISchemaObjectTypeVariant(case, typ)
 
     def _def_union_type(self, expr, info, doc):
         name = expr['union']
         data = expr['data']
         base = expr.get('base')
+        ifcond = expr.get('if')
         tag_name = expr.get('discriminator')
         tag_member = None
         if isinstance(base, dict):
-            base = (self._make_implicit_object_type(
-                name, info, doc, 'base', self._make_members(base, info)))
+            base = self._make_implicit_object_type(
+                name, info, doc, ifcond,
+                'base', self._make_members(base, info))
         if tag_name:
             variants = [self._make_variant(key, value)
                         for (key, value) in data.items()]
@@ -1671,12 +1701,12 @@ class QAPISchema(object):
         else:
             variants = [self._make_simple_variant(key, value, info)
                         for (key, value) in data.items()]
-            typ = self._make_implicit_enum_type(name, info,
+            typ = self._make_implicit_enum_type(name, info, ifcond,
                                                 [v.name for v in variants])
             tag_member = QAPISchemaObjectTypeMember('type', typ, False)
             members = [tag_member]
         self._def_entity(
-            QAPISchemaObjectType(name, info, doc, base, members,
+            QAPISchemaObjectType(name, info, doc, ifcond, base, members,
                                  QAPISchemaObjectTypeVariants(tag_name,
                                                               tag_member,
                                                               variants)))
@@ -1684,11 +1714,12 @@ class QAPISchema(object):
     def _def_alternate_type(self, expr, info, doc):
         name = expr['alternate']
         data = expr['data']
+        ifcond = expr.get('if')
         variants = [self._make_variant(key, value)
                     for (key, value) in data.items()]
         tag_member = QAPISchemaObjectTypeMember('type', 'QType', False)
         self._def_entity(
-            QAPISchemaAlternateType(name, info, doc,
+            QAPISchemaAlternateType(name, info, doc, ifcond,
                                     QAPISchemaObjectTypeVariants(None,
                                                                  tag_member,
                                                                  variants)))
@@ -1701,13 +1732,14 @@ class QAPISchema(object):
         success_response = expr.get('success-response', True)
         boxed = expr.get('boxed', False)
         allow_oob = expr.get('allow-oob', False)
+        ifcond = expr.get('if')
         if isinstance(data, OrderedDict):
             data = self._make_implicit_object_type(
-                name, info, doc, 'arg', self._make_members(data, info))
+                name, info, doc, ifcond, 'arg', self._make_members(data, info))
         if isinstance(rets, list):
             assert len(rets) == 1
             rets = self._make_array_type(rets[0], info)
-        self._def_entity(QAPISchemaCommand(name, info, doc, data, rets,
+        self._def_entity(QAPISchemaCommand(name, info, doc, ifcond, data, rets,
                                            gen, success_response,
                                            boxed, allow_oob))
 
@@ -1715,10 +1747,11 @@ class QAPISchema(object):
         name = expr['event']
         data = expr.get('data')
         boxed = expr.get('boxed', False)
+        ifcond = expr.get('if')
         if isinstance(data, OrderedDict):
             data = self._make_implicit_object_type(
-                name, info, doc, 'arg', self._make_members(data, info))
-        self._def_entity(QAPISchemaEvent(name, info, doc, data, boxed))
+                name, info, doc, ifcond, 'arg', self._make_members(data, info))
+        self._def_entity(QAPISchemaEvent(name, info, doc, ifcond, data, boxed))
 
     def _def_exprs(self, exprs):
         for expr_elem in exprs:
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 05/49] qapi: leave the ifcond attribute undefined until check()
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (3 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 04/49] qapi: pass 'if' condition into QAPISchemaEntity objects Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-19  9:06   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 06/49] qapi: add 'ifcond' to visitor methods Marc-André Lureau
                   ` (48 subsequent siblings)
  53 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

We commonly initialize attributes to None in .init(), then set their
real value in .check().  Accessing the attribute before .check()
yields None.  If we're lucky, the code that accesses the attribute
prematurely chokes on None.

It won't for .ifcond, because None is a legitimate value.

Leave the ifcond attribute undefined until check().

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 | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index d8ab3d8f7f..eb07d641ab 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1026,13 +1026,19 @@ class QAPISchemaEntity(object):
         # such place).
         self.info = info
         self.doc = doc
-        self.ifcond = listify_cond(ifcond)
+        self._ifcond = ifcond  # self.ifcond is set only after .check()
 
     def c_name(self):
         return c_name(self.name)
 
     def check(self, schema):
-        pass
+        if isinstance(self._ifcond, QAPISchemaType):
+            # inherit the condition from a type
+            typ = self._ifcond
+            typ.check(schema)
+            self.ifcond = typ.ifcond
+        else:
+            self.ifcond = listify_cond(self._ifcond)
 
     def is_implicit(self):
         return not self.info
@@ -1169,6 +1175,7 @@ class QAPISchemaEnumType(QAPISchemaType):
         self.prefix = prefix
 
     def check(self, schema):
+        QAPISchemaType.check(self, schema)
         seen = {}
         for v in self.values:
             v.check_clash(self.info, seen)
@@ -1201,8 +1208,10 @@ class QAPISchemaArrayType(QAPISchemaType):
         self.element_type = None
 
     def check(self, schema):
+        QAPISchemaType.check(self, schema)
         self.element_type = schema.lookup_type(self._element_type_name)
         assert self.element_type
+        self.element_type.check(schema)
         self.ifcond = self.element_type.ifcond
 
     def is_implicit(self):
@@ -1245,6 +1254,7 @@ class QAPISchemaObjectType(QAPISchemaType):
         self.members = None
 
     def check(self, schema):
+        QAPISchemaType.check(self, schema)
         if self.members is False:               # check for cycles
             raise QAPISemError(self.info,
                                "Object %s contains itself" % self.name)
@@ -1427,6 +1437,7 @@ class QAPISchemaAlternateType(QAPISchemaType):
         self.variants = variants
 
     def check(self, schema):
+        QAPISchemaType.check(self, schema)
         self.variants.tag_member.check(schema)
         # Not calling self.variants.check_clash(), because there's nothing
         # to clash with
@@ -1470,6 +1481,7 @@ class QAPISchemaCommand(QAPISchemaEntity):
         self.allow_oob = allow_oob
 
     def check(self, schema):
+        QAPISchemaEntity.check(self, schema)
         if self._arg_type_name:
             self.arg_type = schema.lookup_type(self._arg_type_name)
             assert (isinstance(self.arg_type, QAPISchemaObjectType) or
@@ -1504,6 +1516,7 @@ class QAPISchemaEvent(QAPISchemaEntity):
         self.boxed = boxed
 
     def check(self, schema):
+        QAPISchemaEntity.check(self, schema)
         if self._arg_type_name:
             self.arg_type = schema.lookup_type(self._arg_type_name)
             assert (isinstance(self.arg_type, QAPISchemaObjectType) or
@@ -1633,7 +1646,7 @@ class QAPISchema(object):
             # But it's not tight: the disjunction need not imply it.  We
             # may end up compiling useless wrapper types.
             # TODO kill simple unions or implement the disjunction
-            assert ifcond == typ.ifcond
+            assert ifcond == typ._ifcond
         else:
             self._def_entity(QAPISchemaObjectType(name, info, doc, ifcond,
                                                   None, members, None))
@@ -1679,7 +1692,7 @@ class QAPISchema(object):
             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).ifcond,
+            typ, info, None, self.lookup_type(typ),
             'wrapper', [self._make_member('data', typ, info)])
         return QAPISchemaObjectTypeVariant(case, typ)
 
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 06/49] qapi: add 'ifcond' to visitor methods
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (4 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 05/49] qapi: leave the ifcond attribute undefined until check() Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-21  8:18   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 07/49] qapi: mcgen() shouldn't indent # lines Marc-André Lureau
                   ` (47 subsequent siblings)
  53 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Modify the test visitor to check correct passing of values.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
 scripts/qapi/commands.py               |  2 +-
 scripts/qapi/common.py                 | 31 ++++++++++++++------------
 scripts/qapi/doc.py                    | 10 ++++-----
 scripts/qapi/events.py                 |  2 +-
 scripts/qapi/introspect.py             | 12 +++++-----
 scripts/qapi/types.py                  |  8 +++----
 scripts/qapi/visit.py                  |  8 +++----
 tests/qapi-schema/qapi-schema-test.out |  9 ++++++++
 tests/qapi-schema/test-qapi.py         | 19 +++++++++++-----
 9 files changed, 61 insertions(+), 40 deletions(-)
 mode change 100644 => 100755 scripts/qapi/doc.py

diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
index 0c5da3a54d..e2366b4801 100644
--- a/scripts/qapi/commands.py
+++ b/scripts/qapi/commands.py
@@ -275,7 +275,7 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
                        c_prefix=c_name(self._prefix, protect=False)))
         genc.add(gen_registry(self._regy, self._prefix))
 
-    def visit_command(self, name, info, arg_type, ret_type,
+    def visit_command(self, name, info, ifcond, arg_type, ret_type,
                       gen, success_response, boxed, allow_oob):
         if not gen:
             return
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index eb07d641ab..bc4ecd6c76 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1067,26 +1067,26 @@ class QAPISchemaVisitor(object):
     def visit_builtin_type(self, name, info, json_type):
         pass
 
-    def visit_enum_type(self, name, info, values, prefix):
+    def visit_enum_type(self, name, info, ifcond, values, prefix):
         pass
 
-    def visit_array_type(self, name, info, element_type):
+    def visit_array_type(self, name, info, ifcond, element_type):
         pass
 
-    def visit_object_type(self, name, info, base, members, variants):
+    def visit_object_type(self, name, info, ifcond, base, members, variants):
         pass
 
-    def visit_object_type_flat(self, name, info, members, variants):
+    def visit_object_type_flat(self, name, info, ifcond, members, variants):
         pass
 
-    def visit_alternate_type(self, name, info, variants):
+    def visit_alternate_type(self, name, info, ifcond, variants):
         pass
 
-    def visit_command(self, name, info, arg_type, ret_type,
+    def visit_command(self, name, info, ifcond, arg_type, ret_type,
                       gen, success_response, boxed, allow_oob):
         pass
 
-    def visit_event(self, name, info, arg_type, boxed):
+    def visit_event(self, name, info, ifcond, arg_type, boxed):
         pass
 
 
@@ -1196,7 +1196,7 @@ class QAPISchemaEnumType(QAPISchemaType):
         return 'string'
 
     def visit(self, visitor):
-        visitor.visit_enum_type(self.name, self.info,
+        visitor.visit_enum_type(self.name, self.info, self.ifcond,
                                 self.member_names(), self.prefix)
 
 
@@ -1230,7 +1230,8 @@ class QAPISchemaArrayType(QAPISchemaType):
         return 'array of ' + elt_doc_type
 
     def visit(self, visitor):
-        visitor.visit_array_type(self.name, self.info, self.element_type)
+        visitor.visit_array_type(self.name, self.info, self.ifcond,
+                                 self.element_type)
 
 
 class QAPISchemaObjectType(QAPISchemaType):
@@ -1312,9 +1313,9 @@ class QAPISchemaObjectType(QAPISchemaType):
         return 'object'
 
     def visit(self, visitor):
-        visitor.visit_object_type(self.name, self.info,
+        visitor.visit_object_type(self.name, self.info, self.ifcond,
                                   self.base, self.local_members, self.variants)
-        visitor.visit_object_type_flat(self.name, self.info,
+        visitor.visit_object_type_flat(self.name, self.info, self.ifcond,
                                        self.members, self.variants)
 
 
@@ -1459,7 +1460,8 @@ class QAPISchemaAlternateType(QAPISchemaType):
         return 'value'
 
     def visit(self, visitor):
-        visitor.visit_alternate_type(self.name, self.info, self.variants)
+        visitor.visit_alternate_type(self.name, self.info, self.ifcond,
+                                     self.variants)
 
     def is_empty(self):
         return False
@@ -1501,7 +1503,7 @@ class QAPISchemaCommand(QAPISchemaEntity):
             assert isinstance(self.ret_type, QAPISchemaType)
 
     def visit(self, visitor):
-        visitor.visit_command(self.name, self.info,
+        visitor.visit_command(self.name, self.info, self.ifcond,
                               self.arg_type, self.ret_type,
                               self.gen, self.success_response,
                               self.boxed, self.allow_oob)
@@ -1533,7 +1535,8 @@ class QAPISchemaEvent(QAPISchemaEntity):
             raise QAPISemError(self.info, "Use of 'boxed' requires 'data'")
 
     def visit(self, visitor):
-        visitor.visit_event(self.name, self.info, self.arg_type, self.boxed)
+        visitor.visit_event(self.name, self.info, self.ifcond,
+                            self.arg_type, self.boxed)
 
 
 class QAPISchema(object):
diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
old mode 100644
new mode 100755
index 9b312b2c51..d5cfd2336b
--- a/scripts/qapi/doc.py
+++ b/scripts/qapi/doc.py
@@ -204,14 +204,14 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
     def write(self, output_dir):
         self._gen.write(output_dir, self._prefix + 'qapi-doc.texi')
 
-    def visit_enum_type(self, name, info, values, prefix):
+    def visit_enum_type(self, name, info, ifcond, values, prefix):
         doc = self.cur_doc
         self._gen.add(TYPE_FMT(type='Enum',
                                name=doc.symbol,
                                body=texi_entity(doc, 'Values',
                                                 member_func=texi_enum_value)))
 
-    def visit_object_type(self, name, info, base, members, variants):
+    def visit_object_type(self, name, info, ifcond, base, members, variants):
         doc = self.cur_doc
         if base and base.is_implicit():
             base = None
@@ -220,13 +220,13 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
                                body=texi_entity(doc, 'Members',
                                                 base, variants)))
 
-    def visit_alternate_type(self, name, info, variants):
+    def visit_alternate_type(self, name, info, ifcond, variants):
         doc = self.cur_doc
         self._gen.add(TYPE_FMT(type='Alternate',
                                name=doc.symbol,
                                body=texi_entity(doc, 'Members')))
 
-    def visit_command(self, name, info, arg_type, ret_type,
+    def visit_command(self, name, info, ifcond, arg_type, ret_type,
                       gen, success_response, boxed, allow_oob):
         doc = self.cur_doc
         if boxed:
@@ -240,7 +240,7 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
                               name=doc.symbol,
                               body=body))
 
-    def visit_event(self, name, info, arg_type, boxed):
+    def visit_event(self, name, info, ifcond, arg_type, boxed):
         doc = self.cur_doc
         self._gen.add(MSG_FMT(type='Event',
                               name=doc.symbol,
diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
index 3e448ae523..26ae00f6f7 100644
--- a/scripts/qapi/events.py
+++ b/scripts/qapi/events.py
@@ -184,7 +184,7 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
         genh.add(gen_enum(self._enum_name, self._event_names))
         genc.add(gen_enum_lookup(self._enum_name, self._event_names))
 
-    def visit_event(self, name, info, arg_type, boxed):
+    def visit_event(self, name, info, ifcond, arg_type, boxed):
         self._genh.add(gen_event_send_decl(name, arg_type, boxed))
         self._genc.add(gen_event_send(name, arg_type, boxed, self._enum_name))
         self._event_names.append(name)
diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
index f9e67e8227..6cb95cf53e 100644
--- a/scripts/qapi/introspect.py
+++ b/scripts/qapi/introspect.py
@@ -152,26 +152,26 @@ 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, values, prefix):
+    def visit_enum_type(self, name, info, ifcond, values, prefix):
         self._gen_qlit(name, 'enum', {'values': values})
 
-    def visit_array_type(self, name, info, element_type):
+    def visit_array_type(self, name, info, ifcond, element_type):
         element = self._use_type(element_type)
         self._gen_qlit('[' + element + ']', 'array', {'element-type': element})
 
-    def visit_object_type_flat(self, name, info, members, variants):
+    def visit_object_type_flat(self, name, info, ifcond, members, variants):
         obj = {'members': [self._gen_member(m) for m in members]}
         if variants:
             obj.update(self._gen_variants(variants.tag_member.name,
                                           variants.variants))
         self._gen_qlit(name, 'object', obj)
 
-    def visit_alternate_type(self, name, info, variants):
+    def visit_alternate_type(self, name, info, ifcond, variants):
         self._gen_qlit(name, 'alternate',
                        {'members': [{'type': self._use_type(m.type)}
                                     for m in variants.variants]})
 
-    def visit_command(self, name, info, arg_type, ret_type,
+    def visit_command(self, name, info, ifcond, arg_type, ret_type,
                       gen, success_response, boxed, allow_oob):
         arg_type = arg_type or self._schema.the_empty_object_type
         ret_type = ret_type or self._schema.the_empty_object_type
@@ -180,7 +180,7 @@ const QLitObject %(c_name)s = %(c_string)s;
                         'ret-type': self._use_type(ret_type),
                         'allow-oob': allow_oob})
 
-    def visit_event(self, name, info, arg_type, boxed):
+    def visit_event(self, name, info, ifcond, arg_type, boxed):
         arg_type = arg_type or self._schema.the_empty_object_type
         self._gen_qlit(name, 'event', {'arg-type': self._use_type(arg_type)})
 
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index 64d9c0fb37..298a80db62 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -206,16 +206,16 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
         self._genh.add(gen_type_cleanup_decl(name))
         self._genc.add(gen_type_cleanup(name))
 
-    def visit_enum_type(self, name, info, values, prefix):
+    def visit_enum_type(self, name, info, ifcond, values, prefix):
         self._genh.preamble_add(gen_enum(name, values, prefix))
         self._genc.add(gen_enum_lookup(name, values, prefix))
 
-    def visit_array_type(self, name, info, element_type):
+    def visit_array_type(self, name, info, ifcond, element_type):
         self._genh.preamble_add(gen_fwd_object_or_array(name))
         self._genh.add(gen_array(name, element_type))
         self._gen_type_cleanup(name)
 
-    def visit_object_type(self, name, info, base, members, variants):
+    def visit_object_type(self, name, info, ifcond, base, members, variants):
         # Nothing to do for the special empty builtin
         if name == 'q_empty':
             return
@@ -229,7 +229,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
             # implicit types won't be directly allocated/freed
             self._gen_type_cleanup(name)
 
-    def visit_alternate_type(self, name, info, variants):
+    def visit_alternate_type(self, name, info, ifcond, variants):
         self._genh.preamble_add(gen_fwd_object_or_array(name))
         self._genh.add(gen_object(name, None,
                                   [variants.tag_member], variants))
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index 3c5ea1289e..9ea2e04f81 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -301,15 +301,15 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
 ''',
                                       types=types))
 
-    def visit_enum_type(self, name, info, values, prefix):
+    def visit_enum_type(self, name, info, ifcond, values, prefix):
         self._genh.add(gen_visit_decl(name, scalar=True))
         self._genc.add(gen_visit_enum(name))
 
-    def visit_array_type(self, name, info, element_type):
+    def visit_array_type(self, name, info, ifcond, element_type):
         self._genh.add(gen_visit_decl(name))
         self._genc.add(gen_visit_list(name, element_type))
 
-    def visit_object_type(self, name, info, base, members, variants):
+    def visit_object_type(self, name, info, ifcond, base, members, variants):
         # Nothing to do for the special empty builtin
         if name == 'q_empty':
             return
@@ -322,7 +322,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
             self._genh.add(gen_visit_decl(name))
             self._genc.add(gen_visit_object(name, base, members, variants))
 
-    def visit_alternate_type(self, name, info, variants):
+    def visit_alternate_type(self, name, info, ifcond, variants):
         self._genh.add(gen_visit_decl(name))
         self._genc.add(gen_visit_alternate(name, variants))
 
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index b11682314c..8fe9d7a3a8 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -232,23 +232,32 @@ command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Unio
    gen=True success_response=True boxed=False
 object TestIfStruct
     member foo: int optional=False
+    if ['defined(TEST_IF_STRUCT)']
 enum TestIfEnum ['foo', 'bar']
+    if ['defined(TEST_IF_ENUM)']
 object q_obj_TestStruct-wrapper
     member data: TestStruct optional=False
 enum TestIfUnionKind ['foo']
+    if ['defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)']
 object TestIfUnion
     member type: TestIfUnionKind optional=False
     tag type
     case foo: q_obj_TestStruct-wrapper
+    if ['defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)']
 alternate TestIfAlternate
     tag type
     case foo: int
     case bar: TestStruct
+    if ['defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)']
 object q_obj_TestIfCmd-arg
     member foo: TestIfStruct optional=False
+    if ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)']
 command TestIfCmd q_obj_TestIfCmd-arg -> None
    gen=True success_response=True boxed=False
+    if ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)']
 object q_obj_TestIfEvent-arg
     member foo: TestIfStruct optional=False
+    if ['defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)']
 event TestIfEvent q_obj_TestIfEvent-arg
    boxed=False
+    if ['defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)']
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index 10e68b01d9..6d25a37dda 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -23,12 +23,13 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
     def visit_include(self, name, info):
         print('include %s' % name)
 
-    def visit_enum_type(self, name, info, values, prefix):
+    def visit_enum_type(self, name, info, ifcond, values, prefix):
         print('enum %s %s' % (name, values))
         if prefix:
             print('    prefix %s' % prefix)
+        self._print_if(ifcond)
 
-    def visit_object_type(self, name, info, base, members, variants):
+    def visit_object_type(self, name, info, ifcond, base, members, variants):
         print('object %s' % name)
         if base:
             print('    base %s' % base.name)
@@ -36,21 +37,25 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
             print('    member %s: %s optional=%s' % \
                   (m.name, m.type.name, m.optional))
         self._print_variants(variants)
+        self._print_if(ifcond)
 
-    def visit_alternate_type(self, name, info, variants):
+    def visit_alternate_type(self, name, info, ifcond, variants):
         print('alternate %s' % name)
         self._print_variants(variants)
+        self._print_if(ifcond)
 
-    def visit_command(self, name, info, arg_type, ret_type,
+    def visit_command(self, name, info, ifcond, arg_type, ret_type,
                       gen, success_response, boxed, allow_oob):
         print('command %s %s -> %s' % \
               (name, arg_type and arg_type.name, ret_type and ret_type.name))
         print('   gen=%s success_response=%s boxed=%s' % \
               (gen, success_response, boxed))
+        self._print_if(ifcond)
 
-    def visit_event(self, name, info, arg_type, boxed):
+    def visit_event(self, name, info, ifcond, arg_type, boxed):
         print('event %s %s' % (name, arg_type and arg_type.name))
         print('   boxed=%s' % boxed)
+        self._print_if(ifcond)
 
     @staticmethod
     def _print_variants(variants):
@@ -59,6 +64,10 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
             for v in variants.variants:
                 print('    case %s: %s' % (v.name, v.type.name))
 
+    @staticmethod
+    def _print_if(ifcond, indent=4):
+        if ifcond:
+            print('%sif %s' % (' ' * indent, ifcond))
 
 try:
     schema = QAPISchema(sys.argv[1])
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 07/49] qapi: mcgen() shouldn't indent # lines
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (5 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 06/49] qapi: add 'ifcond' to visitor methods Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-20 15:14   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 08/49] qapi: add #if/#endif helpers Marc-André Lureau
                   ` (46 subsequent siblings)
  53 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Skip preprocessor lines when adding indentation, since that would
likely result in invalid code.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/common.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index bc4ecd6c76..47efe79758 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1931,8 +1931,8 @@ def cgen(code, **kwds):
     if indent_level:
         indent = genindent(indent_level)
         # re.subn() lacks flags support before Python 2.7, use re.compile()
-        raw = re.subn(re.compile(r'^.', re.MULTILINE),
-                      indent + r'\g<0>', raw)
+        raw = re.subn(re.compile(r'^(?!(#|$))', re.MULTILINE),
+                      indent, raw)
         raw = raw[0]
     return re.sub(re.escape(eatspace) + r' *', '', raw)
 
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 08/49] qapi: add #if/#endif helpers
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (6 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 07/49] qapi: mcgen() shouldn't indent # lines Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-20 16:01   ` Markus Armbruster
  2018-06-21  7:06   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 09/49] qapi-introspect: modify to_qlit() to append ', ' on level > 0 Marc-André Lureau
                   ` (45 subsequent siblings)
  53 siblings, 2 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Add helpers to wrap generated code with #if/#endif lines.

Add QAPIGenCSnippet class to write C snippet code, make QAPIGenC
inherit from it, for full C files with copyright headers etc.

Add a 'with' statement context manager that will be used to wrap
generator visitor methods.  The manager will check if code was
generated before adding #if/#endif lines on QAPIGenCSnippet
objects. Used in the following patches.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/common.py | 82 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 78 insertions(+), 4 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 47efe79758..60c1d0a783 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -12,6 +12,7 @@
 # See the COPYING file in the top-level directory.
 
 from __future__ import print_function
+from contextlib import contextmanager
 import errno
 import os
 import re
@@ -1964,6 +1965,40 @@ def guardend(name):
                  name=guardname(name))
 
 
+def gen_if(ifcond):
+    ret = ''
+    for ifc in ifcond:
+        ret += mcgen('''
+#if %(cond)s
+''', cond=ifc)
+    return ret
+
+
+def gen_endif(ifcond):
+    ret = ''
+    for ifc in reversed(ifcond):
+        ret += mcgen('''
+#endif /* %(cond)s */
+''', cond=ifc)
+    return ret
+
+
+def wrap_ifcond(ifcond, before, after):
+    if ifcond is None or before == after:
+        return after
+
+    assert after.startswith(before)
+    out = before
+    added = after[len(before):]
+    if added[0] == '\n':
+        out += '\n'
+        added = added[1:]
+    out += gen_if(ifcond)
+    out += added
+    out += gen_endif(ifcond)
+    return out
+
+
 def gen_enum_lookup(name, values, prefix=None):
     ret = mcgen('''
 
@@ -2054,6 +2089,7 @@ class QAPIGen(object):
     def __init__(self):
         self._preamble = ''
         self._body = ''
+        self._ifcond = None
 
     def preamble_add(self, text):
         self._preamble += text
@@ -2061,6 +2097,23 @@ class QAPIGen(object):
     def add(self, text):
         self._body += text
 
+    def start_if(self, ifcond):
+        self._ifcond = ifcond
+        self._start_if_body = self._body
+        self._start_if_preamble = self._preamble
+
+    def _wrap_ifcond(self):
+        pass
+
+    def end_if(self):
+        self._wrap_ifcond()
+        self._ifcond = None
+
+    def get_content(self, fname=None):
+        assert self._ifcond is None
+        return (self._top(fname) + self._preamble + self._body
+                + self._bottom(fname))
+
     def _top(self, fname):
         return ''
 
@@ -2078,8 +2131,7 @@ class QAPIGen(object):
                     raise
         fd = os.open(pathname, os.O_RDWR | os.O_CREAT, 0o666)
         f = os.fdopen(fd, 'r+')
-        text = (self._top(fname) + self._preamble + self._body
-                + self._bottom(fname))
+        text = self.get_content(fname)
         oldtext = f.read(len(text) + 1)
         if text != oldtext:
             f.seek(0)
@@ -2088,10 +2140,32 @@ class QAPIGen(object):
         f.close()
 
 
-class QAPIGenC(QAPIGen):
+@contextmanager
+def ifcontext(ifcond, *args):
+    saved = []
+    for arg in args:
+        arg.start_if(ifcond)
+    yield
+    for arg in args:
+        arg.end_if()
 
-    def __init__(self, blurb, pydoc):
+
+class QAPIGenCSnippet(QAPIGen):
+
+    def __init__(self):
         QAPIGen.__init__(self)
+
+    def _wrap_ifcond(self):
+        self._body = wrap_ifcond(self._ifcond,
+                                 self._start_if_body, self._body)
+        self._preamble = wrap_ifcond(self._ifcond,
+                                     self._start_if_preamble, self._preamble)
+
+
+class QAPIGenC(QAPIGenCSnippet):
+
+    def __init__(self, blurb, pydoc):
+        QAPIGenCSnippet.__init__(self)
         self._blurb = blurb
         self._copyright = '\n * '.join(re.findall(r'^Copyright .*', pydoc,
                                                   re.MULTILINE))
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 09/49] qapi-introspect: modify to_qlit() to append ', ' on level > 0
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (7 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 08/49] qapi: add #if/#endif helpers Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 10/49] qapi-introspect: add preprocessor conditions to generated QLit Marc-André Lureau
                   ` (44 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

The following patch is going to break list entries with #if/#endif, so
they should have the trailing ',' as suffix.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
 scripts/qapi/introspect.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
index 6cb95cf53e..1a8eb9e33e 100644
--- a/scripts/qapi/introspect.py
+++ b/scripts/qapi/introspect.py
@@ -30,7 +30,7 @@ def to_qlit(obj, level=0, suppress_first_indent=False):
                 for elt in obj]
         elts.append(indent(level + 1) + "{}")
         ret += 'QLIT_QLIST(((QLitObject[]) {\n'
-        ret += ',\n'.join(elts) + '\n'
+        ret += '\n'.join(elts) + '\n'
         ret += indent(level) + '}))'
     elif isinstance(obj, dict):
         elts = []
@@ -45,6 +45,8 @@ def to_qlit(obj, level=0, suppress_first_indent=False):
         ret += 'QLIT_QBOOL(%s)' % ('true' if obj else 'false')
     else:
         assert False                # not implemented
+    if level > 0:
+        ret += ','
     return ret
 
 
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 10/49] qapi-introspect: add preprocessor conditions to generated QLit
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (8 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 09/49] qapi-introspect: modify to_qlit() to append ', ' on level > 0 Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-21 13:05   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 11/49] qapi/commands: add #if conditions to commands Marc-André Lureau
                   ` (43 subsequent siblings)
  53 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

The generator will take (obj, condition) tuples to wrap generated QLit
objects for 'obj' with #if/#endif conditions.

This commit adds 'ifcond' condition to top-level QLit objects.

See generated tests/test-qmp-introspect.c. Example diff after this patch:

    --- before	2018-01-08 11:55:24.757083654 +0100
    +++ tests/test-qmp-introspect.c	2018-01-08 13:08:44.477641629 +0100
    @@ -51,6 +51,8 @@
             { "name", QLIT_QSTR("EVENT_F"), },
             {}
         })),
    +#if defined(TEST_IF_CMD)
    +#if defined(TEST_IF_STRUCT)
         QLIT_QDICT(((QLitDictEntry[]) {
             { "arg-type", QLIT_QSTR("5"), },
             { "meta-type", QLIT_QSTR("command"), },
    @@ -58,12 +60,16 @@
             { "ret-type", QLIT_QSTR("0"), },
             {}
         })),
    +#endif /* defined(TEST_IF_STRUCT) */
    +#endif /* defined(TEST_IF_CMD) */

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/introspect.py | 31 +++++++++++++++++++++----------
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
index 1a8eb9e33e..cb4825f134 100644
--- a/scripts/qapi/introspect.py
+++ b/scripts/qapi/introspect.py
@@ -18,6 +18,15 @@ def to_qlit(obj, level=0, suppress_first_indent=False):
     def indent(level):
         return level * 4 * ' '
 
+    if isinstance(obj, tuple):
+        ifobj, ifcond = obj
+        ret = gen_if(ifcond)
+        ret += to_qlit(ifobj, level)
+        endif = gen_endif(ifcond)
+        if endif:
+            ret += '\n' + endif
+        return ret
+
     ret = ''
     if not suppress_first_indent:
         ret += indent(level)
@@ -26,7 +35,7 @@ def to_qlit(obj, level=0, suppress_first_indent=False):
     elif isinstance(obj, str):
         ret += 'QLIT_QSTR(' + to_c_string(obj) + ')'
     elif isinstance(obj, list):
-        elts = [to_qlit(elt, level + 1)
+        elts = [to_qlit(elt, level + 1).strip('\n')
                 for elt in obj]
         elts.append(indent(level + 1) + "{}")
         ret += 'QLIT_QLIST(((QLitObject[]) {\n'
@@ -131,12 +140,12 @@ const QLitObject %(c_name)s = %(c_string)s;
             return '[' + self._use_type(typ.element_type) + ']'
         return self._name(typ.name)
 
-    def _gen_qlit(self, name, mtype, obj):
+    def _gen_qlit(self, name, mtype, obj, ifcond):
         if mtype not in ('command', 'event', 'builtin', 'array'):
             name = self._name(name)
         obj['name'] = name
         obj['meta-type'] = mtype
-        self._qlits.append(obj)
+        self._qlits.append((obj, ifcond))
 
     def _gen_member(self, member):
         ret = {'name': member.name, 'type': self._use_type(member.type)}
@@ -152,26 +161,27 @@ const QLitObject %(c_name)s = %(c_string)s;
         return {'case': variant.name, 'type': self._use_type(variant.type)}
 
     def visit_builtin_type(self, name, info, json_type):
-        self._gen_qlit(name, 'builtin', {'json-type': json_type})
+        self._gen_qlit(name, 'builtin', {'json-type': json_type}, [])
 
     def visit_enum_type(self, name, info, ifcond, values, prefix):
-        self._gen_qlit(name, 'enum', {'values': values})
+        self._gen_qlit(name, 'enum', {'values': values}, ifcond)
 
     def visit_array_type(self, name, info, ifcond, element_type):
         element = self._use_type(element_type)
-        self._gen_qlit('[' + element + ']', 'array', {'element-type': element})
+        self._gen_qlit('[' + element + ']', 'array', {'element-type': element},
+                       ifcond)
 
     def visit_object_type_flat(self, name, info, ifcond, members, variants):
         obj = {'members': [self._gen_member(m) for m in members]}
         if variants:
             obj.update(self._gen_variants(variants.tag_member.name,
                                           variants.variants))
-        self._gen_qlit(name, 'object', obj)
+        self._gen_qlit(name, 'object', obj, ifcond)
 
     def visit_alternate_type(self, name, info, ifcond, variants):
         self._gen_qlit(name, 'alternate',
                        {'members': [{'type': self._use_type(m.type)}
-                                    for m in variants.variants]})
+                                    for m in variants.variants]}, ifcond)
 
     def visit_command(self, name, info, ifcond, arg_type, ret_type,
                       gen, success_response, boxed, allow_oob):
@@ -180,11 +190,12 @@ const QLitObject %(c_name)s = %(c_string)s;
         self._gen_qlit(name, 'command',
                        {'arg-type': self._use_type(arg_type),
                         'ret-type': self._use_type(ret_type),
-                        'allow-oob': allow_oob})
+                        'allow-oob': allow_oob}, ifcond)
 
     def visit_event(self, name, info, ifcond, arg_type, boxed):
         arg_type = arg_type or self._schema.the_empty_object_type
-        self._gen_qlit(name, 'event', {'arg-type': self._use_type(arg_type)})
+        self._gen_qlit(name, 'event', {'arg-type': self._use_type(arg_type)},
+                       ifcond)
 
 
 def gen_introspect(schema, output_dir, prefix, opt_unmask):
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 11/49] qapi/commands: add #if conditions to commands
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (9 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 10/49] qapi-introspect: add preprocessor conditions to generated QLit Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-21 14:35   ` Markus Armbruster
  2018-06-22  8:34   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 12/49] qapi/events: add #if conditions to events Marc-André Lureau
                   ` (42 subsequent siblings)
  53 siblings, 2 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Wrap generated code with #if/#endif using an 'ifcontext' on
QAPIGenCSnippet objects.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/commands.py | 19 ++++++++++---------
 tests/test-qmp-cmds.c    |  4 ++--
 2 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
index e2366b4801..40bb680b7c 100644
--- a/scripts/qapi/commands.py
+++ b/scripts/qapi/commands.py
@@ -237,7 +237,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
         QAPISchemaModularCVisitor.__init__(
             self, prefix, 'qapi-commands',
             ' * Schema-defined QAPI/QMP commands', __doc__)
-        self._regy = ''
+        self._regy = QAPIGenCSnippet()
         self._visited_ret_types = {}
 
     def _begin_module(self, name):
@@ -273,19 +273,20 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
 void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
 ''',
                        c_prefix=c_name(self._prefix, protect=False)))
-        genc.add(gen_registry(self._regy, self._prefix))
+        genc.add(gen_registry(self._regy.get_content(), self._prefix))
 
     def visit_command(self, name, info, ifcond, arg_type, ret_type,
                       gen, success_response, boxed, allow_oob):
         if not gen:
             return
-        self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type))
-        if ret_type and ret_type not in self._visited_ret_types[self._genc]:
-            self._visited_ret_types[self._genc].add(ret_type)
-            self._genc.add(gen_marshal_output(ret_type))
-        self._genh.add(gen_marshal_decl(name))
-        self._genc.add(gen_marshal(name, arg_type, boxed, ret_type))
-        self._regy += gen_register_command(name, success_response, allow_oob)
+        with ifcontext(ifcond, self._genh, self._genc, self._regy):
+            self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type))
+            if ret_type and ret_type not in self._visited_ret_types[self._genc]:
+                self._visited_ret_types[self._genc].add(ret_type)
+                self._genc.add(gen_marshal_output(ret_type))
+            self._genh.add(gen_marshal_decl(name))
+            self._genc.add(gen_marshal(name, arg_type, boxed, ret_type))
+            self._regy.add(gen_register_command(name, success_response, allow_oob))
 
 
 def gen_commands(schema, output_dir, prefix):
diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c
index c25fc2100a..e675722593 100644
--- a/tests/test-qmp-cmds.c
+++ b/tests/test-qmp-cmds.c
@@ -12,11 +12,11 @@
 
 static QmpCommandList qmp_commands;
 
-/* #if defined(TEST_IF_STRUCT) && defined(TEST_IF_CMD) */
+#if defined(TEST_IF_STRUCT) && defined(TEST_IF_CMD)
 void qmp_TestIfCmd(TestIfStruct *foo, Error **errp)
 {
 }
-/* #endif */
+#endif
 
 void qmp_user_def_cmd(Error **errp)
 {
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 12/49] qapi/events: add #if conditions to events
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (10 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 11/49] qapi/commands: add #if conditions to commands Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-21 14:40   ` Markus Armbruster
  2018-06-22  9:02   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 13/49] qapi-types: refactor variants handling Marc-André Lureau
                   ` (41 subsequent siblings)
  53 siblings, 2 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Wrap generated code with #if/#endif using an 'ifcontext' on
QAPIGenCSnippet objects.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/events.py | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
index 26ae00f6f7..dae03e3d88 100644
--- a/scripts/qapi/events.py
+++ b/scripts/qapi/events.py
@@ -185,8 +185,9 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
         genc.add(gen_enum_lookup(self._enum_name, self._event_names))
 
     def visit_event(self, name, info, ifcond, arg_type, boxed):
-        self._genh.add(gen_event_send_decl(name, arg_type, boxed))
-        self._genc.add(gen_event_send(name, arg_type, boxed, self._enum_name))
+        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)
 
 
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 13/49] qapi-types: refactor variants handling
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (11 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 12/49] qapi/events: add #if conditions to events Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-21 15:54   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 14/49] qapi-types: add #if conditions to types & visitors Marc-André Lureau
                   ` (40 subsequent siblings)
  53 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Generate variants objects outside gen_object(). This will allow to
easily wrap gen_object() with ifcond_decorator in the following patch.

gen_variants_objects() calls gen_object() for each variants, so it
remains guarded for each generated variant object.

self._gen_type_cleanup(name) is factored out in _gen_object(), helping
generated code to be wrapped by the same condition in the following
patch.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/types.py | 38 +++++++++++++++++++++++---------------
 1 file changed, 23 insertions(+), 15 deletions(-)

diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index 298a80db62..3d9b0f9a07 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -55,23 +55,27 @@ def gen_struct_members(members):
     return ret
 
 
-def gen_object(name, base, members, variants):
-    if name in objects_seen:
-        return ''
-    objects_seen.add(name)
-
+def gen_variants_objects(variants):
     ret = ''
     if variants:
         for v in variants.variants:
             if isinstance(v.type, QAPISchemaObjectType):
+                ret += gen_variants_objects(v.type.variants)
                 ret += gen_object(v.type.name, v.type.base,
                                   v.type.local_members, v.type.variants)
+    return ret
 
-    ret += mcgen('''
+
+def gen_object(name, base, members, variants):
+    if name in objects_seen:
+        return ''
+    objects_seen.add(name)
+
+    ret = mcgen('''
 
 struct %(c_name)s {
 ''',
-                 c_name=c_name(name))
+                c_name=c_name(name))
 
     if base:
         if not base.is_implicit():
@@ -215,11 +219,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
         self._genh.add(gen_array(name, element_type))
         self._gen_type_cleanup(name)
 
-    def visit_object_type(self, name, info, ifcond, base, members, variants):
-        # Nothing to do for the special empty builtin
-        if name == 'q_empty':
-            return
-        self._genh.preamble_add(gen_fwd_object_or_array(name))
+    def _gen_object(self, name, info, ifcond, base, members, variants):
         self._genh.add(gen_object(name, base, members, variants))
         if base and not base.is_implicit():
             self._genh.add(gen_upcast(name, base))
@@ -229,11 +229,19 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
             # implicit types won't be directly allocated/freed
             self._gen_type_cleanup(name)
 
+    def visit_object_type(self, name, info, ifcond, base, members, variants):
+        # Nothing to do for the special empty builtin
+        if name == 'q_empty':
+            return
+        self._genh.preamble_add(gen_fwd_object_or_array(name))
+        self._genh.add(gen_variants_objects(variants))
+        self._gen_object(name, info, None, base, members, variants)
+
     def visit_alternate_type(self, name, info, ifcond, variants):
         self._genh.preamble_add(gen_fwd_object_or_array(name))
-        self._genh.add(gen_object(name, None,
-                                  [variants.tag_member], variants))
-        self._gen_type_cleanup(name)
+        self._genh.add(gen_variants_objects(variants))
+        self._gen_object(name, info, None, None,
+                         [variants.tag_member], variants)
 
 
 def gen_types(schema, output_dir, prefix, opt_builtins):
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 14/49] qapi-types: add #if conditions to types & visitors
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (12 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 13/49] qapi-types: refactor variants handling Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-21 16:12   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 15/49] qapi: do not define enumeration value explicitely Marc-André Lureau
                   ` (39 subsequent siblings)
  53 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Types & visitors are coupled and must be handled together to avoid
temporary build regression.

Wrap generated types/visitor code with #if/#endif using the context
helpers.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/types.py | 46 ++++++++++++++++++++++++++-----------------
 scripts/qapi/visit.py | 33 ++++++++++++++++++-------------
 2 files changed, 47 insertions(+), 32 deletions(-)

diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index 3d9b0f9a07..ce4c91206c 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -61,8 +61,10 @@ def gen_variants_objects(variants):
         for v in variants.variants:
             if isinstance(v.type, QAPISchemaObjectType):
                 ret += gen_variants_objects(v.type.variants)
+                ret += gen_if(v.type.ifcond)
                 ret += gen_object(v.type.name, v.type.base,
                                   v.type.local_members, v.type.variants)
+                ret += gen_endif(v.type.ifcond)
     return ret
 
 
@@ -206,41 +208,49 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
         # gen_object() is recursive, ensure it doesn't visit the empty type
         objects_seen.add(schema.the_empty_object_type.name)
 
-    def _gen_type_cleanup(self, name):
-        self._genh.add(gen_type_cleanup_decl(name))
-        self._genc.add(gen_type_cleanup(name))
+    def _gen_type_cleanup(self, name, ifcond):
+        with ifcontext(ifcond, self._genh, self._genc):
+            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):
-        self._genh.preamble_add(gen_enum(name, values, prefix))
-        self._genc.add(gen_enum_lookup(name, values, prefix))
+        with ifcontext(ifcond, self._genh, self._genc):
+            self._genh.preamble_add(gen_enum(name, values, prefix))
+            self._genc.add(gen_enum_lookup(name, values, prefix))
 
     def visit_array_type(self, name, info, ifcond, element_type):
-        self._genh.preamble_add(gen_fwd_object_or_array(name))
-        self._genh.add(gen_array(name, element_type))
-        self._gen_type_cleanup(name)
+        with ifcontext(ifcond, self._genh):
+            self._genh.preamble_add(gen_fwd_object_or_array(name))
+            self._genh.add(gen_array(name, element_type))
+        self._gen_type_cleanup(name, ifcond)
 
     def _gen_object(self, name, info, ifcond, base, members, variants):
-        self._genh.add(gen_object(name, base, members, variants))
-        if base and not base.is_implicit():
-            self._genh.add(gen_upcast(name, base))
-        # TODO Worth changing the visitor signature, so we could
-        # directly use rather than repeat type.is_implicit()?
+        with ifcontext(ifcond, self._genh):
+            self._genh.add(gen_object(name, base, members, variants))
+            if base and not base.is_implicit():
+                self._genh.add(gen_upcast(name, base))
+            # TODO Worth changing the visitor signature, so we could
+            # directly use rather than repeat type.is_implicit()?
         if not name.startswith('q_'):
             # implicit types won't be directly allocated/freed
-            self._gen_type_cleanup(name)
+            self._gen_type_cleanup(name, ifcond)
+
+    def _gen_fwd_object_or_array(self, name, ifcond):
+        with ifcontext(ifcond, self._genh):
+            self._genh.preamble_add(gen_fwd_object_or_array(name))
 
     def visit_object_type(self, name, info, ifcond, base, members, variants):
         # Nothing to do for the special empty builtin
         if name == 'q_empty':
             return
-        self._genh.preamble_add(gen_fwd_object_or_array(name))
+        self._gen_fwd_object_or_array(name, ifcond)
         self._genh.add(gen_variants_objects(variants))
-        self._gen_object(name, info, None, base, members, variants)
+        self._gen_object(name, info, ifcond, base, members, variants)
 
     def visit_alternate_type(self, name, info, ifcond, variants):
-        self._genh.preamble_add(gen_fwd_object_or_array(name))
+        self._gen_fwd_object_or_array(name, ifcond)
         self._genh.add(gen_variants_objects(variants))
-        self._gen_object(name, info, None, None,
+        self._gen_object(name, info, ifcond, None,
                          [variants.tag_member], variants)
 
 
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index 9ea2e04f81..e4a62ce030 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -302,29 +302,34 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
                                       types=types))
 
     def visit_enum_type(self, name, info, ifcond, values, prefix):
-        self._genh.add(gen_visit_decl(name, scalar=True))
-        self._genc.add(gen_visit_enum(name))
+        with ifcontext(ifcond, self._genh, self._genc):
+            self._genh.add(gen_visit_decl(name, scalar=True))
+            self._genc.add(gen_visit_enum(name))
 
     def visit_array_type(self, name, info, ifcond, element_type):
-        self._genh.add(gen_visit_decl(name))
-        self._genc.add(gen_visit_list(name, element_type))
+        with ifcontext(ifcond, self._genh, self._genc):
+            self._genh.add(gen_visit_decl(name))
+            self._genc.add(gen_visit_list(name, element_type))
 
     def visit_object_type(self, name, info, ifcond, base, members, variants):
         # Nothing to do for the special empty builtin
         if name == 'q_empty':
             return
-        self._genh.add(gen_visit_members_decl(name))
-        self._genc.add(gen_visit_object_members(name, base, members, variants))
-        # TODO Worth changing the visitor signature, so we could
-        # directly use rather than repeat type.is_implicit()?
-        if not name.startswith('q_'):
-            # only explicit types need an allocating visit
-            self._genh.add(gen_visit_decl(name))
-            self._genc.add(gen_visit_object(name, base, members, variants))
+        with ifcontext(ifcond, self._genh, self._genc):
+            self._genh.add(gen_visit_members_decl(name))
+            self._genc.add(gen_visit_object_members(name, base,
+                                                    members, variants))
+            # TODO Worth changing the visitor signature, so we could
+            # directly use rather than repeat type.is_implicit()?
+            if not name.startswith('q_'):
+                # only explicit types need an allocating visit
+                self._genh.add(gen_visit_decl(name))
+                self._genc.add(gen_visit_object(name, base, members, variants))
 
     def visit_alternate_type(self, name, info, ifcond, variants):
-        self._genh.add(gen_visit_decl(name))
-        self._genc.add(gen_visit_alternate(name, variants))
+        with ifcontext(ifcond, self._genh, self._genc):
+            self._genh.add(gen_visit_decl(name))
+            self._genc.add(gen_visit_alternate(name, variants))
 
 
 def gen_visit(schema, output_dir, prefix, opt_builtins):
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 15/49] qapi: do not define enumeration value explicitely
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (13 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 14/49] qapi-types: add #if conditions to types & visitors Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-22  8:08   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 16/49] qapi: rename QAPISchemaEnumType.values to .members Marc-André Lureau
                   ` (38 subsequent siblings)
  53 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

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.

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 60c1d0a783..68a567f53f 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -2032,14 +2032,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.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 16/49] qapi: rename QAPISchemaEnumType.values to .members
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (14 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 15/49] qapi: do not define enumeration value explicitely Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-22 12:24   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 17/49] qapi: change enum visitor to take QAPISchemaMember Marc-André Lureau
                   ` (37 subsequent siblings)
  53 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

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>
---
 scripts/qapi/common.py         | 36 +++++++++++++++++-----------------
 scripts/qapi/doc.py            |  2 +-
 scripts/qapi/introspect.py     |  4 ++--
 scripts/qapi/types.py          |  6 +++---
 scripts/qapi/visit.py          |  2 +-
 tests/qapi-schema/test-qapi.py |  4 ++--
 6 files changed, 27 insertions(+), 27 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 68a567f53f..ea5cdfe3be 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1068,7 +1068,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):
@@ -1166,22 +1166,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()
@@ -1191,7 +1191,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'
@@ -1999,19 +1999,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, prefix)
         ret += mcgen('''
         [%(index)s] = "%(value)s",
 ''',
-                     index=index, value=value)
+                     index=index, value=m)
 
     ret += mcgen('''
     },
@@ -2022,9 +2022,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 + ['_MAX']
 
     ret = mcgen('''
 
@@ -2032,11 +2032,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, prefix))
 
     ret += mcgen('''
 } %(c_name)s;
diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
index d5cfd2336b..6c2bf98e1d 100755
--- a/scripts/qapi/doc.py
+++ b/scripts/qapi/doc.py
@@ -204,7 +204,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/introspect.py b/scripts/qapi/introspect.py
index cb4825f134..66f7fd00a9 100644
--- a/scripts/qapi/introspect.py
+++ b/scripts/qapi/introspect.py
@@ -163,8 +163,8 @@ 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': 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 ce4c91206c..5b790cb41d 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -213,10 +213,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):
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index e4a62ce030..ee776386ae 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -301,7 +301,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 6d25a37dda..f4b8feb9bc 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, members))
         if prefix:
             print('    prefix %s' % prefix)
         self._print_if(ifcond)
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 17/49] qapi: change enum visitor to take QAPISchemaMember
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (15 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 16/49] qapi: rename QAPISchemaEnumType.values to .members Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-22 12:24   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 18/49] tests: modify visit_enum_type() in test-qapi to print members Marc-André Lureau
                   ` (36 subsequent siblings)
  53 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

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.

Suggested-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/common.py         | 12 ++++++------
 scripts/qapi/events.py         |  2 +-
 scripts/qapi/introspect.py     |  3 ++-
 tests/qapi-schema/test-qapi.py |  2 +-
 4 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index ea5cdfe3be..4d19146064 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1198,7 +1198,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):
@@ -2007,11 +2007,11 @@ const QEnumLookup %(c_name)s_lookup = {
 ''',
                 c_name=c_name(name))
     for m in members:
-        index = c_enum_const(name, m, prefix)
+        index = c_enum_const(name, m.name, prefix)
         ret += mcgen('''
-        [%(index)s] = "%(value)s",
+        [%(index)s] = "%(name)s",
 ''',
-                     index=index, value=m)
+                     index=index, name=m.name)
 
     ret += mcgen('''
     },
@@ -2024,7 +2024,7 @@ const QEnumLookup %(c_name)s_lookup = {
 
 def gen_enum(name, members, prefix=None):
     # append automatically generated _MAX value
-    enum_members = members + ['_MAX']
+    enum_members = members + [QAPISchemaMember('_MAX')]
 
     ret = mcgen('''
 
@@ -2036,7 +2036,7 @@ typedef enum %(c_name)s {
         ret += mcgen('''
     %(c_enum)s,
 ''',
-                     c_enum=c_enum_const(name, m, prefix))
+                     c_enum=c_enum_const(name, m.name, prefix))
 
     ret += mcgen('''
 } %(c_name)s;
diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
index dae03e3d88..233c27a6c8 100644
--- a/scripts/qapi/events.py
+++ b/scripts/qapi/events.py
@@ -188,7 +188,7 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
         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_names.append(QAPISchemaMember(name))
 
 
 def gen_events(schema, output_dir, prefix):
diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
index 66f7fd00a9..d62fca84de 100644
--- a/scripts/qapi/introspect.py
+++ b/scripts/qapi/introspect.py
@@ -164,7 +164,8 @@ const QLitObject %(c_name)s = %(c_string)s;
         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': members}, ifcond)
+        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/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index f4b8feb9bc..3623deae62 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -24,7 +24,7 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
         print('include %s' % name)
 
     def visit_enum_type(self, name, info, ifcond, members, prefix):
-        print('enum %s %s' % (name, members))
+        print('enum %s %s' % (name, [m.name for m in members]))
         if prefix:
             print('    prefix %s' % prefix)
         self._print_if(ifcond)
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 18/49] tests: modify visit_enum_type() in test-qapi to print members
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (16 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 17/49] qapi: change enum visitor to take QAPISchemaMember Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-22 14:10   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 19/49] qapi: factor out check_known_keys() Marc-André Lureau
                   ` (35 subsequent siblings)
  53 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Use a common self._print_members() to print enum members details.

Signed-off-by: Marc-André Lureau <marcandre.lureau@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   | 49 +++++++++++++++++++-----
 tests/qapi-schema/test-qapi.py           | 18 ++++++---
 12 files changed, 158 insertions(+), 31 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 430b5a87db..3cd5c094aa 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
 object Base
     member base1: Enum optional=False
 object Variant1
@@ -17,7 +26,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 ee3b34e623..41b90fb944 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 a79935e8c3..e2ede80310 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
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 8fe9d7a3a8..fb89a798dd 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,24 @@ 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
-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']
+enum EnumOne
+    member value1
+    member value2
+    member value3
 object UserDefZero
     member integer: int optional=False
 object UserDefTwoDictDict
@@ -124,7 +136,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
@@ -197,7 +223,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
@@ -206,7 +233,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
@@ -233,11 +261,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 3623deae62..7e7b8f9f0f 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -12,7 +12,8 @@
 
 from __future__ import print_function
 import sys
-from qapi.common import QAPIError, QAPISchema, QAPISchemaVisitor
+from qapi.common import QAPIError, QAPISchema, QAPISchemaVisitor, \
+    QAPISchemaObjectTypeMember
 
 
 class QAPISchemaTestVisitor(QAPISchemaVisitor):
@@ -24,18 +25,17 @@ 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)
+        self._print_members(members)
         self._print_if(ifcond)
 
     def visit_object_type(self, name, info, ifcond, base, members, variants):
         print('object %s' % name)
         if base:
             print('    base %s' % base.name)
-        for m in members:
-            print('    member %s: %s optional=%s' % \
-                  (m.name, m.type.name, m.optional))
+        self._print_members(members)
         self._print_variants(variants)
         self._print_if(ifcond)
 
@@ -57,6 +57,14 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
         print('   boxed=%s' % boxed)
         self._print_if(ifcond)
 
+    @staticmethod
+    def _print_members(members):
+        for m in members:
+            print('    member %s%s' % (
+                m.name,
+                ': %s optional=%s' % (m.type.name, m.optional)
+                if isinstance(m, QAPISchemaObjectTypeMember) else ''))
+
     @staticmethod
     def _print_variants(variants):
         if variants:
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 19/49] qapi: factor out check_known_keys()
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (17 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 18/49] tests: modify visit_enum_type() in test-qapi to print members Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-25 14:10   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 20/49] qapi: add a dictionnary form with 'name' key for enum members Marc-André Lureau
                   ` (34 subsequent siblings)
  53 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

The following patches are going to need similar checks from various
code path. This refactoring will report all conflicting keys (instead
of the first one encountered).

Modify unknown-expr-key to check plural form.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/common.py                  | 27 ++++++++++++++++++-------
 tests/qapi-schema/alternate-base.err    |  2 +-
 tests/qapi-schema/double-type.err       |  2 +-
 tests/qapi-schema/enum-missing-data.err |  2 +-
 tests/qapi-schema/unknown-expr-key.err  |  2 +-
 tests/qapi-schema/unknown-expr-key.json |  2 +-
 6 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 4d19146064..fdbb5f1823 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -879,6 +879,24 @@ def check_struct(expr, info):
                allow_metas=['struct'])
 
 
+def check_known_keys(info, source, keys, required, optional):
+
+    def pprint(elems):
+        return ', '.join("'" + e + "'" for e in sorted(elems))
+
+    missing = set(required) - set(keys)
+    if missing:
+        raise QAPISemError(info, "%s must have %s key%s"
+                           % (source, pprint(missing),
+                              's' if len(missing) > 1 else ''))
+    allowed = set(required + optional)
+    unknown = set(keys) - allowed
+    if unknown:
+        raise QAPISemError(info, "%s has unknown key%s %s (allowed: %s)"
+                           % (source, 's' if len(unknown) > 1 else '',
+                              pprint(unknown), pprint(allowed)))
+
+
 def check_keys(expr_elem, meta, required, optional=[]):
     expr = expr_elem['expr']
     info = expr_elem['info']
@@ -886,10 +904,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, 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 == 'gen' or key == 'success-response') and value is not False:
             raise QAPISemError(info,
                                "'%s' of %s '%s' should only use false value"
@@ -900,10 +917,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):
diff --git a/tests/qapi-schema/alternate-base.err b/tests/qapi-schema/alternate-base.err
index 30d8a34373..2b09c4c7a3 100644
--- a/tests/qapi-schema/alternate-base.err
+++ b/tests/qapi-schema/alternate-base.err
@@ -1 +1 @@
-tests/qapi-schema/alternate-base.json:4: Unknown key 'base' in alternate 'Alt'
+tests/qapi-schema/alternate-base.json:4: alternate 'Alt' has unknown key 'base' (allowed: 'alternate', 'data', 'if')
diff --git a/tests/qapi-schema/double-type.err b/tests/qapi-schema/double-type.err
index f9613c6d6b..a8c5637659 100644
--- a/tests/qapi-schema/double-type.err
+++ b/tests/qapi-schema/double-type.err
@@ -1 +1 @@
-tests/qapi-schema/double-type.json:2: Unknown key 'command' in struct 'bar'
+tests/qapi-schema/double-type.json:2: struct 'bar' has unknown key 'command' (allowed: 'base', 'data', 'if', 'struct')
diff --git a/tests/qapi-schema/enum-missing-data.err b/tests/qapi-schema/enum-missing-data.err
index ba4873ae69..68e286badc 100644
--- a/tests/qapi-schema/enum-missing-data.err
+++ b/tests/qapi-schema/enum-missing-data.err
@@ -1 +1 @@
-tests/qapi-schema/enum-missing-data.json:2: Key 'data' is missing from enum 'MyEnum'
+tests/qapi-schema/enum-missing-data.json:2: enum 'MyEnum' must have 'data' key
diff --git a/tests/qapi-schema/unknown-expr-key.err b/tests/qapi-schema/unknown-expr-key.err
index 12f5ed5b43..d9f4e41cac 100644
--- a/tests/qapi-schema/unknown-expr-key.err
+++ b/tests/qapi-schema/unknown-expr-key.err
@@ -1 +1 @@
-tests/qapi-schema/unknown-expr-key.json:2: Unknown key 'bogus' in struct 'bar'
+tests/qapi-schema/unknown-expr-key.json:2: struct 'bar' has unknown keys 'bogus', 'foo' (allowed: 'base', 'data', 'if', 'struct')
diff --git a/tests/qapi-schema/unknown-expr-key.json b/tests/qapi-schema/unknown-expr-key.json
index 3b2be00cc4..5bcb8efd1d 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': { }, 'foo': { } }
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 20/49] qapi: add a dictionnary form with 'name' key for enum members
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (18 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 19/49] qapi: factor out check_known_keys() Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 21/49] qapi: add 'if' to " Marc-André Lureau
                   ` (33 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

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  |  1 +
 .../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-missing-data.err       |  2 +-
 13 files changed, 51 insertions(+), 13 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 fdbb5f1823..6aece364f1 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -739,6 +739,10 @@ def check_event(expr, info):
                allow_metas=meta)
 
 
+def enum_get_names(expr):
+    return [e['name'] for e in expr['data']]
+
+
 def check_union(expr, info):
     name = expr['union']
     base = expr.get('base')
@@ -798,7 +802,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'"
@@ -806,7 +810,7 @@ def check_union(expr, info):
 
     # If discriminator is user-defined, ensure all values are covered
     if enum_define:
-        for value in enum_define['data']:
+        for value in enum_get_names(enum_define):
             if value not in members.keys():
                 raise QAPISemError(info, "Union '%s' data missing '%s' branch"
                                    % (name, value))
@@ -837,10 +841,10 @@ 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
+                    if re.match(r'[-+0-9.]', v):  # lazy, could be tightened
                         conflicting.add('QTYPE_QNUM')
             else:
                 conflicting.add('QTYPE_QNUM')
@@ -853,19 +857,34 @@ def check_alternate(expr, info):
             types_seen[qt] = key
 
 
-def check_enum(expr, info):
+def normalize_enum(expr, info):
     name = expr['enum']
     members = expr.get('data')
-    prefix = expr.get('prefix')
 
     if not isinstance(members, list):
         raise QAPISemError(info,
                            "Enum '%s' requires an array for 'data'" % name)
+
+    # translate short member form to dict form
+    for i, member in enumerate(members):
+        if not isinstance(member, dict):
+            member = {'name': member}
+            members[i] = member
+
+
+def check_enum(expr, info):
+    name = expr['enum']
+    members = expr.get('data')
+    prefix = expr.get('prefix')
+
     if prefix is not None and not isinstance(prefix, str):
         raise QAPISemError(info,
                            "Enum '%s' requires a string for 'prefix'" % name)
+
     for member in members:
-        check_name(info, "Member of enum '%s'" % name, member,
+        source = "Dictionary member of enum '%s'" % name
+        check_known_keys(info, source, member, ['name'], [])
+        check_name(info, "Member of enum '%s'" % name, member['name'],
                    enum_member=True)
 
 
@@ -926,6 +945,13 @@ def check_exprs(exprs):
     for builtin in builtin_types.keys():
         all_names[builtin] = 'built-in'
 
+    # Normalize exprs
+    for expr_elem in exprs:
+        expr = expr_elem['expr']
+        info = expr_elem['info']
+        if 'enum' in expr:
+            normalize_enum(expr, info)
+
     # Learn the types and check for valid expression keys
     for expr_elem in exprs:
         expr = expr_elem['expr']
@@ -1631,7 +1657,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 f77ad2ba3b..444c3fd33e 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -476,10 +476,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..7ed48beb2e
--- /dev/null
+++ b/tests/qapi-schema/enum-dict-member-unknown.err
@@ -0,0 +1 @@
+tests/qapi-schema/enum-dict-member-unknown.json:2: Dictionary member of enum 'MyEnum' has unknown key 'bad-key' (allowed: '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' } ] }
diff --git a/tests/qapi-schema/enum-missing-data.err b/tests/qapi-schema/enum-missing-data.err
index 68e286badc..b8ccae071b 100644
--- a/tests/qapi-schema/enum-missing-data.err
+++ b/tests/qapi-schema/enum-missing-data.err
@@ -1 +1 @@
-tests/qapi-schema/enum-missing-data.json:2: enum 'MyEnum' must have 'data' key
+tests/qapi-schema/enum-missing-data.json:2: Enum 'MyEnum' requires an array for 'data'
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 21/49] qapi: add 'if' to enum members
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (19 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 20/49] qapi: add a dictionnary form with 'name' key for enum members Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 22/49] qapi-event: add 'if' condition to implicit event enum Marc-André Lureau
                   ` (32 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

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).

Generated code is not changed by this patch, but with "qapi: add #if
conditions to generated code" patch.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/common.py                         | 10 +++++++---
 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 +
 10 files changed, 20 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 6aece364f1..22ea286191 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -883,7 +883,8 @@ def check_enum(expr, info):
 
     for member in members:
         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)
         check_name(info, "Member of enum '%s'" % name, member['name'],
                    enum_member=True)
 
@@ -1362,9 +1363,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):
@@ -1661,9 +1663,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/tests/Makefile.include b/tests/Makefile.include
index 444c3fd33e..19873ea887 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -481,6 +481,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 7ed48beb2e..3699c89167 100644
--- a/tests/qapi-schema/enum-dict-member-unknown.err
+++ b/tests/qapi-schema/enum-dict-member-unknown.err
@@ -1 +1 @@
-tests/qapi-schema/enum-dict-member-unknown.json:2: Dictionary member of enum 'MyEnum' has unknown key 'bad-key' (allowed: 'name')
+tests/qapi-schema/enum-dict-member-unknown.json:2: Dictionary member of enum 'MyEnum' has unknown key 'bad-key' (allowed: '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 b997b2d43d..6a1d3b6337 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -194,7 +194,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' },
@@ -203,7 +204,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' },
   'if': ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)'] }
 
 { 'event': 'TestIfEvent', 'data': { 'foo': 'TestIfStruct' },
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index fb89a798dd..bcef80efeb 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -264,6 +264,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
@@ -282,6 +283,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 -> None
    gen=True success_response=True boxed=False
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index 7e7b8f9f0f..9582742f90 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -64,6 +64,7 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
                 m.name,
                 ': %s optional=%s' % (m.type.name, m.optional)
                 if isinstance(m, QAPISchemaObjectTypeMember) else ''))
+            QAPISchemaTestVisitor._print_if(m.ifcond, 8)
 
     @staticmethod
     def _print_variants(variants):
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 22/49] qapi-event: add 'if' condition to implicit event enum
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (20 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 21/49] qapi: add 'if' to " Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 23/49] qapi: rename allow_dict to allow_implicit Marc-André Lureau
                   ` (31 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Add condition to QAPIEvent enum members based on the event 'if'.

Generated code is not changed by this patch, but with "qapi: add #if
conditions to generated code" patch.

There is no coverage of this change in qapi-schema-test.out since the
event_names enum is an implicit type created by qapi-event.py.

Signed-off-by: Marc-André Lureau <marcandre.lureau@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 233c27a6c8..f02b65cf5a 100644
--- a/scripts/qapi/events.py
+++ b/scripts/qapi/events.py
@@ -188,7 +188,7 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
         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(QAPISchemaMember(name))
+        self._event_names.append(QAPISchemaMember(name, ifcond))
 
 
 def gen_events(schema, output_dir, prefix):
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 23/49] qapi: rename allow_dict to allow_implicit
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (21 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 22/49] qapi-event: add 'if' condition to implicit event enum Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 24/49] qapi: add a dictionary form with 'type' key for members Marc-André Lureau
                   ` (30 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

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 22ea286191..9eb2b0cc37 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -660,7 +660,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
 
@@ -687,7 +687,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):
@@ -717,7 +717,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:
@@ -735,7 +735,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)
 
 
@@ -763,7 +763,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"
@@ -894,7 +894,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.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 24/49] qapi: add a dictionary form with 'type' key for members
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (22 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 23/49] qapi: rename allow_dict to allow_implicit Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-20 11:13   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 25/49] qapi: add 'if' to implicit struct members Marc-André Lureau
                   ` (29 subsequent siblings)
  53 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

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                        | 57 ++++++++++++-------
 tests/Makefile.include                        |  3 +
 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
 tests/qapi-schema/event-nest-struct.err       |  2 +-
 tests/qapi-schema/flat-union-inline.err       |  2 +-
 tests/qapi-schema/nested-struct-data.err      |  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
 18 files changed, 66 insertions(+), 27 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/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 9eb2b0cc37..3f46ed5530 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -587,11 +587,11 @@ def discriminator_find_enum_define(expr):
     if not base_members:
         return None
 
-    discriminator_type = base_members.get(discriminator)
-    if not discriminator_type:
+    discriminator_member = base_members.get(discriminator)
+    if not discriminator_member:
         return None
 
-    return enum_types.get(discriminator_type)
+    return enum_types.get(discriminator_member['type'])
 
 
 # Names must be letters, numbers, -, and _.  They must start with letter,
@@ -659,6 +659,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=[]):
@@ -703,8 +712,9 @@ 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,
+        member_source = "Member '%s' of %s" % (key, source)
+        check_known_keys(info, member_source, arg, ['type'], [])
+        check_type(info, member_source, arg['type'], allow_array=True,
                    allow_metas=['built-in', 'union', 'alternate', 'struct',
                                 'enum'])
 
@@ -775,13 +785,13 @@ 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_member = base_members.get(discriminator)
+        if not discriminator_member:
             raise QAPISemError(info,
                                "Discriminator '%s' is not a member of base "
                                "struct '%s'"
                                % (discriminator, base))
-        enum_define = enum_types.get(discriminator_type)
+        enum_define = enum_types.get(discriminator_member['type'])
         allow_metas = ['struct']
         # Do not allow string discriminator
         if not enum_define:
@@ -793,11 +803,14 @@ def check_union(expr, info):
     if len(members) == 0:
         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)
+        source = "Member of union '%s'" % name
+        check_name(info, source, key)
+        check_known_keys(info, source, value, ['type'], [])
+        typ = value['type']
 
         # 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.
@@ -828,18 +841,20 @@ def check_alternate(expr, info):
                            "in 'data'" % name)
     for (key, value) in members.items():
         check_name(info, "Member of alternate '%s'" % name, key)
+        source = "Member '%s' of alternate '%s'" % (key, name)
+        check_known_keys(info, source, value, ['type'], [])
+        typ = value['type']
 
         # Ensure alternates have no type conflicts.
-        check_type(info, "Member '%s' of alternate '%s'" % (key, name),
-                   value,
+        check_type(info, source, 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']:
@@ -952,6 +967,10 @@ def check_exprs(exprs):
         info = expr_elem['info']
         if 'enum' in expr:
             normalize_enum(expr, info)
+        elif 'union' in expr:
+            normalize_members(expr, 'base')
+        if {'union', 'alternate', 'struct', 'command', 'event'} & set(expr):
+            normalize_members(expr, 'data')
 
     # Learn the types and check for valid expression keys
     for expr_elem in exprs:
@@ -1726,7 +1745,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):
@@ -1762,11 +1781,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])
@@ -1782,7 +1801,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 19873ea887..7a46c1620d 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -415,6 +415,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
@@ -556,6 +557,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
@@ -567,6 +569,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..39d3b6bca5
--- /dev/null
+++ b/tests/qapi-schema/alternate-invalid-dict.err
@@ -0,0 +1 @@
+tests/qapi-schema/alternate-invalid-dict.json:2: Member 'two' of alternate 'Alt' must have 'type' key
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..45f2c8ebef
--- /dev/null
+++ b/tests/qapi-schema/alternate-invalid-dict.json
@@ -0,0 +1,4 @@
+# invalid field dictionnary, missing 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-nest-struct.err b/tests/qapi-schema/event-nest-struct.err
index 5a42701b8f..66cd141112 100644
--- a/tests/qapi-schema/event-nest-struct.err
+++ b/tests/qapi-schema/event-nest-struct.err
@@ -1 +1 @@
-tests/qapi-schema/event-nest-struct.json:1: Member 'a' of 'data' for event 'EVENT_A' should be a type name
+tests/qapi-schema/event-nest-struct.json:1: Member 'a' of 'data' for event 'EVENT_A' must have 'type' key
diff --git a/tests/qapi-schema/flat-union-inline.err b/tests/qapi-schema/flat-union-inline.err
index 2333358d28..82d511c7ef 100644
--- a/tests/qapi-schema/flat-union-inline.err
+++ b/tests/qapi-schema/flat-union-inline.err
@@ -1 +1 @@
-tests/qapi-schema/flat-union-inline.json:7: Member 'value1' of union 'TestUnion' should be a type name
+tests/qapi-schema/flat-union-inline.json:7: Member of union 'TestUnion' must have 'type' key
diff --git a/tests/qapi-schema/nested-struct-data.err b/tests/qapi-schema/nested-struct-data.err
index da767bade2..728591fde3 100644
--- a/tests/qapi-schema/nested-struct-data.err
+++ b/tests/qapi-schema/nested-struct-data.err
@@ -1 +1 @@
-tests/qapi-schema/nested-struct-data.json:2: Member 'a' of 'data' for command 'foo' should be a type name
+tests/qapi-schema/nested-struct-data.json:2: Member 'a' of 'data' for command 'foo' must have 'type' key
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index 6a1d3b6337..71023fb277 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',
@@ -74,7 +74,7 @@
 { 'union': 'UserDefFlatUnion',
   'base': 'UserDefUnionBase',   # intentional forward reference
   'discriminator': 'enum1',
-  'data': { 'value1' : 'UserDefA',
+  'data': { 'value1' : {'type': 'UserDefA'},
             'value2' : 'UserDefB',
             'value3' : 'UserDefB' } }
 
@@ -93,7 +93,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',
@@ -129,7 +129,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' }
 
 # Returning a non-dictionary requires a name from the whitelist
@@ -156,7 +156,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..8435a78cb4
--- /dev/null
+++ b/tests/qapi-schema/struct-member-invalid-dict.err
@@ -0,0 +1 @@
+tests/qapi-schema/struct-member-invalid-dict.json:2: Member '*a' of 'data' for struct 'foo' must have 'type' key
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..ebd9733b49
--- /dev/null
+++ b/tests/qapi-schema/struct-member-invalid-dict.json
@@ -0,0 +1,3 @@
+# exploded member form must have a '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..65f9999fc0
--- /dev/null
+++ b/tests/qapi-schema/union-branch-invalid-dict.err
@@ -0,0 +1 @@
+tests/qapi-schema/union-branch-invalid-dict.json:2: Member of union 'UnionInvalidBranch' must have 'type' key
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..19c5d9cacd
--- /dev/null
+++ b/tests/qapi-schema/union-branch-invalid-dict.json
@@ -0,0 +1,4 @@
+# exploded member form must have a '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.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 25/49] qapi: add 'if' to implicit struct members
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (23 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 24/49] qapi: add a dictionary form with 'type' key for members Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 26/49] qapi: add an error in case a discriminator is conditionnal Marc-André Lureau
                   ` (28 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Generated code is not changed by this patch, but with "qapi: add #if
conditions to generated code" patch.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/common.py                  | 14 +++++++-------
 tests/qapi-schema/qapi-schema-test.json | 12 +++++++++---
 tests/qapi-schema/qapi-schema-test.out  |  5 +++++
 3 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 3f46ed5530..bbcb417a47 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -713,7 +713,7 @@ def check_type(info, source, value, allow_array=False,
         # Todo: allow dictionaries to represent default values of
         # an optional argument.
         member_source = "Member '%s' of %s" % (key, source)
-        check_known_keys(info, member_source, arg, ['type'], [])
+        check_known_keys(info, member_source, arg, ['type'], ['if'])
         check_type(info, member_source, arg['type'], allow_array=True,
                    allow_metas=['built-in', 'union', 'alternate', 'struct',
                                 'enum'])
@@ -1426,8 +1426,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
@@ -1734,7 +1734,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:]
@@ -1742,10 +1742,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):
@@ -1766,7 +1766,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/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index 71023fb277..e29c9f0769 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -191,7 +191,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':
@@ -204,8 +206,12 @@
 { '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)' } },
   'if': ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)'] }
 
-{ '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 bcef80efeb..e1e41acd52 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -260,6 +260,8 @@ command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Unio
    gen=True success_response=True boxed=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
@@ -284,12 +286,15 @@ 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 -> None
    gen=True success_response=True boxed=False
     if ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)']
 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
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 26/49] qapi: add an error in case a discriminator is conditionnal
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (24 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 25/49] qapi: add 'if' to implicit struct members Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 27/49] qapi: add 'if' on union members Marc-André Lureau
                   ` (27 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Making a discriminator conditonal 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                          | 11 +++++++++--
 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, 29 insertions(+), 2 deletions(-)
 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 bbcb417a47..d75dfbf97a 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -576,7 +576,8 @@ 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):
+def discriminator_find_enum_define(expr, info):
+    name = expr['union']
     base = expr.get('base')
     discriminator = expr.get('discriminator')
 
@@ -591,6 +592,11 @@ def discriminator_find_enum_define(expr):
     if not discriminator_member:
         return None
 
+    if discriminator_member.get('if'):
+        raise QAPISemError(info, 'The discriminator %s.%s for union %s '
+                           'must not be conditional' %
+                           (base, discriminator, name))
+
     return enum_types.get(discriminator_member['type'])
 
 
@@ -1024,7 +1030,8 @@ def check_exprs(exprs):
 
         if 'include' in expr:
             continue
-        if 'union' in expr and not discriminator_find_enum_define(expr):
+        info = expr_elem['info']
+        if 'union' in expr and not discriminator_find_enum_define(expr, info):
             name = '%sKind' % expr['union']
         elif 'alternate' in expr:
             name = '%sKind' % expr['alternate']
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 7a46c1620d..e7429de9df 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -505,6 +505,7 @@ qapi-schema += flat-union-inline.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.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 27/49] qapi: add 'if' on union members
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (25 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 26/49] qapi: add an error in case a discriminator is conditionnal Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 28/49] qapi: add 'if' to alternate members Marc-André Lureau
                   ` (26 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Add 'if' key to union members:

{ 'union': 'TestIfUnion', 'data':
    'mem': { 'type': 'str', '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                  | 17 +++++++++--------
 tests/qapi-schema/qapi-schema-test.json |  7 ++++++-
 tests/qapi-schema/qapi-schema-test.out  | 10 ++++++++++
 tests/qapi-schema/test-qapi.py          |  1 +
 4 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index d75dfbf97a..224e911085 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -811,7 +811,7 @@ def check_union(expr, info):
     for (key, value) in members.items():
         source = "Member of union '%s'" % name
         check_name(info, source, key)
-        check_known_keys(info, source, value, ['type'], [])
+        check_known_keys(info, source, value, ['type'], ['if'])
         typ = value['type']
 
         # Each value must name a known type
@@ -1492,8 +1492,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):
@@ -1767,14 +1767,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']
@@ -1792,10 +1792,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/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index e29c9f0769..b4b8a0a2cc 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -200,9 +200,14 @@
   [ '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)' }
 
+{ '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 e1e41acd52..8dbcd6f24b 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -272,12 +272,22 @@ 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)']
+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
+    if ['defined(TEST_IF_UNION)']
 alternate TestIfAlternate
     tag type
     case foo: int
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index 9582742f90..4dfa8651c8 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -72,6 +72,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, 8)
 
     @staticmethod
     def _print_if(ifcond, indent=4):
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 28/49] qapi: add 'if' to alternate members
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (26 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 27/49] qapi: add 'if' on union members Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 29/49] qapi: add #if conditions to generated code members Marc-André Lureau
                   ` (25 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

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 +++++-----
 tests/qapi-schema/qapi-schema-test.json |  6 +++++-
 tests/qapi-schema/qapi-schema-test.out  |  9 ++++++++-
 3 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 224e911085..c913c18d2d 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -848,7 +848,7 @@ def check_alternate(expr, info):
     for (key, value) in members.items():
         check_name(info, "Member of alternate '%s'" % name, key)
         source = "Member '%s' of alternate '%s'" % (key, name)
-        check_known_keys(info, source, value, ['type'], [])
+        check_known_keys(info, source, value, ['type'], ['if'])
         typ = value['type']
 
         # Ensure alternates have no type conflicts.
@@ -1764,8 +1764,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):
@@ -1788,7 +1788,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:
@@ -1809,7 +1809,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/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index b4b8a0a2cc..cd33c084cb 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -208,9 +208,13 @@
 { 'command': 'TestIfUnionCmd', 'data': { 'union_cmd_arg': 'TestIfUnion' },
   'if': 'defined(TEST_IF_UNION)' }
 
-{ 'alternate': 'TestIfAlternate', 'data': { 'foo': 'int', 'bar': 'TestStruct' },
+{ 'alternate': 'TestIfAlternate', 'data':
+  { 'foo': 'int', 'alt_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 8dbcd6f24b..657e487cbf 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -291,8 +291,15 @@ command TestIfUnionCmd q_obj_TestIfUnionCmd-arg -> None
 alternate TestIfAlternate
     tag type
     case foo: int
-    case bar: TestStruct
+    case alt_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
+    if ['defined(TEST_IF_ALT)']
 object q_obj_TestIfCmd-arg
     member foo: TestIfStruct optional=False
     member bar: TestIfEnum optional=False
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 29/49] qapi: add #if conditions to generated code members
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (27 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 28/49] qapi: add 'if' to alternate members Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 30/49] docs: document schema configuration Marc-André Lureau
                   ` (24 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

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      |  8 +++++++-
 4 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index c913c18d2d..174b39ea50 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -2084,11 +2084,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('''
     },
@@ -2110,10 +2112,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 d62fca84de..5b147a3d6f 100644
--- a/scripts/qapi/introspect.py
+++ b/scripts/qapi/introspect.py
@@ -151,6 +151,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, member.ifcond)
         return ret
 
     def _gen_variants(self, tag_name, variants):
@@ -158,14 +160,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)},
+                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, m.ifcond) for m in members]},
+                       ifcond)
 
     def visit_array_type(self, name, info, ifcond, element_type):
         element = self._use_type(element_type)
@@ -181,8 +185,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)}, 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):
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index 5b790cb41d..b0d3ddb596 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):
                 c_name=c_name(variants.tag_member.name))
 
     for var in variants.variants:
+        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 ee776386ae..dc5a3173fc 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('''
@@ -81,6 +83,7 @@ void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
                      c_name=c_name(variants.tag_member.name))
 
         for var in variants.variants:
+            ret += gen_if(var.ifcond)
             ret += mcgen('''
     case %(case)s:
         visit_type_%(c_type)s_members(v, &obj->u.%(c_name)s, &err);
@@ -91,6 +94,7 @@ void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
                                            variants.tag_member.type.prefix),
                          c_type=var.type.c_name(), c_name=c_name(var.name))
 
+            ret += gen_endif(var.ifcond)
         ret += mcgen('''
     default:
         abort();
@@ -178,9 +182,10 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
     }
     switch ((*obj)->type) {
 ''',
-                 c_name=c_name(name))
+                c_name=c_name(name))
 
     for var in variants.variants:
+        ret += gen_if(var.ifcond)
         ret += mcgen('''
     case %(case)s:
 ''',
@@ -208,6 +213,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.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 30/49] docs: document schema configuration
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (28 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 29/49] qapi: add #if conditions to generated code members Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-22 11:10   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 31/49] qapi2texi: add 'If:' section to generated documentation Marc-André Lureau
                   ` (23 subsequent siblings)
  53 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 docs/devel/qapi-code-gen.txt | 38 ++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
index a569d24745..eec52e63e5 100644
--- a/docs/devel/qapi-code-gen.txt
+++ b/docs/devel/qapi-code-gen.txt
@@ -728,6 +728,44 @@ Example: Red Hat, Inc. controls redhat.com, and may therefore add a
 downstream command __com.redhat_drive-mirror.
 
 
+=== Configuring the schema ===
+
+Top-level QAPI expressions and various type expressions listed below
+can take an 'if' key.  The value must be a string or a list of
+string.  The corresponding generated code will then guard the inclusion
+of that member in the larger struct or function with #if IFCOND
+(or several #if lines for a list), where IFCOND is the value of the
+'if' key.
+
+'struct', 'enum', 'union', 'alternate', 'command' and 'event'
+top-level QAPI expressions can take an 'if' keyword like:
+
+{ 'struct': 'IfStruct', 'data': { 'foo': 'int' },
+  'if': 'defined(IFCOND)' }
+
+Where a member can normally be defined with a single string value as its
+type, it is also possible to supply a dictionary with both 'type' and
+'if' keys.
+
+{ '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:
+
+{ '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.
+
+The presence of 'if' keys in the schema is reflected through to the
+introspection output depending on the build configuration.
+
+
 == Client JSON Protocol introspection ==
 
 Clients of a Client JSON Protocol commonly need to figure out what
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 31/49] qapi2texi: add 'If:' section to generated documentation
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (29 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 30/49] docs: document schema configuration Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-06-21 16:29   ` Markus Armbruster
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 32/49] qapi2texi: add 'If:' condition to enum values Marc-André Lureau
                   ` (22 subsequent siblings)
  53 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

The documentation is generated only once, and doesn't know C
pre-conditions. Add 'If:' sections for top-level entities.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/doc.py             | 22 ++++++++++++----------
 tests/qapi-schema/doc-good.json |  2 +-
 tests/qapi-schema/doc-good.out  |  1 +
 tests/qapi-schema/doc-good.texi |  2 ++
 4 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
index 6c2bf98e1d..783b13303a 100755
--- a/scripts/qapi/doc.py
+++ b/scripts/qapi/doc.py
@@ -174,7 +174,7 @@ def texi_members(doc, what, base, variants, member_func):
     return '\n@b{%s:}\n@table @asis\n%s@end table\n' % (what, items)
 
 
-def texi_sections(doc):
+def texi_sections(doc, ifcond):
     """Format additional sections following arguments"""
     body = ''
     for section in doc.sections:
@@ -185,14 +185,16 @@ def texi_sections(doc):
             body += texi_example(section.text)
         else:
             body += texi_format(section.text)
+    if ifcond:
+        body += '\n\n@b{If:} @code{%s}' % ", ".join(ifcond)
     return body
 
 
-def texi_entity(doc, what, base=None, variants=None,
+def texi_entity(doc, what, ifcond, base=None, variants=None,
                 member_func=texi_member):
     return (texi_body(doc)
             + texi_members(doc, what, base, variants, member_func)
-            + texi_sections(doc))
+            + texi_sections(doc, ifcond))
 
 
 class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
@@ -208,7 +210,7 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
         doc = self.cur_doc
         self._gen.add(TYPE_FMT(type='Enum',
                                name=doc.symbol,
-                               body=texi_entity(doc, 'Values',
+                               body=texi_entity(doc, 'Values', ifcond,
                                                 member_func=texi_enum_value)))
 
     def visit_object_type(self, name, info, ifcond, base, members, variants):
@@ -217,14 +219,14 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
             base = None
         self._gen.add(TYPE_FMT(type='Object',
                                name=doc.symbol,
-                               body=texi_entity(doc, 'Members',
+                               body=texi_entity(doc, 'Members', ifcond,
                                                 base, variants)))
 
     def visit_alternate_type(self, name, info, ifcond, variants):
         doc = self.cur_doc
         self._gen.add(TYPE_FMT(type='Alternate',
                                name=doc.symbol,
-                               body=texi_entity(doc, 'Members')))
+                               body=texi_entity(doc, 'Members', ifcond)))
 
     def visit_command(self, name, info, ifcond, arg_type, ret_type,
                       gen, success_response, boxed, allow_oob):
@@ -233,9 +235,9 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
             body = texi_body(doc)
             body += ('\n@b{Arguments:} the members of @code{%s}\n'
                      % arg_type.name)
-            body += texi_sections(doc)
+            body += texi_sections(doc, ifcond)
         else:
-            body = texi_entity(doc, 'Arguments')
+            body = texi_entity(doc, 'Arguments', ifcond)
         self._gen.add(MSG_FMT(type='Command',
                               name=doc.symbol,
                               body=body))
@@ -244,7 +246,7 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
         doc = self.cur_doc
         self._gen.add(MSG_FMT(type='Event',
                               name=doc.symbol,
-                              body=texi_entity(doc, 'Arguments')))
+                              body=texi_entity(doc, 'Arguments', ifcond)))
 
     def symbol(self, doc, entity):
         if self._gen._body:
@@ -257,7 +259,7 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
         assert not doc.args
         if self._gen._body:
             self._gen.add('\n')
-        self._gen.add(texi_body(doc) + texi_sections(doc))
+        self._gen.add(texi_body(doc) + texi_sections(doc, None))
 
 
 def gen_doc(schema, output_dir, prefix):
diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json
index 97ab4625ff..984cd8ed06 100644
--- a/tests/qapi-schema/doc-good.json
+++ b/tests/qapi-schema/doc-good.json
@@ -55,7 +55,7 @@
 #
 # @two is undocumented
 ##
-{ 'enum': 'Enum', 'data': [ 'one', 'two' ] }
+{ 'enum': 'Enum', 'data': [ 'one', 'two' ], 'if': 'defined(IFCOND)' }
 
 ##
 # @Base:
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
index 3cd5c094aa..e4054e293c 100644
--- a/tests/qapi-schema/doc-good.out
+++ b/tests/qapi-schema/doc-good.out
@@ -12,6 +12,7 @@ module doc-good.json
 enum Enum
     member one
     member two
+    if ['defined(IFCOND)']
 object Base
     member base1: Enum optional=False
 object Variant1
diff --git a/tests/qapi-schema/doc-good.texi b/tests/qapi-schema/doc-good.texi
index 0aed2300a5..e42eace474 100644
--- a/tests/qapi-schema/doc-good.texi
+++ b/tests/qapi-schema/doc-good.texi
@@ -89,6 +89,8 @@ Not documented
 @end table
 @code{two} is undocumented
 
+
+@b{If:} @code{defined(IFCOND)}
 @end deftp
 
 
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 32/49] qapi2texi: add 'If:' condition to enum values
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (30 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 31/49] qapi2texi: add 'If:' section to generated documentation Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 33/49] qapi2texi: add 'If:' condition to struct members Marc-André Lureau
                   ` (21 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/doc.py             | 5 ++++-
 tests/qapi-schema/doc-good.json | 4 +++-
 tests/qapi-schema/doc-good.out  | 1 +
 tests/qapi-schema/doc-good.texi | 2 ++
 4 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
index 783b13303a..f629425f53 100755
--- a/scripts/qapi/doc.py
+++ b/scripts/qapi/doc.py
@@ -128,7 +128,10 @@ def texi_body(doc):
 
 def texi_enum_value(value):
     """Format a table of members item for an enumeration value"""
-    return '@item @code{%s}\n' % value.name
+    return '@item @code{%s}%s\n' % (
+        value.name,
+        '\n@b{If:} @code{%s}\n' %
+        ', '.join(value.ifcond) if value.ifcond else '')
 
 
 def texi_member(member, suffix=''):
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 e4054e293c..d27d345de2 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..2446a1c702 100644
--- a/tests/qapi-schema/doc-good.texi
+++ b/tests/qapi-schema/doc-good.texi
@@ -83,6 +83,8 @@ Examples:
 @b{Values:}
 @table @asis
 @item @code{one}
+@b{If:} @code{defined(IFENUM)}
+
 The @emph{one} @{and only@}
 @item @code{two}
 Not documented
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 33/49] qapi2texi: add 'If:' condition to struct members
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (31 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 32/49] qapi2texi: add 'If:' condition to enum values Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 34/49] qapi2texi: add condition to variants Marc-André Lureau
                   ` (20 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

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 | 2 ++
 4 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
index f629425f53..42e34e1fe3 100755
--- a/scripts/qapi/doc.py
+++ b/scripts/qapi/doc.py
@@ -138,9 +138,11 @@ def texi_member(member, 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%s\n' % (
         member.name, membertype,
         ' (optional)' if member.optional else '',
+        '\n@b{If:} @code{%s}\n' %
+        ', '.join(member.ifcond) if member.ifcond else '',
         suffix)
 
 
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 d27d345de2..9976d29eb0 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 2446a1c702..255eed9a30 100644
--- a/tests/qapi-schema/doc-good.texi
+++ b/tests/qapi-schema/doc-good.texi
@@ -120,6 +120,8 @@ Another paragraph (but no @code{var}: line)
 @b{Members:}
 @table @asis
 @item @code{var1: string}
+@b{If:} @code{defined(IFSTR)}
+
 Not documented
 @end table
 
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 34/49] qapi2texi: add condition to variants
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (32 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 33/49] qapi2texi: add 'If:' condition to struct members Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 35/49] qapi: add conditions to VNC type/commands/events on the schema Marc-André Lureau
                   ` (19 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/doc.py             | 5 +++--
 tests/qapi-schema/doc-good.json | 4 ++--
 tests/qapi-schema/doc-good.out  | 3 +++
 tests/qapi-schema/doc-good.texi | 4 ++--
 4 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
index 42e34e1fe3..40dcedc6ed 100755
--- a/scripts/qapi/doc.py
+++ b/scripts/qapi/doc.py
@@ -165,8 +165,9 @@ 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,
+                ' (@b{If:} @code{%s})' % v.ifcond if v.ifcond else '')
             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 9976d29eb0..4b36cf6f7d 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 255eed9a30..6e226a6231 100644
--- a/tests/qapi-schema/doc-good.texi
+++ b/tests/qapi-schema/doc-good.texi
@@ -145,7 +145,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
@@ -161,7 +161,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.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 35/49] qapi: add conditions to VNC type/commands/events on the schema
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (33 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 34/49] qapi2texi: add condition to variants Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 36/49] qapi: add conditions to SPICE " Marc-André Lureau
                   ` (18 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Add #if defined(CONFIG_VNC) in generated code, and adjust the
qmp/hmp code accordingly.

query-qmp-schema no longer reports the command/events etc as
available when disabled at compile.

Commands made conditional:

* query-vnc, query-vnc-servers, change-vnc-password

  Before the patch, the commands for !CONFIG_VNC are stubs that fail
  like this:

    {"error": {"class": "GenericError",
               "desc": "The feature 'vnc' is not enabled"}}

  Afterwards, they fail like this:

    {"error": {"class": "CommandNotFound",
               "desc": "The command FOO has not been found"}}

  I call that an improvement, because it lets clients distinguish
  between command unavailable (class CommandNotFound) and command failed
  (class GenericError).

Events made conditional:

* VNC_CONNECTED, VNC_INITIALIZED, VNC_DISCONNECTED

HMP change:

* info vnc

  Will return "unknown command: 'info vnc'" when VNC is compiled
  out (same as error for spice when --disable-spice)

Occurrences of VNC (case insensitive) in the schema that aren't
covered by this change:

* add_client

  Command has other uses, including "socket bases character devices".
  These are unconditional as far as I can tell.

* set_password, expire_password

  In theory, these commands could be used for managing any service's
  password.  In practice, they're used for VNC and SPICE services.
  They're documented for "remote display session" / "remote display
  server".

  The service is selected by argument @protocol.  The code special-cases
  protocol-specific argument checking, then calls a protocol-specific
  function to do the work.  If it fails, the command fails with "Could
  not set password".  It does when the service isn't compiled in (it's a
  stub then).

  We could make these commands conditional on the conjunction of all
  services [currently: defined(CONFIG_VNC) || defined(CONFIG_SPICE)],
  but I doubt it's worthwhile.

* change

  Command has other uses, namely changing media.
  This patch inlines a stub; no functional change.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
---
 qapi/ui.json         | 45 +++++++++++++++++++++++++++-----------------
 ui/vnc.h             |  2 ++
 hmp.c                |  9 ++++++++-
 qmp.c                | 30 ++++-------------------------
 hmp-commands-info.hx |  2 ++
 5 files changed, 44 insertions(+), 44 deletions(-)

diff --git a/qapi/ui.json b/qapi/ui.json
index 5d01ad4304..4b96509446 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -377,7 +377,8 @@
   'data': { 'host': 'str',
             'service': 'str',
             'family': 'NetworkAddressFamily',
-            'websocket': 'bool' } }
+            'websocket': 'bool' },
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @VncServerInfo:
@@ -391,7 +392,8 @@
 ##
 { 'struct': 'VncServerInfo',
   'base': 'VncBasicInfo',
-  'data': { '*auth': 'str' } }
+  'data': { '*auth': 'str' },
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @VncClientInfo:
@@ -408,7 +410,8 @@
 ##
 { 'struct': 'VncClientInfo',
   'base': 'VncBasicInfo',
-  'data': { '*x509_dname': 'str', '*sasl_username': 'str' } }
+  'data': { '*x509_dname': 'str', '*sasl_username': 'str' },
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @VncInfo:
@@ -449,7 +452,8 @@
 { 'struct': 'VncInfo',
   'data': {'enabled': 'bool', '*host': 'str',
            '*family': 'NetworkAddressFamily',
-           '*service': 'str', '*auth': 'str', '*clients': ['VncClientInfo']} }
+           '*service': 'str', '*auth': 'str', '*clients': ['VncClientInfo']},
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @VncPrimaryAuth:
@@ -460,7 +464,8 @@
 ##
 { 'enum': 'VncPrimaryAuth',
   'data': [ 'none', 'vnc', 'ra2', 'ra2ne', 'tight', 'ultra',
-            'tls', 'vencrypt', 'sasl' ] }
+            'tls', 'vencrypt', 'sasl' ],
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @VncVencryptSubAuth:
@@ -474,8 +479,8 @@
             'tls-none',  'x509-none',
             'tls-vnc',   'x509-vnc',
             'tls-plain', 'x509-plain',
-            'tls-sasl',  'x509-sasl' ] }
-
+            'tls-sasl',  'x509-sasl' ],
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @VncServerInfo2:
@@ -492,8 +497,8 @@
 { 'struct': 'VncServerInfo2',
   'base': 'VncBasicInfo',
   'data': { 'auth'      : 'VncPrimaryAuth',
-            '*vencrypt' : 'VncVencryptSubAuth' } }
-
+            '*vencrypt' : 'VncVencryptSubAuth' },
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @VncInfo2:
@@ -525,7 +530,8 @@
             'clients'   : ['VncClientInfo'],
             'auth'      : 'VncPrimaryAuth',
             '*vencrypt' : 'VncVencryptSubAuth',
-            '*display'  : 'str' } }
+            '*display'  : 'str' },
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @query-vnc:
@@ -556,8 +562,8 @@
 #    }
 #
 ##
-{ 'command': 'query-vnc', 'returns': 'VncInfo' }
-
+{ 'command': 'query-vnc', 'returns': 'VncInfo',
+  'if': 'defined(CONFIG_VNC)' }
 ##
 # @query-vnc-servers:
 #
@@ -567,7 +573,8 @@
 #
 # Since: 2.3
 ##
-{ 'command': 'query-vnc-servers', 'returns': ['VncInfo2'] }
+{ 'command': 'query-vnc-servers', 'returns': ['VncInfo2'],
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @change-vnc-password:
@@ -581,7 +588,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)' }
 
 ##
 # @VNC_CONNECTED:
@@ -610,7 +618,8 @@
 ##
 { 'event': 'VNC_CONNECTED',
   'data': { 'server': 'VncServerInfo',
-            'client': 'VncBasicInfo' } }
+            'client': 'VncBasicInfo' },
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @VNC_INITIALIZED:
@@ -637,7 +646,8 @@
 ##
 { 'event': 'VNC_INITIALIZED',
   'data': { 'server': 'VncServerInfo',
-            'client': 'VncClientInfo' } }
+            'client': 'VncClientInfo' },
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @VNC_DISCONNECTED:
@@ -663,7 +673,8 @@
 ##
 { 'event': 'VNC_DISCONNECTED',
   'data': { 'server': 'VncServerInfo',
-            'client': 'VncClientInfo' } }
+            'client': 'VncClientInfo' },
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # = Input
diff --git a/ui/vnc.h b/ui/vnc.h
index 7b29def77d..fede2096d9 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -294,7 +294,9 @@ struct VncState
     bool encode_ws;
     bool websocket;
 
+#ifdef CONFIG_VNC
     VncClientInfo *info;
+#endif
 
     /* Job thread bottom half has put data for a forced update
      * into the output buffer. This offset points to the end of
diff --git a/hmp.c b/hmp.c
index 679467d85a..352c2f56f4 100644
--- a/hmp.c
+++ b/hmp.c
@@ -596,6 +596,7 @@ void hmp_info_blockstats(Monitor *mon, const QDict *qdict)
     qapi_free_BlockStatsList(stats_list);
 }
 
+#ifdef CONFIG_VNC
 /* Helper for hmp_info_vnc_clients, _servers */
 static void hmp_info_VncBasicInfo(Monitor *mon, VncBasicInfo *info,
                                   const char *name)
@@ -683,6 +684,7 @@ void hmp_info_vnc(Monitor *mon, const QDict *qdict)
     qapi_free_VncInfo2List(info2l);
 
 }
+#endif
 
 #ifdef CONFIG_SPICE
 void hmp_info_spice(Monitor *mon, const QDict *qdict)
@@ -1721,12 +1723,14 @@ void hmp_eject(Monitor *mon, const QDict *qdict)
     hmp_handle_error(mon, &err);
 }
 
+#ifdef CONFIG_VNC
 static void hmp_change_read_arg(void *opaque, const char *password,
                                 void *readline_opaque)
 {
     qmp_change_vnc_password(password, NULL);
     monitor_read_command(opaque, 1);
 }
+#endif
 
 void hmp_change(Monitor *mon, const QDict *qdict)
 {
@@ -1737,6 +1741,7 @@ void hmp_change(Monitor *mon, const QDict *qdict)
     BlockdevChangeReadOnlyMode read_only_mode = 0;
     Error *err = NULL;
 
+#ifdef CONFIG_VNC
     if (strcmp(device, "vnc") == 0) {
         if (read_only) {
             monitor_printf(mon,
@@ -1751,7 +1756,9 @@ void hmp_change(Monitor *mon, const QDict *qdict)
             }
         }
         qmp_change("vnc", target, !!arg, arg, &err);
-    } else {
+    } else
+#endif
+    {
         if (read_only) {
             read_only_mode =
                 qapi_enum_parse(&BlockdevChangeReadOnlyMode_lookup,
diff --git a/qmp.c b/qmp.c
index f72261667f..ee1a816a42 100644
--- a/qmp.c
+++ b/qmp.c
@@ -129,22 +129,6 @@ void qmp_cpu_add(int64_t id, Error **errp)
     }
 }
 
-#ifndef CONFIG_VNC
-/* If VNC support is enabled, the "true" query-vnc command is
-   defined in the VNC subsystem */
-VncInfo *qmp_query_vnc(Error **errp)
-{
-    error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
-    return NULL;
-};
-
-VncInfo2List *qmp_query_vnc_servers(Error **errp)
-{
-    error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
-    return NULL;
-};
-#endif
-
 #ifndef CONFIG_SPICE
 /*
  * qmp_unregister_commands_hack() ensures that QMP command query-spice
@@ -402,23 +386,17 @@ static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
         qmp_change_vnc_listen(target, errp);
     }
 }
-#else
-void qmp_change_vnc_password(const char *password, Error **errp)
-{
-    error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
-}
-static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
-                           Error **errp)
-{
-    error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
-}
 #endif /* !CONFIG_VNC */
 
 void qmp_change(const char *device, const char *target,
                 bool has_arg, const char *arg, Error **errp)
 {
     if (strcmp(device, "vnc") == 0) {
+#ifdef CONFIG_VNC
         qmp_change_vnc(target, has_arg, arg, errp);
+#else
+        error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
+#endif
     } else {
         qmp_blockdev_change_medium(true, device, false, NULL, target,
                                    has_arg, arg, false, 0, errp);
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index ddfcd5adcc..7f681df119 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -421,6 +421,7 @@ STEXI
 Show which guest mouse is receiving events.
 ETEXI
 
+#if defined(CONFIG_VNC)
     {
         .name       = "vnc",
         .args_type  = "",
@@ -428,6 +429,7 @@ ETEXI
         .help       = "show the vnc server status",
         .cmd        = hmp_info_vnc,
     },
+#endif
 
 STEXI
 @item info vnc
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 36/49] qapi: add conditions to SPICE type/commands/events on the schema
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (34 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 35/49] qapi: add conditions to VNC type/commands/events on the schema Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 37/49] qapi: add conditions to REPLICATION type/commands " Marc-André Lureau
                   ` (17 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Add #if defined(CONFIG_SPICE) in generated code, and adjust the
qmp/hmp code accordingly.

query-qmp-schema no longer reports the command/events etc as
available when disabled at compile time.

Commands made conditional:

* query-spice

  Before the patch, the command for !CONFIG_SPICE is unregistered. It
  will fail with the same error.

Events made conditional:

* SPICE_CONNECTED, SPICE_INITIALIZED, SPICE_DISCONNECTED,
  SPICE_MIGRATE_COMPLETED

Chardev made conditional:

* spiceport, spicevmc

  Before and after the patch for !CONFIG_SPICE, the error is the
  same ('spiceport' is not a valid char driver name).

No HMP change, the code was already conditional.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
---
 qapi/char.json | 10 ++++++----
 qapi/ui.json   | 30 ++++++++++++++++++++----------
 monitor.c      |  3 ---
 qmp.c          | 16 ----------------
 4 files changed, 26 insertions(+), 33 deletions(-)

diff --git a/qapi/char.json b/qapi/char.json
index ae19dcd1ed..7fa1762ae5 100644
--- a/qapi/char.json
+++ b/qapi/char.json
@@ -318,7 +318,8 @@
 # Since: 1.5
 ##
 { 'struct': 'ChardevSpiceChannel', 'data': { 'type'  : 'str' },
-  'base': 'ChardevCommon' }
+  'base': 'ChardevCommon',
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @ChardevSpicePort:
@@ -330,7 +331,8 @@
 # Since: 1.5
 ##
 { 'struct': 'ChardevSpicePort', 'data': { 'fqdn'  : 'str' },
-  'base': 'ChardevCommon' }
+  'base': 'ChardevCommon',
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @ChardevVC:
@@ -384,8 +386,8 @@
                                        'testdev': 'ChardevCommon',
                                        'stdio'  : 'ChardevStdio',
                                        'console': 'ChardevCommon',
-                                       'spicevmc' : 'ChardevSpiceChannel',
-                                       'spiceport' : 'ChardevSpicePort',
+                                       'spicevmc' : { 'type': 'ChardevSpiceChannel', 'if': 'defined(CONFIG_SPICE)' },
+                                       'spiceport' : { 'type': 'ChardevSpicePort', 'if': 'defined(CONFIG_SPICE)' },
                                        'vc'     : 'ChardevVC',
                                        'ringbuf': 'ChardevRingbuf',
                                        # next one is just for compatibility
diff --git a/qapi/ui.json b/qapi/ui.json
index 4b96509446..e47fae2e90 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -118,7 +118,8 @@
 { 'struct': 'SpiceBasicInfo',
   'data': { 'host': 'str',
             'port': 'str',
-            'family': 'NetworkAddressFamily' } }
+            'family': 'NetworkAddressFamily' },
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @SpiceServerInfo:
@@ -131,7 +132,8 @@
 ##
 { 'struct': 'SpiceServerInfo',
   'base': 'SpiceBasicInfo',
-  'data': { '*auth': 'str' } }
+  'data': { '*auth': 'str' },
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @SpiceChannel:
@@ -156,7 +158,8 @@
 { 'struct': 'SpiceChannel',
   'base': 'SpiceBasicInfo',
   'data': {'connection-id': 'int', 'channel-type': 'int', 'channel-id': 'int',
-           'tls': 'bool'} }
+           'tls': 'bool'},
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @SpiceQueryMouseMode:
@@ -175,7 +178,8 @@
 # Since: 1.1
 ##
 { 'enum': 'SpiceQueryMouseMode',
-  'data': [ 'client', 'server', 'unknown' ] }
+  'data': [ 'client', 'server', 'unknown' ],
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @SpiceInfo:
@@ -212,7 +216,8 @@
 { 'struct': 'SpiceInfo',
   'data': {'enabled': 'bool', 'migrated': 'bool', '*host': 'str', '*port': 'int',
            '*tls-port': 'int', '*auth': 'str', '*compiled-version': 'str',
-           'mouse-mode': 'SpiceQueryMouseMode', '*channels': ['SpiceChannel']} }
+           'mouse-mode': 'SpiceQueryMouseMode', '*channels': ['SpiceChannel']},
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @query-spice:
@@ -257,7 +262,8 @@
 #    }
 #
 ##
-{ 'command': 'query-spice', 'returns': 'SpiceInfo' }
+{ 'command': 'query-spice', 'returns': 'SpiceInfo',
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @SPICE_CONNECTED:
@@ -282,7 +288,8 @@
 ##
 { 'event': 'SPICE_CONNECTED',
   'data': { 'server': 'SpiceBasicInfo',
-            'client': 'SpiceBasicInfo' } }
+            'client': 'SpiceBasicInfo' },
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @SPICE_INITIALIZED:
@@ -310,7 +317,8 @@
 ##
 { 'event': 'SPICE_INITIALIZED',
   'data': { 'server': 'SpiceServerInfo',
-            'client': 'SpiceChannel' } }
+            'client': 'SpiceChannel' },
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @SPICE_DISCONNECTED:
@@ -335,7 +343,8 @@
 ##
 { 'event': 'SPICE_DISCONNECTED',
   'data': { 'server': 'SpiceBasicInfo',
-            'client': 'SpiceBasicInfo' } }
+            'client': 'SpiceBasicInfo' },
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @SPICE_MIGRATE_COMPLETED:
@@ -350,7 +359,8 @@
 #      "event": "SPICE_MIGRATE_COMPLETED" }
 #
 ##
-{ 'event': 'SPICE_MIGRATE_COMPLETED' }
+{ 'event': 'SPICE_MIGRATE_COMPLETED',
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # == VNC
diff --git a/monitor.c b/monitor.c
index 6ccd2fc089..8a5539579b 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1087,9 +1087,6 @@ static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
  */
 static void qmp_unregister_commands_hack(void)
 {
-#ifndef CONFIG_SPICE
-    qmp_unregister_command(&qmp_commands, "query-spice");
-#endif
 #ifndef CONFIG_REPLICATION
     qmp_unregister_command(&qmp_commands, "xen-set-replication");
     qmp_unregister_command(&qmp_commands, "query-xen-replication-status");
diff --git a/qmp.c b/qmp.c
index ee1a816a42..d8f80cb04e 100644
--- a/qmp.c
+++ b/qmp.c
@@ -129,22 +129,6 @@ void qmp_cpu_add(int64_t id, Error **errp)
     }
 }
 
-#ifndef CONFIG_SPICE
-/*
- * qmp_unregister_commands_hack() ensures that QMP command query-spice
- * exists only #ifdef CONFIG_SPICE.  Necessary for an accurate
- * query-commands result.  However, the QAPI schema is blissfully
- * unaware of that, and the QAPI code generator happily generates a
- * dead qmp_marshal_query_spice() that calls qmp_query_spice().
- * Provide it one, or else linking fails.  FIXME Educate the QAPI
- * schema on CONFIG_SPICE.
- */
-SpiceInfo *qmp_query_spice(Error **errp)
-{
-    abort();
-};
-#endif
-
 void qmp_cont(Error **errp)
 {
     BlockBackend *blk;
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 37/49] qapi: add conditions to REPLICATION type/commands on the schema
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (35 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 36/49] qapi: add conditions to SPICE " Marc-André Lureau
@ 2018-03-21 11:51 ` Marc-André Lureau
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 38/49] build-sys: move qmp-introspect per target Marc-André Lureau
                   ` (16 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

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>
---
 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 1088ab0c78..c20d39049b 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -2514,7 +2514,9 @@
             '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', 'ssh',
+            'quorum', 'raw', 'rbd',
+            { 'name': 'replication', 'if': 'defined(CONFIG_REPLICATION)' },
+            'sheepdog', 'ssh',
             'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
 
 ##
@@ -3228,7 +3230,8 @@
 #
 # Since: 2.9
 ##
-{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }
+{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ],
+  'if': 'defined(CONFIG_REPLICATION)' }
 
 ##
 # @BlockdevOptionsReplication:
@@ -3246,7 +3249,8 @@
 { 'struct': 'BlockdevOptionsReplication',
   'base': 'BlockdevOptionsGenericFormat',
   'data': { 'mode': 'ReplicationMode',
-            '*top-id': 'str' } }
+            '*top-id': 'str' },
+  'if': 'defined(CONFIG_REPLICATION)' }
 
 ##
 # @NFSTransport:
@@ -3545,7 +3549,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 9d0bf82cf4..d2c6e4d646 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -1121,7 +1121,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:
@@ -1136,7 +1137,8 @@
 # Since: 2.9
 ##
 { 'struct': 'ReplicationStatus',
-  'data': { 'error': 'bool', '*desc': 'str' } }
+  'data': { 'error': 'bool', '*desc': 'str' },
+  'if': 'defined(CONFIG_REPLICATION)' }
 
 ##
 # @query-xen-replication-status:
@@ -1153,7 +1155,8 @@
 # Since: 2.9
 ##
 { 'command': 'query-xen-replication-status',
-  'returns': 'ReplicationStatus' }
+  'returns': 'ReplicationStatus',
+  'if': 'defined(CONFIG_REPLICATION)' }
 
 ##
 # @xen-colo-do-checkpoint:
@@ -1169,4 +1172,5 @@
 #
 # Since: 2.9
 ##
-{ 'command': 'xen-colo-do-checkpoint' }
+{ 'command': 'xen-colo-do-checkpoint',
+  'if': 'defined(CONFIG_REPLICATION)' }
diff --git a/migration/colo.c b/migration/colo.c
index 4381067ed4..2329e78e7f 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
 
 static bool vmstate_loading;
 
@@ -148,11 +150,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;
@@ -171,14 +173,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);
 
@@ -193,19 +191,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
 
 static void colo_send_message(QEMUFile *f, COLOMessage msg,
                               Error **errp)
diff --git a/monitor.c b/monitor.c
index 8a5539579b..88e6fd2e6f 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1087,11 +1087,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.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 38/49] build-sys: move qmp-introspect per target
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (36 preceding siblings ...)
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 37/49] qapi: add conditions to REPLICATION type/commands " Marc-André Lureau
@ 2018-03-21 11:52 ` Marc-André Lureau
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 39/49] qapi-commands: don't initialize command list in qmp_init_marshall() Marc-André Lureau
                   ` (15 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

The following patches are going to introduce per-target #ifdef in the
schemas.

The introspection data is statically generated once, and must thus be
built per-target to reflect target-specific configuration.

Drop "do_test_visitor_in_qmp_introspect(&qmp_schema_qlit)" since the
schema is no longer in a common object. It is covered by the per-target
query-qmp-schema test instead.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 tests/test-qobject-input-visitor.c | 1 -
 Makefile.objs                      | 2 --
 Makefile.target                    | 2 ++
 3 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
index 6dc59c6211..e14544fc89 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -1270,7 +1270,6 @@ static void test_visitor_in_qmp_introspect(TestInputVisitorData *data,
                                            const void *unused)
 {
     do_test_visitor_in_qmp_introspect(data, &test_qmp_schema_qlit);
-    do_test_visitor_in_qmp_introspect(data, &qmp_schema_qlit);
 }
 
 int main(int argc, char **argv)
diff --git a/Makefile.objs b/Makefile.objs
index c6c9b8fc21..f0b10dbf23 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -55,7 +55,6 @@ util-obj-y += qapi/qapi-events-tpm.o
 util-obj-y += qapi/qapi-events-trace.o
 util-obj-y += qapi/qapi-events-transaction.o
 util-obj-y += qapi/qapi-events-ui.o
-util-obj-y += qapi/qapi-introspect.o
 
 chardev-obj-y = chardev/
 
@@ -150,7 +149,6 @@ common-obj-y += qapi/qapi-commands-tpm.o
 common-obj-y += qapi/qapi-commands-trace.o
 common-obj-y += qapi/qapi-commands-transaction.o
 common-obj-y += qapi/qapi-commands-ui.o
-common-obj-y += qapi/qapi-introspect.o
 common-obj-y += qmp.o hmp.o
 endif
 
diff --git a/Makefile.target b/Makefile.target
index 6549481096..0bb18dff9e 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -150,6 +150,8 @@ endif
 
 GENERATED_FILES += hmp-commands.h hmp-commands-info.h
 
+obj-y += qapi/qapi-introspect.o
+
 endif # CONFIG_SOFTMMU
 
 # Workaround for http://gcc.gnu.org/PR55489, see configure.
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 39/49] qapi-commands: don't initialize command list in qmp_init_marshall()
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (37 preceding siblings ...)
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 38/49] build-sys: move qmp-introspect per target Marc-André Lureau
@ 2018-03-21 11:52 ` Marc-André Lureau
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 40/49] RFC: qapi: learn to split schema by 'top-unit' Marc-André Lureau
                   ` (14 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

This will let the caller add several list of commands coming from
different schemas (the following patches split the schemas for common
and arch-specific parts).

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/commands.py | 2 --
 monitor.c                | 1 +
 qga/main.c               | 1 +
 tests/test-qmp-cmds.c    | 1 +
 4 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
index 40bb680b7c..3d3e97f737 100644
--- a/scripts/qapi/commands.py
+++ b/scripts/qapi/commands.py
@@ -220,8 +220,6 @@ def gen_registry(registry, prefix):
 
 void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds)
 {
-    QTAILQ_INIT(cmds);
-
 ''',
                 c_prefix=c_name(prefix, protect=False))
     ret += registry
diff --git a/monitor.c b/monitor.c
index 88e6fd2e6f..0d84c3edb4 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1121,6 +1121,7 @@ static void monitor_init_qmp_commands(void)
      *   "qmp_capabilities", to enforce capability negotiation
      */
 
+    QTAILQ_INIT(&qmp_commands);
     qmp_init_marshal(&qmp_commands);
 
     qmp_register_command(&qmp_commands, "query-qmp-schema",
diff --git a/qga/main.c b/qga/main.c
index df1888edc1..6905c82b6c 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -1364,6 +1364,7 @@ int main(int argc, char **argv)
 
     config->log_level = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL;
 
+    QTAILQ_INIT(&ga_commands);
     qga_qmp_init_marshal(&ga_commands);
 
     init_dfl_pathnames();
diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c
index e675722593..e723b440ca 100644
--- a/tests/test-qmp-cmds.c
+++ b/tests/test-qmp-cmds.c
@@ -285,6 +285,7 @@ int main(int argc, char **argv)
     g_test_add_func("/0.15/dealloc_types", test_dealloc_types);
     g_test_add_func("/0.15/dealloc_partial", test_dealloc_partial);
 
+    QTAILQ_INIT(&qmp_commands);
     test_qmp_init_marshal(&qmp_commands);
     g_test_run();
 
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 40/49] RFC: qapi: learn to split schema by 'top-unit'
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (38 preceding siblings ...)
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 39/49] qapi-commands: don't initialize command list in qmp_init_marshall() Marc-André Lureau
@ 2018-03-21 11:52 ` Marc-André Lureau
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 41/49] qapi: add a top-unit 'target' schema Marc-André Lureau
                   ` (13 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Another take at making the schema modular, this time by introducing
the concept of a 'top-unit'. With this approach, each module is part
of a top-unit, which is visited first before visiting the module
themselfs. The default 'top-unit' is None. Else, a module belong to a
'top-unit' whose name is given by the 'top-unit' pragma value.

This gives a chance to the generators to break generated output into
different files. The point of this excercice is to have modules that
can be compiled per qemu targets, instead of everything belonging to
the top schema without the right to use poisoin defines for
conditional compilation.

Generated types, visitors, events and commands are split by
'top-unit'.

The generated introspection and documentation remain monolithic.

TODO: if this approach is acceptable, write tests & doc.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/commands.py |  22 +++++---
 scripts/qapi/common.py   | 105 +++++++++++++++++++++++++++++++--------
 scripts/qapi/events.py   |  33 ++++++++----
 scripts/qapi/types.py    |   8 +--
 scripts/qapi/visit.py    |   8 +--
 5 files changed, 129 insertions(+), 47 deletions(-)

diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
index 3d3e97f737..3ca36fc33b 100644
--- a/scripts/qapi/commands.py
+++ b/scripts/qapi/commands.py
@@ -235,14 +235,20 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
         QAPISchemaModularCVisitor.__init__(
             self, prefix, 'qapi-commands',
             ' * Schema-defined QAPI/QMP commands', __doc__)
+
+    def visit_unit_begin(self, unit):
+        super(self.__class__, self).visit_unit_begin(unit)
         self._regy = QAPIGenCSnippet()
         self._visited_ret_types = {}
 
-    def _begin_module(self, name):
+    def _begin_module(self, name, main_module):
         self._visited_ret_types[self._genc] = set()
-        commands = self._module_basename('qapi-commands', name)
-        types = self._module_basename('qapi-types', name)
-        visit = self._module_basename('qapi-visit', name)
+        commands = self._module_basename('qapi-commands', name,
+                                         self._unit, main_module)
+        types = self._module_basename('qapi-types', name,
+                                      self._unit, main_module)
+        visit = self._module_basename('qapi-visit', name,
+                                      self._unit, main_module)
         self._genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
@@ -265,13 +271,13 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
 ''',
                              types=types))
 
-    def visit_end(self):
-        (genc, genh) = self._module[self._main_module]
+    def visit_unit_end(self):
+        (genc, genh) = self.get_module_gen(self._main_module)
         genh.add(mcgen('''
 void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
 ''',
-                       c_prefix=c_name(self._prefix, protect=False)))
-        genc.add(gen_registry(self._regy.get_content(), self._prefix))
+                       c_prefix=c_name(self._prefix_unit(), protect=False)))
+        genc.add(gen_registry(self._regy.get_content(), self._prefix_unit()))
 
     def visit_command(self, name, info, ifcond, arg_type, ret_type,
                       gen, success_response, boxed, allow_oob):
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 174b39ea50..bff8de05d1 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -271,11 +271,12 @@ class QAPISchemaParser(object):
         self.exprs = []
         self.docs = []
         self.accept()
+        self._top_unit = None
         cur_doc = None
 
         while self.tok is not None:
             info = {'file': self.fname, 'line': self.line,
-                    'parent': self.incl_info}
+                    'parent': self.incl_info, 'top-unit': self._top_unit}
             if self.tok == '#':
                 self.reject_expr_doc(cur_doc)
                 cur_doc = self.get_doc(info)
@@ -298,6 +299,9 @@ class QAPISchemaParser(object):
                 exprs_include = self._include(include, info, incl_fname,
                                               previously_included)
                 if exprs_include:
+                    incl_info = self.exprs[-1]['info']
+                    if exprs_include._top_unit:
+                        incl_info['has-pragma-top-unit'] = exprs_include._top_unit
                     self.exprs.extend(exprs_include.exprs)
                     self.docs.extend(exprs_include.docs)
             elif "pragma" in expr:
@@ -356,6 +360,11 @@ class QAPISchemaParser(object):
                 raise QAPISemError(info,
                                    "Pragma 'doc-required' must be boolean")
             doc_required = value
+        elif name == 'top-unit':
+            if not isinstance(value, str):
+                raise QAPISemError(info,
+                                   "Pragma 'top-unit' must be a string")
+            self._top_unit = value
         elif name == 'returns-whitelist':
             if (not isinstance(value, list)
                     or any([not isinstance(elt, str) for elt in value])):
@@ -1098,6 +1107,11 @@ class QAPISchemaEntity(object):
     def c_name(self):
         return c_name(self.name)
 
+    def get_top_unit(self):
+        if self.info:
+            return self.info['top-unit']
+        return None
+
     def check(self, schema):
         if isinstance(self._ifcond, QAPISchemaType):
             # inherit the condition from a type
@@ -1118,6 +1132,12 @@ class QAPISchemaVisitor(object):
     def visit_begin(self, schema):
         pass
 
+    def visit_unit_begin(self, unit):
+        pass
+
+    def visit_unit_end(self):
+        pass
+
     def visit_end(self):
         pass
 
@@ -1613,7 +1633,7 @@ class QAPISchema(object):
         parser = QAPISchemaParser(open(fname, 'r'))
         exprs = check_exprs(parser.exprs)
         self.docs = parser.docs
-        self._entity_list = []
+        self._entity_list = {} # dict of unit name -> list of entity
         self._entity_dict = {}
         self._predefining = True
         self._def_predefineds()
@@ -1625,7 +1645,8 @@ class QAPISchema(object):
         # Only the predefined types are allowed to not have info
         assert ent.info or self._predefining
         assert ent.name is None or ent.name not in self._entity_dict
-        self._entity_list.append(ent)
+        entity_list = self._entity_list.setdefault(ent.get_top_unit(), [])
+        entity_list.append(ent)
         if ent.name is not None:
             self._entity_dict[ent.name] = ent
         if ent.info:
@@ -1870,18 +1891,23 @@ class QAPISchema(object):
                 assert False
 
     def check(self):
-        for ent in self._entity_list:
-            ent.check(self)
+        for unit in self._entity_list:
+            for ent in self._entity_list[unit]:
+                ent.check(self)
 
     def visit(self, visitor):
         visitor.visit_begin(self)
-        module = None
-        for entity in self._entity_list:
-            if visitor.visit_needed(entity):
+        for unit in self._entity_list:
+            module = None
+            visitor.visit_unit_begin(unit)
+            for entity in self._entity_list[unit]:
+                if not visitor.visit_needed(entity):
+                    continue
                 if entity.module != module:
                     module = entity.module
                     visitor.visit_module(module)
                 entity.visit(visitor)
+            visitor.visit_unit_end()
         visitor.visit_end()
 
 
@@ -2301,6 +2327,19 @@ class QAPISchemaMonolithicCVisitor(QAPISchemaVisitor):
         self._genh.write(output_dir, self._prefix + self._what + '.h')
 
 
+class QAPIGenCModule(object):
+
+    def __init__(self, blurb, pydoc, unit, main_module=False):
+        self.genc = QAPIGenC(blurb, pydoc)
+        self.genh = QAPIGenH(blurb, pydoc)
+        self.unit = unit
+        self.main_module = main_module
+
+    def write(self, output_dir, basename):
+        self.genc.write(output_dir, basename + '.c')
+        self.genh.write(output_dir, basename + '.h')
+
+
 class QAPISchemaModularCVisitor(QAPISchemaVisitor):
 
     def __init__(self, prefix, what, blurb, pydoc):
@@ -2309,48 +2348,70 @@ class QAPISchemaModularCVisitor(QAPISchemaVisitor):
         self._blurb = blurb
         self._pydoc = pydoc
         self._module = {}
+        self._unit = None
         self._main_module = None
 
-    def _module_basename(self, what, name):
+    def _module_basename(self, what, name, unit=None, main_module=False):
         if name is None:
             return re.sub(r'-', '-builtin-', what)
         basename = os.path.join(os.path.dirname(name),
                                 self._prefix + what)
-        if name == self._main_module:
+        if unit:
+            basename = unit + '-' + basename
+        if main_module:
             return basename
         return basename + '-' + os.path.splitext(os.path.basename(name))[0]
 
+    def _prefix_unit(self):
+        if self._unit:
+            return self._prefix + self._unit + '-'
+        return self._prefix
+
+    def visit_unit_begin(self, unit):
+        self._unit = unit
+        self._main_module = None
+
     def _add_module(self, name, blurb):
-        if self._main_module is None and name is not None:
+        main_module = False
+        if (name is not None and
+            ((self._unit is None and self._main_module is None) or
+             (self._unit == os.path.splitext(os.path.basename(name))[0]))):
             self._main_module = name
-        genc = QAPIGenC(blurb, self._pydoc)
-        genh = QAPIGenH(blurb, self._pydoc)
-        self._module[name] = (genc, genh)
+            main_module = True
+        self._module[name] = QAPIGenCModule(blurb, self._pydoc,
+                                            self._unit, main_module)
         self._set_module(name)
+        return main_module
+
+    def get_module_gen(self, name):
+        mod = self._module[name]
+        return mod.genc, mod.genh
 
     def _set_module(self, name):
-        self._genc, self._genh = self._module[name]
+        self._genc, self._genh = self.get_module_gen(name)
 
     def write(self, output_dir, opt_builtins=False):
         for name in self._module:
             if name is None and not opt_builtins:
                 continue
-            basename = self._module_basename(self._what, name)
-            (genc, genh) = self._module[name]
-            genc.write(output_dir, basename + '.c')
-            genh.write(output_dir, basename + '.h')
+            module = self._module[name]
+            basename = self._module_basename(self._what, name,
+                                             module.unit, module.main_module)
+            module.write(output_dir, basename)
 
-    def _begin_module(self, name):
+    def _begin_module(self, name, main_module):
         pass
 
     def visit_module(self, name):
         if name in self._module:
             self._set_module(name)
             return
-        self._add_module(name, self._blurb)
-        self._begin_module(name)
+        main_module = self._add_module(name, self._blurb)
+        self._begin_module(name, main_module)
 
     def visit_include(self, name, info):
+        if 'has-pragma-top-unit' in info:
+            return
         basename = self._module_basename(self._what, name)
         self._genh.preamble_add(mcgen('''
 #include "%(basename)s.h"
diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
index f02b65cf5a..88bfcfcf2a 100644
--- a/scripts/qapi/events.py
+++ b/scripts/qapi/events.py
@@ -58,7 +58,12 @@ def gen_param_var(typ):
     return ret
 
 
-def gen_event_send(name, arg_type, boxed, event_enum_name):
+def gen_event_send(unit, name, arg_type, boxed, event_enum_name):
+    if not unit:
+        unit = ''
+    else:
+        unit += '_'
+
     # FIXME: Our declaration of local variables (and of 'errp' in the
     # parameter list) can collide with exploded members of the event's
     # data type passed in as parameters.  If this collision ever hits in
@@ -87,7 +92,7 @@ def gen_event_send(name, arg_type, boxed, event_enum_name):
 
     ret += mcgen('''
 
-    emit = qmp_event_get_func_emit();
+    emit = %(unit)sqmp_event_get_func_emit();
     if (!emit) {
         return;
     }
@@ -95,7 +100,7 @@ def gen_event_send(name, arg_type, boxed, event_enum_name):
     qmp = qmp_event_build_dict("%(name)s");
 
 ''',
-                 name=name)
+                 name=name, unit=unit)
 
     if arg_type and not arg_type.is_empty():
         ret += mcgen('''
@@ -154,12 +159,17 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
         QAPISchemaModularCVisitor.__init__(
             self, prefix, 'qapi-events',
             ' * Schema-defined QAPI/QMP events', __doc__)
-        self._enum_name = c_name(prefix + 'QAPIEvent', protect=False)
+
+    def visit_unit_begin(self, unit):
+        super(self.__class__, self).visit_unit_begin(unit)
+        self._enum_name = c_name(self._prefix_unit() + 'QAPIEvent', protect=False)
         self._event_names = []
 
-    def _begin_module(self, name):
-        types = self._module_basename('qapi-types', name)
-        visit = self._module_basename('qapi-visit', name)
+    def _begin_module(self, name, main_module):
+        types = self._module_basename('qapi-types', name,
+                                      self._unit, main_module)
+        visit = self._module_basename('qapi-visit', name,
+                                      self._unit, main_module)
         self._genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
@@ -171,7 +181,7 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
 #include "qapi/qmp-event.h"
 
 ''',
-                             visit=visit, prefix=self._prefix))
+                             visit=visit, prefix=self._prefix_unit()))
         self._genh.add(mcgen('''
 #include "qapi/util.h"
 #include "%(types)s.h"
@@ -179,15 +189,16 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
 ''',
                              types=types))
 
-    def visit_end(self):
-        (genc, genh) = self._module[self._main_module]
+    def visit_unit_end(self):
+        (genc, genh) = self.get_module_gen(self._main_module)
         genh.add(gen_enum(self._enum_name, self._event_names))
         genc.add(gen_enum_lookup(self._enum_name, self._event_names))
 
     def visit_event(self, name, info, 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._genc.add(gen_event_send(self._unit, name,
+                                          arg_type, boxed, self._enum_name))
         self._event_names.append(QAPISchemaMember(name, ifcond))
 
 
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index b0d3ddb596..ac0c4603d4 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -194,9 +194,11 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
 #include "qapi/util.h"
 '''))
 
-    def _begin_module(self, name):
-        types = self._module_basename('qapi-types', name)
-        visit = self._module_basename('qapi-visit', name)
+    def _begin_module(self, name, main_module):
+        types = self._module_basename('qapi-types', name,
+                                      self._unit, main_module)
+        visit = self._module_basename('qapi-visit', name,
+                                      self._unit, main_module)
         self._genc.preamble_add(mcgen('''
 #include "qemu/osdep.h"
 #include "qapi/dealloc-visitor.h"
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index dc5a3173fc..60625aae72 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -289,9 +289,11 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
 ''',
                                       prefix=prefix))
 
-    def _begin_module(self, name):
-        types = self._module_basename('qapi-types', name)
-        visit = self._module_basename('qapi-visit', name)
+    def _begin_module(self, name, main_module):
+        types = self._module_basename('qapi-types', name,
+                                      self._unit, main_module)
+        visit = self._module_basename('qapi-visit', name,
+                                      self._unit, main_module)
         self._genc.preamble_add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 41/49] qapi: add a top-unit 'target' schema
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (39 preceding siblings ...)
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 40/49] RFC: qapi: learn to split schema by 'top-unit' Marc-André Lureau
@ 2018-03-21 11:52 ` Marc-André Lureau
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 42/49] qapi: make rtc-reset-reinjection and SEV depend on TARGET_I386 Marc-André Lureau
                   ` (12 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Add a 'target' top-unit to be compiled seperately from the common qapi
modules, in order to allow poisoined target #ifdef.

The generated commands must be registered seperately.

The events have a different enum, and must thus use a different
limiter/emitter.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 qapi/qapi-schema.json    |   1 +
 qapi/target.json         |  13 +++
 include/qapi/qmp-event.h |   4 +
 monitor.c                | 205 ++++++++++++++++++++++++++-------------
 qapi/qmp-event.c         |  11 +++
 Makefile                 |   1 +
 Makefile.target          |   2 +
 7 files changed, 170 insertions(+), 67 deletions(-)
 create mode 100644 qapi/target.json

diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json
index 25bce78352..6e7f85ae6d 100644
--- a/qapi/qapi-schema.json
+++ b/qapi/qapi-schema.json
@@ -93,3 +93,4 @@
 { 'include': 'trace.json' }
 { 'include': 'introspect.json' }
 { 'include': 'misc.json' }
+{ 'include': 'target.json' }
diff --git a/qapi/target.json b/qapi/target.json
new file mode 100644
index 0000000000..be2360ca34
--- /dev/null
+++ b/qapi/target.json
@@ -0,0 +1,13 @@
+# -*- Mode: Python -*-
+#
+
+##
+# = Target-specific commands & events
+##
+
+{ 'pragma': { 'top-unit': 'target' } }
+
+##
+# @DUMMY:
+##
+{ 'event': 'DUMMY' }
diff --git a/include/qapi/qmp-event.h b/include/qapi/qmp-event.h
index 0c87ad833e..cdf3b9b970 100644
--- a/include/qapi/qmp-event.h
+++ b/include/qapi/qmp-event.h
@@ -21,5 +21,9 @@ void qmp_event_set_func_emit(QMPEventFuncEmit emit);
 
 QMPEventFuncEmit qmp_event_get_func_emit(void);
 
+void target_qmp_event_set_func_emit(QMPEventFuncEmit emit);
+
+QMPEventFuncEmit target_qmp_event_get_func_emit(void);
+
 QDict *qmp_event_build_dict(const char *event_name);
 #endif
diff --git a/monitor.c b/monitor.c
index 0d84c3edb4..0b96285e94 100644
--- a/monitor.c
+++ b/monitor.c
@@ -77,6 +77,8 @@
 #include "block/qapi.h"
 #include "qapi/qapi-commands.h"
 #include "qapi/qapi-events.h"
+#include "qapi/target-qapi-commands.h"
+#include "qapi/target-qapi-events.h"
 #include "qapi/error.h"
 #include "qapi/qmp-event.h"
 #include "qapi/qapi-introspect.h"
@@ -184,22 +186,25 @@ typedef struct {
     GQueue *qmp_responses;
 } MonitorQMP;
 
+typedef struct {
+    GHashTable *state;
+    const size_t size;    /* size of array == number of events */
+    const int64_t rate[]; /* Minimum time (in ns) between two events */
+} MonitorQAPIEventRateLimit;
+
 /*
  * To prevent flooding clients, events can be throttled. The
  * throttling is calculated globally, rather than per-Monitor
  * instance.
  */
 typedef struct MonitorQAPIEventState {
-    QAPIEvent event;    /* Throttling state for this event type and... */
+    const MonitorQAPIEventRateLimit *limiter;
+    unsigned event;     /* Throttling state for this event type and... */
     QDict *data;        /* ... data, see qapi_event_throttle_equal() */
     QEMUTimer *timer;   /* Timer for handling delayed events */
     QDict *qdict;       /* Delayed event (if any) */
 } MonitorQAPIEventState;
 
-typedef struct {
-    int64_t rate;       /* Minimum time (in ns) between two events */
-} MonitorQAPIEventConf;
-
 struct Monitor {
     CharBackend chr;
     int reset_seen;
@@ -502,23 +507,11 @@ static void monitor_qmp_bh_responder(void *opaque)
     }
 }
 
-static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT__MAX] = {
-    /* Limit guest-triggerable events to 1 per second */
-    [QAPI_EVENT_RTC_CHANGE]        = { 1000 * SCALE_MS },
-    [QAPI_EVENT_WATCHDOG]          = { 1000 * SCALE_MS },
-    [QAPI_EVENT_BALLOON_CHANGE]    = { 1000 * SCALE_MS },
-    [QAPI_EVENT_QUORUM_REPORT_BAD] = { 1000 * SCALE_MS },
-    [QAPI_EVENT_QUORUM_FAILURE]    = { 1000 * SCALE_MS },
-    [QAPI_EVENT_VSERPORT_CHANGE]   = { 1000 * SCALE_MS },
-};
-
-GHashTable *monitor_qapi_event_state;
-
 /*
  * Emits the event to every monitor instance, @event is only used for trace
  * Called with monitor_lock held.
  */
-static void monitor_qapi_event_emit(QAPIEvent event, QDict *qdict)
+static void monitor_qapi_event_emit(unsigned event, QDict *qdict)
 {
     Monitor *mon;
 
@@ -538,30 +531,31 @@ static void monitor_qapi_event_handler(void *opaque);
  * applying any rate limiting if required.
  */
 static void
-monitor_qapi_event_queue(QAPIEvent event, QDict *qdict, Error **errp)
+monitor_qapi_event_queue_limit(const MonitorQAPIEventRateLimit *limiter,
+                              unsigned event, QDict *qdict, Error **errp)
 {
-    MonitorQAPIEventConf *evconf;
+    int64_t rate;
     MonitorQAPIEventState *evstate;
 
-    assert(event < QAPI_EVENT__MAX);
-    evconf = &monitor_qapi_event_conf[event];
-    trace_monitor_protocol_event_queue(event, qdict, evconf->rate);
+    assert(event < limiter->size);
+    rate = limiter->rate[event];
+    trace_monitor_protocol_event_queue(event, qdict, rate);
 
     qemu_mutex_lock(&monitor_lock);
 
-    if (!evconf->rate) {
+    if (!rate) {
         /* Unthrottled event */
         monitor_qapi_event_emit(event, qdict);
     } else {
         QDict *data = qobject_to(QDict, qdict_get(qdict, "data"));
         MonitorQAPIEventState key = { .event = event, .data = data };
 
-        evstate = g_hash_table_lookup(monitor_qapi_event_state, &key);
+        evstate = g_hash_table_lookup(limiter->state, &key);
         assert(!evstate || timer_pending(evstate->timer));
 
         if (evstate) {
             /*
-             * Timer is pending for (at least) evconf->rate ns after
+             * Timer is pending for (at least) rate ns after
              * last send.  Store event for sending when timer fires,
              * replacing a prior stored event if any.
              */
@@ -570,9 +564,9 @@ monitor_qapi_event_queue(QAPIEvent event, QDict *qdict, Error **errp)
             QINCREF(evstate->qdict);
         } else {
             /*
-             * Last send was (at least) evconf->rate ns ago.
+             * Last send was (at least) rate ns ago.
              * Send immediately, and arm the timer to call
-             * monitor_qapi_event_handler() in evconf->rate ns.  Any
+             * monitor_qapi_event_handler() in rate ns.  Any
              * events arriving before then will be delayed until then.
              */
             int64_t now = qemu_clock_get_ns(event_clock_type);
@@ -580,6 +574,7 @@ monitor_qapi_event_queue(QAPIEvent event, QDict *qdict, Error **errp)
             monitor_qapi_event_emit(event, qdict);
 
             evstate = g_new(MonitorQAPIEventState, 1);
+            evstate->limiter = limiter;
             evstate->event = event;
             evstate->data = data;
             QINCREF(evstate->data);
@@ -587,44 +582,14 @@ monitor_qapi_event_queue(QAPIEvent event, QDict *qdict, Error **errp)
             evstate->timer = timer_new_ns(event_clock_type,
                                           monitor_qapi_event_handler,
                                           evstate);
-            g_hash_table_add(monitor_qapi_event_state, evstate);
-            timer_mod_ns(evstate->timer, now + evconf->rate);
+            g_hash_table_add(limiter->state, evstate);
+            timer_mod_ns(evstate->timer, now + rate);
         }
     }
 
     qemu_mutex_unlock(&monitor_lock);
 }
 
-/*
- * This function runs evconf->rate ns after sending a throttled
- * event.
- * If another event has since been stored, send it.
- */
-static void monitor_qapi_event_handler(void *opaque)
-{
-    MonitorQAPIEventState *evstate = opaque;
-    MonitorQAPIEventConf *evconf = &monitor_qapi_event_conf[evstate->event];
-
-    trace_monitor_protocol_event_handler(evstate->event, evstate->qdict);
-    qemu_mutex_lock(&monitor_lock);
-
-    if (evstate->qdict) {
-        int64_t now = qemu_clock_get_ns(event_clock_type);
-
-        monitor_qapi_event_emit(evstate->event, evstate->qdict);
-        QDECREF(evstate->qdict);
-        evstate->qdict = NULL;
-        timer_mod_ns(evstate->timer, now + evconf->rate);
-    } else {
-        g_hash_table_remove(monitor_qapi_event_state, evstate);
-        QDECREF(evstate->data);
-        timer_free(evstate->timer);
-        g_free(evstate);
-    }
-
-    qemu_mutex_unlock(&monitor_lock);
-}
-
 static unsigned int qapi_event_throttle_hash(const void *key)
 {
     const MonitorQAPIEventState *evstate = key;
@@ -663,15 +628,108 @@ static gboolean qapi_event_throttle_equal(const void *a, const void *b)
     return TRUE;
 }
 
+static void
+monitor_qapi_event_queue(unsigned event, QDict *qdict, Error **errp)
+{
+    static MonitorQAPIEventRateLimit limiter = {
+        .size = QAPI_EVENT__MAX,
+        .rate = {
+            /* Limit guest-triggerable events to 1 per second */
+            [QAPI_EVENT_RTC_CHANGE]        = 1000 * SCALE_MS,
+            [QAPI_EVENT_WATCHDOG]          = 1000 * SCALE_MS,
+            [QAPI_EVENT_BALLOON_CHANGE]    = 1000 * SCALE_MS,
+            [QAPI_EVENT_QUORUM_REPORT_BAD] = 1000 * SCALE_MS,
+            [QAPI_EVENT_QUORUM_FAILURE]    = 1000 * SCALE_MS,
+            [QAPI_EVENT_VSERPORT_CHANGE]   = 1000 * SCALE_MS,
+            [QAPI_EVENT__MAX]              = 0,
+        },
+    };
+
+    if (!limiter.state) {
+        limiter.state = g_hash_table_new(qapi_event_throttle_hash,
+                                         qapi_event_throttle_equal);
+    }
+
+    monitor_qapi_event_queue_limit(&limiter, event, qdict, errp);
+}
+
+static unsigned int target_qapi_event_throttle_hash(const void *key)
+{
+    const MonitorQAPIEventState *evstate = key;
+    unsigned int hash = evstate->event * 255;
+
+    return hash;
+}
+
+static gboolean target_qapi_event_throttle_equal(const void *a, const void *b)
+{
+    const MonitorQAPIEventState *eva = a;
+    const MonitorQAPIEventState *evb = b;
+
+    if (eva->event != evb->event) {
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+static void
+target_monitor_qapi_event_queue(unsigned event, QDict *qdict, Error **errp)
+{
+    static MonitorQAPIEventRateLimit limiter = {
+        .size = TARGET_QAPI_EVENT__MAX,
+        .rate = {
+            /* Limit guest-triggerable events to 1 per second */
+            [TARGET_QAPI_EVENT__MAX]       = 0,
+        },
+    };
+
+    if (!limiter.state) {
+        limiter.state = g_hash_table_new(target_qapi_event_throttle_hash,
+                                         target_qapi_event_throttle_equal);
+    }
+    monitor_qapi_event_queue_limit(&limiter, event, qdict, errp);
+}
+
+/*
+ * This function runs evconf->rate ns after sending a throttled
+ * event.
+ * If another event has since been stored, send it.
+ */
+static void monitor_qapi_event_handler(void *opaque)
+{
+    MonitorQAPIEventState *evstate = opaque;
+    const MonitorQAPIEventRateLimit *limiter = evstate->limiter;
+    int64_t rate = limiter->rate[evstate->event];
+
+    trace_monitor_protocol_event_handler(evstate->event, evstate->qdict);
+    qemu_mutex_lock(&monitor_lock);
+
+    if (evstate->qdict) {
+        int64_t now = qemu_clock_get_ns(event_clock_type);
+
+        monitor_qapi_event_emit(evstate->event, evstate->qdict);
+        QDECREF(evstate->qdict);
+        evstate->qdict = NULL;
+        timer_mod_ns(evstate->timer, now + rate);
+    } else {
+        g_hash_table_remove(limiter->state, evstate);
+        QDECREF(evstate->data);
+        timer_free(evstate->timer);
+        g_free(evstate);
+    }
+
+    qemu_mutex_unlock(&monitor_lock);
+}
+
 static void monitor_qapi_event_init(void)
 {
     if (qtest_enabled()) {
         event_clock_type = QEMU_CLOCK_VIRTUAL;
     }
 
-    monitor_qapi_event_state = g_hash_table_new(qapi_event_throttle_hash,
-                                                qapi_event_throttle_equal);
     qmp_event_set_func_emit(monitor_qapi_event_queue);
+    target_qmp_event_set_func_emit(target_monitor_qapi_event_queue);
 }
 
 static void handle_hmp_command(Monitor *mon, const char *cmdline);
@@ -1039,9 +1097,10 @@ CommandInfoList *qmp_query_commands(Error **errp)
     return list;
 }
 
-EventInfoList *qmp_query_events(Error **errp)
+static void qmp_query_events_list(EventInfoList **list,
+                                  const QEnumLookup *qenum, int max)
 {
-    EventInfoList *info, *ev_list = NULL;
+    EventInfoList *info;
     QAPIEvent e;
 
     for (e = 0 ; e < QAPI_EVENT__MAX ; e++) {
@@ -1051,11 +1110,22 @@ EventInfoList *qmp_query_events(Error **errp)
         info->value = g_malloc0(sizeof(*info->value));
         info->value->name = g_strdup(event_name);
 
-        info->next = ev_list;
-        ev_list = info;
+        info->next = *list;
+        *list = info;
     }
 
-    return ev_list;
+}
+
+EventInfoList *qmp_query_events(Error **errp)
+{
+    EventInfoList *list = NULL;
+
+    qmp_query_events_list(&list, &QAPIEvent_lookup,
+                          QAPI_EVENT__MAX);
+    qmp_query_events_list(&list, &target_QAPIEvent_lookup,
+                          TARGET_QAPI_EVENT__MAX);
+
+    return list;
 }
 
 /*
@@ -1123,6 +1193,7 @@ static void monitor_init_qmp_commands(void)
 
     QTAILQ_INIT(&qmp_commands);
     qmp_init_marshal(&qmp_commands);
+    target_qmp_init_marshal(&qmp_commands);
 
     qmp_register_command(&qmp_commands, "query-qmp-schema",
                          qmp_query_qmp_schema,
diff --git a/qapi/qmp-event.c b/qapi/qmp-event.c
index 9d7e88e84a..72fd83841d 100644
--- a/qapi/qmp-event.c
+++ b/qapi/qmp-event.c
@@ -20,6 +20,7 @@
 #include "qapi/qmp/qjson.h"
 
 static QMPEventFuncEmit qmp_emit;
+static QMPEventFuncEmit target_qmp_emit;
 
 void qmp_event_set_func_emit(QMPEventFuncEmit emit)
 {
@@ -31,6 +32,16 @@ QMPEventFuncEmit qmp_event_get_func_emit(void)
     return qmp_emit;
 }
 
+void target_qmp_event_set_func_emit(QMPEventFuncEmit emit)
+{
+    target_qmp_emit = emit;
+}
+
+QMPEventFuncEmit target_qmp_event_get_func_emit(void)
+{
+    return target_qmp_emit;
+}
+
 static void timestamp_put(QDict *qdict)
 {
     int err;
diff --git a/Makefile b/Makefile
index 727ef118f3..93a8ff5b78 100644
--- a/Makefile
+++ b/Makefile
@@ -588,6 +588,7 @@ qapi-modules = $(SRC_PATH)/qapi/qapi-schema.json $(SRC_PATH)/qapi/common.json \
                $(SRC_PATH)/qapi/rocker.json \
                $(SRC_PATH)/qapi/run-state.json \
                $(SRC_PATH)/qapi/sockets.json \
+               $(SRC_PATH)/qapi/target.json \
                $(SRC_PATH)/qapi/tpm.json \
                $(SRC_PATH)/qapi/trace.json \
                $(SRC_PATH)/qapi/transaction.json \
diff --git a/Makefile.target b/Makefile.target
index 0bb18dff9e..9db617cda9 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -150,6 +150,8 @@ endif
 
 GENERATED_FILES += hmp-commands.h hmp-commands-info.h
 
+obj-y += qapi/target-qapi-types.o qapi/target-qapi-visit.o
+obj-y += qapi/target-qapi-events.o qapi/target-qapi-commands.o
 obj-y += qapi/qapi-introspect.o
 
 endif # CONFIG_SOFTMMU
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 42/49] qapi: make rtc-reset-reinjection and SEV depend on TARGET_I386
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (40 preceding siblings ...)
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 41/49] qapi: add a top-unit 'target' schema Marc-André Lureau
@ 2018-03-21 11:52 ` Marc-André Lureau
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 43/49] qapi: make s390 commands depend on TARGET_S390X Marc-André Lureau
                   ` (11 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Move rtc-reset-reinjection and SEV in target.json and make them
conditional on TARGET_I386.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 qapi/misc.json         | 166 --------------------------------------
 qapi/target.json       | 175 ++++++++++++++++++++++++++++++++++++++++-
 target/i386/sev_i386.h |   2 +-
 hw/timer/mc146818rtc.c |   2 +-
 monitor.c              |  31 --------
 5 files changed, 175 insertions(+), 201 deletions(-)

diff --git a/qapi/misc.json b/qapi/misc.json
index 5636f4a149..690eeda41f 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -3005,24 +3005,6 @@
 { 'event': 'ACPI_DEVICE_OST',
      'data': { 'info': 'ACPIOSTInfo' } }
 
-##
-# @rtc-reset-reinjection:
-#
-# This command will reset the RTC interrupt reinjection backlog.
-# Can be used if another mechanism to synchronize guest time
-# is in effect, for example QEMU guest agent's guest-set-time
-# command.
-#
-# Since: 2.1
-#
-# Example:
-#
-# -> { "execute": "rtc-reset-reinjection" }
-# <- { "return": {} }
-#
-##
-{ 'command': 'rtc-reset-reinjection' }
-
 ##
 # @RTC_CHANGE:
 #
@@ -3247,154 +3229,6 @@
 ##
 { 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' }
 
-
-##
-# @SevState:
-#
-# An enumeration of SEV state information used during @query-sev.
-#
-# @uninit: The guest is uninitialized.
-#
-# @launch-update: The guest is currently being launched; plaintext data and
-#                 register state is being imported.
-#
-# @launch-secret: The guest is currently being launched; ciphertext data
-#                 is being imported.
-#
-# @running: The guest is fully launched or migrated in.
-#
-# @send-update: The guest is currently being migrated out to another machine.
-#
-# @receive-update: The guest is currently being migrated from another machine.
-#
-# Since: 2.12
-##
-{ 'enum': 'SevState',
-  'data': ['uninit', 'launch-update', 'launch-secret', 'running',
-           'send-update', 'receive-update' ] }
-
-##
-# @SevInfo:
-#
-# Information about Secure Encrypted Virtualization (SEV) support
-#
-# @enabled: true if SEV is active
-#
-# @api-major: SEV API major version
-#
-# @api-minor: SEV API minor version
-#
-# @build-id: SEV FW build id
-#
-# @policy: SEV policy value
-#
-# @state: SEV guest state
-#
-# @handle: SEV firmware handle
-#
-# Since: 2.12
-##
-{ 'struct': 'SevInfo',
-    'data': { 'enabled': 'bool',
-              'api-major': 'uint8',
-              'api-minor' : 'uint8',
-              'build-id' : 'uint8',
-              'policy' : 'uint32',
-              'state' : 'SevState',
-              'handle' : 'uint32'
-            }
-}
-
-##
-# @query-sev:
-#
-# Returns information about SEV
-#
-# Returns: @SevInfo
-#
-# Since: 2.12
-#
-# Example:
-#
-# -> { "execute": "query-sev" }
-# <- { "return": { "enabled": true, "api-major" : 0, "api-minor" : 0,
-#                  "build-id" : 0, "policy" : 0, "state" : "running",
-#                  "handle" : 1 } }
-#
-##
-{ 'command': 'query-sev', 'returns': 'SevInfo' }
-
-##
-# @SevLaunchMeasureInfo:
-#
-# SEV Guest Launch measurement information
-#
-# @data: the measurement value encoded in base64
-#
-# Since: 2.12
-#
-##
-{ 'struct': 'SevLaunchMeasureInfo', 'data': {'data': 'str'} }
-
-##
-# @query-sev-launch-measure:
-#
-# Query the SEV guest launch information.
-#
-# Returns: The @SevLaunchMeasureInfo for the guest
-#
-# Since: 2.12
-#
-# Example:
-#
-# -> { "execute": "query-sev-launch-measure" }
-# <- { "return": { "data": "4l8LXeNlSPUDlXPJG5966/8%YZ" } }
-#
-##
-{ 'command': 'query-sev-launch-measure', 'returns': 'SevLaunchMeasureInfo' }
-
-##
-# @SevCapability:
-#
-# The struct describes capability for a Secure Encrypted Virtualization
-# feature.
-#
-# @pdh:  Platform Diffie-Hellman key (base64 encoded)
-#
-# @cert-chain:  PDH certificate chain (base64 encoded)
-#
-# @cbitpos: C-bit location in page table entry
-#
-# @reduced-phys-bits: Number of physical Address bit reduction when SEV is
-#                     enabled
-#
-# Since: 2.12
-##
-{ 'struct': 'SevCapability',
-  'data': { 'pdh': 'str',
-            'cert-chain': 'str',
-            'cbitpos': 'int',
-            'reduced-phys-bits': 'int'} }
-
-##
-# @query-sev-capabilities:
-#
-# This command is used to get the SEV capabilities, and is supported on AMD
-# X86 platforms only.
-#
-# Returns: SevCapability objects.
-#
-# Since: 2.12
-#
-# Example:
-#
-# -> { "execute": "query-sev-capabilities" }
-# <- { "return": { "pdh": "8CCDD8DDD", "cert-chain": "888CCCDDDEE",
-#                  "cbitpos": 47, "reduced-phys-bits": 5}}
-#
-##
-{ 'command': 'query-sev-capabilities', 'returns': 'SevCapability' }
-
 ##
 # @CommandDropReason:
 #
diff --git a/qapi/target.json b/qapi/target.json
index be2360ca34..f277b69a2a 100644
--- a/qapi/target.json
+++ b/qapi/target.json
@@ -8,6 +8,177 @@
 { 'pragma': { 'top-unit': 'target' } }
 
 ##
-# @DUMMY:
+# @rtc-reset-reinjection:
+#
+# This command will reset the RTC interrupt reinjection backlog.
+# Can be used if another mechanism to synchronize guest time
+# is in effect, for example QEMU guest agent's guest-set-time
+# command.
+#
+# Since: 2.1
+#
+# Example:
+#
+# -> { "execute": "rtc-reset-reinjection" }
+# <- { "return": {} }
+#
+##
+{ 'command': 'rtc-reset-reinjection',
+  'if': 'defined(TARGET_I386)' }
+
+
+##
+# @SevState:
+#
+# An enumeration of SEV state information used during @query-sev.
+#
+# @uninit: The guest is uninitialized.
+#
+# @launch-update: The guest is currently being launched; plaintext data and
+#                 register state is being imported.
+#
+# @launch-secret: The guest is currently being launched; ciphertext data
+#                 is being imported.
+#
+# @running: The guest is fully launched or migrated in.
+#
+# @send-update: The guest is currently being migrated out to another machine.
+#
+# @receive-update: The guest is currently being migrated from another machine.
+#
+# Since: 2.12
+##
+{ 'enum': 'SevState',
+  'data': ['uninit', 'launch-update', 'launch-secret', 'running',
+           'send-update', 'receive-update' ],
+  'if': 'defined(TARGET_I386)' }
+
+##
+# @SevInfo:
+#
+# Information about Secure Encrypted Virtualization (SEV) support
+#
+# @enabled: true if SEV is active
+#
+# @api-major: SEV API major version
+#
+# @api-minor: SEV API minor version
+#
+# @build-id: SEV FW build id
+#
+# @policy: SEV policy value
+#
+# @state: SEV guest state
+#
+# @handle: SEV firmware handle
+#
+# Since: 2.12
+##
+{ 'struct': 'SevInfo',
+    'data': { 'enabled': 'bool',
+              'api-major': 'uint8',
+              'api-minor' : 'uint8',
+              'build-id' : 'uint8',
+              'policy' : 'uint32',
+              'state' : 'SevState',
+              'handle' : 'uint32'
+            },
+  'if': 'defined(TARGET_I386)'
+}
+
+##
+# @query-sev:
+#
+# Returns information about SEV
+#
+# Returns: @SevInfo
+#
+# Since: 2.12
+#
+# Example:
+#
+# -> { "execute": "query-sev" }
+# <- { "return": { "enabled": true, "api-major" : 0, "api-minor" : 0,
+#                  "build-id" : 0, "policy" : 0, "state" : "running",
+#                  "handle" : 1 } }
+#
+##
+{ 'command': 'query-sev', 'returns': 'SevInfo',
+  'if': 'defined(TARGET_I386)' }
+
+
+##
+# @SevLaunchMeasureInfo:
+#
+# SEV Guest Launch measurement information
+#
+# @data: the measurement value encoded in base64
+#
+# Since: 2.12
+#
+##
+{ 'struct': 'SevLaunchMeasureInfo', 'data': {'data': 'str'},
+  'if': 'defined(TARGET_I386)' }
+
+##
+# @query-sev-launch-measure:
+#
+# Query the SEV guest launch information.
+#
+# Returns: The @SevLaunchMeasureInfo for the guest
+#
+# Since: 2.12
+#
+# Example:
+#
+# -> { "execute": "query-sev-launch-measure" }
+# <- { "return": { "data": "4l8LXeNlSPUDlXPJG5966/8%YZ" } }
+#
+##
+{ 'command': 'query-sev-launch-measure', 'returns': 'SevLaunchMeasureInfo',
+  'if': 'defined(TARGET_I386)' }
+
+
+##
+# @SevCapability:
+#
+# The struct describes capability for a Secure Encrypted Virtualization
+# feature.
+#
+# @pdh:  Platform Diffie-Hellman key (base64 encoded)
+#
+# @cert-chain:  PDH certificate chain (base64 encoded)
+#
+# @cbitpos: C-bit location in page table entry
+#
+# @reduced-phys-bits: Number of physical Address bit reduction when SEV is
+#                     enabled
+#
+# Since: 2.12
+##
+{ 'struct': 'SevCapability',
+  'data': { 'pdh': 'str',
+            'cert-chain': 'str',
+            'cbitpos': 'int',
+            'reduced-phys-bits': 'int'},
+  'if': 'defined(TARGET_I386)' }
+
+##
+# @query-sev-capabilities:
+#
+# This command is used to get the SEV capabilities, and is supported on AMD
+# X86 platforms only.
+#
+# Returns: SevCapability objects.
+#
+# Since: 2.12
+#
+# Example:
+#
+# -> { "execute": "query-sev-capabilities" }
+# <- { "return": { "pdh": "8CCDD8DDD", "cert-chain": "888CCCDDDEE",
+#                  "cbitpos": 47, "reduced-phys-bits": 5}}
+#
 ##
-{ 'event': 'DUMMY' }
+{ 'command': 'query-sev-capabilities', 'returns': 'SevCapability',
+  'if': 'defined(TARGET_I386)' }
diff --git a/target/i386/sev_i386.h b/target/i386/sev_i386.h
index b8622dfb1e..8f88f86952 100644
--- a/target/i386/sev_i386.h
+++ b/target/i386/sev_i386.h
@@ -19,7 +19,7 @@
 #include "sysemu/kvm.h"
 #include "sysemu/sev.h"
 #include "qemu/error-report.h"
-#include "qapi/qapi-commands-misc.h"
+#include "qapi/target-qapi-commands.h"
 
 #define SEV_POLICY_NODBG        0x1
 #define SEV_POLICY_NOKS         0x2
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 6f1f723b1f..dd575ffbdf 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -31,7 +31,7 @@
 #include "sysemu/replay.h"
 #include "hw/timer/mc146818rtc.h"
 #include "qapi/error.h"
-#include "qapi/qapi-commands-misc.h"
+#include "qapi/target-qapi-commands.h"
 #include "qapi/qapi-events-misc.h"
 #include "qapi/visitor.h"
 
diff --git a/monitor.c b/monitor.c
index 0b96285e94..4ad9225425 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1157,12 +1157,6 @@ static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
  */
 static void qmp_unregister_commands_hack(void)
 {
-#ifndef TARGET_I386
-    qmp_unregister_command(&qmp_commands, "rtc-reset-reinjection");
-    qmp_unregister_command(&qmp_commands, "query-sev");
-    qmp_unregister_command(&qmp_commands, "query-sev-launch-measure");
-    qmp_unregister_command(&qmp_commands, "query-sev-capabilities");
-#endif
 #ifndef TARGET_S390X
     qmp_unregister_command(&qmp_commands, "dump-skeys");
 #endif
@@ -4709,31 +4703,6 @@ QemuOptsList qemu_mon_opts = {
     },
 };
 
-#ifndef TARGET_I386
-void qmp_rtc_reset_reinjection(Error **errp)
-{
-    error_setg(errp, QERR_FEATURE_DISABLED, "rtc-reset-reinjection");
-}
-
-SevInfo *qmp_query_sev(Error **errp)
-{
-    error_setg(errp, QERR_FEATURE_DISABLED, "query-sev");
-    return NULL;
-}
-
-SevLaunchMeasureInfo *qmp_query_sev_launch_measure(Error **errp)
-{
-    error_setg(errp, QERR_FEATURE_DISABLED, "query-sev-launch-measure");
-    return NULL;
-}
-
-SevCapability *qmp_query_sev_capabilities(Error **errp)
-{
-    error_setg(errp, QERR_FEATURE_DISABLED, "query-sev-capabilities");
-    return NULL;
-}
-#endif
-
 #ifndef TARGET_S390X
 void qmp_dump_skeys(const char *filename, Error **errp)
 {
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 43/49] qapi: make s390 commands depend on TARGET_S390X
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (41 preceding siblings ...)
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 42/49] qapi: make rtc-reset-reinjection and SEV depend on TARGET_I386 Marc-André Lureau
@ 2018-03-21 11:52 ` Marc-André Lureau
  2018-03-22  5:42   ` Thomas Huth
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 44/49] target.json: add a note about query-cpu* not being s390x-specific Marc-André Lureau
                   ` (10 subsequent siblings)
  53 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Cornelia Huck <cohuck@redhat.com>
---
 qapi/misc.json                          | 101 ----------------------
 qapi/target.json                        | 106 ++++++++++++++++++++++++
 include/sysemu/arch_init.h              |   7 --
 hw/s390x/s390-skeys.c                   |   2 +-
 monitor.c                               |  14 ----
 qmp.c                                   |  14 ----
 stubs/arch-query-cpu-model-baseline.c   |  13 ---
 stubs/arch-query-cpu-model-comparison.c |  13 ---
 target/s390x/cpu_models.c               |   5 +-
 stubs/Makefile.objs                     |   2 -
 10 files changed, 110 insertions(+), 167 deletions(-)
 delete mode 100644 stubs/arch-query-cpu-model-baseline.c
 delete mode 100644 stubs/arch-query-cpu-model-comparison.c

diff --git a/qapi/misc.json b/qapi/misc.json
index 690eeda41f..1753a81b1e 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -1821,27 +1821,6 @@
 { 'command': 'query-dump-guest-memory-capability',
   'returns': 'DumpGuestMemoryCapability' }
 
-##
-# @dump-skeys:
-#
-# Dump guest's storage keys
-#
-# @filename: the path to the file to dump to
-#
-# This command is only supported on s390 architecture.
-#
-# Since: 2.5
-#
-# Example:
-#
-# -> { "execute": "dump-skeys",
-#      "arguments": { "filename": "/tmp/skeys" } }
-# <- { "return": {} }
-#
-##
-{ 'command': 'dump-skeys',
-  'data': { 'filename': 'str' } }
-
 ##
 # @object-add:
 #
@@ -2208,46 +2187,6 @@
           }
 }
 
-##
-# @query-cpu-model-comparison:
-#
-# Compares two CPU models, returning how they compare in a specific
-# configuration. The results indicates how both models compare regarding
-# runnability. This result can be used by tooling to make decisions if a
-# certain CPU model will run in a certain configuration or if a compatible
-# CPU model has to be created by baselining.
-#
-# Usually, a CPU model is compared against the maximum possible CPU model
-# of a certain configuration (e.g. the "host" model for KVM). If that CPU
-# model is identical or a subset, it will run in that configuration.
-#
-# The result returned by this command may be affected by:
-#
-# * QEMU version: CPU models may look different depending on the QEMU version.
-#   (Except for CPU models reported as "static" in query-cpu-definitions.)
-# * machine-type: CPU model may look different depending on the machine-type.
-#   (Except for CPU models reported as "static" in query-cpu-definitions.)
-# * machine options (including accelerator): in some architectures, CPU models
-#   may look different depending on machine and accelerator options. (Except for
-#   CPU models reported as "static" in query-cpu-definitions.)
-# * "-cpu" arguments and global properties: arguments to the -cpu option and
-#   global properties may affect expansion of CPU models. Using
-#   query-cpu-model-expansion while using these is not advised.
-#
-# Some architectures may not support comparing CPU models. s390x supports
-# comparing CPU models.
-#
-# Returns: a CpuModelBaselineInfo. Returns an error if comparing CPU models is
-#          not supported, if a model cannot be used, if a model contains
-#          an unknown cpu definition name, unknown properties or properties
-#          with wrong types.
-#
-# Since: 2.8.0
-##
-{ 'command': 'query-cpu-model-comparison',
-  'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
-  'returns': 'CpuModelCompareInfo' }
-
 ##
 # @CpuModelBaselineInfo:
 #
@@ -2260,46 +2199,6 @@
 { 'struct': 'CpuModelBaselineInfo',
   'data': { 'model': 'CpuModelInfo' } }
 
-##
-# @query-cpu-model-baseline:
-#
-# Baseline two CPU models, creating a compatible third model. The created
-# model will always be a static, migration-safe CPU model (see "static"
-# CPU model expansion for details).
-#
-# This interface can be used by tooling to create a compatible CPU model out
-# two CPU models. The created CPU model will be identical to or a subset of
-# both CPU models when comparing them. Therefore, the created CPU model is
-# guaranteed to run where the given CPU models run.
-#
-# The result returned by this command may be affected by:
-#
-# * QEMU version: CPU models may look different depending on the QEMU version.
-#   (Except for CPU models reported as "static" in query-cpu-definitions.)
-# * machine-type: CPU model may look different depending on the machine-type.
-#   (Except for CPU models reported as "static" in query-cpu-definitions.)
-# * machine options (including accelerator): in some architectures, CPU models
-#   may look different depending on machine and accelerator options. (Except for
-#   CPU models reported as "static" in query-cpu-definitions.)
-# * "-cpu" arguments and global properties: arguments to the -cpu option and
-#   global properties may affect expansion of CPU models. Using
-#   query-cpu-model-expansion while using these is not advised.
-#
-# Some architectures may not support baselining CPU models. s390x supports
-# baselining CPU models.
-#
-# Returns: a CpuModelBaselineInfo. Returns an error if baselining CPU models is
-#          not supported, if a model cannot be used, if a model contains
-#          an unknown cpu definition name, unknown properties or properties
-#          with wrong types.
-#
-# Since: 2.8.0
-##
-{ 'command': 'query-cpu-model-baseline',
-  'data': { 'modela': 'CpuModelInfo',
-            'modelb': 'CpuModelInfo' },
-  'returns': 'CpuModelBaselineInfo' }
-
 ##
 # @AddfdInfo:
 #
diff --git a/qapi/target.json b/qapi/target.json
index f277b69a2a..b07a8926d8 100644
--- a/qapi/target.json
+++ b/qapi/target.json
@@ -7,6 +7,8 @@
 
 { 'pragma': { 'top-unit': 'target' } }
 
+{ 'include': 'misc.json' }
+
 ##
 # @rtc-reset-reinjection:
 #
@@ -182,3 +184,107 @@
 ##
 { 'command': 'query-sev-capabilities', 'returns': 'SevCapability',
   'if': 'defined(TARGET_I386)' }
+
+##
+# @dump-skeys:
+#
+# Dump guest's storage keys
+#
+# @filename: the path to the file to dump to
+#
+# This command is only supported on s390 architecture.
+#
+# Since: 2.5
+#
+# Example:
+#
+# -> { "execute": "dump-skeys",
+#      "arguments": { "filename": "/tmp/skeys" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'dump-skeys',
+  'data': { 'filename': 'str' },
+  'if': 'defined(TARGET_S390X)' }
+
+##
+# @query-cpu-model-comparison:
+#
+# Compares two CPU models, returning how they compare in a specific
+# configuration. The results indicates how both models compare regarding
+# runnability. This result can be used by tooling to make decisions if a
+# certain CPU model will run in a certain configuration or if a compatible
+# CPU model has to be created by baselining.
+#
+# Usually, a CPU model is compared against the maximum possible CPU model
+# of a certain configuration (e.g. the "host" model for KVM). If that CPU
+# model is identical or a subset, it will run in that configuration.
+#
+# The result returned by this command may be affected by:
+#
+# * QEMU version: CPU models may look different depending on the QEMU version.
+#   (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine-type: CPU model may look different depending on the machine-type.
+#   (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine options (including accelerator): in some architectures, CPU models
+#   may look different depending on machine and accelerator options. (Except for
+#   CPU models reported as "static" in query-cpu-definitions.)
+# * "-cpu" arguments and global properties: arguments to the -cpu option and
+#   global properties may affect expansion of CPU models. Using
+#   query-cpu-model-expansion while using these is not advised.
+#
+# Some architectures may not support comparing CPU models. s390x supports
+# comparing CPU models.
+#
+# Returns: a CpuModelBaselineInfo. Returns an error if comparing CPU models is
+#          not supported, if a model cannot be used, if a model contains
+#          an unknown cpu definition name, unknown properties or properties
+#          with wrong types.
+#
+# Since: 2.8.0
+##
+{ 'command': 'query-cpu-model-comparison',
+  'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
+  'returns': 'CpuModelCompareInfo',
+  'if': 'defined(TARGET_S390X)' }
+
+##
+# @query-cpu-model-baseline:
+#
+# Baseline two CPU models, creating a compatible third model. The created
+# model will always be a static, migration-safe CPU model (see "static"
+# CPU model expansion for details).
+#
+# This interface can be used by tooling to create a compatible CPU model out
+# two CPU models. The created CPU model will be identical to or a subset of
+# both CPU models when comparing them. Therefore, the created CPU model is
+# guaranteed to run where the given CPU models run.
+#
+# The result returned by this command may be affected by:
+#
+# * QEMU version: CPU models may look different depending on the QEMU version.
+#   (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine-type: CPU model may look different depending on the machine-type.
+#   (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine options (including accelerator): in some architectures, CPU models
+#   may look different depending on machine and accelerator options. (Except for
+#   CPU models reported as "static" in query-cpu-definitions.)
+# * "-cpu" arguments and global properties: arguments to the -cpu option and
+#   global properties may affect expansion of CPU models. Using
+#   query-cpu-model-expansion while using these is not advised.
+#
+# Some architectures may not support baselining CPU models. s390x supports
+# baselining CPU models.
+#
+# Returns: a CpuModelBaselineInfo. Returns an error if baselining CPU models is
+#          not supported, if a model cannot be used, if a model contains
+#          an unknown cpu definition name, unknown properties or properties
+#          with wrong types.
+#
+# Since: 2.8.0
+##
+{ 'command': 'query-cpu-model-baseline',
+  'data': { 'modela': 'CpuModelInfo',
+            'modelb': 'CpuModelInfo' },
+  'returns': 'CpuModelBaselineInfo',
+  'if': 'defined(TARGET_S390X)' }
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index 32abdfe6a1..f0ef652b2a 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -36,11 +36,4 @@ CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp);
 CpuModelExpansionInfo *arch_query_cpu_model_expansion(CpuModelExpansionType type,
                                                       CpuModelInfo *mode,
                                                       Error **errp);
-CpuModelCompareInfo *arch_query_cpu_model_comparison(CpuModelInfo *modela,
-                                                     CpuModelInfo *modelb,
-                                                     Error **errp);
-CpuModelBaselineInfo *arch_query_cpu_model_baseline(CpuModelInfo *modela,
-                                                    CpuModelInfo *modelb,
-                                                    Error **errp);
-
 #endif
diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c
index 76241c240e..59d28c2358 100644
--- a/hw/s390x/s390-skeys.c
+++ b/hw/s390x/s390-skeys.c
@@ -13,7 +13,7 @@
 #include "hw/boards.h"
 #include "hw/s390x/storage-keys.h"
 #include "qapi/error.h"
-#include "qapi/qapi-commands-misc.h"
+#include "qapi/target-qapi-commands.h"
 #include "qapi/qmp/qdict.h"
 #include "qemu/error-report.h"
 #include "sysemu/kvm.h"
diff --git a/monitor.c b/monitor.c
index 4ad9225425..bd9a6950cf 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1157,19 +1157,12 @@ static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
  */
 static void qmp_unregister_commands_hack(void)
 {
-#ifndef TARGET_S390X
-    qmp_unregister_command(&qmp_commands, "dump-skeys");
-#endif
 #ifndef TARGET_ARM
     qmp_unregister_command(&qmp_commands, "query-gic-capabilities");
 #endif
 #if !defined(TARGET_S390X) && !defined(TARGET_I386)
     qmp_unregister_command(&qmp_commands, "query-cpu-model-expansion");
 #endif
-#if !defined(TARGET_S390X)
-    qmp_unregister_command(&qmp_commands, "query-cpu-model-baseline");
-    qmp_unregister_command(&qmp_commands, "query-cpu-model-comparison");
-#endif
 #if !defined(TARGET_PPC) && !defined(TARGET_ARM) && !defined(TARGET_I386) \
     && !defined(TARGET_S390X)
     qmp_unregister_command(&qmp_commands, "query-cpu-definitions");
@@ -4703,13 +4696,6 @@ QemuOptsList qemu_mon_opts = {
     },
 };
 
-#ifndef TARGET_S390X
-void qmp_dump_skeys(const char *filename, Error **errp)
-{
-    error_setg(errp, QERR_FEATURE_DISABLED, "dump-skeys");
-}
-#endif
-
 #ifndef TARGET_ARM
 GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
 {
diff --git a/qmp.c b/qmp.c
index d8f80cb04e..14972b78df 100644
--- a/qmp.c
+++ b/qmp.c
@@ -601,20 +601,6 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
     return arch_query_cpu_model_expansion(type, model, errp);
 }
 
-CpuModelCompareInfo *qmp_query_cpu_model_comparison(CpuModelInfo *modela,
-                                                    CpuModelInfo *modelb,
-                                                    Error **errp)
-{
-    return arch_query_cpu_model_comparison(modela, modelb, errp);
-}
-
-CpuModelBaselineInfo *qmp_query_cpu_model_baseline(CpuModelInfo *modela,
-                                                   CpuModelInfo *modelb,
-                                                   Error **errp)
-{
-    return arch_query_cpu_model_baseline(modela, modelb, errp);
-}
-
 void qmp_add_client(const char *protocol, const char *fdname,
                     bool has_skipauth, bool skipauth, bool has_tls, bool tls,
                     Error **errp)
diff --git a/stubs/arch-query-cpu-model-baseline.c b/stubs/arch-query-cpu-model-baseline.c
deleted file mode 100644
index 0d066da328..0000000000
--- a/stubs/arch-query-cpu-model-baseline.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "sysemu/arch_init.h"
-#include "qapi/error.h"
-#include "qapi/qmp/qerror.h"
-
-CpuModelBaselineInfo *arch_query_cpu_model_baseline(CpuModelInfo *modela,
-                                                    CpuModelInfo *modelb,
-                                                    Error **errp)
-{
-    error_setg(errp, QERR_UNSUPPORTED);
-    return NULL;
-}
diff --git a/stubs/arch-query-cpu-model-comparison.c b/stubs/arch-query-cpu-model-comparison.c
deleted file mode 100644
index 8eb311a26c..0000000000
--- a/stubs/arch-query-cpu-model-comparison.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "sysemu/arch_init.h"
-#include "qapi/error.h"
-#include "qapi/qmp/qerror.h"
-
-CpuModelCompareInfo *arch_query_cpu_model_comparison(CpuModelInfo *modela,
-                                                     CpuModelInfo *modelb,
-                                                     Error **errp)
-{
-    error_setg(errp, QERR_UNSUPPORTED);
-    return NULL;
-}
diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c
index 2741b6803f..ffca1d9a2d 100644
--- a/target/s390x/cpu_models.c
+++ b/target/s390x/cpu_models.c
@@ -25,6 +25,7 @@
 #include "sysemu/arch_init.h"
 #include "hw/pci/pci.h"
 #endif
+#include "qapi/target-qapi-commands.h"
 
 #define CPUDEF_INIT(_type, _gen, _ec_ga, _mha_pow, _hmfai, _name, _desc) \
     {                                                                    \
@@ -597,7 +598,7 @@ static void list_add_feat(const char *name, void *opaque)
     *last = entry;
 }
 
-CpuModelCompareInfo *arch_query_cpu_model_comparison(CpuModelInfo *infoa,
+CpuModelCompareInfo *qmp_query_cpu_model_comparison(CpuModelInfo *infoa,
                                                      CpuModelInfo *infob,
                                                      Error **errp)
 {
@@ -670,7 +671,7 @@ CpuModelCompareInfo *arch_query_cpu_model_comparison(CpuModelInfo *infoa,
     return compare_info;
 }
 
-CpuModelBaselineInfo *arch_query_cpu_model_baseline(CpuModelInfo *infoa,
+CpuModelBaselineInfo *qmp_query_cpu_model_baseline(CpuModelInfo *infoa,
                                                     CpuModelInfo *infob,
                                                     Error **errp)
 {
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 2d59d84091..9a91e49578 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -1,7 +1,5 @@
 stub-obj-y += arch-query-cpu-def.o
 stub-obj-y += arch-query-cpu-model-expansion.o
-stub-obj-y += arch-query-cpu-model-comparison.o
-stub-obj-y += arch-query-cpu-model-baseline.o
 stub-obj-y += bdrv-next-monitor-owned.o
 stub-obj-y += blk-commit-all.o
 stub-obj-y += blockdev-close-all-bdrv-states.o
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 44/49] target.json: add a note about query-cpu* not being s390x-specific
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (42 preceding siblings ...)
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 43/49] qapi: make s390 commands depend on TARGET_S390X Marc-André Lureau
@ 2018-03-21 11:52 ` Marc-André Lureau
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 45/49] qapi: make query-gic-capabilities depend on TARGET_ARM Marc-André Lureau
                   ` (9 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Cornelia Huck <cohuck@redhat.com>
---
 qapi/target.json | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/qapi/target.json b/qapi/target.json
index b07a8926d8..be0ff84a6e 100644
--- a/qapi/target.json
+++ b/qapi/target.json
@@ -241,6 +241,9 @@
 #          an unknown cpu definition name, unknown properties or properties
 #          with wrong types.
 #
+# Note: this command isn't specific to s390x, but is only implemented
+# on this architecture currently.
+#
 # Since: 2.8.0
 ##
 { 'command': 'query-cpu-model-comparison',
@@ -281,6 +284,9 @@
 #          an unknown cpu definition name, unknown properties or properties
 #          with wrong types.
 #
+# Note: this command isn't specific to s390x, but is only implemented
+# on this architecture currently.
+#
 # Since: 2.8.0
 ##
 { 'command': 'query-cpu-model-baseline',
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 45/49] qapi: make query-gic-capabilities depend on TARGET_ARM
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (43 preceding siblings ...)
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 44/49] target.json: add a note about query-cpu* not being s390x-specific Marc-André Lureau
@ 2018-03-21 11:52 ` Marc-André Lureau
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 46/49] qapi: make query-cpu-model-expansion depend on s390 or x86 Marc-André Lureau
                   ` (8 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 qapi/misc.json       | 43 ------------------------------------------
 qapi/target.json     | 45 ++++++++++++++++++++++++++++++++++++++++++++
 monitor.c            | 11 -----------
 target/arm/monitor.c |  2 +-
 4 files changed, 46 insertions(+), 55 deletions(-)

diff --git a/qapi/misc.json b/qapi/misc.json
index 1753a81b1e..a0032120da 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -2965,49 +2965,6 @@
 ##
 { 'command': 'xen-load-devices-state', 'data': {'filename': 'str'} }
 
-##
-# @GICCapability:
-#
-# The struct describes capability for a specific GIC (Generic
-# Interrupt Controller) version. These bits are not only decided by
-# QEMU/KVM software version, but also decided by the hardware that
-# the program is running upon.
-#
-# @version:  version of GIC to be described. Currently, only 2 and 3
-#            are supported.
-#
-# @emulated: whether current QEMU/hardware supports emulated GIC
-#            device in user space.
-#
-# @kernel:   whether current QEMU/hardware supports hardware
-#            accelerated GIC device in kernel.
-#
-# Since: 2.6
-##
-{ 'struct': 'GICCapability',
-  'data': { 'version': 'int',
-            'emulated': 'bool',
-            'kernel': 'bool' } }
-
-##
-# @query-gic-capabilities:
-#
-# This command is ARM-only. It will return a list of GICCapability
-# objects that describe its capability bits.
-#
-# Returns: a list of GICCapability objects.
-#
-# Since: 2.6
-#
-# Example:
-#
-# -> { "execute": "query-gic-capabilities" }
-# <- { "return": [{ "version": 2, "emulated": true, "kernel": false },
-#                 { "version": 3, "emulated": false, "kernel": true } ] }
-#
-##
-{ 'command': 'query-gic-capabilities', 'returns': ['GICCapability'] }
-
 ##
 # @CpuInstanceProperties:
 #
diff --git a/qapi/target.json b/qapi/target.json
index be0ff84a6e..2ab18b38a9 100644
--- a/qapi/target.json
+++ b/qapi/target.json
@@ -294,3 +294,48 @@
             'modelb': 'CpuModelInfo' },
   'returns': 'CpuModelBaselineInfo',
   'if': 'defined(TARGET_S390X)' }
+
+##
+# @GICCapability:
+#
+# The struct describes capability for a specific GIC (Generic
+# Interrupt Controller) version. These bits are not only decided by
+# QEMU/KVM software version, but also decided by the hardware that
+# the program is running upon.
+#
+# @version:  version of GIC to be described. Currently, only 2 and 3
+#            are supported.
+#
+# @emulated: whether current QEMU/hardware supports emulated GIC
+#            device in user space.
+#
+# @kernel:   whether current QEMU/hardware supports hardware
+#            accelerated GIC device in kernel.
+#
+# Since: 2.6
+##
+{ 'struct': 'GICCapability',
+  'data': { 'version': 'int',
+            'emulated': 'bool',
+            'kernel': 'bool' },
+  'if': 'defined(TARGET_ARM)' }
+
+##
+# @query-gic-capabilities:
+#
+# This command is ARM-only. It will return a list of GICCapability
+# objects that describe its capability bits.
+#
+# Returns: a list of GICCapability objects.
+#
+# Since: 2.6
+#
+# Example:
+#
+# -> { "execute": "query-gic-capabilities" }
+# <- { "return": [{ "version": 2, "emulated": true, "kernel": false },
+#                 { "version": 3, "emulated": false, "kernel": true } ] }
+#
+##
+{ 'command': 'query-gic-capabilities', 'returns': ['GICCapability'],
+  'if': 'defined(TARGET_ARM)' }
diff --git a/monitor.c b/monitor.c
index bd9a6950cf..67b433f12d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1157,9 +1157,6 @@ static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
  */
 static void qmp_unregister_commands_hack(void)
 {
-#ifndef TARGET_ARM
-    qmp_unregister_command(&qmp_commands, "query-gic-capabilities");
-#endif
 #if !defined(TARGET_S390X) && !defined(TARGET_I386)
     qmp_unregister_command(&qmp_commands, "query-cpu-model-expansion");
 #endif
@@ -4696,14 +4693,6 @@ QemuOptsList qemu_mon_opts = {
     },
 };
 
-#ifndef TARGET_ARM
-GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
-{
-    error_setg(errp, QERR_FEATURE_DISABLED, "query-gic-capabilities");
-    return NULL;
-}
-#endif
-
 HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp)
 {
     MachineState *ms = MACHINE(qdev_get_machine());
diff --git a/target/arm/monitor.c b/target/arm/monitor.c
index 4cdd2676dd..250405bf4d 100644
--- a/target/arm/monitor.c
+++ b/target/arm/monitor.c
@@ -23,7 +23,7 @@
 #include "qemu/osdep.h"
 #include "hw/boards.h"
 #include "kvm_arm.h"
-#include "qapi/qapi-commands-misc.h"
+#include "qapi/target-qapi-commands.h"
 
 static GICCapability *gic_cap_new(int version)
 {
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 46/49] qapi: make query-cpu-model-expansion depend on s390 or x86
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (44 preceding siblings ...)
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 45/49] qapi: make query-gic-capabilities depend on TARGET_ARM Marc-André Lureau
@ 2018-03-21 11:52 ` Marc-André Lureau
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 47/49] qapi: make query-cpu-definitions depend on specific targets Marc-André Lureau
                   ` (7 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Acked-by: Cornelia Huck <cohuck@redhat.com>
---
 qapi/misc.json                         | 38 -------------------------
 qapi/target.json                       | 39 ++++++++++++++++++++++++++
 include/sysemu/arch_init.h             |  3 --
 monitor.c                              |  3 --
 qmp.c                                  |  7 -----
 stubs/arch-query-cpu-model-expansion.c | 13 ---------
 target/i386/cpu.c                      |  3 +-
 target/s390x/cpu_models.c              |  2 +-
 stubs/Makefile.objs                    |  1 -
 9 files changed, 42 insertions(+), 67 deletions(-)
 delete mode 100644 stubs/arch-query-cpu-model-expansion.c

diff --git a/qapi/misc.json b/qapi/misc.json
index a0032120da..602c99b174 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -2102,44 +2102,6 @@
   'data': { 'model': 'CpuModelInfo' } }
 
 
-##
-# @query-cpu-model-expansion:
-#
-# Expands a given CPU model (or a combination of CPU model + additional options)
-# to different granularities, allowing tooling to get an understanding what a
-# specific CPU model looks like in QEMU under a certain configuration.
-#
-# This interface can be used to query the "host" CPU model.
-#
-# The data returned by this command may be affected by:
-#
-# * QEMU version: CPU models may look different depending on the QEMU version.
-#   (Except for CPU models reported as "static" in query-cpu-definitions.)
-# * machine-type: CPU model  may look different depending on the machine-type.
-#   (Except for CPU models reported as "static" in query-cpu-definitions.)
-# * machine options (including accelerator): in some architectures, CPU models
-#   may look different depending on machine and accelerator options. (Except for
-#   CPU models reported as "static" in query-cpu-definitions.)
-# * "-cpu" arguments and global properties: arguments to the -cpu option and
-#   global properties may affect expansion of CPU models. Using
-#   query-cpu-model-expansion while using these is not advised.
-#
-# Some architectures may not support all expansion types. s390x supports
-# "full" and "static".
-#
-# Returns: a CpuModelExpansionInfo. Returns an error if expanding CPU models is
-#          not supported, if the model cannot be expanded, if the model contains
-#          an unknown CPU definition name, unknown properties or properties
-#          with a wrong type. Also returns an error if an expansion type is
-#          not supported.
-#
-# Since: 2.8.0
-##
-{ 'command': 'query-cpu-model-expansion',
-  'data': { 'type': 'CpuModelExpansionType',
-            'model': 'CpuModelInfo' },
-  'returns': 'CpuModelExpansionInfo' }
-
 ##
 # @CpuModelCompareResult:
 #
diff --git a/qapi/target.json b/qapi/target.json
index 2ab18b38a9..323994a6ec 100644
--- a/qapi/target.json
+++ b/qapi/target.json
@@ -339,3 +339,42 @@
 ##
 { 'command': 'query-gic-capabilities', 'returns': ['GICCapability'],
   'if': 'defined(TARGET_ARM)' }
+
+##
+# @query-cpu-model-expansion:
+#
+# Expands a given CPU model (or a combination of CPU model + additional options)
+# to different granularities, allowing tooling to get an understanding what a
+# specific CPU model looks like in QEMU under a certain configuration.
+#
+# This interface can be used to query the "host" CPU model.
+#
+# The data returned by this command may be affected by:
+#
+# * QEMU version: CPU models may look different depending on the QEMU version.
+#   (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine-type: CPU model  may look different depending on the machine-type.
+#   (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine options (including accelerator): in some architectures, CPU models
+#   may look different depending on machine and accelerator options. (Except for
+#   CPU models reported as "static" in query-cpu-definitions.)
+# * "-cpu" arguments and global properties: arguments to the -cpu option and
+#   global properties may affect expansion of CPU models. Using
+#   query-cpu-model-expansion while using these is not advised.
+#
+# Some architectures may not support all expansion types. s390x supports
+# "full" and "static".
+#
+# Returns: a CpuModelExpansionInfo. Returns an error if expanding CPU models is
+#          not supported, if the model cannot be expanded, if the model contains
+#          an unknown CPU definition name, unknown properties or properties
+#          with a wrong type. Also returns an error if an expansion type is
+#          not supported.
+#
+# Since: 2.8.0
+##
+{ 'command': 'query-cpu-model-expansion',
+  'data': { 'type': 'CpuModelExpansionType',
+            'model': 'CpuModelInfo' },
+  'returns': 'CpuModelExpansionInfo',
+  'if': 'defined(TARGET_S390X) || defined(TARGET_I386)' }
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index f0ef652b2a..2497fd3351 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -33,7 +33,4 @@ int kvm_available(void);
 int xen_available(void);
 
 CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp);
-CpuModelExpansionInfo *arch_query_cpu_model_expansion(CpuModelExpansionType type,
-                                                      CpuModelInfo *mode,
-                                                      Error **errp);
 #endif
diff --git a/monitor.c b/monitor.c
index 67b433f12d..63c51ee05d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1157,9 +1157,6 @@ static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
  */
 static void qmp_unregister_commands_hack(void)
 {
-#if !defined(TARGET_S390X) && !defined(TARGET_I386)
-    qmp_unregister_command(&qmp_commands, "query-cpu-model-expansion");
-#endif
 #if !defined(TARGET_PPC) && !defined(TARGET_ARM) && !defined(TARGET_I386) \
     && !defined(TARGET_S390X)
     qmp_unregister_command(&qmp_commands, "query-cpu-definitions");
diff --git a/qmp.c b/qmp.c
index 14972b78df..9ded2f48c4 100644
--- a/qmp.c
+++ b/qmp.c
@@ -594,13 +594,6 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
     return arch_query_cpu_definitions(errp);
 }
 
-CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
-                                                     CpuModelInfo *model,
-                                                     Error **errp)
-{
-    return arch_query_cpu_model_expansion(type, model, errp);
-}
-
 void qmp_add_client(const char *protocol, const char *fdname,
                     bool has_skipauth, bool skipauth, bool has_tls, bool tls,
                     Error **errp)
diff --git a/stubs/arch-query-cpu-model-expansion.c b/stubs/arch-query-cpu-model-expansion.c
deleted file mode 100644
index 26273a8b10..0000000000
--- a/stubs/arch-query-cpu-model-expansion.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "sysemu/arch_init.h"
-#include "qapi/error.h"
-#include "qapi/qmp/qerror.h"
-
-CpuModelExpansionInfo *arch_query_cpu_model_expansion(CpuModelExpansionType type,
-                                                      CpuModelInfo *mode,
-                                                      Error **errp)
-{
-    error_setg(errp, QERR_UNSUPPORTED);
-    return NULL;
-}
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 555ae79d29..563dad644c 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -39,6 +39,7 @@
 #include "qapi/visitor.h"
 #include "qom/qom-qobject.h"
 #include "sysemu/arch_init.h"
+#include "qapi/target-qapi-commands.h"
 
 #if defined(CONFIG_KVM)
 #include <linux/kvm_para.h>
@@ -3125,7 +3126,7 @@ out:
 }
 
 CpuModelExpansionInfo *
-arch_query_cpu_model_expansion(CpuModelExpansionType type,
+qmp_query_cpu_model_expansion(CpuModelExpansionType type,
                                                       CpuModelInfo *model,
                                                       Error **errp)
 {
diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c
index ffca1d9a2d..e25034231d 100644
--- a/target/s390x/cpu_models.c
+++ b/target/s390x/cpu_models.c
@@ -559,7 +559,7 @@ static void cpu_info_from_model(CpuModelInfo *info, const S390CPUModel *model,
     }
 }
 
-CpuModelExpansionInfo *arch_query_cpu_model_expansion(CpuModelExpansionType type,
+CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
                                                       CpuModelInfo *model,
                                                       Error **errp)
 {
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 9a91e49578..1cd325841c 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -1,5 +1,4 @@
 stub-obj-y += arch-query-cpu-def.o
-stub-obj-y += arch-query-cpu-model-expansion.o
 stub-obj-y += bdrv-next-monitor-owned.o
 stub-obj-y += blk-commit-all.o
 stub-obj-y += blockdev-close-all-bdrv-states.o
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 47/49] qapi: make query-cpu-definitions depend on specific targets
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (45 preceding siblings ...)
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 46/49] qapi: make query-cpu-model-expansion depend on s390 or x86 Marc-André Lureau
@ 2018-03-21 11:52 ` Marc-André Lureau
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 48/49] qapi: remove qmp_unregister_command() Marc-André Lureau
                   ` (6 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

It depends on TARGET_PPC || TARGET_ARM || TARGET_I386 || TARGET_S390X.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Acked-by: Cornelia Huck <cohuck@redhat.com>
---
 qapi/misc.json              | 10 ----------
 qapi/target.json            | 12 ++++++++++++
 include/sysemu/arch_init.h  |  1 -
 monitor.c                   | 22 ----------------------
 qmp.c                       |  5 -----
 stubs/arch-query-cpu-def.c  | 11 -----------
 target/arm/helper.c         |  3 ++-
 target/i386/cpu.c           |  3 ++-
 target/ppc/translate_init.c |  3 ++-
 target/s390x/cpu_models.c   |  2 +-
 stubs/Makefile.objs         |  1 -
 11 files changed, 19 insertions(+), 54 deletions(-)
 delete mode 100644 stubs/arch-query-cpu-def.c

diff --git a/qapi/misc.json b/qapi/misc.json
index 602c99b174..e9538ecae6 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -2027,16 +2027,6 @@
 ##
 { 'command': 'query-memory-size-summary', 'returns': 'MemoryInfo' }
 
-##
-# @query-cpu-definitions:
-#
-# Return a list of supported virtual CPU definitions
-#
-# Returns: a list of CpuDefInfo
-#
-# Since: 1.2.0
-##
-{ 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'] }
 
 ##
 # @CpuModelInfo:
diff --git a/qapi/target.json b/qapi/target.json
index 323994a6ec..89ba4207b1 100644
--- a/qapi/target.json
+++ b/qapi/target.json
@@ -378,3 +378,15 @@
             'model': 'CpuModelInfo' },
   'returns': 'CpuModelExpansionInfo',
   'if': 'defined(TARGET_S390X) || defined(TARGET_I386)' }
+
+##
+# @query-cpu-definitions:
+#
+# Return a list of supported virtual CPU definitions
+#
+# Returns: a list of CpuDefInfo
+#
+# Since: 1.2.0
+##
+{ 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'],
+  'if': 'defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_I386) || defined(TARGET_S390X)' }
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index 2497fd3351..10cbafe970 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -32,5 +32,4 @@ extern const uint32_t arch_type;
 int kvm_available(void);
 int xen_available(void);
 
-CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp);
 #endif
diff --git a/monitor.c b/monitor.c
index 63c51ee05d..377ea3c98b 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1143,26 +1143,6 @@ static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
     *ret_data = qobject_from_qlit(&qmp_schema_qlit);
 }
 
-/*
- * We used to define commands in qmp-commands.hx in addition to the
- * QAPI schema.  This permitted defining some of them only in certain
- * configurations.  query-commands has always reflected that (good,
- * because it lets QMP clients figure out what's actually available),
- * while query-qmp-schema never did (not so good).  This function is a
- * hack to keep the configuration-specific commands defined exactly as
- * before, even though qmp-commands.hx is gone.
- *
- * FIXME Educate the QAPI schema on configuration-specific commands,
- * and drop this hack.
- */
-static void qmp_unregister_commands_hack(void)
-{
-#if !defined(TARGET_PPC) && !defined(TARGET_ARM) && !defined(TARGET_I386) \
-    && !defined(TARGET_S390X)
-    qmp_unregister_command(&qmp_commands, "query-cpu-definitions");
-#endif
-}
-
 static void monitor_init_qmp_commands(void)
 {
     /*
@@ -1184,8 +1164,6 @@ static void monitor_init_qmp_commands(void)
     qmp_register_command(&qmp_commands, "netdev_add", qmp_netdev_add,
                          QCO_NO_OPTIONS);
 
-    qmp_unregister_commands_hack();
-
     QTAILQ_INIT(&qmp_cap_negotiation_commands);
     qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
                          qmp_marshal_qmp_capabilities, QCO_NO_OPTIONS);
diff --git a/qmp.c b/qmp.c
index 9ded2f48c4..cafda4417d 100644
--- a/qmp.c
+++ b/qmp.c
@@ -589,11 +589,6 @@ ObjectPropertyInfoList *qmp_qom_list_properties(const char *typename,
     return prop_list;
 }
 
-CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
-{
-    return arch_query_cpu_definitions(errp);
-}
-
 void qmp_add_client(const char *protocol, const char *fdname,
                     bool has_skipauth, bool skipauth, bool has_tls, bool tls,
                     Error **errp)
diff --git a/stubs/arch-query-cpu-def.c b/stubs/arch-query-cpu-def.c
deleted file mode 100644
index d436f95314..0000000000
--- a/stubs/arch-query-cpu-def.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "sysemu/arch_init.h"
-#include "qapi/error.h"
-#include "qapi/qmp/qerror.h"
-
-CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
-{
-    error_setg(errp, QERR_UNSUPPORTED);
-    return NULL;
-}
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 09893e3f72..ab8520f07d 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -17,6 +17,7 @@
 #include "exec/semihost.h"
 #include "sysemu/kvm.h"
 #include "fpu/softfloat.h"
+#include "qapi/target-qapi-commands.h"
 
 #define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */
 
@@ -5549,7 +5550,7 @@ static void arm_cpu_add_definition(gpointer data, gpointer user_data)
     *cpu_list = entry;
 }
 
-CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
+CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
 {
     CpuDefinitionInfoList *cpu_list = NULL;
     GSList *list;
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 563dad644c..62c0c5b1eb 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -34,6 +34,7 @@
 #include "qapi/error.h"
 #include "qapi/qapi-visit-misc.h"
 #include "qapi/qapi-visit-run-state.h"
+#include "qapi/target-qapi-commands.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qerror.h"
 #include "qapi/visitor.h"
@@ -2865,7 +2866,7 @@ static void x86_cpu_definition_entry(gpointer data, gpointer user_data)
     *cpu_list = entry;
 }
 
-CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
+CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
 {
     CpuDefinitionInfoList *cpu_list = NULL;
     GSList *list = get_sorted_cpu_model_list();
diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c
index 391b94b97d..e679e8d301 100644
--- a/target/ppc/translate_init.c
+++ b/target/ppc/translate_init.c
@@ -39,6 +39,7 @@
 #include "qemu/cutils.h"
 #include "disas/capstone.h"
 #include "fpu/softfloat.h"
+#include "qapi/target-qapi-commands.h"
 
 //#define PPC_DUMP_CPU
 //#define PPC_DEBUG_SPR
@@ -10298,7 +10299,7 @@ static void ppc_cpu_defs_entry(gpointer data, gpointer user_data)
     *first = entry;
 }
 
-CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
+CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
 {
     CpuDefinitionInfoList *cpu_list = NULL;
     GSList *list;
diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c
index e25034231d..c9b5216284 100644
--- a/target/s390x/cpu_models.c
+++ b/target/s390x/cpu_models.c
@@ -425,7 +425,7 @@ static void create_cpu_model_list(ObjectClass *klass, void *opaque)
     *cpu_list = entry;
 }
 
-CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
+CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
 {
     struct CpuDefinitionInfoListData list_data = {
         .list = NULL,
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 1cd325841c..54f3e7e152 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -1,4 +1,3 @@
-stub-obj-y += arch-query-cpu-def.o
 stub-obj-y += bdrv-next-monitor-owned.o
 stub-obj-y += blk-commit-all.o
 stub-obj-y += blockdev-close-all-bdrv-states.o
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 48/49] qapi: remove qmp_unregister_command()
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (46 preceding siblings ...)
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 47/49] qapi: make query-cpu-definitions depend on specific targets Marc-André Lureau
@ 2018-03-21 11:52 ` Marc-André Lureau
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 49/49] RFC: make RTC_CHANGE per-target Marc-André Lureau
                   ` (5 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

This command is no longer needed after the schema is made conditional.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/qapi/qmp/dispatch.h | 1 -
 qapi/qmp-registry.c         | 8 --------
 2 files changed, 9 deletions(-)

diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h
index ffb4652f71..dba9ee70b3 100644
--- a/include/qapi/qmp/dispatch.h
+++ b/include/qapi/qmp/dispatch.h
@@ -38,7 +38,6 @@ typedef QTAILQ_HEAD(QmpCommandList, QmpCommand) QmpCommandList;
 
 void qmp_register_command(QmpCommandList *cmds, const char *name,
                           QmpCommandFunc *fn, QmpCommandOptions options);
-void qmp_unregister_command(QmpCommandList *cmds, const char *name);
 QmpCommand *qmp_find_command(QmpCommandList *cmds, const char *name);
 QObject *qmp_dispatch(QmpCommandList *cmds, QObject *request);
 void qmp_disable_command(QmpCommandList *cmds, const char *name);
diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c
index 5af484cd9a..ca00f74795 100644
--- a/qapi/qmp-registry.c
+++ b/qapi/qmp-registry.c
@@ -27,14 +27,6 @@ void qmp_register_command(QmpCommandList *cmds, const char *name,
     QTAILQ_INSERT_TAIL(cmds, cmd, node);
 }
 
-void qmp_unregister_command(QmpCommandList *cmds, const char *name)
-{
-    QmpCommand *cmd = qmp_find_command(cmds, name);
-
-    QTAILQ_REMOVE(cmds, cmd, node);
-    g_free(cmd);
-}
-
 QmpCommand *qmp_find_command(QmpCommandList *cmds, const char *name)
 {
     QmpCommand *cmd;
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [Qemu-devel] [PATCH v3 49/49] RFC: make RTC_CHANGE per-target
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (47 preceding siblings ...)
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 48/49] qapi: remove qmp_unregister_command() Marc-André Lureau
@ 2018-03-21 11:52 ` Marc-André Lureau
  2018-03-21 12:47 ` [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code no-reply
                   ` (4 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-21 11:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

A few targets don't emit RTC_CHANGE, we could restrict the event to
the tagets that do emit it.

Note: There is a lot more of events & commands that we could restrict
to capable targets, with the cost of some additional complexity, but
the benefit of added correctness and better introspection.

Note2: The rate limite could perhaps be part of the schema, and the
common event emitter code, to simplify the need of custom and #ifdef
code in the monitor.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 qapi/misc.json         | 22 ----------------------
 qapi/target.json       | 23 +++++++++++++++++++++++
 hw/ppc/spapr_rtc.c     |  2 +-
 hw/timer/mc146818rtc.c |  2 +-
 monitor.c              |  4 +++-
 5 files changed, 28 insertions(+), 25 deletions(-)

diff --git a/qapi/misc.json b/qapi/misc.json
index e9538ecae6..6415bbb7fe 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -2856,28 +2856,6 @@
 { 'event': 'ACPI_DEVICE_OST',
      'data': { 'info': 'ACPIOSTInfo' } }
 
-##
-# @RTC_CHANGE:
-#
-# Emitted when the guest changes the RTC time.
-#
-# @offset: offset between base RTC clock (as specified by -rtc base), and
-#          new RTC clock value
-#
-# Note: This event is rate-limited.
-#
-# Since: 0.13.0
-#
-# Example:
-#
-# <-   { "event": "RTC_CHANGE",
-#        "data": { "offset": 78 },
-#        "timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
-#
-##
-{ 'event': 'RTC_CHANGE',
-  'data': { 'offset': 'int' } }
-
 ##
 # @ReplayMode:
 #
diff --git a/qapi/target.json b/qapi/target.json
index 89ba4207b1..b9f6741fbf 100644
--- a/qapi/target.json
+++ b/qapi/target.json
@@ -9,6 +9,29 @@
 
 { 'include': 'misc.json' }
 
+##
+# @RTC_CHANGE:
+#
+# Emitted when the guest changes the RTC time.
+#
+# @offset: offset between base RTC clock (as specified by -rtc base), and
+#          new RTC clock value
+#
+# Note: This event is rate-limited.
+#
+# Since: 0.13.0
+#
+# Example:
+#
+# <-   { "event": "RTC_CHANGE",
+#        "data": { "offset": 78 },
+#        "timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
+#
+##
+{ 'event': 'RTC_CHANGE',
+  'data': { 'offset': 'int' },
+  'if': 'defined(TARGET_ALPHA) || defined(TARGET_ARM) || defined(TARGET_HPPA) || defined(TARGET_I386) || defined(TARGET_MIPS) || defined(TARGET_MIPS64) || defined(TARGET_MOXIE) || defined(TARGET_PPC) || defined(TARGET_PPC64) || defined(TARGET_S390X) || defined(TARGET_SH4) || defined(TARGET_SPARC)' }
+
 ##
 # @rtc-reset-reinjection:
 #
diff --git a/hw/ppc/spapr_rtc.c b/hw/ppc/spapr_rtc.c
index a37360537e..4cb73abf4a 100644
--- a/hw/ppc/spapr_rtc.c
+++ b/hw/ppc/spapr_rtc.c
@@ -31,7 +31,7 @@
 #include "sysemu/sysemu.h"
 #include "hw/ppc/spapr.h"
 #include "qapi/error.h"
-#include "qapi/qapi-events-misc.h"
+#include "qapi/target-qapi-events.h"
 #include "qemu/cutils.h"
 
 void spapr_rtc_read(sPAPRRTCState *rtc, struct tm *tm, uint32_t *ns)
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index dd575ffbdf..7de7562850 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -32,7 +32,7 @@
 #include "hw/timer/mc146818rtc.h"
 #include "qapi/error.h"
 #include "qapi/target-qapi-commands.h"
-#include "qapi/qapi-events-misc.h"
+#include "qapi/target-qapi-events.h"
 #include "qapi/visitor.h"
 
 #ifdef TARGET_I386
diff --git a/monitor.c b/monitor.c
index 377ea3c98b..3c972206d9 100644
--- a/monitor.c
+++ b/monitor.c
@@ -635,7 +635,6 @@ monitor_qapi_event_queue(unsigned event, QDict *qdict, Error **errp)
         .size = QAPI_EVENT__MAX,
         .rate = {
             /* Limit guest-triggerable events to 1 per second */
-            [QAPI_EVENT_RTC_CHANGE]        = 1000 * SCALE_MS,
             [QAPI_EVENT_WATCHDOG]          = 1000 * SCALE_MS,
             [QAPI_EVENT_BALLOON_CHANGE]    = 1000 * SCALE_MS,
             [QAPI_EVENT_QUORUM_REPORT_BAD] = 1000 * SCALE_MS,
@@ -680,6 +679,9 @@ target_monitor_qapi_event_queue(unsigned event, QDict *qdict, Error **errp)
         .size = TARGET_QAPI_EVENT__MAX,
         .rate = {
             /* Limit guest-triggerable events to 1 per second */
+#if defined(TARGET_ALPHA) || defined(TARGET_ARM) || defined(TARGET_HPPA) || defined(TARGET_I386) || defined(TARGET_MIPS) | defined(TARGET_MIPS64) || defined(TARGET_MOXIE) || defined(TARGET_PPC) || defined(TARGET_PPC64) || defined(TARGET_S390X) || defined(TARGET_SH4) || defined(TARGET_SPARC)
+            [TARGET_QAPI_EVENT_RTC_CHANGE] = 1000 * SCALE_MS,
+#endif
             [TARGET_QAPI_EVENT__MAX]       = 0,
         },
     };
-- 
2.16.2.521.g9aa15f885a

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (48 preceding siblings ...)
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 49/49] RFC: make RTC_CHANGE per-target Marc-André Lureau
@ 2018-03-21 12:47 ` no-reply
  2018-03-21 14:20 ` no-reply
                   ` (3 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: no-reply @ 2018-03-21 12:47 UTC (permalink / raw)
  To: marcandre.lureau; +Cc: famz, qemu-devel, armbru

Hi,

This series failed build test on s390x host. Please find the details below.

Type: series
Message-id: 20180321115211.17937-1-marcandre.lureau@redhat.com
Subject: [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code

=== TEST SCRIPT BEGIN ===
#!/bin/bash
# Testing script will be invoked under the git checkout with
# HEAD pointing to a commit that has the patches applied on top of "base"
# branch
set -e
echo "=== ENV ==="
env
echo "=== PACKAGES ==="
rpm -qa
echo "=== TEST BEGIN ==="
CC=$HOME/bin/cc
INSTALL=$PWD/install
BUILD=$PWD/build
echo -n "Using CC: "
realpath $CC
mkdir -p $BUILD $INSTALL
SRC=$PWD
cd $BUILD
$SRC/configure --cc=$CC --prefix=$INSTALL
make -j4
# XXX: we need reliable clean up
# make check -j4 V=1
make install
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]               patchew/1521634071-16519-1-git-send-email-stefanb@linux.vnet.ibm.com -> patchew/1521634071-16519-1-git-send-email-stefanb@linux.vnet.ibm.com
 * [new tag]               patchew/20180321115211.17937-1-marcandre.lureau@redhat.com -> patchew/20180321115211.17937-1-marcandre.lureau@redhat.com
 * [new tag]               patchew/20180321120853.14293-1-lvivier@redhat.com -> patchew/20180321120853.14293-1-lvivier@redhat.com
Switched to a new branch 'test'
ca50a2d8e3 RFC: make RTC_CHANGE per-target
032f3d2f59 qapi: remove qmp_unregister_command()
7a4b17cf54 qapi: make query-cpu-definitions depend on specific targets
557f536176 qapi: make query-cpu-model-expansion depend on s390 or x86
dc1b218319 qapi: make query-gic-capabilities depend on TARGET_ARM
af9625c6c3 target.json: add a note about query-cpu* not being s390x-specific
c9801977e9 qapi: make s390 commands depend on TARGET_S390X
6a49803445 qapi: make rtc-reset-reinjection and SEV depend on TARGET_I386
13b093aaae qapi: add a top-unit 'target' schema
8e42b4bfd8 RFC: qapi: learn to split schema by 'top-unit'
2984459cd6 qapi-commands: don't initialize command list in qmp_init_marshall()
7c39c807b5 build-sys: move qmp-introspect per target
af7d5d518d qapi: add conditions to REPLICATION type/commands on the schema
9e583d1a1d qapi: add conditions to SPICE type/commands/events on the schema
8bc16dec62 qapi: add conditions to VNC type/commands/events on the schema
72664dbe15 qapi2texi: add condition to variants
d7ff0ab4ef qapi2texi: add 'If:' condition to struct members
bde44a6b1d qapi2texi: add 'If:' condition to enum values
c87e1bc65f qapi2texi: add 'If:' section to generated documentation
3364d5099f docs: document schema configuration
77f7bafdc4 qapi: add #if conditions to generated code members
a95929de93 qapi: add 'if' to alternate members
b205d6198c qapi: add 'if' on union members
9613ba2cc2 qapi: add an error in case a discriminator is conditionnal
cd025039c0 qapi: add 'if' to implicit struct members
6799c824a8 qapi: add a dictionary form with 'type' key for members
c5b50ed9e3 qapi: rename allow_dict to allow_implicit
ba4011e602 qapi-event: add 'if' condition to implicit event enum
7d828e85b9 qapi: add 'if' to enum members
a20c2dc973 qapi: add a dictionnary form with 'name' key for enum members
061635eff1 qapi: factor out check_known_keys()
b0ad9a471a tests: modify visit_enum_type() in test-qapi to print members
86933fb39c qapi: change enum visitor to take QAPISchemaMember
cd6fb8e83f qapi: rename QAPISchemaEnumType.values to .members
31ea46dcec qapi: do not define enumeration value explicitely
55c7453f3c qapi-types: add #if conditions to types & visitors
4507e44d86 qapi-types: refactor variants handling
9c91a8fa1d qapi/events: add #if conditions to events
7ba12f474f qapi/commands: add #if conditions to commands
fcf4dfeb56 qapi-introspect: add preprocessor conditions to generated QLit
51163f6ba0 qapi-introspect: modify to_qlit() to append ', ' on level > 0
75baac460c qapi: add #if/#endif helpers
a001949a31 qapi: mcgen() shouldn't indent # lines
a2ef5afa63 qapi: add 'ifcond' to visitor methods
688755b5fd qapi: leave the ifcond attribute undefined until check()
0566f4cb49 qapi: pass 'if' condition into QAPISchemaEntity objects
7b98d1b34c qapi: add 'if' to top-level expressions
6c36d8fa28 qapi/events: generate event enum in main module
7ced623f53 qapi/visit: remove useless prefix argument

=== OUTPUT BEGIN ===
=== ENV ===
LANG=en_US.UTF-8
XDG_SESSION_ID=107260
USER=fam
PWD=/var/tmp/patchew-tester-tmp-1tgugnof/src
HOME=/home/fam
SHELL=/bin/sh
SHLVL=2
PATCHEW=/home/fam/patchew/patchew-cli -s http://patchew.org --nodebug
LOGNAME=fam
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1012/bus
XDG_RUNTIME_DIR=/run/user/1012
PATH=/usr/bin:/bin
_=/usr/bin/env
=== PACKAGES ===
gpg-pubkey-873529b8-54e386ff
glibc-debuginfo-common-2.24-10.fc25.s390x
fedora-release-26-1.noarch
dejavu-sans-mono-fonts-2.35-4.fc26.noarch
xemacs-filesystem-21.5.34-22.20170124hgf412e9f093d4.fc26.noarch
bash-4.4.12-7.fc26.s390x
freetype-2.7.1-9.fc26.s390x
libSM-1.2.2-5.fc26.s390x
libmpc-1.0.2-6.fc26.s390x
libaio-0.3.110-7.fc26.s390x
libverto-0.2.6-7.fc26.s390x
perl-Scalar-List-Utils-1.48-1.fc26.s390x
iptables-libs-1.6.1-2.fc26.s390x
p11-kit-trust-0.23.9-2.fc26.s390x
tcl-8.6.6-2.fc26.s390x
libxshmfence-1.2-4.fc26.s390x
expect-5.45-23.fc26.s390x
perl-Thread-Queue-3.12-1.fc26.noarch
perl-encoding-2.19-6.fc26.s390x
keyutils-1.5.10-1.fc26.s390x
gmp-devel-6.1.2-4.fc26.s390x
enchant-1.6.0-16.fc26.s390x
net-snmp-libs-5.7.3-17.fc26.s390x
python-gobject-base-3.24.1-1.fc26.s390x
python3-enchant-1.6.10-1.fc26.noarch
python-lockfile-0.11.0-6.fc26.noarch
python2-pyparsing-2.1.10-3.fc26.noarch
python2-lxml-4.1.1-1.fc26.s390x
librados2-10.2.7-2.fc26.s390x
trousers-lib-0.3.13-7.fc26.s390x
libpaper-1.1.24-14.fc26.s390x
libdatrie-0.2.9-4.fc26.s390x
libsoup-2.58.2-1.fc26.s390x
passwd-0.79-9.fc26.s390x
bind99-libs-9.9.10-3.P3.fc26.s390x
python3-rpm-4.13.0.2-1.fc26.s390x
systemd-233-7.fc26.s390x
virglrenderer-0.6.0-1.20170210git76b3da97b.fc26.s390x
s390utils-ziomon-1.36.1-3.fc26.s390x
s390utils-osasnmpd-1.36.1-3.fc26.s390x
libXrandr-1.5.1-2.fc26.s390x
libglvnd-glx-1.0.0-1.fc26.s390x
texlive-ifxetex-svn19685.0.5-33.fc26.2.noarch
texlive-psnfss-svn33946.9.2a-33.fc26.2.noarch
texlive-dvipdfmx-def-svn40328-33.fc26.2.noarch
texlive-natbib-svn20668.8.31b-33.fc26.2.noarch
texlive-xdvi-bin-svn40750-33.20160520.fc26.2.s390x
texlive-cm-svn32865.0-33.fc26.2.noarch
texlive-beton-svn15878.0-33.fc26.2.noarch
texlive-fpl-svn15878.1.002-33.fc26.2.noarch
texlive-mflogo-svn38628-33.fc26.2.noarch
texlive-texlive-docindex-svn41430-33.fc26.2.noarch
texlive-luaotfload-bin-svn34647.0-33.20160520.fc26.2.noarch
texlive-koma-script-svn41508-33.fc26.2.noarch
texlive-pst-tree-svn24142.1.12-33.fc26.2.noarch
texlive-breqn-svn38099.0.98d-33.fc26.2.noarch
texlive-xetex-svn41438-33.fc26.2.noarch
gstreamer1-plugins-bad-free-1.12.3-1.fc26.s390x
xorg-x11-font-utils-7.5-33.fc26.s390x
ghostscript-fonts-5.50-36.fc26.noarch
libXext-devel-1.3.3-5.fc26.s390x
libusbx-devel-1.0.21-2.fc26.s390x
libglvnd-devel-1.0.0-1.fc26.s390x
emacs-25.3-3.fc26.s390x
alsa-lib-devel-1.1.4.1-1.fc26.s390x
kbd-2.0.4-2.fc26.s390x
dconf-0.26.0-2.fc26.s390x
ccache-3.3.4-1.fc26.s390x
mc-4.8.19-5.fc26.s390x
doxygen-1.8.13-9.fc26.s390x
dpkg-1.18.24-1.fc26.s390x
libtdb-1.3.13-1.fc26.s390x
python2-pynacl-1.1.1-1.fc26.s390x
nss-sysinit-3.34.0-1.0.fc26.s390x
kernel-4.13.16-202.fc26.s390x
perl-Filter-1.58-1.fc26.s390x
python2-pip-9.0.1-11.fc26.noarch
dnf-2.7.5-2.fc26.noarch
sssd-common-1.16.0-4.fc26.s390x
python2-sssdconfig-1.16.0-4.fc26.noarch
bind-license-9.11.2-1.P1.fc26.noarch
libtasn1-4.13-1.fc26.s390x
glusterfs-fuse-3.10.10-1.fc26.s390x
cpp-7.3.1-2.fc26.s390x
pkgconf-1.3.12-2.fc26.s390x
python2-fedora-0.10.0-1.fc26.noarch
cmake-filesystem-3.10.1-11.fc26.s390x
selinux-policy-targeted-3.13.1-260.18.fc26.noarch
python3-requests-kerberos-0.12.0-1.fc26.noarch
libmicrohttpd-0.9.59-1.fc26.s390x
GeoIP-GeoLite-data-2018.01-1.fc26.noarch
glibc-debuginfo-2.24-10.fc25.s390x
dejavu-fonts-common-2.35-4.fc26.noarch
bind99-license-9.9.10-3.P3.fc26.noarch
ncurses-libs-6.0-8.20170212.fc26.s390x
libpng-1.6.28-2.fc26.s390x
libICE-1.0.9-9.fc26.s390x
perl-Text-ParseWords-3.30-366.fc26.noarch
libtool-ltdl-2.4.6-17.fc26.s390x
libselinux-utils-2.6-7.fc26.s390x
userspace-rcu-0.9.3-2.fc26.s390x
libXfont-1.5.2-5.fc26.s390x
perl-Class-Inspector-1.31-3.fc26.noarch
perl-open-1.10-395.fc26.noarch
keyutils-libs-devel-1.5.10-1.fc26.s390x
isl-0.16.1-1.fc26.s390x
libsecret-0.18.5-3.fc26.s390x
compat-openssl10-1.0.2m-1.fc26.s390x
python3-iniparse-0.4-24.fc26.noarch
python3-dateutil-2.6.0-3.fc26.noarch
python3-firewall-0.4.4.5-1.fc26.noarch
python-enum34-1.1.6-1.fc26.noarch
python2-pygments-2.2.0-7.fc26.noarch
python2-dockerfile-parse-0.0.7-1.fc26.noarch
perl-Net-SSLeay-1.81-1.fc26.s390x
hostname-3.18-2.fc26.s390x
libtirpc-1.0.2-0.fc26.s390x
rpm-build-libs-4.13.0.2-1.fc26.s390x
libutempter-1.1.6-9.fc26.s390x
systemd-pam-233-7.fc26.s390x
libXinerama-1.1.3-7.fc26.s390x
mesa-libGL-17.2.4-2.fc26.s390x
texlive-amsfonts-svn29208.3.04-33.fc26.2.noarch
texlive-caption-svn41409-33.fc26.2.noarch
texlive-enumitem-svn24146.3.5.2-33.fc26.2.noarch
texlive-pdftex-def-svn22653.0.06d-33.fc26.2.noarch
texlive-xdvi-svn40768-33.fc26.2.noarch
texlive-courier-svn35058.0-33.fc26.2.noarch
texlive-charter-svn15878.0-33.fc26.2.noarch
texlive-graphics-def-svn41879-33.fc26.2.noarch
texlive-mfnfss-svn19410.0-33.fc26.2.noarch
texlive-texlive-en-svn41185-33.fc26.2.noarch
texlive-ifplatform-svn21156.0.4-33.fc26.2.noarch
texlive-ms-svn29849.0-33.fc26.2.noarch
texlive-pst-tools-svn34067.0.05-33.fc26.2.noarch
texlive-powerdot-svn38984-33.fc26.2.noarch
texlive-xetexconfig-svn41133-33.fc26.2.noarch
libvdpau-1.1.1-4.fc26.s390x
zlib-devel-1.2.11-2.fc26.s390x
gdk-pixbuf2-devel-2.36.9-1.fc26.s390x
libX11-devel-1.6.5-2.fc26.s390x
libglvnd-core-devel-1.0.0-1.fc26.s390x
SDL2-devel-2.0.7-2.fc26.s390x
webkitgtk3-2.4.11-5.fc26.s390x
grubby-8.40-4.fc26.s390x
uboot-tools-2017.05-4.fc26.s390x
cracklib-dicts-2.9.6-5.fc26.s390x
texinfo-6.3-3.fc26.s390x
time-1.7-52.fc26.s390x
python2-deltarpm-3.6-19.fc26.s390x
nss-3.34.0-1.0.fc26.s390x
python2-setuptools-37.0.0-1.fc26.noarch
python2-dnf-2.7.5-2.fc26.noarch
groff-base-1.22.3-10.fc26.s390x
python2-devel-2.7.14-4.fc26.s390x
python2-GitPython-2.1.7-2.fc26.noarch
boost-iostreams-1.63.0-10.fc26.s390x
distribution-gpg-keys-1.18-1.fc26.noarch
glusterfs-client-xlators-3.10.10-1.fc26.s390x
cups-libs-2.2.2-8.fc26.s390x
bind-libs-lite-9.11.2-1.P1.fc26.s390x
libpkgconf-1.3.12-2.fc26.s390x
python2-rpkg-1.51-3.fc26.noarch
java-1.8.0-openjdk-headless-1.8.0.161-5.b14.fc26.s390x
fedpkg-1.31-5.fc26.noarch
python3-dnf-plugin-system-upgrade-2.0.5-1.fc26.noarch
dtc-1.4.6-1.fc26.s390x
fedora-repos-26-2.noarch
gpg-pubkey-efe550f5-5220ba41
gpg-pubkey-81b46521-55b3ca9a
filesystem-3.2-40.fc26.s390x
basesystem-11-3.fc26.noarch
js-jquery-3.2.1-1.fc26.noarch
elfutils-libelf-0.169-1.fc26.s390x
libidn-1.33-2.fc26.s390x
libogg-1.3.2-6.fc26.s390x
slang-2.3.1a-2.fc26.s390x
apr-1.6.3-1.fc26.s390x
libxkbcommon-0.7.1-3.fc26.s390x
perl-IO-1.36-395.fc26.s390x
libvorbis-1.3.5-2.fc26.s390x
less-487-3.fc26.s390x
lttng-ust-2.9.0-2.fc26.s390x
OpenEXR-libs-2.2.0-6.fc26.s390x
ipset-libs-6.29-3.fc26.s390x
perl-XML-XPath-1.42-1.fc26.noarch
lua-filesystem-1.6.3-3.fc24.s390x
sqlite-3.20.1-1.fc26.s390x
gstreamer1-1.12.3-1.fc26.s390x
libpwquality-1.3.0-8.fc26.s390x
gettext-libs-0.19.8.1-9.fc26.s390x
python3-chardet-2.3.0-3.fc26.noarch
python3-slip-dbus-0.6.4-6.fc26.noarch
python-chardet-2.3.0-3.fc26.noarch
python2-pyasn1-0.2.3-1.fc26.noarch
python-slip-dbus-0.6.4-6.fc26.noarch
libarchive-3.2.2-4.fc26.s390x
libbabeltrace-1.5.2-2.fc26.s390x
cdparanoia-libs-10.2-22.fc26.s390x
krb5-workstation-1.15.2-4.fc26.s390x
gpgme-1.8.0-12.fc26.s390x
python2-gpg-1.8.0-12.fc26.s390x
shadow-utils-4.3.1-3.fc26.s390x
cryptsetup-libs-1.7.5-1.fc26.s390x
kpartx-0.4.9-88.fc26.s390x
net-snmp-agent-libs-5.7.3-17.fc26.s390x
libXi-1.7.9-2.fc26.s390x
texlive-tetex-svn41059-33.fc26.2.noarch
texlive-tools-svn40934-33.fc26.2.noarch
texlive-bibtex-bin-svn40473-33.20160520.fc26.2.s390x
texlive-mfware-bin-svn40473-33.20160520.fc26.2.s390x
texlive-underscore-svn18261.0-33.fc26.2.noarch
texlive-avantgar-svn31835.0-33.fc26.2.noarch
texlive-anysize-svn15878.0-33.fc26.2.noarch
texlive-lineno-svn21442.4.41-33.fc26.2.noarch
texlive-mathpazo-svn15878.1.003-33.fc26.2.noarch
texlive-soul-svn15878.2.4-33.fc26.2.noarch
texlive-luatexbase-svn38550-33.fc26.2.noarch
texlive-listings-svn37534.1.6-33.fc26.2.noarch
texlive-pstricks-svn41321-33.fc26.2.noarch
texlive-metalogo-svn18611.0.12-33.fc26.2.noarch
texlive-dvipdfmx-svn41149-33.fc26.2.noarch
kbd-legacy-2.0.4-2.fc26.noarch
nspr-devel-4.17.0-1.fc26.s390x
ghostscript-x11-9.20-10.fc26.s390x
libXrender-devel-0.9.10-2.fc26.s390x
libxkbcommon-devel-0.7.1-3.fc26.s390x
mesa-libGL-devel-17.2.4-2.fc26.s390x
sqlite-devel-3.20.1-1.fc26.s390x
usbredir-devel-0.7.1-3.fc26.s390x
libcap-devel-2.25-5.fc26.s390x
brlapi-devel-0.6.6-5.fc26.s390x
python3-pygpgme-0.3-22.fc26.s390x
pinentry-0.9.7-3.fc26.s390x
perl-Test-Harness-3.39-1.fc26.noarch
qemu-sanity-check-nodeps-1.1.5-6.fc26.s390x
libldb-1.1.29-5.fc26.s390x
nss-util-devel-3.34.0-1.0.fc26.s390x
python2-2.7.14-4.fc26.s390x
libwayland-cursor-1.13.0-3.fc26.s390x
pulseaudio-libs-devel-11.1-7.fc26.s390x
json-c-0.12.1-5.fc26.s390x
kernel-headers-4.15.4-200.fc26.s390x
libgcrypt-1.8.2-1.fc26.s390x
libgo-devel-7.3.1-2.fc26.s390x
glusterfs-cli-3.10.10-1.fc26.s390x
glusterfs-server-3.10.10-1.fc26.s390x
redhat-rpm-config-64-1.fc26.noarch
ca-certificates-2018.2.22-1.0.fc26.noarch
python2-sphinx-1.5.6-1.fc26.noarch
libtevent-0.9.35-1.fc26.s390x
dnsmasq-2.76-6.fc26.s390x
perl-Module-CoreList-5.20180120-1.fc26.noarch
gpg-pubkey-34ec9cba-54e38751
gpg-pubkey-030d5aed-55b577f0
setup-2.10.5-2.fc26.noarch
lato-fonts-2.015-3.fc26.noarch
web-assets-filesystem-5-5.fc26.noarch
libsepol-2.6-2.fc26.s390x
libcap-2.25-5.fc26.s390x
tcp_wrappers-libs-7.6-85.fc26.s390x
libnl3-3.3.0-1.fc26.s390x
pixman-0.34.0-3.fc26.s390x
lzo-2.08-9.fc26.s390x
perl-5.24.3-395.fc26.s390x
libnl3-cli-3.3.0-1.fc26.s390x
gpm-libs-1.20.7-10.fc26.s390x
iso-codes-3.74-2.fc26.noarch
ipset-6.29-3.fc26.s390x
lua-term-0.07-1.fc25.s390x
libdb-utils-5.3.28-24.fc26.s390x
dbus-glib-0.108-2.fc26.s390x
pam-1.3.0-2.fc26.s390x
avahi-glib-0.6.32-7.fc26.s390x
python2-dateutil-2.6.0-3.fc26.noarch
python3-asn1crypto-0.23.0-1.fc26.noarch
python3-slip-0.6.4-6.fc26.noarch
python-backports-ssl_match_hostname-3.5.0.1-4.fc26.noarch
python2-pyOpenSSL-16.2.0-6.fc26.noarch
python-slip-0.6.4-6.fc26.noarch
nss-pem-1.0.3-3.fc26.s390x
fipscheck-1.5.0-1.fc26.s390x
elfutils-0.169-1.fc26.s390x
cyrus-sasl-lib-2.1.26-32.fc26.s390x
libkadm5-1.15.2-4.fc26.s390x
python3-kerberos-1.2.5-3.fc26.s390x
rpmconf-1.0.19-1.fc26.noarch
libsemanage-2.6-4.fc26.s390x
device-mapper-libs-1.02.137-6.fc26.s390x
yum-3.4.3-512.fc26.noarch
device-mapper-multipath-0.4.9-88.fc26.s390x
net-snmp-5.7.3-17.fc26.s390x
libXtst-1.2.3-2.fc26.s390x
libXxf86vm-1.1.4-4.fc26.s390x
texlive-amsmath-svn41561-33.fc26.2.noarch
texlive-xkeyval-svn35741.2.7a-33.fc26.2.noarch
texlive-bibtex-svn40768-33.fc26.2.noarch
texlive-mfware-svn40768-33.fc26.2.noarch
texlive-wasy-svn35831.0-33.fc26.2.noarch
texlive-bookman-svn31835.0-33.fc26.2.noarch
texlive-babel-english-svn30264.3.3p-33.fc26.2.noarch
texlive-fix2col-svn38770-33.fc26.2.noarch
texlive-mdwtools-svn15878.1.05.4-33.fc26.2.noarch
texlive-tex-gyre-math-svn41264-33.fc26.2.noarch
texlive-luaotfload-svn40902-33.fc26.2.noarch
texlive-showexpl-svn32737.v0.3l-33.fc26.2.noarch
texlive-pstricks-add-svn40744-33.fc26.2.noarch
texlive-l3experimental-svn41163-33.fc26.2.noarch
texlive-xetex-bin-svn41091-33.20160520.fc26.2.s390x
kbd-misc-2.0.4-2.fc26.noarch
libpng-devel-1.6.28-2.fc26.s390x
ghostscript-core-9.20-10.fc26.s390x
libXfixes-devel-5.0.3-2.fc26.s390x
libverto-devel-0.2.6-7.fc26.s390x
mesa-libEGL-devel-17.2.4-2.fc26.s390x
popt-devel-1.16-12.fc26.s390x
readline-devel-7.0-5.fc26.s390x
cyrus-sasl-devel-2.1.26-32.fc26.s390x
sendmail-8.15.2-19.fc26.s390x
systemd-bootchart-231-3.fc26.s390x
perl-IO-Socket-SSL-2.049-1.fc26.noarch
python2-enchant-1.6.10-1.fc26.noarch
perl-generators-1.10-2.fc26.noarch
createrepo-0.10.3-11.fc26.noarch
nss-tools-3.34.0-1.0.fc26.s390x
pulseaudio-libs-glib2-11.1-7.fc26.s390x
dhcp-libs-4.3.5-10.fc26.s390x
libtiff-4.0.9-1.fc26.s390x
python-srpm-macros-3-21.fc26.noarch
libcurl-7.53.1-14.fc26.s390x
gnupg2-2.2.4-1.fc26.s390x
libtalloc-2.1.11-1.fc26.s390x
nfs-utils-2.2.1-4.rc2.fc26.s390x
qt5-srpm-macros-5.9.4-2.fc26.noarch
python2-dnf-plugins-core-2.1.5-4.fc26.noarch
mariadb-libs-10.1.30-2.fc26.s390x
bind-libs-9.11.2-1.P1.fc26.s390x
acpica-tools-20180105-1.fc26.s390x
perl-podlators-4.09-3.fc26.noarch
fontpackages-filesystem-1.44-18.fc26.noarch
vte-profile-0.48.4-1.fc26.s390x
texlive-kpathsea-doc-svn41139-33.fc26.2.noarch
zlib-1.2.11-2.fc26.s390x
readline-7.0-5.fc26.s390x
libattr-2.4.47-18.fc26.s390x
libglvnd-1.0.0-1.fc26.s390x
lz4-libs-1.8.0-1.fc26.s390x
jansson-2.10-2.fc26.s390x
perl-File-Path-2.12-367.fc26.noarch
perl-Unicode-EastAsianWidth-1.33-9.fc26.noarch
hunspell-1.5.4-2.fc26.s390x
libasyncns-0.8-11.fc26.s390x
libnetfilter_conntrack-1.0.6-2.fc26.s390x
perl-Storable-2.56-368.fc26.s390x
autoconf-2.69-24.fc26.noarch
device-mapper-persistent-data-0.6.3-5.fc26.s390x
quota-4.03-9.fc26.s390x
crypto-policies-20170606-1.git7c32281.fc26.noarch
glib2-2.52.3-2.fc26.s390x
python2-idna-2.5-1.fc26.noarch
python2-libcomps-0.1.8-3.fc26.s390x
gsettings-desktop-schemas-3.24.1-1.fc26.s390x
javapackages-tools-4.7.0-17.fc26.noarch
libselinux-python3-2.6-7.fc26.s390x
python-backports-1.0-9.fc26.s390x
python2-cryptography-2.0.2-2.fc26.s390x
libselinux-python-2.6-7.fc26.s390x
Lmod-7.5.3-1.fc26.s390x
fipscheck-lib-1.5.0-1.fc26.s390x
elfutils-libs-0.169-1.fc26.s390x
krb5-libs-1.15.2-4.fc26.s390x
libuser-0.62-6.fc26.s390x
npth-1.5-1.fc26.s390x
packagedb-cli-2.14.1-2.fc26.noarch
ustr-1.0.4-22.fc26.s390x
device-mapper-1.02.137-6.fc26.s390x
polkit-pkla-compat-0.1-8.fc26.s390x
fakeroot-1.22-1.fc26.s390x
libXmu-1.1.2-5.fc26.s390x
cairo-gobject-1.14.10-1.fc26.s390x
texlive-booktabs-svn40846-33.fc26.2.noarch
texlive-dvips-bin-svn40987-33.20160520.fc26.2.s390x
texlive-float-svn15878.1.3d-33.fc26.2.noarch
texlive-tex-svn40793-33.fc26.2.noarch
texlive-fancyref-svn15878.0.9c-33.fc26.2.noarch
texlive-manfnt-font-svn35799.0-33.fc26.2.noarch
texlive-cmap-svn41168-33.fc26.2.noarch
texlive-hyph-utf8-svn41189-33.fc26.2.noarch
texlive-paralist-svn39247-33.fc26.2.noarch
texlive-trimspaces-svn15878.1.1-33.fc26.2.noarch
texlive-tipa-svn29349.1.3-33.fc26.2.noarch
texlive-l3packages-svn41246-33.fc26.2.noarch
texlive-pst-pdf-svn31660.1.1v-33.fc26.2.noarch
texlive-tex-gyre-svn18651.2.004-33.fc26.2.noarch
texlive-beamer-svn36461.3.36-33.fc26.2.noarch
gd-2.2.5-1.fc26.s390x
elfutils-libelf-devel-0.169-1.fc26.s390x
gc-devel-7.6.0-2.fc26.s390x
libXft-devel-2.3.2-5.fc26.s390x
krb5-devel-1.15.2-4.fc26.s390x
rpm-devel-4.13.0.2-1.fc26.s390x
bluez-libs-devel-5.46-6.fc26.s390x
systemtap-3.2-2.fc26.s390x
trousers-0.3.13-7.fc26.s390x
iproute-tc-4.11.0-1.fc26.s390x
libgnome-keyring-3.12.0-8.fc26.s390x
perl-File-ShareDir-1.102-8.fc26.noarch
python2-paramiko-2.2.1-1.fc26.noarch
python2-openidc-client-0.4.0-1.20171113git54dee6e.fc26.noarch
openssh-server-7.5p1-4.fc26.s390x
pulseaudio-libs-11.1-7.fc26.s390x
python2-bodhi-2.12.2-3.fc26.noarch
lua-libs-5.3.4-7.fc26.s390x
dhcp-common-4.3.5-10.fc26.noarch
python3-pip-9.0.1-11.fc26.noarch
python3-sssdconfig-1.16.0-4.fc26.noarch
python2-py-1.4.34-1.fc26.noarch
glibc-common-2.25-13.fc26.s390x
webkitgtk4-jsc-2.18.6-1.fc26.s390x
python3-libs-3.6.4-2.fc26.s390x
glibc-devel-2.25-13.fc26.s390x
pcre2-10.23-13.fc26.s390x
linux-firmware-20171215-82.git2451bb22.fc26.noarch
glusterfs-api-devel-3.10.10-1.fc26.s390x
libfdt-devel-1.4.6-1.fc26.s390x
audit-2.8.2-1.fc26.s390x
perl-Socket-2.027-1.fc26.s390x
nosync-1.0-6.fc26.s390x
gpg-pubkey-95a43f54-5284415a
gpg-pubkey-fdb19c98-56fd6333
gpg-pubkey-64dab85d-57d33e22
firewalld-filesystem-0.4.4.5-1.fc26.noarch
xkeyboard-config-2.21-3.fc26.noarch
texlive-texlive-common-doc-svn40682-33.fc26.2.noarch
ncurses-base-6.0-8.20170212.fc26.noarch
libselinux-2.6-7.fc26.s390x
bzip2-libs-1.0.6-22.fc26.s390x
libdb-5.3.28-24.fc26.s390x
mpfr-3.1.5-3.fc26.s390x
file-libs-5.30-11.fc26.s390x
libunistring-0.9.7-1.fc26.s390x
libxslt-1.1.29-1.fc26.s390x
gdbm-1.13-1.fc26.s390x
libepoxy-1.4.3-1.fc26.s390x
libpsl-0.18.0-1.fc26.s390x
perl-Carp-1.40-366.fc26.noarch
e2fsprogs-libs-1.43.4-2.fc26.s390x
libmnl-1.0.4-2.fc26.s390x
openjpeg2-2.2.0-3.fc26.s390x
perl-PathTools-3.63-367.fc26.s390x
perl-File-Temp-0.230.400-2.fc26.noarch
perl-XML-Parser-2.44-6.fc26.s390x
libss-1.43.4-2.fc26.s390x
ilmbase-2.2.0-8.fc26.s390x
fuse-libs-2.9.7-2.fc26.s390x
libdaemon-0.14-11.fc26.s390x
libbasicobjects-0.1.1-34.fc26.s390x
iptables-1.6.1-2.fc26.s390x
perl-TermReadKey-2.37-2.fc26.s390x
perl-Term-ANSIColor-4.06-2.fc26.noarch
perl-libintl-perl-1.26-2.fc26.s390x
usbredir-0.7.1-3.fc26.s390x
fftw-libs-double-3.3.5-4.fc26.s390x
libiscsi-1.15.0-3.fc26.s390x
ttmkfdir-3.0.9-49.fc26.s390x
texlive-base-2016-33.20160520.fc26.1.noarch
python2-six-1.10.0-9.fc26.noarch
atk-2.24.0-1.fc26.s390x
python2-kitchen-1.2.4-6.fc26.noarch
guile-2.0.14-1.fc26.s390x
desktop-file-utils-0.23-3.fc26.s390x
pyxattr-0.5.3-10.fc26.s390x
shared-mime-info-1.8-2.fc26.s390x
libyaml-0.1.7-2.fc26.s390x
python3-PyYAML-3.12-3.fc26.s390x
openssh-7.5p1-4.fc26.s390x
kernel-core-4.13.16-202.fc26.s390x
perl-Git-2.13.6-2.fc26.noarch
openssl-1.1.0g-1.fc26.s390x
gawk-4.1.4-6.fc26.s390x
gnutls-3.5.16-4.fc26.s390x
openldap-2.4.45-2.fc26.s390x
NetworkManager-libnm-1.8.2-4.fc26.s390x
gnutls-devel-3.5.16-4.fc26.s390x
python2-urllib3-1.20-2.fc26.noarch
sssd-nfs-idmap-1.16.0-4.fc26.s390x
libsss_sudo-1.16.0-4.fc26.s390x
python3-py-1.4.34-1.fc26.noarch
perl-ExtUtils-Command-7.24-3.fc26.noarch
tzdata-2018c-1.fc26.noarch
libcrypt-nss-2.25-13.fc26.s390x
libstdc++-devel-7.3.1-2.fc26.s390x
rpcbind-0.2.4-8.rc3.fc26.s390x
gdb-headless-8.0.1-36.fc26.s390x
python3-dnf-plugins-extras-common-2.0.5-1.fc26.noarch
glibc-headers-2.25-13.fc26.s390x
libfdt-1.4.6-1.fc26.s390x
pcre-utf32-8.41-5.fc26.s390x
wget-1.19.4-1.fc26.s390x
mariadb-common-10.1.30-2.fc26.s390x
glusterfs-extra-xlators-3.10.10-1.fc26.s390x
python2-dnf-plugin-migrate-2.1.5-4.fc26.noarch
pcre2-devel-10.23-13.fc26.s390x
perl-threads-shared-1.58-1.fc26.s390x
gcc-c++-7.3.1-2.fc26.s390x
ImageMagick-libs-6.9.9.27-1.fc26.s390x
poppler-0.52.0-11.fc26.s390x
perl-Data-Dumper-2.161-4.fc26.s390x
python2-dnf-plugins-extras-common-2.0.5-1.fc26.noarch
gcc-debuginfo-7.3.1-2.fc26.s390x
libgudev-232-1.fc26.s390x
python3-javapackages-4.7.0-17.fc26.noarch
python3-ply-3.9-3.fc26.noarch
python3-systemd-234-1.fc26.s390x
python3-requests-2.13.0-1.fc26.noarch
blktrace-1.1.0-4.fc26.s390x
python2-asn1crypto-0.23.0-1.fc26.noarch
python2-cffi-1.9.1-2.fc26.s390x
python2-sphinx_rtd_theme-0.2.4-1.fc26.noarch
lua-json-1.3.2-7.fc26.noarch
libcephfs1-10.2.7-2.fc26.s390x
glib-networking-2.50.0-2.fc26.s390x
elfutils-default-yama-scope-0.169-1.fc26.noarch
libedit-3.1-17.20160618cvs.fc26.s390x
libverto-libev-0.2.6-7.fc26.s390x
libserf-1.3.9-3.fc26.s390x
python2-kerberos-1.2.5-3.fc26.s390x
libsrtp-1.5.4-4.fc26.s390x
lzo-minilzo-2.08-9.fc26.s390x
librepo-1.8.0-1.fc26.s390x
koji-1.14.0-1.fc26.noarch
sg3_utils-1.42-1.fc26.s390x
policycoreutils-2.6-6.fc26.s390x
systemtap-client-3.2-2.fc26.s390x
lvm2-2.02.168-6.fc26.s390x
device-mapper-multipath-libs-0.4.9-88.fc26.s390x
s390utils-cmsfs-1.36.1-3.fc26.s390x
libXdamage-1.1.4-9.fc26.s390x
libXaw-1.0.13-5.fc26.s390x
brltty-5.5-5.fc26.s390x
librsvg2-2.40.18-1.fc26.s390x
texlive-tetex-bin-svn36770.0-33.20160520.fc26.2.noarch
texlive-etex-pkg-svn39355-33.fc26.2.noarch
texlive-graphics-svn41015-33.fc26.2.noarch
texlive-dvips-svn41149-33.fc26.2.noarch
texlive-zapfding-svn31835.0-33.fc26.2.noarch
texlive-footmisc-svn23330.5.5b-33.fc26.2.noarch
texlive-makeindex-svn40768-33.fc26.2.noarch
texlive-pst-ovl-svn40873-33.fc26.2.noarch
texlive-texlive-scripts-svn41433-33.fc26.2.noarch
texlive-ltabptch-svn17533.1.74d-33.fc26.2.noarch
texlive-euro-svn22191.1.1-33.fc26.2.noarch
texlive-mflogo-font-svn36898.1.002-33.fc26.2.noarch
texlive-zapfchan-svn31835.0-33.fc26.2.noarch
texlive-cmextra-svn32831.0-33.fc26.2.noarch
texlive-finstrut-svn21719.0.5-33.fc26.2.noarch
texlive-hyphen-base-svn41138-33.fc26.2.noarch
texlive-marginnote-svn41382-33.fc26.2.noarch
texlive-parallel-svn15878.0-33.fc26.2.noarch
texlive-sepnum-svn20186.2.0-33.fc26.2.noarch
texlive-environ-svn33821.0.3-33.fc26.2.noarch
texlive-type1cm-svn21820.0-33.fc26.2.noarch
texlive-xunicode-svn30466.0.981-33.fc26.2.noarch
texlive-attachfile-svn38830-33.fc26.2.noarch
texlive-fontspec-svn41262-33.fc26.2.noarch
texlive-fancyvrb-svn18492.2.8-33.fc26.2.noarch
texlive-pst-pdf-bin-svn7838.0-33.20160520.fc26.2.noarch
texlive-xcolor-svn41044-33.fc26.2.noarch
texlive-pdfpages-svn40638-33.fc26.2.noarch
texlive-sansmathaccent-svn30187.0-33.fc26.2.noarch
texlive-ucs-svn35853.2.2-33.fc26.2.noarch
texlive-dvipdfmx-bin-svn40273-33.20160520.fc26.2.s390x
libotf-0.9.13-8.fc26.s390x
go-srpm-macros-2-8.fc26.noarch
mesa-libwayland-egl-devel-17.2.4-2.fc26.s390x
ghostscript-9.20-10.fc26.s390x
libcephfs_jni-devel-10.2.7-2.fc26.s390x
libXdamage-devel-1.1.4-9.fc26.s390x
freetype-devel-2.7.1-9.fc26.s390x
ncurses-devel-6.0-8.20170212.fc26.s390x
fontconfig-devel-2.12.6-4.fc26.s390x
cairo-devel-1.14.10-1.fc26.s390x
libselinux-devel-2.6-7.fc26.s390x
guile-devel-2.0.14-1.fc26.s390x
libcap-ng-devel-0.7.8-3.fc26.s390x
bash-completion-2.6-1.fc26.noarch
libXevie-1.0.3-12.fc26.s390x
python-firewall-0.4.4.5-1.fc26.noarch
python3-html5lib-0.999-13.fc26.noarch
python2-simplejson-3.10.0-3.fc26.s390x
flex-2.6.1-3.fc26.s390x
telnet-0.17-69.fc26.s390x
gpg-pubkey-8e1431d5-53bcbac7
emacs-filesystem-25.3-3.fc26.noarch
fontawesome-fonts-4.7.0-2.fc26.noarch
fontawesome-fonts-web-4.7.0-2.fc26.noarch
rpmconf-base-1.0.19-1.fc26.noarch
info-6.3-3.fc26.s390x
sqlite-libs-3.20.1-1.fc26.s390x
texlive-lib-2016-33.20160520.fc26.1.s390x
libicu-57.1-7.fc26.s390x
libcap-ng-0.7.8-3.fc26.s390x
nettle-3.3-2.fc26.s390x
libidn2-2.0.4-1.fc26.s390x
lcms2-2.8-3.fc26.s390x
dbus-libs-1.11.18-1.fc26.s390x
perl-Exporter-5.72-367.fc26.noarch
unzip-6.0-34.fc26.s390x
iproute-4.11.0-1.fc26.s390x
zip-3.0-18.fc26.s390x
perl-constant-1.33-368.fc26.noarch
perl-MIME-Base64-3.15-366.fc26.s390x
lua-posix-33.3.1-4.fc26.s390x
bzip2-1.0.6-22.fc26.s390x
hyphen-2.8.8-6.fc26.s390x
libdvdread-5.0.3-4.fc26.s390x
libcollection-0.7.0-34.fc26.s390x
libdvdnav-5.0.3-5.fc26.s390x
perl-version-0.99.18-1.fc26.s390x
perl-Encode-2.88-6.fc26.s390x
automake-1.15-9.fc26.noarch
plymouth-core-libs-0.9.3-0.7.20160620git0e65b86c.fc26.s390x
hesiod-3.2.1-7.fc26.s390x
jasper-libs-2.0.14-1.fc26.s390x
mozjs17-17.0.0-18.fc26.s390x
fontconfig-2.12.6-4.fc26.s390x
harfbuzz-1.4.4-1.fc26.s390x
alsa-lib-1.1.4.1-1.fc26.s390x
make-4.2.1-2.fc26.s390x
gobject-introspection-1.52.1-1.fc26.s390x
hicolor-icon-theme-0.15-5.fc26.noarch
gdk-pixbuf2-2.36.9-1.fc26.s390x
libgusb-0.2.11-1.fc26.s390x
libdhash-0.5.0-34.fc26.s390x
python2-bcrypt-3.1.4-2.fc26.s390x
PyYAML-3.12-3.fc26.s390x
nss-softokn-freebl-3.34.0-1.0.fc26.s390x
kernel-modules-4.13.16-202.fc26.s390x
git-2.13.6-2.fc26.s390x
openssl-devel-1.1.0g-1.fc26.s390x
copy-jdk-configs-3.3-2.fc26.noarch
python3-setuptools-37.0.0-1.fc26.noarch
kernel-core-4.14.8-200.fc26.s390x
NetworkManager-1.8.2-4.fc26.s390x
libjpeg-turbo-devel-1.5.3-1.fc26.s390x
lua-5.3.4-7.fc26.s390x
boost-thread-1.63.0-10.fc26.s390x
libwebp-0.6.1-1.fc26.s390x
kernel-devel-4.14.8-200.fc26.s390x
perl-autodie-2.29-367.fc26.noarch
tzdata-java-2018c-1.fc26.noarch
glusterfs-3.10.10-1.fc26.s390x
glusterfs-api-3.10.10-1.fc26.s390x
pcre-8.41-5.fc26.s390x
createrepo_c-0.10.0-15.fc26.s390x
mock-core-configs-28.2-1.fc26.noarch
libgfortran-7.3.1-2.fc26.s390x
libdrm-2.4.89-1.fc26.s390x
pcre-utf16-8.41-5.fc26.s390x
vim-common-8.0.1438-1.fc26.s390x
mariadb-config-10.1.30-2.fc26.s390x
python2-gluster-3.10.10-1.fc26.s390x
java-1.8.0-openjdk-1.8.0.161-5.b14.fc26.s390x
libtasn1-devel-4.13-1.fc26.s390x
vim-enhanced-8.0.1438-1.fc26.s390x
gcc-gdb-plugin-7.3.1-2.fc26.s390x
gnupg2-smime-2.2.4-1.fc26.s390x
python2-libxml2-2.9.7-1.fc26.s390x
net-tools-2.0-0.44.20160912git.fc26.s390x
python2-requests-kerberos-0.12.0-1.fc26.noarch
gcc-base-debuginfo-7.3.1-2.fc26.s390x
python3-lxml-4.1.1-1.fc26.s390x
python3-ordered-set-2.0.0-6.fc26.noarch
python3-rpmconf-1.0.19-1.fc26.noarch
python-offtrac-0.1.0-9.fc26.noarch
python2-pycparser-2.14-10.fc26.noarch
python2-sphinx-theme-alabaster-0.7.9-3.fc26.noarch
python2-pysocks-1.6.7-1.fc26.noarch
lua-lpeg-1.0.1-2.fc26.s390x
libproxy-0.4.15-2.fc26.s390x
crontabs-1.11-14.20150630git.fc26.noarch
libev-4.24-2.fc26.s390x
libsigsegv-2.11-1.fc26.s390x
fedora-cert-0.6.0.1-2.fc26.noarch
drpm-0.3.0-6.fc26.s390x
python2-cccolutils-1.5-3.fc26.s390x
m17n-lib-1.7.0-6.fc26.s390x
lsscsi-0.28-4.fc26.s390x
python2-koji-1.14.0-1.fc26.noarch
python3-koji-1.14.0-1.fc26.noarch
python3-gpg-1.8.0-12.fc26.s390x
sg3_utils-libs-1.42-1.fc26.s390x
SDL2-2.0.7-2.fc26.s390x
util-linux-2.30.2-1.fc26.s390x
s390utils-mon_statd-1.36.1-3.fc26.s390x
GConf2-3.2.6-17.fc26.s390x
systemd-container-233-7.fc26.s390x
usermode-1.111-9.fc26.s390x
libXt-1.1.5-4.fc26.s390x
libXpm-3.5.12-2.fc26.s390x
at-spi2-core-2.24.1-1.fc26.s390x
cairo-1.14.10-1.fc26.s390x
texlive-kpathsea-bin-svn40473-33.20160520.fc26.2.s390x
texlive-ifluatex-svn41346-33.fc26.2.noarch
texlive-babel-svn40706-33.fc26.2.noarch
texlive-colortbl-svn29803.v1.0a-33.fc26.2.noarch
texlive-marvosym-svn29349.2.2a-33.fc26.2.noarch
texlive-euler-svn17261.2.5-33.fc26.2.noarch
texlive-latexconfig-svn40274-33.fc26.2.noarch
texlive-plain-svn40274-33.fc26.2.noarch
texlive-texconfig-bin-svn29741.0-33.20160520.fc26.2.noarch
giflib-4.1.6-16.fc26.s390x
texlive-microtype-svn41127-33.fc26.2.noarch
texlive-eurosym-svn17265.1.4_subrfix-33.fc26.2.noarch
texlive-symbol-svn31835.0-33.fc26.2.noarch
texlive-chngcntr-svn17157.1.0a-33.fc26.2.noarch
texlive-euenc-svn19795.0.1h-33.fc26.2.noarch
texlive-luatex-svn40963-33.fc26.2.noarch
texlive-knuth-local-svn38627-33.fc26.2.noarch
texlive-mparhack-svn15878.1.4-33.fc26.2.noarch
texlive-rcs-svn15878.0-33.fc26.2.noarch
texlive-texlive-msg-translations-svn41431-33.fc26.2.noarch
texlive-updmap-map-svn41159-33.fc26.2.noarch
texlive-geometry-svn19716.5.6-33.fc26.2.noarch
texlive-memoir-svn41203-33.fc26.2.noarch
texlive-l3kernel-svn41246-33.fc26.2.noarch
texlive-pst-eps-svn15878.1.0-33.fc26.2.noarch
texlive-pst-text-svn15878.1.00-33.fc26.2.noarch
texlive-amscls-svn36804.0-33.fc26.2.noarch
texlive-pst-slpe-svn24391.1.31-33.fc26.2.noarch
texlive-extsizes-svn17263.1.4a-33.fc26.2.noarch
texlive-xetex-def-svn40327-33.fc26.2.noarch
texlive-collection-latex-svn41011-33.20160520.fc26.2.noarch
gstreamer1-plugins-base-1.12.3-1.fc26.s390x
fpc-srpm-macros-1.1-2.fc26.noarch
xorg-x11-proto-devel-7.7-22.fc26.noarch
urw-fonts-2.4-23.fc26.noarch
atk-devel-2.24.0-1.fc26.s390x
libxcb-devel-1.12-3.fc26.s390x
libXrandr-devel-1.5.1-2.fc26.s390x
libcom_err-devel-1.43.4-2.fc26.s390x
dbus-devel-1.11.18-1.fc26.s390x
libepoxy-devel-1.4.3-1.fc26.s390x
libicu-devel-57.1-7.fc26.s390x
p11-kit-devel-0.23.9-2.fc26.s390x
rpm-build-4.13.0.2-1.fc26.s390x
libssh2-devel-1.8.0-5.fc26.s390x
graphviz-2.40.1-4.fc26.s390x
zlib-static-1.2.11-2.fc26.s390x
mesa-libgbm-devel-17.2.4-2.fc26.s390x
screen-4.6.2-1.fc26.s390x
python-osbs-client-0.39.1-1.fc26.noarch
pyparsing-2.1.10-3.fc26.noarch
python3-pyasn1-0.2.3-1.fc26.noarch
python2-html5lib-0.999-13.fc26.noarch
teamd-1.27-1.fc26.s390x
hardlink-1.3-1.fc26.s390x
chrpath-0.16-4.fc26.s390x
texlive-pdftex-doc-svn41149-33.fc26.2.noarch
nspr-4.17.0-1.fc26.s390x
grep-3.1-1.fc26.s390x
libacl-2.2.52-15.fc26.s390x
cpio-2.12-4.fc26.s390x
libatomic_ops-7.4.4-2.fc26.s390x
p11-kit-0.23.9-2.fc26.s390x
gc-7.6.0-2.fc26.s390x
psmisc-22.21-9.fc26.s390x
systemd-libs-233-7.fc26.s390x
xz-5.2.3-2.fc26.s390x
perl-libs-5.24.3-395.fc26.s390x
libpcap-1.8.1-3.fc26.s390x
perl-macros-5.24.3-395.fc26.s390x
perl-parent-0.236-2.fc26.noarch
perl-Text-Unidecode-1.30-2.fc26.noarch
newt-0.52.20-1.fc26.s390x
libcomps-0.1.8-3.fc26.s390x
libfontenc-1.1.3-4.fc26.s390x
ipcalc-0.2.0-1.fc26.s390x
libnfnetlink-1.0.1-9.fc26.s390x
libref_array-0.1.5-34.fc26.s390x
perl-Term-Cap-1.17-366.fc26.noarch
perl-Digest-1.17-367.fc26.noarch
perl-SelfLoader-1.23-395.fc26.noarch
perl-Pod-Simple-3.35-2.fc26.noarch
perl-URI-1.71-6.fc26.noarch
attr-2.4.47-18.fc26.s390x
gmp-c++-6.1.2-4.fc26.s390x
harfbuzz-icu-1.4.4-1.fc26.s390x
http-parser-2.7.1-5.fc26.s390x
libsodium-1.0.14-1.fc26.s390x
python-gssapi-1.2.0-5.fc26.s390x
nss-softokn-3.34.0-1.0.fc26.s390x
nss-devel-3.34.0-1.0.fc26.s390x
perl-libnet-3.11-1.fc26.noarch
kernel-devel-4.13.16-202.fc26.s390x
python2-libs-2.7.14-4.fc26.s390x
libwayland-client-1.13.0-3.fc26.s390x
python3-dnf-2.7.5-2.fc26.noarch
kernel-modules-4.14.8-200.fc26.s390x
NetworkManager-ppp-1.8.2-4.fc26.s390x
wayland-devel-1.13.0-3.fc26.s390x
kernel-4.14.8-200.fc26.s390x
boost-random-1.63.0-10.fc26.s390x
mailx-12.5-24.fc26.s390x
NetworkManager-glib-1.8.2-4.fc26.s390x
perl-IPC-System-Simple-1.25-12.fc26.noarch
vim-filesystem-8.0.1438-1.fc26.s390x
glusterfs-libs-3.10.10-1.fc26.s390x
sed-4.4-2.fc26.s390x
libassuan-2.5.1-1.fc26.s390x
createrepo_c-libs-0.10.0-15.fc26.s390x
dnf-utils-2.1.5-4.fc26.noarch
libobjc-7.3.1-2.fc26.s390x
dracut-046-8.git20180105.fc26.s390x
libseccomp-2.3.3-1.fc26.s390x
mock-1.4.8-1.fc26.noarch
python-sphinx-locale-1.5.6-1.fc26.noarch
pcre-devel-8.41-5.fc26.s390x
libxml2-devel-2.9.7-1.fc26.s390x
libseccomp-devel-2.3.3-1.fc26.s390x
fedora-upgrade-28.1-1.fc26.noarch
gcc-gfortran-7.3.1-2.fc26.s390x
gdb-8.0.1-36.fc26.s390x
unbound-libs-1.6.8-1.fc26.s390x
man-db-2.7.6.1-9.fc26.s390x
python2-rpm-macros-3-21.fc26.noarch
kernel-devel-4.15.4-200.fc26.s390x
libcroco-0.6.12-1.fc26.s390x
libssh2-1.8.0-5.fc26.s390x
json-glib-1.2.6-1.fc26.s390x
libevent-2.0.22-3.fc26.s390x
gdk-pixbuf2-modules-2.36.9-1.fc26.s390x
colord-libs-1.3.5-1.fc26.s390x
python3-magic-5.30-11.fc26.noarch
python3-gobject-base-3.24.1-1.fc26.s390x
python3-pyroute2-0.4.13-1.fc26.noarch
python3-pysocks-1.6.7-1.fc26.noarch
python2-click-6.7-3.fc26.noarch
python-munch-2.1.0-2.fc26.noarch
python2-ply-3.9-3.fc26.noarch
python2-snowballstemmer-1.2.1-3.fc26.noarch
python-magic-5.30-11.fc26.noarch
python-beautifulsoup4-4.6.0-1.fc26.noarch
python2-gitdb-2.0.3-1.fc26.noarch
librados-devel-10.2.7-2.fc26.s390x
libcacard-2.5.3-1.fc26.s390x
libmodman-2.0.1-13.fc26.s390x
zziplib-0.13.62-8.fc26.s390x
lksctp-tools-1.0.16-6.fc26.s390x
procmail-3.22-44.fc26.s390x
libthai-0.1.25-2.fc26.s390x
libpipeline-1.4.1-3.fc26.s390x
python2-pycurl-7.43.0-8.fc26.s390x
deltarpm-3.6-19.fc26.s390x
subversion-libs-1.9.7-1.fc26.s390x
python-krbV-1.0.90-13.fc26.s390x
m17n-db-1.7.0-8.fc26.noarch
linux-atm-libs-2.5.1-17.fc26.s390x
python2-rpm-4.13.0.2-1.fc26.s390x
python2-librepo-1.8.0-1.fc26.s390x
qrencode-libs-3.4.4-1.fc26.s390x
s390utils-iucvterm-1.36.1-3.fc26.s390x
libsmartcols-2.30.2-1.fc26.s390x
dbus-1.11.18-1.fc26.s390x
systemd-udev-233-7.fc26.s390x
device-mapper-event-1.02.137-6.fc26.s390x
polkit-0.113-8.fc26.s390x
libwmf-lite-0.2.8.4-53.fc26.s390x
libXcomposite-0.4.4-9.fc26.s390x
libXcursor-1.1.14-8.fc26.s390x
at-spi2-atk-2.24.1-1.fc26.s390x
pango-1.40.12-1.fc26.s390x
texlive-metafont-bin-svn40987-33.20160520.fc26.2.s390x
texlive-url-svn32528.3.4-33.fc26.2.noarch
texlive-fp-svn15878.0-33.fc26.2.noarch
texlive-latex-fonts-svn28888.0-33.fc26.2.noarch
texlive-mptopdf-bin-svn18674.0-33.20160520.fc26.2.noarch
texlive-fancybox-svn18304.1.4-33.fc26.2.noarch
texlive-lua-alt-getopt-svn29349.0.7.0-33.fc26.2.noarch
texlive-tex-bin-svn40987-33.20160520.fc26.2.s390x
texlive-texconfig-svn40768-33.fc26.2.noarch
texlive-wasy2-ps-svn35830.0-33.fc26.2.noarch
texlive-psfrag-svn15878.3.04-33.fc26.2.noarch
texlive-helvetic-svn31835.0-33.fc26.2.noarch
texlive-times-svn35058.0-33.fc26.2.noarch
texlive-cite-svn36428.5.5-33.fc26.2.noarch
texlive-fancyhdr-svn15878.3.1-33.fc26.2.noarch
texlive-luatex-bin-svn41091-33.20160520.fc26.2.s390x
texlive-lm-math-svn36915.1.959-33.fc26.2.noarch
texlive-ntgclass-svn15878.2.1a-33.fc26.2.noarch
texlive-sansmath-svn17997.1.1-33.fc26.2.noarch
texlive-textcase-svn15878.0-33.fc26.2.noarch
texlive-unicode-data-svn39808-33.fc26.2.noarch
texlive-breakurl-svn29901.1.40-33.fc26.2.noarch
texlive-latex-svn40218-33.fc26.2.noarch
texlive-lualatex-math-svn40621-33.fc26.2.noarch
texlive-pst-coil-svn37377.1.07-33.fc26.2.noarch
texlive-pst-plot-svn41242-33.fc26.2.noarch
texlive-unicode-math-svn38462-33.fc26.2.noarch
texlive-pst-blur-svn15878.2.0-33.fc26.2.noarch
texlive-cm-super-svn15878.0-33.fc26.2.noarch
texlive-wasysym-svn15878.2.0-33.fc26.2.noarch
texlive-collection-fontsrecommended-svn35830.0-33.20160520.fc26.2.noarch
libXv-1.0.11-2.fc26.s390x
ghc-srpm-macros-1.4.2-5.fc26.noarch
latex2html-2017.2-2.fc26.noarch
libXau-devel-1.0.8-7.fc26.s390x
libXcursor-devel-1.1.14-8.fc26.s390x
graphite2-devel-1.3.10-1.fc26.s390x
pixman-devel-0.34.0-3.fc26.s390x
wayland-protocols-devel-1.9-1.fc26.noarch
mesa-libGLES-devel-17.2.4-2.fc26.s390x
vte291-devel-0.48.4-1.fc26.s390x
ceph-devel-compat-10.2.7-2.fc26.s390x
lzo-devel-2.08-9.fc26.s390x
libiscsi-devel-1.15.0-3.fc26.s390x
avahi-autoipd-0.6.32-7.fc26.s390x
rpm-plugin-systemd-inhibit-4.13.0.2-1.fc26.s390x
python2-ndg_httpsclient-0.4.0-7.fc26.noarch
gettext-0.19.8.1-9.fc26.s390x
btrfs-progs-4.9.1-2.fc26.s390x
fedora-logos-26.0.1-1.fc26.s390x
dejagnu-1.6-2.fc26.noarch
libaio-devel-0.3.110-7.fc26.s390x
dos2unix-7.3.4-2.fc26.s390x
popt-1.16-12.fc26.s390x
tar-1.29-5.fc26.s390x
avahi-libs-0.6.32-7.fc26.s390x
m4-1.4.18-3.fc26.s390x
perl-Time-Local-1.250-2.fc26.noarch
libmetalink-0.1.3-2.fc26.s390x
jbigkit-libs-2.1-6.fc26.s390x
netpbm-10.80.00-2.fc26.s390x
perl-Digest-MD5-2.55-3.fc26.s390x
perl-Getopt-Long-2.49.1-2.fc26.noarch
libglvnd-opengl-1.0.0-1.fc26.s390x
libattr-devel-2.4.47-18.fc26.s390x
teckit-2.5.1-16.fc26.s390x
python3-six-1.10.0-9.fc26.noarch
python3-libcomps-0.1.8-3.fc26.s390x
python3-pyparsing-2.1.10-3.fc26.noarch
python2-markupsafe-0.23-13.fc26.s390x
python2-mock-2.0.0-4.fc26.noarch
python2-yubico-1.3.2-7.fc26.noarch
python2-smmap-2.0.3-1.fc26.noarch
librbd-devel-10.2.7-2.fc26.s390x
libnghttp2-1.21.1-1.fc26.s390x
ykpers-1.18.0-2.fc26.s390x
python3-librepo-1.8.0-1.fc26.s390x
systemtap-runtime-3.2-2.fc26.s390x
geoclue2-2.4.5-4.fc26.s390x
initscripts-9.72-1.fc26.s390x
plymouth-0.9.3-0.7.20160620git0e65b86c.fc26.s390x
ebtables-2.0.10-22.fc26.s390x
gssproxy-0.7.0-9.fc26.s390x
libXext-1.3.3-5.fc26.s390x
mesa-libEGL-17.2.4-2.fc26.s390x
texlive-texlive.infra-bin-svn40312-33.20160520.fc26.2.s390x
texlive-thumbpdf-svn34621.3.16-33.fc26.2.noarch
texlive-carlisle-svn18258.0-33.fc26.2.noarch
texlive-gsftopk-svn40768-33.fc26.2.noarch
texlive-pdftex-svn41149-33.fc26.2.noarch
texlive-crop-svn15878.1.5-33.fc26.2.noarch
texlive-pxfonts-svn15878.0-33.fc26.2.noarch
texlive-enctex-svn34957.0-33.fc26.2.noarch
texlive-kastrup-svn15878.0-33.fc26.2.noarch
texlive-pspicture-svn15878.0-33.fc26.2.noarch
texlive-varwidth-svn24104.0.92-33.fc26.2.noarch
texlive-currfile-svn40725-33.fc26.2.noarch
texlive-pst-grad-svn15878.1.06-33.fc26.2.noarch
texlive-latex-bin-svn41438-33.fc26.2.noarch
texlive-ltxmisc-svn21927.0-33.fc26.2.noarch
lasi-1.1.2-7.fc26.s390x
adwaita-icon-theme-3.24.0-2.fc26.noarch
xz-devel-5.2.3-2.fc26.s390x
xorg-x11-fonts-Type1-7.5-17.fc26.noarch
libXi-devel-1.7.9-2.fc26.s390x
at-spi2-atk-devel-2.24.1-1.fc26.s390x
pango-devel-1.40.12-1.fc26.s390x
libcacard-devel-2.5.3-1.fc26.s390x
subversion-1.9.7-1.fc26.s390x
sudo-1.8.21p2-1.fc26.s390x
pykickstart-2.35-2.fc26.noarch
e2fsprogs-1.43.4-2.fc26.s390x
libbsd-0.8.3-3.fc26.s390x
c-ares-1.13.0-1.fc26.s390x
python2-pyxdg-0.25-12.fc26.noarch
nss-softokn-freebl-devel-3.34.0-1.0.fc26.s390x
strace-4.20-1.fc26.s390x
valgrind-3.13.0-12.fc26.s390x
libsss_idmap-1.16.0-4.fc26.s390x
gnutls-c++-3.5.16-4.fc26.s390x
libwayland-server-1.13.0-3.fc26.s390x
dhcp-client-4.3.5-10.fc26.s390x
man-pages-4.09-4.fc26.noarch
libffi-devel-3.1-12.fc26.s390x
libxml2-2.9.7-1.fc26.s390x
kmod-25-1.fc26.s390x
dnf-plugins-core-2.1.5-4.fc26.noarch
kmod-libs-25-1.fc26.s390x
pigz-2.4-1.fc26.s390x
pkgconf-pkg-config-1.3.12-2.fc26.s390x
libdrm-devel-2.4.89-1.fc26.s390x
gcc-go-7.3.1-2.fc26.s390x
system-python-3.6.4-2.fc26.s390x
python-rpm-macros-3-21.fc26.noarch
gpg-pubkey-a29cb19c-53bcbba6
quota-nls-4.03-9.fc26.noarch
xz-libs-5.2.3-2.fc26.s390x
gmp-6.1.2-4.fc26.s390x
file-5.30-11.fc26.s390x
libusbx-1.0.21-2.fc26.s390x
binutils-2.27-28.fc26.s390x
perl-Errno-1.25-395.fc26.s390x
perl-HTTP-Tiny-0.070-2.fc26.noarch
xml-common-0.6.3-45.fc26.noarch
opus-1.2.1-1.fc26.s390x
flac-libs-1.3.2-2.fc26.s390x
libacl-devel-2.2.52-15.fc26.s390x
coreutils-common-8.27-7.fc26.s390x
cracklib-2.9.6-5.fc26.s390x
pyliblzma-0.5.3-17.fc26.s390x
libnotify-0.7.7-2.fc26.s390x
python3-idna-2.5-1.fc26.noarch
python3-pyOpenSSL-16.2.0-6.fc26.noarch
python2-pbr-1.10.0-4.fc26.noarch
pyusb-1.0.0-4.fc26.noarch
librbd1-10.2.7-2.fc26.s390x
libnfs-1.9.8-3.fc26.s390x
libsolv-0.6.30-2.fc26.s390x
python3-pycurl-7.43.0-8.fc26.s390x
libyubikey-1.13-3.fc26.s390x
rpmlint-1.10-5.fc26.noarch
python2-pygpgme-0.3-22.fc26.s390x
s390utils-base-1.36.1-3.fc26.s390x
ppp-2.4.7-11.fc26.s390x
s390utils-cpuplugd-1.36.1-3.fc26.s390x
libXrender-0.9.10-2.fc26.s390x
libglvnd-gles-1.0.0-1.fc26.s390x
texlive-texlive.infra-svn41280-33.fc26.2.noarch
texlive-lm-svn28119.2.004-33.fc26.2.noarch
texlive-babelbib-svn25245.1.31-33.fc26.2.noarch
texlive-index-svn24099.4.1beta-33.fc26.2.noarch
texlive-pdftex-bin-svn40987-33.20160520.fc26.2.s390x
texlive-csquotes-svn39538-33.fc26.2.noarch
texlive-rsfs-svn15878.0-33.fc26.2.noarch
texlive-etex-svn37057.0-33.fc26.2.noarch
texlive-knuth-lib-svn35820.0-33.fc26.2.noarch
texlive-pst-math-svn34786.0.63-33.fc26.2.noarch
texlive-utopia-svn15878.0-33.fc26.2.noarch
texlive-eso-pic-svn37925.2.0g-33.fc26.2.noarch
texlive-pst-fill-svn15878.1.01-33.fc26.2.noarch
texlive-latex-bin-bin-svn14050.0-33.20160520.fc26.2.noarch
texlive-jknapltx-svn19440.0-33.fc26.2.noarch
texlive-collection-latexrecommended-svn35765.0-33.20160520.fc26.2.noarch
adwaita-cursor-theme-3.24.0-2.fc26.noarch
xorg-x11-fonts-ISO8859-1-100dpi-7.5-17.fc26.noarch
libXcomposite-devel-0.4.4-9.fc26.s390x
at-spi2-core-devel-2.24.1-1.fc26.s390x
harfbuzz-devel-1.4.4-1.fc26.s390x
rpmdevtools-8.10-2.fc26.noarch
texi2html-5.0-5.fc26.noarch
libnfs-devel-1.9.8-3.fc26.s390x
firewalld-0.4.4.5-1.fc26.noarch
wpa_supplicant-2.6-12.fc26.s390x
systemtap-sdt-devel-3.2-2.fc26.s390x
newt-python-0.52.20-1.fc26.s390x
perl-Mozilla-CA-20160104-4.fc26.noarch
pth-2.0.7-28.fc26.s390x
python3-pyxdg-0.25-12.fc26.noarch
nss-softokn-devel-3.34.0-1.0.fc26.s390x
timedatex-0.4-3.fc26.s390x
libjpeg-turbo-1.5.3-1.fc26.s390x
libsss_nss_idmap-1.16.0-4.fc26.s390x
dnf-yum-2.7.5-2.fc26.noarch
libuv-devel-1.11.0-1.fc26.s390x
libstdc++-7.3.1-2.fc26.s390x
libgo-7.3.1-2.fc26.s390x
python3-dnf-plugins-core-2.1.5-4.fc26.noarch
gtk3-3.22.21-3.fc26.s390x
perl-threads-2.21-1.fc26.s390x
pkgconf-m4-1.3.12-2.fc26.noarch
gtk3-devel-3.22.21-3.fc26.s390x
gcc-objc-7.3.1-2.fc26.s390x
curl-7.53.1-14.fc26.s390x
vim-minimal-8.0.1438-1.fc26.s390x
python-async-0.6.1-9.fc22.s390x
poppler-data-0.4.7-7.fc26.noarch
ocaml-srpm-macros-4-2.fc26.noarch
libuuid-2.30.2-1.fc26.s390x
libgpg-error-1.25-2.fc26.s390x
graphite2-1.3.10-1.fc26.s390x
perl-Text-Tabs+Wrap-2013.0523-366.fc26.noarch
perl-Error-0.17024-8.fc26.noarch
which-2.21-2.fc26.s390x
libXau-1.0.8-7.fc26.s390x
orc-0.4.27-1.fc26.s390x
perl-Pod-Perldoc-3.28-1.fc26.noarch
libsndfile-1.0.28-6.fc26.s390x
patch-2.7.5-4.fc26.s390x
gzip-1.8-2.fc26.s390x
python-ipaddress-1.0.16-4.fc26.noarch
yum-metadata-parser-1.1.4-18.fc26.s390x
python3-dbus-1.2.4-6.fc26.s390x
python3-cryptography-2.0.2-2.fc26.s390x
python3-kickstart-2.35-2.fc26.noarch
python2-imagesize-0.7.1-5.fc26.noarch
python2-jinja2-2.9.6-1.fc26.noarch
libradosstriper-devel-10.2.7-2.fc26.s390x
soundtouch-1.9.2-4.fc26.s390x
libndp-1.6-2.fc26.s390x
rpm-4.13.0.2-1.fc26.s390x
rest-0.8.0-2.fc26.s390x
libvisual-0.4.0-21.fc26.s390x
python2-hawkey-0.11.1-1.fc26.s390x
fakeroot-libs-1.22-1.fc26.s390x
device-mapper-event-libs-1.02.137-6.fc26.s390x
cyrus-sasl-2.1.26-32.fc26.s390x
cronie-anacron-1.5.1-5.fc26.s390x
libpath_utils-0.2.1-34.fc26.s390x
libX11-common-1.6.5-2.fc26.noarch
libXft-2.3.2-5.fc26.s390x
gtk2-2.24.31-4.fc26.s390x
texlive-etoolbox-svn38031.2.2a-33.fc26.2.noarch
texlive-multido-svn18302.1.42-33.fc26.2.noarch
texlive-glyphlist-svn28576.0-33.fc26.2.noarch
texlive-setspace-svn24881.6.7a-33.fc26.2.noarch
texlive-mathtools-svn38833-33.fc26.2.noarch
texlive-ncntrsbk-svn31835.0-33.fc26.2.noarch
texlive-dvisvgm-def-svn41011-33.fc26.2.noarch
texlive-ifetex-svn24853.1.2-33.fc26.2.noarch
texlive-parskip-svn19963.2.0-33.fc26.2.noarch
texlive-bera-svn20031.0-33.fc26.2.noarch
texlive-pgf-svn40966-33.fc26.2.noarch
texlive-auto-pst-pdf-svn23723.0.6-33.fc26.2.noarch
texlive-ctable-svn38672-33.fc26.2.noarch
texlive-typehtml-svn17134.0-33.fc26.2.noarch
mesa-libGLES-17.2.4-2.fc26.s390x
vte291-0.48.4-1.fc26.s390x
libcephfs_jni1-10.2.7-2.fc26.s390x
bzip2-devel-1.0.6-22.fc26.s390x
expat-devel-2.2.4-1.fc26.s390x
libsepol-devel-2.6-2.fc26.s390x
glib2-static-2.52.3-2.fc26.s390x
virglrenderer-devel-0.6.0-1.20170210git76b3da97b.fc26.s390x
parted-3.2-24.fc26.s390x
python3-beautifulsoup4-4.6.0-1.fc26.noarch
python-bunch-1.0.1-10.fc26.noarch
lz4-1.8.0-1.fc26.s390x
nss-util-3.34.0-1.0.fc26.s390x
openssh-clients-7.5p1-4.fc26.s390x
chrony-3.2-1.fc26.s390x
dnf-conf-2.7.5-2.fc26.noarch
sssd-client-1.16.0-4.fc26.s390x
bodhi-client-2.12.2-3.fc26.noarch
libuv-1.11.0-1.fc26.s390x
glibc-2.25-13.fc26.s390x
libgomp-7.3.1-2.fc26.s390x
cmake-rpm-macros-3.10.1-11.fc26.noarch
gtk-update-icon-cache-3.22.21-3.fc26.s390x
pcre2-utf32-10.23-13.fc26.s390x
kernel-modules-4.15.4-200.fc26.s390x
libcurl-devel-7.53.1-14.fc26.s390x
webkitgtk4-2.18.6-1.fc26.s390x
libstdc++-static-7.3.1-2.fc26.s390x
rsync-3.1.3-2.fc26.s390x
hawkey-0.6.4-3.fc25.s390x
perl-srpm-macros-1-21.fc26.noarch
expat-2.2.4-1.fc26.s390x
chkconfig-1.10-1.fc26.s390x
findutils-4.6.0-12.fc26.s390x
mesa-libwayland-egl-17.2.4-2.fc26.s390x
procps-ng-3.3.10-13.fc26.s390x
mesa-libglapi-17.2.4-2.fc26.s390x
perl-Unicode-Normalize-1.25-366.fc26.s390x
perl-IO-Socket-IP-0.39-1.fc26.noarch
hunspell-en-US-0.20140811.1-6.fc26.noarch
libxcb-1.12-3.fc26.s390x
perl-Pod-Escapes-1.07-366.fc26.noarch
perl-Pod-Usage-1.69-2.fc26.noarch
libtheora-1.1.1-15.fc26.s390x
tcp_wrappers-7.6-85.fc26.s390x
coreutils-8.27-7.fc26.s390x
libmount-2.30.2-1.fc26.s390x
python2-iniparse-0.4-24.fc26.noarch
python2-decorator-4.0.11-2.fc26.noarch
ModemManager-glib-1.6.10-1.fc26.s390x
python3-decorator-4.0.11-2.fc26.noarch
python3-cffi-1.9.1-2.fc26.s390x
python-bugzilla-cli-2.1.0-1.fc26.noarch
python2-funcsigs-1.0.2-5.fc26.noarch
python2-babel-2.3.4-5.fc26.noarch
python-bugzilla-2.1.0-1.fc26.noarch
libradosstriper1-10.2.7-2.fc26.s390x
snappy-1.1.4-3.fc26.s390x
libmpcdec-1.2.6-17.fc26.s390x
rpm-libs-4.13.0.2-1.fc26.s390x
python-urlgrabber-3.10.1-11.fc26.noarch
sysfsutils-2.1.0-20.fc26.s390x
python3-hawkey-0.11.1-1.fc26.s390x
ethtool-4.13-1.fc26.s390x
iputils-20161105-5.fc26.s390x
plymouth-scripts-0.9.3-0.7.20160620git0e65b86c.fc26.s390x
cronie-1.5.1-5.fc26.s390x
libini_config-1.3.1-34.fc26.s390x
libX11-1.6.5-2.fc26.s390x
libglvnd-egl-1.0.0-1.fc26.s390x
texlive-kpathsea-svn41139-33.fc26.2.noarch
texlive-thumbpdf-bin-svn6898.0-33.20160520.fc26.2.noarch
texlive-subfig-svn15878.1.3-33.fc26.2.noarch
texlive-gsftopk-bin-svn40473-33.20160520.fc26.2.s390x
texlive-tex-ini-files-svn40533-33.fc26.2.noarch
texlive-qstest-svn15878.0-33.fc26.2.noarch
texlive-palatino-svn31835.0-33.fc26.2.noarch
texlive-ec-svn25033.1.0-33.fc26.2.noarch
texlive-iftex-svn29654.0.2-33.fc26.2.noarch
texlive-pslatex-svn16416.0-33.fc26.2.noarch
texlive-algorithms-svn38085.0.1-33.fc26.2.noarch
texlive-filehook-svn24280.0.5d-33.fc26.2.noarch
texlive-pst-node-svn40743-33.fc26.2.noarch
texlive-rotating-svn16832.2.16b-33.fc26.2.noarch
texlive-seminar-svn34011.1.62-33.fc26.2.noarch
libuuid-devel-2.30.2-1.fc26.s390x
libXinerama-devel-1.1.3-7.fc26.s390x
emacs-common-25.3-3.fc26.s390x
fedora-packager-0.6.0.1-2.fc26.noarch
snappy-devel-1.1.4-3.fc26.s390x
authconfig-7.0.1-2.fc26.s390x
newt-python3-0.52.20-1.fc26.s390x
python-decoratortools-1.8-13.fc26.noarch
python-systemd-doc-234-1.fc26.s390x
openssl-libs-1.1.0g-1.fc26.s390x
git-core-2.13.6-2.fc26.s390x
libsss_certmap-1.16.0-4.fc26.s390x
lsof-4.89-5.fc26.s390x
glibc-all-langpacks-2.25-13.fc26.s390x
audit-libs-2.8.2-1.fc26.s390x
python3-3.6.4-2.fc26.s390x
gcc-7.3.1-2.fc26.s390x
pcre2-utf16-10.23-13.fc26.s390x
kernel-core-4.15.4-200.fc26.s390x
pcre-static-8.41-5.fc26.s390x
dracut-config-rescue-046-8.git20180105.fc26.s390x
webkitgtk4-plugin-process-gtk2-2.18.6-1.fc26.s390x
perl-Time-HiRes-1.9753-1.fc26.s390x
haveged-1.9.1-6.fc26.s390x
gpg-pubkey-a0a7badb-52844296
gpg-pubkey-e372e838-56fd7943
gpg-pubkey-3b921d09-57a87096
google-roboto-slab-fonts-1.100263-0.5.20150923git.fc26.noarch
libreport-filesystem-2.9.1-3.fc26.s390x
libcom_err-1.43.4-2.fc26.s390x
libffi-3.1-12.fc26.s390x
keyutils-libs-1.5.10-1.fc26.s390x
diffutils-3.5-3.fc26.s390x
apr-util-1.5.4-6.fc26.s390x
bluez-libs-5.46-6.fc26.s390x
libksba-1.3.5-3.fc26.s390x
ncurses-6.0-8.20170212.fc26.s390x
gsm-1.0.17-1.fc26.s390x
libteam-1.27-1.fc26.s390x
perl-Fedora-VSP-0.001-5.fc26.noarch
libusb-0.1.5-8.fc26.s390x
acl-2.2.52-15.fc26.s390x
dwz-0.12-3.fc26.s390x
libblkid-2.30.2-1.fc26.s390x
polkit-libs-0.113-8.fc26.s390x
dbus-python-1.2.4-6.fc26.s390x
gts-0.7.6-30.20121130.fc26.s390x
libfdisk-2.30.2-1.fc26.s390x
python3-pycparser-2.14-10.fc26.noarch
python3-bugzilla-2.1.0-1.fc26.noarch
python2-docutils-0.13.1-4.fc26.noarch
pytz-2016.10-4.fc26.noarch
python2-requests-2.13.0-1.fc26.noarch
libcephfs-devel-10.2.7-2.fc26.s390x
ncurses-c++-libs-6.0-8.20170212.fc26.s390x
GeoIP-1.6.11-1.fc26.s390x
liblockfile-1.09-5.fc26.s390x
rpm-plugin-selinux-4.13.0.2-1.fc26.s390x
systemtap-devel-3.2-2.fc26.s390x
libsysfs-2.1.0-20.fc26.s390x
libdnf-0.11.1-1.fc26.s390x
mesa-libgbm-17.2.4-2.fc26.s390x
lvm2-libs-2.02.168-6.fc26.s390x
libXfixes-5.0.3-2.fc26.s390x
brlapi-0.6.6-5.fc26.s390x
texlive-metafont-svn40793-33.fc26.2.noarch
texlive-graphics-cfg-svn40269-33.fc26.2.noarch
texlive-mptopdf-svn41282-33.fc26.2.noarch
texlive-makeindex-bin-svn40473-33.20160520.fc26.2.s390x
texlive-texlive-scripts-bin-svn29741.0-33.20160520.fc26.2.noarch
texlive-sauerj-svn15878.0-33.fc26.2.noarch
texlive-txfonts-svn15878.0-33.fc26.2.noarch
texlive-filecontents-svn24250.1.3-33.fc26.2.noarch
texlive-lualibs-svn40370-33.fc26.2.noarch
texlive-section-svn20180.0-33.fc26.2.noarch
texlive-ucharcat-svn38907-33.fc26.2.noarch
texlive-hyperref-svn41396-33.fc26.2.noarch
texlive-pst-3d-svn17257.1.10-33.fc26.2.noarch
texlive-oberdiek-svn41346-33.fc26.2.noarch
texlive-ae-svn15878.1.4-33.fc26.2.noarch
texlive-collection-basic-svn41149-33.20160520.fc26.2.noarch
gnat-srpm-macros-4-2.fc26.noarch
glib2-devel-2.52.3-2.fc26.s390x
netpbm-progs-10.80.00-2.fc26.s390x
libXxf86vm-devel-1.1.4-4.fc26.s390x
nettle-devel-3.3-2.fc26.s390x
cairo-gobject-devel-1.14.10-1.fc26.s390x
fedora-rpm-macros-26-2.fc26.noarch
elfutils-devel-0.169-1.fc26.s390x
libidn-devel-1.33-2.fc26.s390x
s390utils-1.36.1-3.fc26.s390x
libtool-2.4.6-17.fc26.s390x
python3-cssselect-0.9.2-4.fc26.noarch
python2-cssselect-0.9.2-4.fc26.noarch
bison-3.0.4-6.fc26.s390x
rootfiles-8.1-20.fc26.noarch
git-core-doc-2.13.6-2.fc26.s390x
boost-system-1.63.0-10.fc26.s390x
gnutls-dane-3.5.16-4.fc26.s390x
python3-urllib3-1.20-2.fc26.noarch
libsss_autofs-1.16.0-4.fc26.s390x
libgcc-7.3.1-2.fc26.s390x
system-python-libs-3.6.4-2.fc26.s390x
pcre-cpp-8.41-5.fc26.s390x
python3-distro-1.2.0-1.fc26.noarch
libnfsidmap-2.2.1-4.rc2.fc26.s390x
selinux-policy-3.13.1-260.18.fc26.noarch
glusterfs-devel-3.10.10-1.fc26.s390x
kernel-4.15.4-200.fc26.s390x
glibc-static-2.25-13.fc26.s390x
xapian-core-libs-1.4.5-1.fc26.s390x
publicsuffix-list-dafsa-20171228-1.fc26.noarch
=== TEST BEGIN ===
Using CC: /home/fam/bin/cc
Install prefix    /var/tmp/patchew-tester-tmp-1tgugnof/src/install
BIOS directory    /var/tmp/patchew-tester-tmp-1tgugnof/src/install/share/qemu
firmware path     /var/tmp/patchew-tester-tmp-1tgugnof/src/install/share/qemu-firmware
binary directory  /var/tmp/patchew-tester-tmp-1tgugnof/src/install/bin
library directory /var/tmp/patchew-tester-tmp-1tgugnof/src/install/lib
module directory  /var/tmp/patchew-tester-tmp-1tgugnof/src/install/lib/qemu
libexec directory /var/tmp/patchew-tester-tmp-1tgugnof/src/install/libexec
include directory /var/tmp/patchew-tester-tmp-1tgugnof/src/install/include
config directory  /var/tmp/patchew-tester-tmp-1tgugnof/src/install/etc
local state directory   /var/tmp/patchew-tester-tmp-1tgugnof/src/install/var
Manual directory  /var/tmp/patchew-tester-tmp-1tgugnof/src/install/share/man
ELF interp prefix /usr/gnemul/qemu-%M
Source path       /var/tmp/patchew-tester-tmp-1tgugnof/src
GIT binary        git
GIT submodules    ui/keycodemapdb capstone
C compiler        /home/fam/bin/cc
Host C compiler   cc
C++ compiler      c++
Objective-C compiler /home/fam/bin/cc
ARFLAGS           rv
CFLAGS            -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -g 
QEMU_CFLAGS       -I/usr/include/pixman-1   -Werror -DHAS_LIBSSH2_SFTP_FSYNC -pthread -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include  -m64 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv  -Wexpansion-to-defined -Wendif-labels -Wno-shift-negative-value -Wno-missing-include-dirs -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits -fstack-protector-strong -I/usr/include/p11-kit-1     -I/usr/include/libpng16  -I/usr/include/libdrm  -I$(SRC_PATH)/capstone/include
LDFLAGS           -Wl,--warn-common -m64 -g 
make              make
install           install
python            python -B
smbd              /usr/sbin/smbd
module support    no
host CPU          s390x
host big endian   yes
target list       aarch64-softmmu alpha-softmmu arm-softmmu cris-softmmu hppa-softmmu i386-softmmu lm32-softmmu m68k-softmmu microblazeel-softmmu microblaze-softmmu mips64el-softmmu mips64-softmmu mipsel-softmmu mips-softmmu moxie-softmmu nios2-softmmu or1k-softmmu ppc64-softmmu ppcemb-softmmu ppc-softmmu riscv32-softmmu riscv64-softmmu s390x-softmmu sh4eb-softmmu sh4-softmmu sparc64-softmmu sparc-softmmu tricore-softmmu unicore32-softmmu x86_64-softmmu xtensaeb-softmmu xtensa-softmmu aarch64_be-linux-user aarch64-linux-user alpha-linux-user armeb-linux-user arm-linux-user cris-linux-user hppa-linux-user i386-linux-user m68k-linux-user microblazeel-linux-user microblaze-linux-user mips64el-linux-user mips64-linux-user mipsel-linux-user mips-linux-user mipsn32el-linux-user mipsn32-linux-user nios2-linux-user or1k-linux-user ppc64abi32-linux-user ppc64le-linux-user ppc64-linux-user ppc-linux-user riscv32-linux-user riscv64-linux-user s390x-linux-user sh4eb-linux-user sh4-linux-user sparc32plus-linux-user sparc64-linux-user sparc-linux-user tilegx-linux-user x86_64-linux-user xtensaeb-linux-user xtensa-linux-user
gprof enabled     no
sparse enabled    no
strip binaries    yes
profiler          no
static build      no
SDL support       yes (2.0.7)
GTK support       yes (3.22.21)
GTK GL support    yes
VTE support       yes (0.48.4)
TLS priority      NORMAL
GNUTLS support    yes
GNUTLS rnd        yes
libgcrypt         no
libgcrypt kdf     no
nettle            yes (3.3)
nettle kdf        yes
libtasn1          yes
curses support    yes
virgl support     yes
curl support      yes
mingw32 support   no
Audio drivers     oss
Block whitelist (rw) 
Block whitelist (ro) 
VirtFS support    yes
Multipath support no
VNC support       yes
VNC SASL support  yes
VNC JPEG support  yes
VNC PNG support   yes
xen support       no
brlapi support    yes
bluez  support    yes
Documentation     yes
PIE               no
vde support       no
netmap support    no
Linux AIO support yes
ATTR/XATTR support yes
Install blobs     yes
KVM support       yes
HAX support       no
HVF support       no
WHPX support      no
TCG support       yes
TCG debug enabled no
TCG interpreter   no
malloc trim support yes
RDMA support      no
fdt support       yes
membarrier        no
preadv support    yes
fdatasync         yes
madvise           yes
posix_madvise     yes
posix_memalign    yes
libcap-ng support yes
vhost-net support yes
vhost-crypto support yes
vhost-scsi support yes
vhost-vsock support yes
vhost-user support yes
Trace backends    log
spice support     no 
rbd support       yes
xfsctl support    no
smartcard support yes
libusb            yes
usb net redir     yes
OpenGL support    yes
OpenGL dmabufs    yes
libiscsi support  yes
libnfs support    yes
build guest agent yes
QGA VSS support   no
QGA w32 disk info no
QGA MSI support   no
seccomp support   yes
coroutine backend ucontext
coroutine pool    yes
debug stack usage no
crypto afalg      no
GlusterFS support yes
gcov              gcov
gcov enabled      no
TPM support       yes
libssh2 support   yes
TPM passthrough   no
TPM emulator      yes
QOM debugging     yes
Live block migration yes
lzo support       yes
snappy support    yes
bzip2 support     yes
NUMA host support no
libxml2           yes
tcmalloc support  no
jemalloc support  no
avx2 optimization no
replication support yes
VxHS block device no
capstone          git
  GEN     aarch64-softmmu/config-devices.mak.tmp
  GEN     alpha-softmmu/config-devices.mak.tmp
  GEN     arm-softmmu/config-devices.mak.tmp
  GEN     cris-softmmu/config-devices.mak.tmp
  GEN     cris-softmmu/config-devices.mak
  GEN     hppa-softmmu/config-devices.mak.tmp
  GEN     arm-softmmu/config-devices.mak
  GEN     alpha-softmmu/config-devices.mak
  GEN     aarch64-softmmu/config-devices.mak
  GEN     i386-softmmu/config-devices.mak.tmp
  GEN     lm32-softmmu/config-devices.mak.tmp
  GEN     m68k-softmmu/config-devices.mak.tmp
  GEN     lm32-softmmu/config-devices.mak
  GEN     m68k-softmmu/config-devices.mak
  GEN     hppa-softmmu/config-devices.mak
  GEN     microblaze-softmmu/config-devices.mak.tmp
  GEN     microblazeel-softmmu/config-devices.mak.tmp
  GEN     mips64el-softmmu/config-devices.mak.tmp
  GEN     i386-softmmu/config-devices.mak
  GEN     mips64-softmmu/config-devices.mak.tmp
  GEN     microblaze-softmmu/config-devices.mak
  GEN     microblazeel-softmmu/config-devices.mak
  GEN     mipsel-softmmu/config-devices.mak.tmp
  GEN     mips-softmmu/config-devices.mak.tmp
  GEN     mips64el-softmmu/config-devices.mak
  GEN     moxie-softmmu/config-devices.mak.tmp
  GEN     mips64-softmmu/config-devices.mak
  GEN     nios2-softmmu/config-devices.mak.tmp
  GEN     mipsel-softmmu/config-devices.mak
  GEN     moxie-softmmu/config-devices.mak
  GEN     mips-softmmu/config-devices.mak
  GEN     nios2-softmmu/config-devices.mak
  GEN     or1k-softmmu/config-devices.mak.tmp
  GEN     ppc64-softmmu/config-devices.mak.tmp
  GEN     ppcemb-softmmu/config-devices.mak.tmp
  GEN     ppc-softmmu/config-devices.mak.tmp
  GEN     or1k-softmmu/config-devices.mak
  GEN     riscv32-softmmu/config-devices.mak.tmp
  GEN     ppc-softmmu/config-devices.mak
  GEN     ppc64-softmmu/config-devices.mak
  GEN     riscv64-softmmu/config-devices.mak.tmp
  GEN     ppcemb-softmmu/config-devices.mak
  GEN     riscv32-softmmu/config-devices.mak
  GEN     s390x-softmmu/config-devices.mak.tmp
  GEN     sh4eb-softmmu/config-devices.mak.tmp
  GEN     sh4-softmmu/config-devices.mak.tmp
  GEN     riscv64-softmmu/config-devices.mak
  GEN     sparc64-softmmu/config-devices.mak.tmp
  GEN     s390x-softmmu/config-devices.mak
  GEN     sh4-softmmu/config-devices.mak
  GEN     sparc-softmmu/config-devices.mak.tmp
  GEN     tricore-softmmu/config-devices.mak.tmp
  GEN     sh4eb-softmmu/config-devices.mak
  GEN     unicore32-softmmu/config-devices.mak.tmp
  GEN     sparc64-softmmu/config-devices.mak
  GEN     sparc-softmmu/config-devices.mak
  GEN     tricore-softmmu/config-devices.mak
  GEN     x86_64-softmmu/config-devices.mak.tmp
  GEN     xtensaeb-softmmu/config-devices.mak.tmp
  GEN     xtensa-softmmu/config-devices.mak.tmp
  GEN     unicore32-softmmu/config-devices.mak
  GEN     aarch64_be-linux-user/config-devices.mak.tmp
  GEN     xtensa-softmmu/config-devices.mak
  GEN     xtensaeb-softmmu/config-devices.mak
  GEN     x86_64-softmmu/config-devices.mak
  GEN     aarch64-linux-user/config-devices.mak.tmp
  GEN     aarch64_be-linux-user/config-devices.mak
  GEN     alpha-linux-user/config-devices.mak.tmp
  GEN     armeb-linux-user/config-devices.mak.tmp
  GEN     arm-linux-user/config-devices.mak.tmp
  GEN     armeb-linux-user/config-devices.mak
  GEN     alpha-linux-user/config-devices.mak
  GEN     aarch64-linux-user/config-devices.mak
  GEN     arm-linux-user/config-devices.mak
  GEN     cris-linux-user/config-devices.mak.tmp
  GEN     hppa-linux-user/config-devices.mak.tmp
  GEN     i386-linux-user/config-devices.mak.tmp
  GEN     m68k-linux-user/config-devices.mak.tmp
  GEN     cris-linux-user/config-devices.mak
  GEN     hppa-linux-user/config-devices.mak
  GEN     i386-linux-user/config-devices.mak
  GEN     m68k-linux-user/config-devices.mak
  GEN     microblazeel-linux-user/config-devices.mak.tmp
  GEN     microblaze-linux-user/config-devices.mak.tmp
  GEN     mips64el-linux-user/config-devices.mak.tmp
  GEN     mips64-linux-user/config-devices.mak.tmp
  GEN     microblaze-linux-user/config-devices.mak
  GEN     mips64el-linux-user/config-devices.mak
  GEN     microblazeel-linux-user/config-devices.mak
  GEN     mipsel-linux-user/config-devices.mak.tmp
  GEN     mips-linux-user/config-devices.mak.tmp
  GEN     mipsn32el-linux-user/config-devices.mak.tmp
  GEN     mips64-linux-user/config-devices.mak
  GEN     mipsn32-linux-user/config-devices.mak.tmp
  GEN     mipsn32el-linux-user/config-devices.mak
  GEN     mipsel-linux-user/config-devices.mak
  GEN     mips-linux-user/config-devices.mak
  GEN     nios2-linux-user/config-devices.mak.tmp
  GEN     or1k-linux-user/config-devices.mak.tmp
  GEN     mipsn32-linux-user/config-devices.mak
  GEN     ppc64abi32-linux-user/config-devices.mak.tmp
  GEN     ppc64le-linux-user/config-devices.mak.tmp
  GEN     nios2-linux-user/config-devices.mak
  GEN     or1k-linux-user/config-devices.mak
  GEN     ppc64-linux-user/config-devices.mak.tmp
  GEN     ppc64abi32-linux-user/config-devices.mak
  GEN     ppc-linux-user/config-devices.mak.tmp
  GEN     ppc64le-linux-user/config-devices.mak
  GEN     riscv32-linux-user/config-devices.mak.tmp
  GEN     riscv64-linux-user/config-devices.mak.tmp
  GEN     ppc64-linux-user/config-devices.mak
  GEN     ppc-linux-user/config-devices.mak
  GEN     s390x-linux-user/config-devices.mak.tmp
  GEN     sh4eb-linux-user/config-devices.mak.tmp
  GEN     riscv32-linux-user/config-devices.mak
  GEN     riscv64-linux-user/config-devices.mak
  GEN     s390x-linux-user/config-devices.mak
  GEN     sh4-linux-user/config-devices.mak.tmp
  GEN     sparc32plus-linux-user/config-devices.mak.tmp
  GEN     sparc64-linux-user/config-devices.mak.tmp
  GEN     sh4eb-linux-user/config-devices.mak
  GEN     sh4-linux-user/config-devices.mak
  GEN     sparc-linux-user/config-devices.mak.tmp
  GEN     sparc32plus-linux-user/config-devices.mak
  GEN     tilegx-linux-user/config-devices.mak.tmp
  GEN     sparc64-linux-user/config-devices.mak
  GEN     x86_64-linux-user/config-devices.mak.tmp
  GEN     xtensaeb-linux-user/config-devices.mak.tmp
  GEN     tilegx-linux-user/config-devices.mak
  GEN     sparc-linux-user/config-devices.mak
  GEN     xtensa-linux-user/config-devices.mak.tmp
  GEN     x86_64-linux-user/config-devices.mak
  GEN     xtensaeb-linux-user/config-devices.mak
  GEN     config-host.h
  GIT     ui/keycodemapdb capstone
  GEN     xtensa-linux-user/config-devices.mak
  GEN     qemu-options.def
  GEN     qapi-gen
  GEN     trace/generated-tcg-tracers.h
  GEN     trace/generated-helpers-wrappers.h
  GEN     trace/generated-helpers.h
  GEN     trace/generated-helpers.c
  GEN     module_block.h
  GEN     trace-root.h
  GEN     tests/test-qapi-gen
  GEN     util/trace.h
Submodule 'capstone' (git://git.qemu.org/capstone.git) registered for path 'capstone'
Submodule 'ui/keycodemapdb' (git://git.qemu.org/keycodemapdb.git) registered for path 'ui/keycodemapdb'
  GEN     crypto/trace.h
Cloning into '/var/tmp/patchew-tester-tmp-1tgugnof/src/capstone'...
  GEN     io/trace.h
  GEN     migration/trace.h
  GEN     block/trace.h
  GEN     chardev/trace.h
  GEN     hw/block/trace.h
  GEN     hw/block/dataplane/trace.h
  GEN     hw/char/trace.h
  GEN     hw/intc/trace.h
  GEN     hw/net/trace.h
  GEN     hw/rdma/trace.h
  GEN     hw/rdma/vmw/trace.h
  GEN     hw/virtio/trace.h
  GEN     hw/audio/trace.h
  GEN     hw/misc/trace.h
  GEN     hw/misc/macio/trace.h
  GEN     hw/usb/trace.h
  GEN     hw/scsi/trace.h
  GEN     hw/nvram/trace.h
  GEN     hw/display/trace.h
  GEN     hw/input/trace.h
  GEN     hw/timer/trace.h
  GEN     hw/dma/trace.h
  GEN     hw/sparc/trace.h
  GEN     hw/sparc64/trace.h
  GEN     hw/sd/trace.h
  GEN     hw/isa/trace.h
  GEN     hw/mem/trace.h
  GEN     hw/i386/trace.h
  GEN     hw/i386/xen/trace.h
  GEN     hw/9pfs/trace.h
  GEN     hw/ppc/trace.h
  GEN     hw/pci/trace.h
  GEN     hw/pci-host/trace.h
  GEN     hw/s390x/trace.h
  GEN     hw/vfio/trace.h
  GEN     hw/acpi/trace.h
  GEN     hw/arm/trace.h
  GEN     hw/alpha/trace.h
  GEN     hw/hppa/trace.h
  GEN     hw/xen/trace.h
  GEN     hw/ide/trace.h
  GEN     hw/tpm/trace.h
  GEN     ui/trace.h
  GEN     audio/trace.h
  GEN     net/trace.h
  GEN     target/arm/trace.h
  GEN     target/i386/trace.h
  GEN     target/mips/trace.h
  GEN     target/sparc/trace.h
  GEN     target/s390x/trace.h
  GEN     target/ppc/trace.h
  GEN     qom/trace.h
  GEN     linux-user/trace.h
  GEN     qapi/trace.h
  GEN     accel/tcg/trace.h
  GEN     accel/kvm/trace.h
  GEN     nbd/trace.h
  GEN     scsi/trace.h
  GEN     trace-root.c
  GEN     util/trace.c
  GEN     crypto/trace.c
  GEN     io/trace.c
  GEN     migration/trace.c
  GEN     block/trace.c
  GEN     chardev/trace.c
  GEN     hw/block/trace.c
  GEN     hw/block/dataplane/trace.c
  GEN     hw/char/trace.c
  GEN     hw/intc/trace.c
  GEN     hw/net/trace.c
  GEN     hw/rdma/trace.c
  GEN     hw/rdma/vmw/trace.c
  GEN     hw/virtio/trace.c
  GEN     hw/audio/trace.c
  GEN     hw/misc/trace.c
  GEN     hw/misc/macio/trace.c
  GEN     hw/usb/trace.c
  GEN     hw/scsi/trace.c
  GEN     hw/nvram/trace.c
  GEN     hw/display/trace.c
  GEN     hw/input/trace.c
  GEN     hw/timer/trace.c
  GEN     hw/dma/trace.c
  GEN     hw/sparc/trace.c
  GEN     hw/sparc64/trace.c
  GEN     hw/sd/trace.c
  GEN     hw/isa/trace.c
  GEN     hw/mem/trace.c
  GEN     hw/i386/trace.c
  GEN     hw/i386/xen/trace.c
  GEN     hw/9pfs/trace.c
  GEN     hw/ppc/trace.c
  GEN     hw/pci/trace.c
  GEN     hw/pci-host/trace.c
  GEN     hw/s390x/trace.c
  GEN     hw/vfio/trace.c
  GEN     hw/acpi/trace.c
  GEN     hw/arm/trace.c
  GEN     hw/alpha/trace.c
  GEN     hw/hppa/trace.c
  GEN     hw/xen/trace.c
  GEN     hw/ide/trace.c
  GEN     hw/tpm/trace.c
  GEN     ui/trace.c
  GEN     audio/trace.c
  GEN     net/trace.c
  GEN     target/arm/trace.c
  GEN     target/i386/trace.c
  GEN     target/mips/trace.c
  GEN     target/sparc/trace.c
  GEN     target/s390x/trace.c
  GEN     target/ppc/trace.c
  GEN     qom/trace.c
  GEN     linux-user/trace.c
  GEN     qapi/trace.c
  GEN     accel/tcg/trace.c
  GEN     accel/kvm/trace.c
  GEN     nbd/trace.c
  GEN     scsi/trace.c
  GEN     config-all-devices.mak
Cloning into '/var/tmp/patchew-tester-tmp-1tgugnof/src/ui/keycodemapdb'...
  GEN     ui/input-keymap-atset1-to-qcode.c
  GEN     ui/input-keymap-linux-to-qcode.c
  GEN     ui/input-keymap-qcode-to-atset1.c
  GEN     ui/input-keymap-qcode-to-atset2.c
  GEN     ui/input-keymap-qcode-to-atset3.c
  GEN     ui/input-keymap-qcode-to-linux.c
  CC      cs.o
  GEN     ui/input-keymap-qcode-to-qnum.c
  GEN     ui/input-keymap-qcode-to-sun.c
  GEN     ui/input-keymap-qnum-to-qcode.c
  GEN     ui/input-keymap-usb-to-qcode.c
  GEN     ui/input-keymap-win32-to-qcode.c
  CC      utils.o
  GEN     ui/input-keymap-x11-to-qcode.c
  CC      SStream.o
  CC      MCInstrDesc.o
  CC      MCRegisterInfo.o
  GEN     ui/input-keymap-xorgevdev-to-qcode.c
  CC      arch/ARM/ARMDisassembler.o
  GEN     ui/input-keymap-xorgkbd-to-qcode.c
  GEN     ui/input-keymap-xorgxquartz-to-qcode.c
  GEN     ui/input-keymap-xorgxwin-to-qcode.c
  CC      arch/ARM/ARMInstPrinter.o
  CC      arch/ARM/ARMMapping.o
  CC      arch/ARM/ARMModule.o
  CC      arch/AArch64/AArch64BaseInfo.o
  CC      arch/AArch64/AArch64Disassembler.o
  CC      arch/AArch64/AArch64InstPrinter.o
  CC      arch/AArch64/AArch64Mapping.o
  CC      arch/AArch64/AArch64Module.o
  CC      arch/Mips/MipsDisassembler.o
  CC      arch/Mips/MipsInstPrinter.o
  CC      arch/Mips/MipsMapping.o
  CC      arch/Mips/MipsModule.o
  CC      arch/PowerPC/PPCDisassembler.o
  CC      arch/PowerPC/PPCInstPrinter.o
  CC      arch/PowerPC/PPCMapping.o
  CC      arch/PowerPC/PPCModule.o
  CC      arch/Sparc/SparcDisassembler.o
  CC      arch/Sparc/SparcInstPrinter.o
  CC      arch/Sparc/SparcMapping.o
  CC      arch/Sparc/SparcModule.o
  CC      arch/SystemZ/SystemZDisassembler.o
  CC      arch/SystemZ/SystemZInstPrinter.o
  CC      arch/SystemZ/SystemZMapping.o
  CC      arch/SystemZ/SystemZModule.o
  CC      arch/SystemZ/SystemZMCTargetDesc.o
  CC      arch/X86/X86DisassemblerDecoder.o
  CC      arch/X86/X86Disassembler.o
  CC      arch/X86/X86IntelInstPrinter.o
  CC      arch/X86/X86ATTInstPrinter.o
  CC      arch/X86/X86Mapping.o
  CC      arch/X86/X86Module.o
  CC      arch/XCore/XCoreDisassembler.o
  CC      arch/XCore/XCoreInstPrinter.o
  CC      arch/XCore/XCoreMapping.o
  CC      arch/XCore/XCoreModule.o
  CC      MCInst.o
  AR      libcapstone.a
ar: creating /var/tmp/patchew-tester-tmp-1tgugnof/src/build/capstone/libcapstone.a
  GEN     docs/version.texi
  GEN     qemu-options.texi
  CC      tests/qemu-iotests/socket_scm_helper.o
  GEN     qemu-monitor.texi
  GEN     qemu-img-cmds.texi
  GEN     qemu-monitor-info.texi
  GEN     qemu-img.1
  GEN     qemu-nbd.8
  GEN     qemu-ga.8
  GEN     qga/qapi-generated/qapi-gen
  GEN     docs/qemu-block-drivers.7
  GEN     fsdev/virtfs-proxy-helper.1
  CC      qapi/qapi-builtin-types.o
  CC      qapi/qapi-types.o
  CC      qapi/qapi-types-block-core.o
  CC      qapi/qapi-types-block.o
In file included from /var/tmp/patchew-tester-tmp-1tgugnof/src/include/qapi/dealloc-visitor.h:17:0,
                 from qapi/qapi-builtin-types.c:14:
/var/tmp/patchew-tester-tmp-1tgugnof/src/include/qapi/visitor.h:243:5: error: unknown type name ‘QType’
     QType type;
     ^~~~~
make: *** [/var/tmp/patchew-tester-tmp-1tgugnof/src/rules.mak:66: qapi/qapi-builtin-types.o] Error 1
make: *** Waiting for unfinished jobs....
In file included from /var/tmp/patchew-tester-tmp-1tgugnof/src/include/qapi/dealloc-visitor.h:17:0,
                 from qapi/qapi-types.c:14:
/var/tmp/patchew-tester-tmp-1tgugnof/src/include/qapi/visitor.h:243:5: error: unknown type name ‘QType’
     QType type;
     ^~~~~
In file included from qapi/qapi-types.h:17:0,
                 from qapi/qapi-types.c:15:
qapi/qapi-types-common.h:95:5: error: unknown type name ‘QType’
     QType type;
     ^~~~~
In file included from qapi/qapi-types-block.h:17:0,
                 from qapi/qapi-types.h:21,
                 from qapi/qapi-types.c:15:
qapi/qapi-types-block-core.h:1018:5: error: unknown type name ‘uint64List’
     uint64List *boundaries;
     ^~~~~~~~~~
qapi/qapi-types-block-core.h:1019:5: error: unknown type name ‘uint64List’
     uint64List *bins;
     ^~~~~~~~~~
qapi/qapi-types-block-core.h:1027:5: error: unknown type name ‘uint64List’
     uint64List *boundaries;
     ^~~~~~~~~~
qapi/qapi-types-block-core.h:1029:5: error: unknown type name ‘uint64List’
     uint64List *boundaries_read;
     ^~~~~~~~~~
qapi/qapi-types-block-core.h:1031:5: error: unknown type name ‘uint64List’
     uint64List *boundaries_write;
     ^~~~~~~~~~
qapi/qapi-types-block-core.h:1033:5: error: unknown type name ‘uint64List’
     uint64List *boundaries_flush;
     ^~~~~~~~~~
qapi/qapi-types-block-core.h:1623:5: error: unknown type name ‘QType’
     QType type;
     ^~~~~
qapi/qapi-types-block-core.h:2213:5: error: unknown type name ‘QType’
     QType type;
     ^~~~~
qapi/qapi-types-block-core.h:2225:5: error: unknown type name ‘QType’
     QType type;
     ^~~~~
In file included from qapi/qapi-types.h:23:0,
                 from qapi/qapi-types.c:15:
qapi/qapi-types-net.h:416:5: error: unknown type name ‘intList’
     intList *vlan_table;
     ^~~~~~~
qapi/qapi-types-net.h:417:5: error: unknown type name ‘strList’
     strList *unicast_table;
     ^~~~~~~
qapi/qapi-types-net.h:418:5: error: unknown type name ‘strList’
     strList *multicast_table;
     ^~~~~~~
In file included from qapi/qapi-types.h:24:0,
                 from qapi/qapi-types.c:15:
qapi/qapi-types-rocker.h:204:5: error: unknown type name ‘uint32List’
     uint32List *group_ids;
     ^~~~~~~~~~
In file included from qapi/qapi-types.h:30:0,
                 from qapi/qapi-types.c:15:
qapi/qapi-types-introspect.h:100:5: error: unknown type name ‘strList’
     strList *values;
     ^~~~~~~
In file included from qapi/qapi-types.h:31:0,
                 from qapi/qapi-types.c:15:
qapi/qapi-types-misc.h:993:5: error: unknown type name ‘strList’
     strList *unavailable_features;
     ^~~~~~~
qapi/qapi-types-misc.h:1023:5: error: unknown type name ‘strList’
     strList *responsible_properties;
     ^~~~~~~
qapi/qapi-types-misc.h:1180:5: error: unknown type name ‘uint16List’
     uint16List *cpus;
     ^~~~~~~~~~
qapi/qapi-types-misc.h:1235:5: error: unknown type name ‘uint16List’
     uint16List *host_nodes;
     ^~~~~~~~~~
make: *** [/var/tmp/patchew-tester-tmp-1tgugnof/src/rules.mak:66: qapi/qapi-types.o] Error 1
In file included from /var/tmp/patchew-tester-tmp-1tgugnof/src/include/qapi/dealloc-visitor.h:17:0,
                 from qapi/qapi-types-block-core.c:14:
/var/tmp/patchew-tester-tmp-1tgugnof/src/include/qapi/visitor.h:243:5: error: unknown type name ‘QType’
     QType type;
     ^~~~~
In file included from qapi/qapi-types-block-core.h:17:0,
                 from qapi/qapi-types-block-core.c:15:
qapi/qapi-types-common.h:95:5: error: unknown type name ‘QType’
     QType type;
     ^~~~~
In file included from qapi/qapi-types-block-core.c:15:0:
qapi/qapi-types-block-core.h:1018:5: error: unknown type name ‘uint64List’
     uint64List *boundaries;
     ^~~~~~~~~~
qapi/qapi-types-block-core.h:1019:5: error: unknown type name ‘uint64List’
     uint64List *bins;
     ^~~~~~~~~~
qapi/qapi-types-block-core.h:1027:5: error: unknown type name ‘uint64List’
     uint64List *boundaries;
     ^~~~~~~~~~
qapi/qapi-types-block-core.h:1029:5: error: unknown type name ‘uint64List’
     uint64List *boundaries_read;
     ^~~~~~~~~~
qapi/qapi-types-block-core.h:1031:5: error: unknown type name ‘uint64List’
     uint64List *boundaries_write;
     ^~~~~~~~~~
qapi/qapi-types-block-core.h:1033:5: error: unknown type name ‘uint64List’
     uint64List *boundaries_flush;
     ^~~~~~~~~~
qapi/qapi-types-block-core.h:1623:5: error: unknown type name ‘QType’
     QType type;
     ^~~~~
qapi/qapi-types-block-core.h:2213:5: error: unknown type name ‘QType’
     QType type;
     ^~~~~
qapi/qapi-types-block-core.h:2225:5: error: unknown type name ‘QType’
     QType type;
     ^~~~~
make: *** [/var/tmp/patchew-tester-tmp-1tgugnof/src/rules.mak:66: qapi/qapi-types-block-core.o] Error 1
In file included from /var/tmp/patchew-tester-tmp-1tgugnof/src/include/qapi/dealloc-visitor.h:17:0,
                 from qapi/qapi-types-block.c:14:
/var/tmp/patchew-tester-tmp-1tgugnof/src/include/qapi/visitor.h:243:5: error: unknown type name ‘QType’
     QType type;
     ^~~~~
In file included from qapi/qapi-types-block-core.h:17:0,
                 from qapi/qapi-types-block.h:17,
                 from qapi/qapi-types-block.c:15:
qapi/qapi-types-common.h:95:5: error: unknown type name ‘QType’
     QType type;
     ^~~~~
In file included from qapi/qapi-types-block.h:17:0,
                 from qapi/qapi-types-block.c:15:
qapi/qapi-types-block-core.h:1018:5: error: unknown type name ‘uint64List’
     uint64List *boundaries;
     ^~~~~~~~~~
qapi/qapi-types-block-core.h:1019:5: error: unknown type name ‘uint64List’
     uint64List *bins;
     ^~~~~~~~~~
qapi/qapi-types-block-core.h:1027:5: error: unknown type name ‘uint64List’
     uint64List *boundaries;
     ^~~~~~~~~~
qapi/qapi-types-block-core.h:1029:5: error: unknown type name ‘uint64List’
     uint64List *boundaries_read;
     ^~~~~~~~~~
qapi/qapi-types-block-core.h:1031:5: error: unknown type name ‘uint64List’
     uint64List *boundaries_write;
     ^~~~~~~~~~
qapi/qapi-types-block-core.h:1033:5: error: unknown type name ‘uint64List’
     uint64List *boundaries_flush;
     ^~~~~~~~~~
qapi/qapi-types-block-core.h:1623:5: error: unknown type name ‘QType’
     QType type;
     ^~~~~
qapi/qapi-types-block-core.h:2213:5: error: unknown type name ‘QType’
     QType type;
     ^~~~~
qapi/qapi-types-block-core.h:2225:5: error: unknown type name ‘QType’
     QType type;
     ^~~~~
make: *** [/var/tmp/patchew-tester-tmp-1tgugnof/src/rules.mak:66: qapi/qapi-types-block.o] Error 1
=== OUTPUT END ===

Test command exited with code: 2


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (49 preceding siblings ...)
  2018-03-21 12:47 ` [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code no-reply
@ 2018-03-21 14:20 ` no-reply
  2018-03-21 22:08 ` no-reply
                   ` (2 subsequent siblings)
  53 siblings, 0 replies; 95+ messages in thread
From: no-reply @ 2018-03-21 14:20 UTC (permalink / raw)
  To: marcandre.lureau; +Cc: famz, qemu-devel, armbru

Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20180321115211.17937-1-marcandre.lureau@redhat.com
Subject: [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
    echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
    if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
        failed=1
        echo
    fi
    n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
ca50a2d8e3 RFC: make RTC_CHANGE per-target
032f3d2f59 qapi: remove qmp_unregister_command()
7a4b17cf54 qapi: make query-cpu-definitions depend on specific targets
557f536176 qapi: make query-cpu-model-expansion depend on s390 or x86
dc1b218319 qapi: make query-gic-capabilities depend on TARGET_ARM
af9625c6c3 target.json: add a note about query-cpu* not being s390x-specific
c9801977e9 qapi: make s390 commands depend on TARGET_S390X
6a49803445 qapi: make rtc-reset-reinjection and SEV depend on TARGET_I386
13b093aaae qapi: add a top-unit 'target' schema
8e42b4bfd8 RFC: qapi: learn to split schema by 'top-unit'
2984459cd6 qapi-commands: don't initialize command list in qmp_init_marshall()
7c39c807b5 build-sys: move qmp-introspect per target
af7d5d518d qapi: add conditions to REPLICATION type/commands on the schema
9e583d1a1d qapi: add conditions to SPICE type/commands/events on the schema
8bc16dec62 qapi: add conditions to VNC type/commands/events on the schema
72664dbe15 qapi2texi: add condition to variants
d7ff0ab4ef qapi2texi: add 'If:' condition to struct members
bde44a6b1d qapi2texi: add 'If:' condition to enum values
c87e1bc65f qapi2texi: add 'If:' section to generated documentation
3364d5099f docs: document schema configuration
77f7bafdc4 qapi: add #if conditions to generated code members
a95929de93 qapi: add 'if' to alternate members
b205d6198c qapi: add 'if' on union members
9613ba2cc2 qapi: add an error in case a discriminator is conditionnal
cd025039c0 qapi: add 'if' to implicit struct members
6799c824a8 qapi: add a dictionary form with 'type' key for members
c5b50ed9e3 qapi: rename allow_dict to allow_implicit
ba4011e602 qapi-event: add 'if' condition to implicit event enum
7d828e85b9 qapi: add 'if' to enum members
a20c2dc973 qapi: add a dictionnary form with 'name' key for enum members
061635eff1 qapi: factor out check_known_keys()
b0ad9a471a tests: modify visit_enum_type() in test-qapi to print members
86933fb39c qapi: change enum visitor to take QAPISchemaMember
cd6fb8e83f qapi: rename QAPISchemaEnumType.values to .members
31ea46dcec qapi: do not define enumeration value explicitely
55c7453f3c qapi-types: add #if conditions to types & visitors
4507e44d86 qapi-types: refactor variants handling
9c91a8fa1d qapi/events: add #if conditions to events
7ba12f474f qapi/commands: add #if conditions to commands
fcf4dfeb56 qapi-introspect: add preprocessor conditions to generated QLit
51163f6ba0 qapi-introspect: modify to_qlit() to append ', ' on level > 0
75baac460c qapi: add #if/#endif helpers
a001949a31 qapi: mcgen() shouldn't indent # lines
a2ef5afa63 qapi: add 'ifcond' to visitor methods
688755b5fd qapi: leave the ifcond attribute undefined until check()
0566f4cb49 qapi: pass 'if' condition into QAPISchemaEntity objects
7b98d1b34c qapi: add 'if' to top-level expressions
6c36d8fa28 qapi/events: generate event enum in main module
7ced623f53 qapi/visit: remove useless prefix argument

=== OUTPUT BEGIN ===
Checking PATCH 1/49: qapi/visit: remove useless prefix argument...
Checking PATCH 2/49: qapi/events: generate event enum in main module...
Checking PATCH 3/49: qapi: add 'if' to top-level expressions...
Checking PATCH 4/49: qapi: pass 'if' condition into QAPISchemaEntity objects...
Checking PATCH 5/49: qapi: leave the ifcond attribute undefined until check()...
Checking PATCH 6/49: qapi: add 'ifcond' to visitor methods...
Checking PATCH 7/49: qapi: mcgen() shouldn't indent # lines...
Checking PATCH 8/49: qapi: add #if/#endif helpers...
Checking PATCH 9/49: qapi-introspect: modify to_qlit() to append ', ' on level > 0...
Checking PATCH 10/49: qapi-introspect: add preprocessor conditions to generated QLit...
Checking PATCH 11/49: qapi/commands: add #if conditions to commands...
WARNING: line over 80 characters
#53: FILE: scripts/qapi/commands.py:289:
+            self._regy.add(gen_register_command(name, success_response, allow_oob))

total: 0 errors, 1 warnings, 49 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Checking PATCH 12/49: qapi/events: add #if conditions to events...
WARNING: line over 80 characters
#27: FILE: scripts/qapi/events.py:190:
+            self._genc.add(gen_event_send(name, arg_type, boxed, self._enum_name))

total: 0 errors, 1 warnings, 11 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Checking PATCH 13/49: qapi-types: refactor variants handling...
Checking PATCH 14/49: qapi-types: add #if conditions to types & visitors...
Checking PATCH 15/49: qapi: do not define enumeration value explicitely...
Checking PATCH 16/49: qapi: rename QAPISchemaEnumType.values to .members...
Checking PATCH 17/49: qapi: change enum visitor to take QAPISchemaMember...
Checking PATCH 18/49: tests: modify visit_enum_type() in test-qapi to print members...
Checking PATCH 19/49: qapi: factor out check_known_keys()...
Checking PATCH 20/49: qapi: add a dictionnary form with 'name' key for enum members...
Checking PATCH 21/49: qapi: add 'if' to enum members...
Checking PATCH 22/49: qapi-event: add 'if' condition to implicit event enum...
Checking PATCH 23/49: qapi: rename allow_dict to allow_implicit...
Checking PATCH 24/49: qapi: add a dictionary form with 'type' key for members...
Checking PATCH 25/49: qapi: add 'if' to implicit struct members...
Checking PATCH 26/49: qapi: add an error in case a discriminator is conditionnal...
Checking PATCH 27/49: qapi: add 'if' on union members...
Checking PATCH 28/49: qapi: add 'if' to alternate members...
Checking PATCH 29/49: qapi: add #if conditions to generated code members...
Checking PATCH 30/49: docs: document schema configuration...
Checking PATCH 31/49: qapi2texi: add 'If:' section to generated documentation...
Checking PATCH 32/49: qapi2texi: add 'If:' condition to enum values...
Checking PATCH 33/49: qapi2texi: add 'If:' condition to struct members...
Checking PATCH 34/49: qapi2texi: add condition to variants...
Checking PATCH 35/49: qapi: add conditions to VNC type/commands/events on the schema...
Checking PATCH 36/49: qapi: add conditions to SPICE type/commands/events on the schema...
Checking PATCH 37/49: qapi: add conditions to REPLICATION type/commands on the schema...
Checking PATCH 38/49: build-sys: move qmp-introspect per target...
Checking PATCH 39/49: qapi-commands: don't initialize command list in qmp_init_marshall()...
Checking PATCH 40/49: RFC: qapi: learn to split schema by 'top-unit'...
WARNING: line over 80 characters
#102: FILE: scripts/qapi/common.py:304:
+                        incl_info['has-pragma-top-unit'] = exprs_include._top_unit

WARNING: line over 80 characters
#340: FILE: scripts/qapi/events.py:165:
+        self._enum_name = c_name(self._prefix_unit() + 'QAPIEvent', protect=False)

total: 0 errors, 2 warnings, 350 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Checking PATCH 41/49: qapi: add a top-unit 'target' schema...
Checking PATCH 42/49: qapi: make rtc-reset-reinjection and SEV depend on TARGET_I386...
Checking PATCH 43/49: qapi: make s390 commands depend on TARGET_S390X...
Checking PATCH 44/49: target.json: add a note about query-cpu* not being s390x-specific...
Checking PATCH 45/49: qapi: make query-gic-capabilities depend on TARGET_ARM...
Checking PATCH 46/49: qapi: make query-cpu-model-expansion depend on s390 or x86...
Checking PATCH 47/49: qapi: make query-cpu-definitions depend on specific targets...
Checking PATCH 48/49: qapi: remove qmp_unregister_command()...
Checking PATCH 49/49: RFC: make RTC_CHANGE per-target...
ERROR: line over 90 characters
#65: FILE: monitor.c:682:
+#if defined(TARGET_ALPHA) || defined(TARGET_ARM) || defined(TARGET_HPPA) || defined(TARGET_I386) || defined(TARGET_MIPS) | defined(TARGET_MIPS64) || defined(TARGET_MOXIE) || defined(TARGET_PPC) || defined(TARGET_PPC64) || defined(TARGET_S390X) || defined(TARGET_SH4) || defined(TARGET_SPARC)

total: 1 errors, 0 warnings, 89 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

=== OUTPUT END ===

Test command exited with code: 1


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (50 preceding siblings ...)
  2018-03-21 14:20 ` no-reply
@ 2018-03-21 22:08 ` no-reply
  2018-03-22  5:11 ` no-reply
  2018-06-21 16:47 ` Markus Armbruster
  53 siblings, 0 replies; 95+ messages in thread
From: no-reply @ 2018-03-21 22:08 UTC (permalink / raw)
  To: marcandre.lureau; +Cc: famz, qemu-devel, armbru

Hi,

This series failed docker-quick@centos6 build test. Please find the testing commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

Type: series
Message-id: 20180321115211.17937-1-marcandre.lureau@redhat.com
Subject: [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code

=== TEST SCRIPT BEGIN ===
#!/bin/bash
set -e
git submodule update --init dtc
# Let docker tests dump environment info
export SHOW_ENV=1
export J=8
time make docker-test-quick@centos6
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]               patchew/1521665220-3869-1-git-send-email-mjc@sifive.com -> patchew/1521665220-3869-1-git-send-email-mjc@sifive.com
 * [new tag]               patchew/20180321211056.3339-1-yuval.shaia@oracle.com -> patchew/20180321211056.3339-1-yuval.shaia@oracle.com
Switched to a new branch 'test'
ca50a2d8e3 RFC: make RTC_CHANGE per-target
032f3d2f59 qapi: remove qmp_unregister_command()
7a4b17cf54 qapi: make query-cpu-definitions depend on specific targets
557f536176 qapi: make query-cpu-model-expansion depend on s390 or x86
dc1b218319 qapi: make query-gic-capabilities depend on TARGET_ARM
af9625c6c3 target.json: add a note about query-cpu* not being s390x-specific
c9801977e9 qapi: make s390 commands depend on TARGET_S390X
6a49803445 qapi: make rtc-reset-reinjection and SEV depend on TARGET_I386
13b093aaae qapi: add a top-unit 'target' schema
8e42b4bfd8 RFC: qapi: learn to split schema by 'top-unit'
2984459cd6 qapi-commands: don't initialize command list in qmp_init_marshall()
7c39c807b5 build-sys: move qmp-introspect per target
af7d5d518d qapi: add conditions to REPLICATION type/commands on the schema
9e583d1a1d qapi: add conditions to SPICE type/commands/events on the schema
8bc16dec62 qapi: add conditions to VNC type/commands/events on the schema
72664dbe15 qapi2texi: add condition to variants
d7ff0ab4ef qapi2texi: add 'If:' condition to struct members
bde44a6b1d qapi2texi: add 'If:' condition to enum values
c87e1bc65f qapi2texi: add 'If:' section to generated documentation
3364d5099f docs: document schema configuration
77f7bafdc4 qapi: add #if conditions to generated code members
a95929de93 qapi: add 'if' to alternate members
b205d6198c qapi: add 'if' on union members
9613ba2cc2 qapi: add an error in case a discriminator is conditionnal
cd025039c0 qapi: add 'if' to implicit struct members
6799c824a8 qapi: add a dictionary form with 'type' key for members
c5b50ed9e3 qapi: rename allow_dict to allow_implicit
ba4011e602 qapi-event: add 'if' condition to implicit event enum
7d828e85b9 qapi: add 'if' to enum members
a20c2dc973 qapi: add a dictionnary form with 'name' key for enum members
061635eff1 qapi: factor out check_known_keys()
b0ad9a471a tests: modify visit_enum_type() in test-qapi to print members
86933fb39c qapi: change enum visitor to take QAPISchemaMember
cd6fb8e83f qapi: rename QAPISchemaEnumType.values to .members
31ea46dcec qapi: do not define enumeration value explicitely
55c7453f3c qapi-types: add #if conditions to types & visitors
4507e44d86 qapi-types: refactor variants handling
9c91a8fa1d qapi/events: add #if conditions to events
7ba12f474f qapi/commands: add #if conditions to commands
fcf4dfeb56 qapi-introspect: add preprocessor conditions to generated QLit
51163f6ba0 qapi-introspect: modify to_qlit() to append ', ' on level > 0
75baac460c qapi: add #if/#endif helpers
a001949a31 qapi: mcgen() shouldn't indent # lines
a2ef5afa63 qapi: add 'ifcond' to visitor methods
688755b5fd qapi: leave the ifcond attribute undefined until check()
0566f4cb49 qapi: pass 'if' condition into QAPISchemaEntity objects
7b98d1b34c qapi: add 'if' to top-level expressions
6c36d8fa28 qapi/events: generate event enum in main module
7ced623f53 qapi/visit: remove useless prefix argument

=== OUTPUT BEGIN ===
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into '/var/tmp/patchew-tester-tmp-_42j_rgl/src/dtc'...
Submodule path 'dtc': checked out 'e54388015af1fb4bf04d0bca99caba1074d9cc42'
  BUILD   centos6
make[1]: Entering directory '/var/tmp/patchew-tester-tmp-_42j_rgl/src'
  GEN     /var/tmp/patchew-tester-tmp-_42j_rgl/src/docker-src.2018-03-21-18.07.28.25329/qemu.tar
Cloning into '/var/tmp/patchew-tester-tmp-_42j_rgl/src/docker-src.2018-03-21-18.07.28.25329/qemu.tar.vroot'...
done.
Your branch is up-to-date with 'origin/test'.
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into '/var/tmp/patchew-tester-tmp-_42j_rgl/src/docker-src.2018-03-21-18.07.28.25329/qemu.tar.vroot/dtc'...
Submodule path 'dtc': checked out 'e54388015af1fb4bf04d0bca99caba1074d9cc42'
Submodule 'ui/keycodemapdb' (git://git.qemu.org/keycodemapdb.git) registered for path 'ui/keycodemapdb'
Cloning into '/var/tmp/patchew-tester-tmp-_42j_rgl/src/docker-src.2018-03-21-18.07.28.25329/qemu.tar.vroot/ui/keycodemapdb'...
Submodule path 'ui/keycodemapdb': checked out '6b3d716e2b6472eb7189d3220552280ef3d832ce'
  COPY    RUNNER
    RUN test-quick in qemu:centos6 
Packages installed:
SDL-devel-1.2.14-7.el6_7.1.x86_64
bison-2.4.1-5.el6.x86_64
bzip2-devel-1.0.5-7.el6_0.x86_64
ccache-3.1.6-2.el6.x86_64
csnappy-devel-0-6.20150729gitd7bc683.el6.x86_64
flex-2.5.35-9.el6.x86_64
gcc-4.4.7-18.el6.x86_64
gettext-0.17-18.el6.x86_64
git-1.7.1-9.el6_9.x86_64
glib2-devel-2.28.8-9.el6.x86_64
libepoxy-devel-1.2-3.el6.x86_64
libfdt-devel-1.4.0-1.el6.x86_64
librdmacm-devel-1.0.21-0.el6.x86_64
lzo-devel-2.03-3.1.el6_5.1.x86_64
make-3.81-23.el6.x86_64
mesa-libEGL-devel-11.0.7-4.el6.x86_64
mesa-libgbm-devel-11.0.7-4.el6.x86_64
package g++ is not installed
pixman-devel-0.32.8-1.el6.x86_64
spice-glib-devel-0.26-8.el6.x86_64
spice-server-devel-0.12.4-16.el6.x86_64
tar-1.23-15.el6_8.x86_64
vte-devel-0.25.1-9.el6.x86_64
xen-devel-4.6.6-2.el6.x86_64
zlib-devel-1.2.3-29.el6.x86_64

Environment variables:
PACKAGES=bison     bzip2-devel     ccache     csnappy-devel     flex     g++     gcc     gettext     git     glib2-devel     libepoxy-devel     libfdt-devel     librdmacm-devel     lzo-devel     make     mesa-libEGL-devel     mesa-libgbm-devel     pixman-devel     SDL-devel     spice-glib-devel     spice-server-devel     tar     vte-devel     xen-devel     zlib-devel
HOSTNAME=82b26ca1d6f9
MAKEFLAGS= -j8
J=8
CCACHE_DIR=/var/tmp/ccache
EXTRA_CONFIGURE_OPTS=
V=
SHOW_ENV=1
PATH=/usr/lib/ccache:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
TARGET_LIST=
SHLVL=1
HOME=/root
TEST_DIR=/tmp/qemu-test
FEATURES= dtc
DEBUG=
_=/usr/bin/env

Configure options:
--enable-werror --target-list=x86_64-softmmu,aarch64-softmmu --prefix=/tmp/qemu-test/install
No C++ compiler available; disabling C++ specific optional code
Install prefix    /tmp/qemu-test/install
BIOS directory    /tmp/qemu-test/install/share/qemu
firmware path     /tmp/qemu-test/install/share/qemu-firmware
binary directory  /tmp/qemu-test/install/bin
library directory /tmp/qemu-test/install/lib
module directory  /tmp/qemu-test/install/lib/qemu
libexec directory /tmp/qemu-test/install/libexec
include directory /tmp/qemu-test/install/include
config directory  /tmp/qemu-test/install/etc
local state directory   /tmp/qemu-test/install/var
Manual directory  /tmp/qemu-test/install/share/man
ELF interp prefix /usr/gnemul/qemu-%M
Source path       /tmp/qemu-test/src
GIT binary        git
GIT submodules    
C compiler        cc
Host C compiler   cc
C++ compiler      
Objective-C compiler cc
ARFLAGS           rv
CFLAGS            -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -g 
QEMU_CFLAGS       -I/usr/include/pixman-1   -I$(SRC_PATH)/dtc/libfdt -pthread -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include   -fPIE -DPIE -m64 -mcx16 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv  -Wendif-labels -Wno-missing-include-dirs -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits -fstack-protector-all -Wno-missing-braces  -I/usr/include/libpng12   -I/usr/include/libdrm   -I/usr/include/spice-server -I/usr/include/cacard -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/nss3 -I/usr/include/nspr4 -I/usr/include/spice-1  
LDFLAGS           -Wl,--warn-common -Wl,-z,relro -Wl,-z,now -pie -m64 -g 
make              make
install           install
python            python -B
smbd              /usr/sbin/smbd
module support    no
host CPU          x86_64
host big endian   no
target list       x86_64-softmmu aarch64-softmmu
gprof enabled     no
sparse enabled    no
strip binaries    yes
profiler          no
static build      no
SDL support       yes (1.2.14)
GTK support       yes (2.24.23)
GTK GL support    no
VTE support       yes (0.25.1)
TLS priority      NORMAL
GNUTLS support    no
GNUTLS rnd        no
libgcrypt         no
libgcrypt kdf     no
nettle            no 
nettle kdf        no
libtasn1          no
curses support    yes
virgl support     no
curl support      no
mingw32 support   no
Audio drivers     oss
Block whitelist (rw) 
Block whitelist (ro) 
VirtFS support    no
Multipath support no
VNC support       yes
VNC SASL support  no
VNC JPEG support  yes
VNC PNG support   yes
xen support       yes
xen ctrl version  40600
pv dom build      no
brlapi support    no
bluez  support    no
Documentation     no
PIE               yes
vde support       no
netmap support    no
Linux AIO support no
ATTR/XATTR support yes
Install blobs     yes
KVM support       yes
HAX support       no
HVF support       no
WHPX support      no
TCG support       yes
TCG debug enabled no
TCG interpreter   no
malloc trim support yes
RDMA support      no
fdt support       yes
membarrier        no
preadv support    yes
fdatasync         yes
madvise           yes
posix_madvise     yes
posix_memalign    yes
libcap-ng support no
vhost-net support yes
vhost-crypto support yes
vhost-scsi support yes
vhost-vsock support yes
vhost-user support yes
Trace backends    log
spice support     yes (0.12.6/0.12.4)
rbd support       no
xfsctl support    no
smartcard support yes
libusb            no
usb net redir     no
OpenGL support    yes
OpenGL dmabufs    no
libiscsi support  no
libnfs support    no
build guest agent yes
QGA VSS support   no
QGA w32 disk info no
QGA MSI support   no
seccomp support   no
coroutine backend ucontext
coroutine pool    yes
debug stack usage no
crypto afalg      no
GlusterFS support no
gcov              gcov
gcov enabled      no
TPM support       yes
libssh2 support   no
TPM passthrough   yes
TPM emulator      yes
QOM debugging     yes
Live block migration yes
lzo support       yes
snappy support    no
bzip2 support     yes
NUMA host support no
libxml2           no
tcmalloc support  no
jemalloc support  no
avx2 optimization no
replication support yes
VxHS block device no
capstone          no

WARNING: Use of GTK 2.0 is deprecated and will be removed in
WARNING: future releases. Please switch to using GTK 3.0

WARNING: Use of SDL 1.2 is deprecated and will be removed in
WARNING: future releases. Please switch to using SDL 2.0
  GEN     x86_64-softmmu/config-devices.mak.tmp
  GEN     aarch64-softmmu/config-devices.mak.tmp
mkdir -p dtc/libfdt
  GEN     config-host.h
mkdir -p dtc/tests
  GEN     qemu-options.def
  GEN     qapi-gen
  GEN     trace/generated-tcg-tracers.h
  GEN     trace/generated-helpers-wrappers.h
  GEN     trace/generated-helpers.h
  GEN     x86_64-softmmu/config-devices.mak
  GEN     aarch64-softmmu/config-devices.mak
  GEN     trace/generated-helpers.c
  GEN     module_block.h
Traceback (most recent call last):
  File "/tmp/qemu-test/src/scripts/qapi-gen.py", line 11, in <module>
    from qapi.common import QAPIError, QAPISchema
  File "/tmp/qemu-test/src/scripts/qapi/common.py", line 987
    if {'union', 'alternate', 'struct', 'command', 'event'} & set(expr):
               ^
SyntaxError: invalid syntax
make: *** [qapi-gen-timestamp] Error 1
make: *** Waiting for unfinished jobs....
Traceback (most recent call last):
  File "./tests/docker/docker.py", line 407, in <module>
    sys.exit(main())
  File "./tests/docker/docker.py", line 404, in main
    return args.cmdobj.run(args, argv)
  File "./tests/docker/docker.py", line 261, in run
    return Docker().run(argv, args.keep, quiet=args.quiet)
  File "./tests/docker/docker.py", line 229, in run
    quiet=quiet)
  File "./tests/docker/docker.py", line 147, in _do_check
    return subprocess.check_call(self._command + cmd, **kwargs)
  File "/usr/lib64/python2.7/subprocess.py", line 186, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['docker', 'run', '--label', 'com.qemu.instance.uuid=48e2d3042d5411e8a75c52540069c830', '-u', '0', '--security-opt', 'seccomp=unconfined', '--rm', '--net=none', '-e', 'TARGET_LIST=', '-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=8', '-e', 'DEBUG=', '-e', 'SHOW_ENV=1', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', '/root/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', '/var/tmp/patchew-tester-tmp-_42j_rgl/src/docker-src.2018-03-21-18.07.28.25329:/var/tmp/qemu:z,ro', 'qemu:centos6', '/var/tmp/qemu/run', 'test-quick']' returned non-zero exit status 2
make[1]: *** [tests/docker/Makefile.include:129: docker-run] Error 1
make[1]: Leaving directory '/var/tmp/patchew-tester-tmp-_42j_rgl/src'
make: *** [tests/docker/Makefile.include:163: docker-run-test-quick@centos6] Error 2

real	1m23.270s
user	0m8.174s
sys	0m6.373s
=== OUTPUT END ===

Test command exited with code: 2


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (51 preceding siblings ...)
  2018-03-21 22:08 ` no-reply
@ 2018-03-22  5:11 ` no-reply
  2018-06-21 16:47 ` Markus Armbruster
  53 siblings, 0 replies; 95+ messages in thread
From: no-reply @ 2018-03-22  5:11 UTC (permalink / raw)
  To: marcandre.lureau; +Cc: famz, qemu-devel, armbru

Hi,

This series failed docker-build@min-glib build test. Please find the testing commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

Type: series
Message-id: 20180321115211.17937-1-marcandre.lureau@redhat.com
Subject: [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code

=== TEST SCRIPT BEGIN ===
#!/bin/bash
set -e
git submodule update --init dtc
# Let docker tests dump environment info
export SHOW_ENV=1
export J=8
time make docker-test-build@min-glib
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 t [tag update]            patchew/20180321211056.3339-1-yuval.shaia@oracle.com -> patchew/20180321211056.3339-1-yuval.shaia@oracle.com
Switched to a new branch 'test'
ca50a2d8e3 RFC: make RTC_CHANGE per-target
032f3d2f59 qapi: remove qmp_unregister_command()
7a4b17cf54 qapi: make query-cpu-definitions depend on specific targets
557f536176 qapi: make query-cpu-model-expansion depend on s390 or x86
dc1b218319 qapi: make query-gic-capabilities depend on TARGET_ARM
af9625c6c3 target.json: add a note about query-cpu* not being s390x-specific
c9801977e9 qapi: make s390 commands depend on TARGET_S390X
6a49803445 qapi: make rtc-reset-reinjection and SEV depend on TARGET_I386
13b093aaae qapi: add a top-unit 'target' schema
8e42b4bfd8 RFC: qapi: learn to split schema by 'top-unit'
2984459cd6 qapi-commands: don't initialize command list in qmp_init_marshall()
7c39c807b5 build-sys: move qmp-introspect per target
af7d5d518d qapi: add conditions to REPLICATION type/commands on the schema
9e583d1a1d qapi: add conditions to SPICE type/commands/events on the schema
8bc16dec62 qapi: add conditions to VNC type/commands/events on the schema
72664dbe15 qapi2texi: add condition to variants
d7ff0ab4ef qapi2texi: add 'If:' condition to struct members
bde44a6b1d qapi2texi: add 'If:' condition to enum values
c87e1bc65f qapi2texi: add 'If:' section to generated documentation
3364d5099f docs: document schema configuration
77f7bafdc4 qapi: add #if conditions to generated code members
a95929de93 qapi: add 'if' to alternate members
b205d6198c qapi: add 'if' on union members
9613ba2cc2 qapi: add an error in case a discriminator is conditionnal
cd025039c0 qapi: add 'if' to implicit struct members
6799c824a8 qapi: add a dictionary form with 'type' key for members
c5b50ed9e3 qapi: rename allow_dict to allow_implicit
ba4011e602 qapi-event: add 'if' condition to implicit event enum
7d828e85b9 qapi: add 'if' to enum members
a20c2dc973 qapi: add a dictionnary form with 'name' key for enum members
061635eff1 qapi: factor out check_known_keys()
b0ad9a471a tests: modify visit_enum_type() in test-qapi to print members
86933fb39c qapi: change enum visitor to take QAPISchemaMember
cd6fb8e83f qapi: rename QAPISchemaEnumType.values to .members
31ea46dcec qapi: do not define enumeration value explicitely
55c7453f3c qapi-types: add #if conditions to types & visitors
4507e44d86 qapi-types: refactor variants handling
9c91a8fa1d qapi/events: add #if conditions to events
7ba12f474f qapi/commands: add #if conditions to commands
fcf4dfeb56 qapi-introspect: add preprocessor conditions to generated QLit
51163f6ba0 qapi-introspect: modify to_qlit() to append ', ' on level > 0
75baac460c qapi: add #if/#endif helpers
a001949a31 qapi: mcgen() shouldn't indent # lines
a2ef5afa63 qapi: add 'ifcond' to visitor methods
688755b5fd qapi: leave the ifcond attribute undefined until check()
0566f4cb49 qapi: pass 'if' condition into QAPISchemaEntity objects
7b98d1b34c qapi: add 'if' to top-level expressions
6c36d8fa28 qapi/events: generate event enum in main module
7ced623f53 qapi/visit: remove useless prefix argument

=== OUTPUT BEGIN ===
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into '/var/tmp/patchew-tester-tmp-6a3ah8qp/src/dtc'...
Submodule path 'dtc': checked out 'e54388015af1fb4bf04d0bca99caba1074d9cc42'
  BUILD   min-glib
make[1]: Entering directory '/var/tmp/patchew-tester-tmp-6a3ah8qp/src'
  GEN     /var/tmp/patchew-tester-tmp-6a3ah8qp/src/docker-src.2018-03-22-01.10.50.7274/qemu.tar
Cloning into '/var/tmp/patchew-tester-tmp-6a3ah8qp/src/docker-src.2018-03-22-01.10.50.7274/qemu.tar.vroot'...
done.
Your branch is up-to-date with 'origin/test'.
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into '/var/tmp/patchew-tester-tmp-6a3ah8qp/src/docker-src.2018-03-22-01.10.50.7274/qemu.tar.vroot/dtc'...
Submodule path 'dtc': checked out 'e54388015af1fb4bf04d0bca99caba1074d9cc42'
Submodule 'ui/keycodemapdb' (git://git.qemu.org/keycodemapdb.git) registered for path 'ui/keycodemapdb'
Cloning into '/var/tmp/patchew-tester-tmp-6a3ah8qp/src/docker-src.2018-03-22-01.10.50.7274/qemu.tar.vroot/ui/keycodemapdb'...
Submodule path 'ui/keycodemapdb': checked out '6b3d716e2b6472eb7189d3220552280ef3d832ce'
  COPY    RUNNER
    RUN test-build in qemu:min-glib 
Environment variables:
HOSTNAME=17719477dad1
MAKEFLAGS= -j8
J=8
CCACHE_DIR=/var/tmp/ccache
EXTRA_CONFIGURE_OPTS=
V=
SHOW_ENV=1
PATH=/usr/lib/ccache:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
TARGET_LIST=
SHLVL=1
HOME=/root
TEST_DIR=/tmp/qemu-test
FEATURES= dtc
DEBUG=
_=/usr/bin/env

Configure options:
--enable-werror --target-list=x86_64-softmmu,aarch64-softmmu --prefix=/tmp/qemu-test/install
No C++ compiler available; disabling C++ specific optional code
Install prefix    /tmp/qemu-test/install
BIOS directory    /tmp/qemu-test/install/share/qemu
firmware path     /tmp/qemu-test/install/share/qemu-firmware
binary directory  /tmp/qemu-test/install/bin
library directory /tmp/qemu-test/install/lib
module directory  /tmp/qemu-test/install/lib/qemu
libexec directory /tmp/qemu-test/install/libexec
include directory /tmp/qemu-test/install/include
config directory  /tmp/qemu-test/install/etc
local state directory   /tmp/qemu-test/install/var
Manual directory  /tmp/qemu-test/install/share/man
ELF interp prefix /usr/gnemul/qemu-%M
Source path       /tmp/qemu-test/src
GIT binary        git
GIT submodules    
C compiler        cc
Host C compiler   cc
C++ compiler      
Objective-C compiler cc
ARFLAGS           rv
CFLAGS            -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -g 
QEMU_CFLAGS       -I/usr/include/pixman-1   -I$(SRC_PATH)/dtc/libfdt -pthread -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include   -fPIE -DPIE -m64 -mcx16 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv  -Wendif-labels -Wno-missing-include-dirs -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits -fstack-protector-all -Wno-missing-braces
LDFLAGS           -Wl,--warn-common -Wl,-z,relro -Wl,-z,now -pie -m64 -g 
make              make
install           install
python            python -B
smbd              /usr/sbin/smbd
module support    no
host CPU          x86_64
host big endian   no
target list       x86_64-softmmu aarch64-softmmu
gprof enabled     no
sparse enabled    no
strip binaries    yes
profiler          no
static build      no
SDL support       yes (1.2.14)
GTK support       no 
GTK GL support    no
VTE support       no 
TLS priority      NORMAL
GNUTLS support    no
GNUTLS rnd        no
libgcrypt         no
libgcrypt kdf     no
nettle            no 
nettle kdf        no
libtasn1          no
curses support    no
virgl support     no
curl support      no
mingw32 support   no
Audio drivers     oss
Block whitelist (rw) 
Block whitelist (ro) 
VirtFS support    no
Multipath support no
VNC support       yes
VNC SASL support  no
VNC JPEG support  no
VNC PNG support   no
xen support       no
brlapi support    no
bluez  support    no
Documentation     no
PIE               yes
vde support       no
netmap support    no
Linux AIO support no
ATTR/XATTR support yes
Install blobs     yes
KVM support       yes
HAX support       no
HVF support       no
WHPX support      no
TCG support       yes
TCG debug enabled no
TCG interpreter   no
malloc trim support yes
RDMA support      no
fdt support       yes
membarrier        no
preadv support    yes
fdatasync         yes
madvise           yes
posix_madvise     yes
posix_memalign    yes
libcap-ng support no
vhost-net support yes
vhost-crypto support yes
vhost-scsi support yes
vhost-vsock support yes
vhost-user support yes
Trace backends    log
spice support     no 
rbd support       no
xfsctl support    no
smartcard support no
libusb            no
usb net redir     no
OpenGL support    no
OpenGL dmabufs    no
libiscsi support  no
libnfs support    no
build guest agent yes
QGA VSS support   no
QGA w32 disk info no
QGA MSI support   no
seccomp support   no
coroutine backend ucontext
coroutine pool    yes
debug stack usage no
crypto afalg      no
GlusterFS support no
gcov              gcov
gcov enabled      no
TPM support       yes
libssh2 support   no
TPM passthrough   yes
TPM emulator      yes
QOM debugging     yes
Live block migration yes
lzo support       no
snappy support    no
bzip2 support     no
NUMA host support no
libxml2           no
tcmalloc support  no
jemalloc support  no
avx2 optimization no
replication support yes
VxHS block device no
capstone          no

WARNING: Use of SDL 1.2 is deprecated and will be removed in
WARNING: future releases. Please switch to using SDL 2.0
mkdir -p dtc/libfdt
mkdir -p dtc/tests
  GEN     x86_64-softmmu/config-devices.mak.tmp
  GEN     aarch64-softmmu/config-devices.mak.tmp
  GEN     config-host.h
  GEN     qemu-options.def
  GEN     qapi-gen
  GEN     trace/generated-tcg-tracers.h
  GEN     trace/generated-helpers-wrappers.h
  GEN     trace/generated-helpers.h
  GEN     aarch64-softmmu/config-devices.mak
  GEN     x86_64-softmmu/config-devices.mak
  GEN     trace/generated-helpers.c
  GEN     module_block.h
  GEN     ui/input-keymap-atset1-to-qcode.c
  GEN     ui/input-keymap-linux-to-qcode.c
  GEN     ui/input-keymap-qcode-to-atset1.c
  GEN     ui/input-keymap-qcode-to-atset2.c
  GEN     ui/input-keymap-qcode-to-atset3.c
  GEN     ui/input-keymap-qcode-to-linux.c
Traceback (most recent call last):
  File "/tmp/qemu-test/src/scripts/qapi-gen.py", line 11, in <module>
    from qapi.common import QAPIError, QAPISchema
  File "/tmp/qemu-test/src/scripts/qapi/common.py", line 987
    if {'union', 'alternate', 'struct', 'command', 'event'} & set(expr):
               ^
SyntaxError: invalid syntax
make: *** [qapi-gen-timestamp] Error 1
make: *** Waiting for unfinished jobs....
Traceback (most recent call last):
  File "./tests/docker/docker.py", line 407, in <module>
    sys.exit(main())
  File "./tests/docker/docker.py", line 404, in main
    return args.cmdobj.run(args, argv)
  File "./tests/docker/docker.py", line 261, in run
    return Docker().run(argv, args.keep, quiet=args.quiet)
  File "./tests/docker/docker.py", line 229, in run
    quiet=quiet)
  File "./tests/docker/docker.py", line 147, in _do_check
    return subprocess.check_call(self._command + cmd, **kwargs)
  File "/usr/lib64/python2.7/subprocess.py", line 186, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['docker', 'run', '--label', 'com.qemu.instance.uuid=6d6d77202d8f11e8b66352540069c830', '-u', '0', '--security-opt', 'seccomp=unconfined', '--rm', '--net=none', '-e', 'TARGET_LIST=', '-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=8', '-e', 'DEBUG=', '-e', 'SHOW_ENV=1', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', '/root/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', '/var/tmp/patchew-tester-tmp-6a3ah8qp/src/docker-src.2018-03-22-01.10.50.7274:/var/tmp/qemu:z,ro', 'qemu:min-glib', '/var/tmp/qemu/run', 'test-build']' returned non-zero exit status 2
make[1]: *** [tests/docker/Makefile.include:129: docker-run] Error 1
make[1]: Leaving directory '/var/tmp/patchew-tester-tmp-6a3ah8qp/src'
make: *** [tests/docker/Makefile.include:163: docker-run-test-build@min-glib] Error 2

real	1m9.340s
user	0m8.633s
sys	0m6.243s
=== OUTPUT END ===

Test command exited with code: 2


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 43/49] qapi: make s390 commands depend on TARGET_S390X
  2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 43/49] qapi: make s390 commands depend on TARGET_S390X Marc-André Lureau
@ 2018-03-22  5:42   ` Thomas Huth
  2018-03-22  9:41     ` Marc-André Lureau
  0 siblings, 1 reply; 95+ messages in thread
From: Thomas Huth @ 2018-03-22  5:42 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel, David Hildenbrand
  Cc: armbru, Qemu-s390x list

On 21.03.2018 12:52, Marc-André Lureau wrote:
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> Acked-by: Cornelia Huck <cohuck@redhat.com>
> ---
>  qapi/misc.json                          | 101 ----------------------
>  qapi/target.json                        | 106 ++++++++++++++++++++++++
>  include/sysemu/arch_init.h              |   7 --
>  hw/s390x/s390-skeys.c                   |   2 +-
>  monitor.c                               |  14 ----
>  qmp.c                                   |  14 ----
>  stubs/arch-query-cpu-model-baseline.c   |  13 ---
>  stubs/arch-query-cpu-model-comparison.c |  13 ---
>  target/s390x/cpu_models.c               |   5 +-
>  stubs/Makefile.objs                     |   2 -
>  10 files changed, 110 insertions(+), 167 deletions(-)
>  delete mode 100644 stubs/arch-query-cpu-model-baseline.c
>  delete mode 100644 stubs/arch-query-cpu-model-comparison.c
> 
> diff --git a/qapi/misc.json b/qapi/misc.json
> index 690eeda41f..1753a81b1e 100644
> --- a/qapi/misc.json
> +++ b/qapi/misc.json
> @@ -1821,27 +1821,6 @@
>  { 'command': 'query-dump-guest-memory-capability',
>    'returns': 'DumpGuestMemoryCapability' }
>  
> -##
> -# @dump-skeys:
> -#
> -# Dump guest's storage keys
> -#
> -# @filename: the path to the file to dump to
> -#
> -# This command is only supported on s390 architecture.
> -#
> -# Since: 2.5
> -#
> -# Example:
> -#
> -# -> { "execute": "dump-skeys",
> -#      "arguments": { "filename": "/tmp/skeys" } }
> -# <- { "return": {} }
> -#
> -##
> -{ 'command': 'dump-skeys',
> -  'data': { 'filename': 'str' } }
> -
>  ##
>  # @object-add:
>  #
> @@ -2208,46 +2187,6 @@
>            }
>  }
>  
> -##
> -# @query-cpu-model-comparison:
> -#
> -# Compares two CPU models, returning how they compare in a specific
> -# configuration. The results indicates how both models compare regarding
> -# runnability. This result can be used by tooling to make decisions if a
> -# certain CPU model will run in a certain configuration or if a compatible
> -# CPU model has to be created by baselining.
> -#
> -# Usually, a CPU model is compared against the maximum possible CPU model
> -# of a certain configuration (e.g. the "host" model for KVM). If that CPU
> -# model is identical or a subset, it will run in that configuration.
> -#
> -# The result returned by this command may be affected by:
> -#
> -# * QEMU version: CPU models may look different depending on the QEMU version.
> -#   (Except for CPU models reported as "static" in query-cpu-definitions.)
> -# * machine-type: CPU model may look different depending on the machine-type.
> -#   (Except for CPU models reported as "static" in query-cpu-definitions.)
> -# * machine options (including accelerator): in some architectures, CPU models
> -#   may look different depending on machine and accelerator options. (Except for
> -#   CPU models reported as "static" in query-cpu-definitions.)
> -# * "-cpu" arguments and global properties: arguments to the -cpu option and
> -#   global properties may affect expansion of CPU models. Using
> -#   query-cpu-model-expansion while using these is not advised.
> -#
> -# Some architectures may not support comparing CPU models. s390x supports
> -# comparing CPU models.
> -#
> -# Returns: a CpuModelBaselineInfo. Returns an error if comparing CPU models is
> -#          not supported, if a model cannot be used, if a model contains
> -#          an unknown cpu definition name, unknown properties or properties
> -#          with wrong types.
> -#
> -# Since: 2.8.0
> -##
> -{ 'command': 'query-cpu-model-comparison',
> -  'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
> -  'returns': 'CpuModelCompareInfo' }
> -
>  ##
>  # @CpuModelBaselineInfo:
>  #
> @@ -2260,46 +2199,6 @@
>  { 'struct': 'CpuModelBaselineInfo',
>    'data': { 'model': 'CpuModelInfo' } }
>  
> -##
> -# @query-cpu-model-baseline:
> -#
> -# Baseline two CPU models, creating a compatible third model. The created
> -# model will always be a static, migration-safe CPU model (see "static"
> -# CPU model expansion for details).
> -#
> -# This interface can be used by tooling to create a compatible CPU model out
> -# two CPU models. The created CPU model will be identical to or a subset of
> -# both CPU models when comparing them. Therefore, the created CPU model is
> -# guaranteed to run where the given CPU models run.
> -#
> -# The result returned by this command may be affected by:
> -#
> -# * QEMU version: CPU models may look different depending on the QEMU version.
> -#   (Except for CPU models reported as "static" in query-cpu-definitions.)
> -# * machine-type: CPU model may look different depending on the machine-type.
> -#   (Except for CPU models reported as "static" in query-cpu-definitions.)
> -# * machine options (including accelerator): in some architectures, CPU models
> -#   may look different depending on machine and accelerator options. (Except for
> -#   CPU models reported as "static" in query-cpu-definitions.)
> -# * "-cpu" arguments and global properties: arguments to the -cpu option and
> -#   global properties may affect expansion of CPU models. Using
> -#   query-cpu-model-expansion while using these is not advised.
> -#
> -# Some architectures may not support baselining CPU models. s390x supports
> -# baselining CPU models.
> -#
> -# Returns: a CpuModelBaselineInfo. Returns an error if baselining CPU models is
> -#          not supported, if a model cannot be used, if a model contains
> -#          an unknown cpu definition name, unknown properties or properties
> -#          with wrong types.
> -#
> -# Since: 2.8.0
> -##
> -{ 'command': 'query-cpu-model-baseline',
> -  'data': { 'modela': 'CpuModelInfo',
> -            'modelb': 'CpuModelInfo' },
> -  'returns': 'CpuModelBaselineInfo' }
> -
>  ##
>  # @AddfdInfo:
>  #
> diff --git a/qapi/target.json b/qapi/target.json
> index f277b69a2a..b07a8926d8 100644
> --- a/qapi/target.json
> +++ b/qapi/target.json
> @@ -7,6 +7,8 @@
>  
>  { 'pragma': { 'top-unit': 'target' } }
>  
> +{ 'include': 'misc.json' }
> +
>  ##
>  # @rtc-reset-reinjection:
>  #
> @@ -182,3 +184,107 @@
>  ##
>  { 'command': 'query-sev-capabilities', 'returns': 'SevCapability',
>    'if': 'defined(TARGET_I386)' }
> +
> +##
> +# @dump-skeys:
> +#
> +# Dump guest's storage keys
> +#
> +# @filename: the path to the file to dump to
> +#
> +# This command is only supported on s390 architecture.
> +#
> +# Since: 2.5
> +#
> +# Example:
> +#
> +# -> { "execute": "dump-skeys",
> +#      "arguments": { "filename": "/tmp/skeys" } }
> +# <- { "return": {} }
> +#
> +##
> +{ 'command': 'dump-skeys',
> +  'data': { 'filename': 'str' },
> +  'if': 'defined(TARGET_S390X)' }
> +
> +##
> +# @query-cpu-model-comparison:
> +#
> +# Compares two CPU models, returning how they compare in a specific
> +# configuration. The results indicates how both models compare regarding
> +# runnability. This result can be used by tooling to make decisions if a
> +# certain CPU model will run in a certain configuration or if a compatible
> +# CPU model has to be created by baselining.
> +#
> +# Usually, a CPU model is compared against the maximum possible CPU model
> +# of a certain configuration (e.g. the "host" model for KVM). If that CPU
> +# model is identical or a subset, it will run in that configuration.
> +#
> +# The result returned by this command may be affected by:
> +#
> +# * QEMU version: CPU models may look different depending on the QEMU version.
> +#   (Except for CPU models reported as "static" in query-cpu-definitions.)
> +# * machine-type: CPU model may look different depending on the machine-type.
> +#   (Except for CPU models reported as "static" in query-cpu-definitions.)
> +# * machine options (including accelerator): in some architectures, CPU models
> +#   may look different depending on machine and accelerator options. (Except for
> +#   CPU models reported as "static" in query-cpu-definitions.)
> +# * "-cpu" arguments and global properties: arguments to the -cpu option and
> +#   global properties may affect expansion of CPU models. Using
> +#   query-cpu-model-expansion while using these is not advised.
> +#
> +# Some architectures may not support comparing CPU models. s390x supports
> +# comparing CPU models.
> +#
> +# Returns: a CpuModelBaselineInfo. Returns an error if comparing CPU models is
> +#          not supported, if a model cannot be used, if a model contains
> +#          an unknown cpu definition name, unknown properties or properties
> +#          with wrong types.
> +#
> +# Since: 2.8.0
> +##
> +{ 'command': 'query-cpu-model-comparison',
> +  'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
> +  'returns': 'CpuModelCompareInfo',
> +  'if': 'defined(TARGET_S390X)' }
> +
> +##
> +# @query-cpu-model-baseline:
> +#
> +# Baseline two CPU models, creating a compatible third model. The created
> +# model will always be a static, migration-safe CPU model (see "static"
> +# CPU model expansion for details).
> +#
> +# This interface can be used by tooling to create a compatible CPU model out
> +# two CPU models. The created CPU model will be identical to or a subset of
> +# both CPU models when comparing them. Therefore, the created CPU model is
> +# guaranteed to run where the given CPU models run.
> +#
> +# The result returned by this command may be affected by:
> +#
> +# * QEMU version: CPU models may look different depending on the QEMU version.
> +#   (Except for CPU models reported as "static" in query-cpu-definitions.)
> +# * machine-type: CPU model may look different depending on the machine-type.
> +#   (Except for CPU models reported as "static" in query-cpu-definitions.)
> +# * machine options (including accelerator): in some architectures, CPU models
> +#   may look different depending on machine and accelerator options. (Except for
> +#   CPU models reported as "static" in query-cpu-definitions.)
> +# * "-cpu" arguments and global properties: arguments to the -cpu option and
> +#   global properties may affect expansion of CPU models. Using
> +#   query-cpu-model-expansion while using these is not advised.
> +#
> +# Some architectures may not support baselining CPU models. s390x supports
> +# baselining CPU models.
> +#
> +# Returns: a CpuModelBaselineInfo. Returns an error if baselining CPU models is
> +#          not supported, if a model cannot be used, if a model contains
> +#          an unknown cpu definition name, unknown properties or properties
> +#          with wrong types.
> +#
> +# Since: 2.8.0
> +##
> +{ 'command': 'query-cpu-model-baseline',
> +  'data': { 'modela': 'CpuModelInfo',
> +            'modelb': 'CpuModelInfo' },
> +  'returns': 'CpuModelBaselineInfo',
> +  'if': 'defined(TARGET_S390X)' }
> diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
> index 32abdfe6a1..f0ef652b2a 100644
> --- a/include/sysemu/arch_init.h
> +++ b/include/sysemu/arch_init.h
> @@ -36,11 +36,4 @@ CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp);
>  CpuModelExpansionInfo *arch_query_cpu_model_expansion(CpuModelExpansionType type,
>                                                        CpuModelInfo *mode,
>                                                        Error **errp);
> -CpuModelCompareInfo *arch_query_cpu_model_comparison(CpuModelInfo *modela,
> -                                                     CpuModelInfo *modelb,
> -                                                     Error **errp);
> -CpuModelBaselineInfo *arch_query_cpu_model_baseline(CpuModelInfo *modela,
> -                                                    CpuModelInfo *modelb,
> -                                                    Error **errp);
> -
>  #endif
> diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c
> index 76241c240e..59d28c2358 100644
> --- a/hw/s390x/s390-skeys.c
> +++ b/hw/s390x/s390-skeys.c
> @@ -13,7 +13,7 @@
>  #include "hw/boards.h"
>  #include "hw/s390x/storage-keys.h"
>  #include "qapi/error.h"
> -#include "qapi/qapi-commands-misc.h"
> +#include "qapi/target-qapi-commands.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qemu/error-report.h"
>  #include "sysemu/kvm.h"
> diff --git a/monitor.c b/monitor.c
> index 4ad9225425..bd9a6950cf 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -1157,19 +1157,12 @@ static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
>   */
>  static void qmp_unregister_commands_hack(void)
>  {
> -#ifndef TARGET_S390X
> -    qmp_unregister_command(&qmp_commands, "dump-skeys");
> -#endif
>  #ifndef TARGET_ARM
>      qmp_unregister_command(&qmp_commands, "query-gic-capabilities");
>  #endif
>  #if !defined(TARGET_S390X) && !defined(TARGET_I386)
>      qmp_unregister_command(&qmp_commands, "query-cpu-model-expansion");
>  #endif
> -#if !defined(TARGET_S390X)
> -    qmp_unregister_command(&qmp_commands, "query-cpu-model-baseline");
> -    qmp_unregister_command(&qmp_commands, "query-cpu-model-comparison");
> -#endif
>  #if !defined(TARGET_PPC) && !defined(TARGET_ARM) && !defined(TARGET_I386) \
>      && !defined(TARGET_S390X)
>      qmp_unregister_command(&qmp_commands, "query-cpu-definitions");
> @@ -4703,13 +4696,6 @@ QemuOptsList qemu_mon_opts = {
>      },
>  };
>  
> -#ifndef TARGET_S390X
> -void qmp_dump_skeys(const char *filename, Error **errp)
> -{
> -    error_setg(errp, QERR_FEATURE_DISABLED, "dump-skeys");
> -}
> -#endif
> -
>  #ifndef TARGET_ARM
>  GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
>  {
> diff --git a/qmp.c b/qmp.c
> index d8f80cb04e..14972b78df 100644
> --- a/qmp.c
> +++ b/qmp.c
> @@ -601,20 +601,6 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
>      return arch_query_cpu_model_expansion(type, model, errp);
>  }
>  
> -CpuModelCompareInfo *qmp_query_cpu_model_comparison(CpuModelInfo *modela,
> -                                                    CpuModelInfo *modelb,
> -                                                    Error **errp)
> -{
> -    return arch_query_cpu_model_comparison(modela, modelb, errp);
> -}
> -
> -CpuModelBaselineInfo *qmp_query_cpu_model_baseline(CpuModelInfo *modela,
> -                                                   CpuModelInfo *modelb,
> -                                                   Error **errp)
> -{
> -    return arch_query_cpu_model_baseline(modela, modelb, errp);
> -}

Not sure, but couldn't these two commands be implemented on other
architectures in the long run, too? So removing them now here seems
somewhat counterproductive?

 Thomas

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 43/49] qapi: make s390 commands depend on TARGET_S390X
  2018-03-22  5:42   ` Thomas Huth
@ 2018-03-22  9:41     ` Marc-André Lureau
  2018-03-22 16:10       ` Thomas Huth
  0 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-03-22  9:41 UTC (permalink / raw)
  To: Thomas Huth; +Cc: QEMU, David Hildenbrand, Qemu-s390x list, Markus Armbruster

Hi

On Thu, Mar 22, 2018 at 6:42 AM, Thomas Huth <thuth@redhat.com> wrote:
> On 21.03.2018 12:52, Marc-André Lureau wrote:
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> Acked-by: Cornelia Huck <cohuck@redhat.com>
>> ---
>>  qapi/misc.json                          | 101 ----------------------
>>  qapi/target.json                        | 106 ++++++++++++++++++++++++
>>  include/sysemu/arch_init.h              |   7 --
>>  hw/s390x/s390-skeys.c                   |   2 +-
>>  monitor.c                               |  14 ----
>>  qmp.c                                   |  14 ----
>>  stubs/arch-query-cpu-model-baseline.c   |  13 ---
>>  stubs/arch-query-cpu-model-comparison.c |  13 ---
>>  target/s390x/cpu_models.c               |   5 +-
>>  stubs/Makefile.objs                     |   2 -
>>  10 files changed, 110 insertions(+), 167 deletions(-)
>>  delete mode 100644 stubs/arch-query-cpu-model-baseline.c
>>  delete mode 100644 stubs/arch-query-cpu-model-comparison.c
>>
>> diff --git a/qapi/misc.json b/qapi/misc.json
>> index 690eeda41f..1753a81b1e 100644
>> --- a/qapi/misc.json
>> +++ b/qapi/misc.json
>> @@ -1821,27 +1821,6 @@
>>  { 'command': 'query-dump-guest-memory-capability',
>>    'returns': 'DumpGuestMemoryCapability' }
>>
>> -##
>> -# @dump-skeys:
>> -#
>> -# Dump guest's storage keys
>> -#
>> -# @filename: the path to the file to dump to
>> -#
>> -# This command is only supported on s390 architecture.
>> -#
>> -# Since: 2.5
>> -#
>> -# Example:
>> -#
>> -# -> { "execute": "dump-skeys",
>> -#      "arguments": { "filename": "/tmp/skeys" } }
>> -# <- { "return": {} }
>> -#
>> -##
>> -{ 'command': 'dump-skeys',
>> -  'data': { 'filename': 'str' } }
>> -
>>  ##
>>  # @object-add:
>>  #
>> @@ -2208,46 +2187,6 @@
>>            }
>>  }
>>
>> -##
>> -# @query-cpu-model-comparison:
>> -#
>> -# Compares two CPU models, returning how they compare in a specific
>> -# configuration. The results indicates how both models compare regarding
>> -# runnability. This result can be used by tooling to make decisions if a
>> -# certain CPU model will run in a certain configuration or if a compatible
>> -# CPU model has to be created by baselining.
>> -#
>> -# Usually, a CPU model is compared against the maximum possible CPU model
>> -# of a certain configuration (e.g. the "host" model for KVM). If that CPU
>> -# model is identical or a subset, it will run in that configuration.
>> -#
>> -# The result returned by this command may be affected by:
>> -#
>> -# * QEMU version: CPU models may look different depending on the QEMU version.
>> -#   (Except for CPU models reported as "static" in query-cpu-definitions.)
>> -# * machine-type: CPU model may look different depending on the machine-type.
>> -#   (Except for CPU models reported as "static" in query-cpu-definitions.)
>> -# * machine options (including accelerator): in some architectures, CPU models
>> -#   may look different depending on machine and accelerator options. (Except for
>> -#   CPU models reported as "static" in query-cpu-definitions.)
>> -# * "-cpu" arguments and global properties: arguments to the -cpu option and
>> -#   global properties may affect expansion of CPU models. Using
>> -#   query-cpu-model-expansion while using these is not advised.
>> -#
>> -# Some architectures may not support comparing CPU models. s390x supports
>> -# comparing CPU models.
>> -#
>> -# Returns: a CpuModelBaselineInfo. Returns an error if comparing CPU models is
>> -#          not supported, if a model cannot be used, if a model contains
>> -#          an unknown cpu definition name, unknown properties or properties
>> -#          with wrong types.
>> -#
>> -# Since: 2.8.0
>> -##
>> -{ 'command': 'query-cpu-model-comparison',
>> -  'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
>> -  'returns': 'CpuModelCompareInfo' }
>> -
>>  ##
>>  # @CpuModelBaselineInfo:
>>  #
>> @@ -2260,46 +2199,6 @@
>>  { 'struct': 'CpuModelBaselineInfo',
>>    'data': { 'model': 'CpuModelInfo' } }
>>
>> -##
>> -# @query-cpu-model-baseline:
>> -#
>> -# Baseline two CPU models, creating a compatible third model. The created
>> -# model will always be a static, migration-safe CPU model (see "static"
>> -# CPU model expansion for details).
>> -#
>> -# This interface can be used by tooling to create a compatible CPU model out
>> -# two CPU models. The created CPU model will be identical to or a subset of
>> -# both CPU models when comparing them. Therefore, the created CPU model is
>> -# guaranteed to run where the given CPU models run.
>> -#
>> -# The result returned by this command may be affected by:
>> -#
>> -# * QEMU version: CPU models may look different depending on the QEMU version.
>> -#   (Except for CPU models reported as "static" in query-cpu-definitions.)
>> -# * machine-type: CPU model may look different depending on the machine-type.
>> -#   (Except for CPU models reported as "static" in query-cpu-definitions.)
>> -# * machine options (including accelerator): in some architectures, CPU models
>> -#   may look different depending on machine and accelerator options. (Except for
>> -#   CPU models reported as "static" in query-cpu-definitions.)
>> -# * "-cpu" arguments and global properties: arguments to the -cpu option and
>> -#   global properties may affect expansion of CPU models. Using
>> -#   query-cpu-model-expansion while using these is not advised.
>> -#
>> -# Some architectures may not support baselining CPU models. s390x supports
>> -# baselining CPU models.
>> -#
>> -# Returns: a CpuModelBaselineInfo. Returns an error if baselining CPU models is
>> -#          not supported, if a model cannot be used, if a model contains
>> -#          an unknown cpu definition name, unknown properties or properties
>> -#          with wrong types.
>> -#
>> -# Since: 2.8.0
>> -##
>> -{ 'command': 'query-cpu-model-baseline',
>> -  'data': { 'modela': 'CpuModelInfo',
>> -            'modelb': 'CpuModelInfo' },
>> -  'returns': 'CpuModelBaselineInfo' }
>> -
>>  ##
>>  # @AddfdInfo:
>>  #
>> diff --git a/qapi/target.json b/qapi/target.json
>> index f277b69a2a..b07a8926d8 100644
>> --- a/qapi/target.json
>> +++ b/qapi/target.json
>> @@ -7,6 +7,8 @@
>>
>>  { 'pragma': { 'top-unit': 'target' } }
>>
>> +{ 'include': 'misc.json' }
>> +
>>  ##
>>  # @rtc-reset-reinjection:
>>  #
>> @@ -182,3 +184,107 @@
>>  ##
>>  { 'command': 'query-sev-capabilities', 'returns': 'SevCapability',
>>    'if': 'defined(TARGET_I386)' }
>> +
>> +##
>> +# @dump-skeys:
>> +#
>> +# Dump guest's storage keys
>> +#
>> +# @filename: the path to the file to dump to
>> +#
>> +# This command is only supported on s390 architecture.
>> +#
>> +# Since: 2.5
>> +#
>> +# Example:
>> +#
>> +# -> { "execute": "dump-skeys",
>> +#      "arguments": { "filename": "/tmp/skeys" } }
>> +# <- { "return": {} }
>> +#
>> +##
>> +{ 'command': 'dump-skeys',
>> +  'data': { 'filename': 'str' },
>> +  'if': 'defined(TARGET_S390X)' }
>> +
>> +##
>> +# @query-cpu-model-comparison:
>> +#
>> +# Compares two CPU models, returning how they compare in a specific
>> +# configuration. The results indicates how both models compare regarding
>> +# runnability. This result can be used by tooling to make decisions if a
>> +# certain CPU model will run in a certain configuration or if a compatible
>> +# CPU model has to be created by baselining.
>> +#
>> +# Usually, a CPU model is compared against the maximum possible CPU model
>> +# of a certain configuration (e.g. the "host" model for KVM). If that CPU
>> +# model is identical or a subset, it will run in that configuration.
>> +#
>> +# The result returned by this command may be affected by:
>> +#
>> +# * QEMU version: CPU models may look different depending on the QEMU version.
>> +#   (Except for CPU models reported as "static" in query-cpu-definitions.)
>> +# * machine-type: CPU model may look different depending on the machine-type.
>> +#   (Except for CPU models reported as "static" in query-cpu-definitions.)
>> +# * machine options (including accelerator): in some architectures, CPU models
>> +#   may look different depending on machine and accelerator options. (Except for
>> +#   CPU models reported as "static" in query-cpu-definitions.)
>> +# * "-cpu" arguments and global properties: arguments to the -cpu option and
>> +#   global properties may affect expansion of CPU models. Using
>> +#   query-cpu-model-expansion while using these is not advised.
>> +#
>> +# Some architectures may not support comparing CPU models. s390x supports
>> +# comparing CPU models.
>> +#
>> +# Returns: a CpuModelBaselineInfo. Returns an error if comparing CPU models is
>> +#          not supported, if a model cannot be used, if a model contains
>> +#          an unknown cpu definition name, unknown properties or properties
>> +#          with wrong types.
>> +#
>> +# Since: 2.8.0
>> +##
>> +{ 'command': 'query-cpu-model-comparison',
>> +  'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
>> +  'returns': 'CpuModelCompareInfo',
>> +  'if': 'defined(TARGET_S390X)' }
>> +
>> +##
>> +# @query-cpu-model-baseline:
>> +#
>> +# Baseline two CPU models, creating a compatible third model. The created
>> +# model will always be a static, migration-safe CPU model (see "static"
>> +# CPU model expansion for details).
>> +#
>> +# This interface can be used by tooling to create a compatible CPU model out
>> +# two CPU models. The created CPU model will be identical to or a subset of
>> +# both CPU models when comparing them. Therefore, the created CPU model is
>> +# guaranteed to run where the given CPU models run.
>> +#
>> +# The result returned by this command may be affected by:
>> +#
>> +# * QEMU version: CPU models may look different depending on the QEMU version.
>> +#   (Except for CPU models reported as "static" in query-cpu-definitions.)
>> +# * machine-type: CPU model may look different depending on the machine-type.
>> +#   (Except for CPU models reported as "static" in query-cpu-definitions.)
>> +# * machine options (including accelerator): in some architectures, CPU models
>> +#   may look different depending on machine and accelerator options. (Except for
>> +#   CPU models reported as "static" in query-cpu-definitions.)
>> +# * "-cpu" arguments and global properties: arguments to the -cpu option and
>> +#   global properties may affect expansion of CPU models. Using
>> +#   query-cpu-model-expansion while using these is not advised.
>> +#
>> +# Some architectures may not support baselining CPU models. s390x supports
>> +# baselining CPU models.
>> +#
>> +# Returns: a CpuModelBaselineInfo. Returns an error if baselining CPU models is
>> +#          not supported, if a model cannot be used, if a model contains
>> +#          an unknown cpu definition name, unknown properties or properties
>> +#          with wrong types.
>> +#
>> +# Since: 2.8.0
>> +##
>> +{ 'command': 'query-cpu-model-baseline',
>> +  'data': { 'modela': 'CpuModelInfo',
>> +            'modelb': 'CpuModelInfo' },
>> +  'returns': 'CpuModelBaselineInfo',
>> +  'if': 'defined(TARGET_S390X)' }
>> diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
>> index 32abdfe6a1..f0ef652b2a 100644
>> --- a/include/sysemu/arch_init.h
>> +++ b/include/sysemu/arch_init.h
>> @@ -36,11 +36,4 @@ CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp);
>>  CpuModelExpansionInfo *arch_query_cpu_model_expansion(CpuModelExpansionType type,
>>                                                        CpuModelInfo *mode,
>>                                                        Error **errp);
>> -CpuModelCompareInfo *arch_query_cpu_model_comparison(CpuModelInfo *modela,
>> -                                                     CpuModelInfo *modelb,
>> -                                                     Error **errp);
>> -CpuModelBaselineInfo *arch_query_cpu_model_baseline(CpuModelInfo *modela,
>> -                                                    CpuModelInfo *modelb,
>> -                                                    Error **errp);
>> -
>>  #endif
>> diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c
>> index 76241c240e..59d28c2358 100644
>> --- a/hw/s390x/s390-skeys.c
>> +++ b/hw/s390x/s390-skeys.c
>> @@ -13,7 +13,7 @@
>>  #include "hw/boards.h"
>>  #include "hw/s390x/storage-keys.h"
>>  #include "qapi/error.h"
>> -#include "qapi/qapi-commands-misc.h"
>> +#include "qapi/target-qapi-commands.h"
>>  #include "qapi/qmp/qdict.h"
>>  #include "qemu/error-report.h"
>>  #include "sysemu/kvm.h"
>> diff --git a/monitor.c b/monitor.c
>> index 4ad9225425..bd9a6950cf 100644
>> --- a/monitor.c
>> +++ b/monitor.c
>> @@ -1157,19 +1157,12 @@ static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
>>   */
>>  static void qmp_unregister_commands_hack(void)
>>  {
>> -#ifndef TARGET_S390X
>> -    qmp_unregister_command(&qmp_commands, "dump-skeys");
>> -#endif
>>  #ifndef TARGET_ARM
>>      qmp_unregister_command(&qmp_commands, "query-gic-capabilities");
>>  #endif
>>  #if !defined(TARGET_S390X) && !defined(TARGET_I386)
>>      qmp_unregister_command(&qmp_commands, "query-cpu-model-expansion");
>>  #endif
>> -#if !defined(TARGET_S390X)
>> -    qmp_unregister_command(&qmp_commands, "query-cpu-model-baseline");
>> -    qmp_unregister_command(&qmp_commands, "query-cpu-model-comparison");
>> -#endif
>>  #if !defined(TARGET_PPC) && !defined(TARGET_ARM) && !defined(TARGET_I386) \
>>      && !defined(TARGET_S390X)
>>      qmp_unregister_command(&qmp_commands, "query-cpu-definitions");
>> @@ -4703,13 +4696,6 @@ QemuOptsList qemu_mon_opts = {
>>      },
>>  };
>>
>> -#ifndef TARGET_S390X
>> -void qmp_dump_skeys(const char *filename, Error **errp)
>> -{
>> -    error_setg(errp, QERR_FEATURE_DISABLED, "dump-skeys");
>> -}
>> -#endif
>> -
>>  #ifndef TARGET_ARM
>>  GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
>>  {
>> diff --git a/qmp.c b/qmp.c
>> index d8f80cb04e..14972b78df 100644
>> --- a/qmp.c
>> +++ b/qmp.c
>> @@ -601,20 +601,6 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
>>      return arch_query_cpu_model_expansion(type, model, errp);
>>  }
>>
>> -CpuModelCompareInfo *qmp_query_cpu_model_comparison(CpuModelInfo *modela,
>> -                                                    CpuModelInfo *modelb,
>> -                                                    Error **errp)
>> -{
>> -    return arch_query_cpu_model_comparison(modela, modelb, errp);
>> -}
>> -
>> -CpuModelBaselineInfo *qmp_query_cpu_model_baseline(CpuModelInfo *modela,
>> -                                                   CpuModelInfo *modelb,
>> -                                                   Error **errp)
>> -{
>> -    return arch_query_cpu_model_baseline(modela, modelb, errp);
>> -}
>
> Not sure, but couldn't these two commands be implemented on other
> architectures in the long run, too? So removing them now here seems
> somewhat counterproductive?

They would have modify the qapi ifdef and implement the qmp handler in
their target, similar to what would be done by implementing arch_query
handlers. How counterproductive is that? The benefit is that we don't
have to have stubs and "de-register" the commands.



-- 
Marc-André Lureau

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 43/49] qapi: make s390 commands depend on TARGET_S390X
  2018-03-22  9:41     ` Marc-André Lureau
@ 2018-03-22 16:10       ` Thomas Huth
  0 siblings, 0 replies; 95+ messages in thread
From: Thomas Huth @ 2018-03-22 16:10 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: QEMU, David Hildenbrand, Qemu-s390x list, Markus Armbruster

On 22.03.2018 10:41, Marc-André Lureau wrote:
> Hi
> 
> On Thu, Mar 22, 2018 at 6:42 AM, Thomas Huth <thuth@redhat.com> wrote:
>> On 21.03.2018 12:52, Marc-André Lureau wrote:
[...]
>>> diff --git a/qmp.c b/qmp.c
>>> index d8f80cb04e..14972b78df 100644
>>> --- a/qmp.c
>>> +++ b/qmp.c
>>> @@ -601,20 +601,6 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
>>>      return arch_query_cpu_model_expansion(type, model, errp);
>>>  }
>>>
>>> -CpuModelCompareInfo *qmp_query_cpu_model_comparison(CpuModelInfo *modela,
>>> -                                                    CpuModelInfo *modelb,
>>> -                                                    Error **errp)
>>> -{
>>> -    return arch_query_cpu_model_comparison(modela, modelb, errp);
>>> -}
>>> -
>>> -CpuModelBaselineInfo *qmp_query_cpu_model_baseline(CpuModelInfo *modela,
>>> -                                                   CpuModelInfo *modelb,
>>> -                                                   Error **errp)
>>> -{
>>> -    return arch_query_cpu_model_baseline(modela, modelb, errp);
>>> -}
>>
>> Not sure, but couldn't these two commands be implemented on other
>> architectures in the long run, too? So removing them now here seems
>> somewhat counterproductive?
> 
> They would have modify the qapi ifdef and implement the qmp handler in
> their target, similar to what would be done by implementing arch_query
> handlers. How counterproductive is that? The benefit is that we don't
> have to have stubs and "de-register" the commands.

Yes, thinking about that again, I guess you're right, this should be
fine. I first thought that there would likely be some common code
between the targets finally, but it's more likely that this CPU stuff is
completely different everywhere. So never mind!

 Thomas

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 01/49] qapi/visit: remove useless prefix argument
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 01/49] qapi/visit: remove useless prefix argument Marc-André Lureau
@ 2018-06-18 14:29   ` Markus Armbruster
  0 siblings, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-18 14:29 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, armbru

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi/visit.py | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
> index 5d72d8936c..3c5ea1289e 100644
> --- a/scripts/qapi/visit.py
> +++ b/scripts/qapi/visit.py
> @@ -293,7 +293,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
>  #include "qapi/qmp/qerror.h"
>  #include "%(visit)s.h"
>  ''',
> -                                      visit=visit, prefix=self._prefix))
> +                                      visit=visit))
>          self._genh.preamble_add(mcgen('''
>  #include "qapi/qapi-builtin-visit.h"
>  #include "%(types)s.h"

Reviewed-by: Markus Armbruster <armbru@redhat.com>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 02/49] qapi/events: generate event enum in main module
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 02/49] qapi/events: generate event enum in main module Marc-André Lureau
@ 2018-06-18 14:33   ` Markus Armbruster
  0 siblings, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-18 14:33 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> The event generator produces an enum, and put it in the last visited
> module. It fits better in the main module, since it's the set of all
> visited events, from all modules.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi/events.py | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
> index 3dc523cf39..3e448ae523 100644
> --- a/scripts/qapi/events.py
> +++ b/scripts/qapi/events.py
> @@ -180,8 +180,9 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
>                               types=types))
>  
>      def visit_end(self):
> -        self._genh.add(gen_enum(self._enum_name, self._event_names))
> -        self._genc.add(gen_enum_lookup(self._enum_name, self._event_names))
> +        (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))
>  
>      def visit_event(self, name, info, arg_type, boxed):
>          self._genh.add(gen_event_send_decl(name, arg_type, boxed))

Much better indeed.

Reviewed-by: Markus Armbruster <armbru@redhat.com>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 03/49] qapi: add 'if' to top-level expressions
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 03/49] qapi: add 'if' to top-level expressions Marc-André Lureau
@ 2018-06-19  7:57   ` Markus Armbruster
  2018-06-19  8:41     ` Marc-André Lureau
  0 siblings, 1 reply; 95+ messages in thread
From: Markus Armbruster @ 2018-06-19  7:57 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Accept 'if' key in top-level elements, accepted as string or list of
> string type. The following patches will modify the test visitor to
> check the value is correctly saved, and generate #if/#endif code (as a
> single #if/endif line or a series for a list).
>
> Example of 'if' key:
> { 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
>   'if': 'defined(TEST_IF_STRUCT)' }
>
> The generated code is for now *unconditional*. Later patches generate
> the conditionals.
>
> A following patch for qapi-code-gen.txt will provide more complete
> documentation for 'if' usage.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
[...]
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index 0b277036df..f77ad2ba3b 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -436,6 +436,10 @@ qapi-schema += args-unknown.json
>  qapi-schema += bad-base.json
>  qapi-schema += bad-data.json
>  qapi-schema += bad-ident.json
> +qapi-schema += bad-if.json
> +qapi-schema += bad-if-empty.json
> +qapi-schema += bad-if-empty-list.json
> +qapi-schema += bad-if-list.json
>  qapi-schema += bad-type-bool.json
>  qapi-schema += bad-type-dict.json
>  qapi-schema += bad-type-int.json
> @@ -933,6 +937,8 @@ $(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json
>  		"TEST","$*.out")
>  	@# Sanitize error messages (make them independent of build directory)
>  	@perl -p -e 's|\Q$(SRC_PATH)\E/||g' $*.test.err | diff -u $(SRC_PATH)/$*.err -
> +	@if test "$(QAPI_REGENERATE)" == 1 ; then cp $*.test.out $(SRC_PATH)/$*.out ; fi
> +	@if test "$(QAPI_REGENERATE)" == 1 ; then cp $*.test.err $(SRC_PATH)/$*.err ; fi
>  	@diff -u $(SRC_PATH)/$*.out $*.test.out
>  	@diff -u $(SRC_PATH)/$*.exit $*.test.exit
>  

Huh?

[...]

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/49] qapi: pass 'if' condition into QAPISchemaEntity objects
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 04/49] qapi: pass 'if' condition into QAPISchemaEntity objects Marc-André Lureau
@ 2018-06-19  8:09   ` Markus Armbruster
  0 siblings, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-19  8:09 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, armbru

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Built-in objects remain unconditional.  Explicitly defined objects
> use the condition specified in the schema.  Implicitly defined
> objects inherit their condition from their users.  For most of them,
> there is exactly one user, so the condition to use is obvious.  The
> exception is the wrapped type's generated for simple union variants,

Editing accident in v4: you changed "is the wrapper types" to "is the
wrapped type's" here instead of...

> which can be shared by any number of simple unions.  The tight
> condition would be the disjunction of the conditions of these simple
> unions.  For now, use wrapped type's condition instead.  Much

... changing "use wrapped type's" to "use the wrapped type's" here.  Can
touch up on commit.

> simpler and good enough for now.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> Reviewed-by: Markus Armbruster <armbru@redhat.com>

R-by stands.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 03/49] qapi: add 'if' to top-level expressions
  2018-06-19  7:57   ` Markus Armbruster
@ 2018-06-19  8:41     ` Marc-André Lureau
  2018-06-19 11:35       ` Markus Armbruster
  0 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-06-19  8:41 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: QEMU

On Tue, Jun 19, 2018 at 9:57 AM, Markus Armbruster <armbru@redhat.com> wrote:
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
>> Accept 'if' key in top-level elements, accepted as string or list of
>> string type. The following patches will modify the test visitor to
>> check the value is correctly saved, and generate #if/#endif code (as a
>> single #if/endif line or a series for a list).
>>
>> Example of 'if' key:
>> { 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
>>   'if': 'defined(TEST_IF_STRUCT)' }
>>
>> The generated code is for now *unconditional*. Later patches generate
>> the conditionals.
>>
>> A following patch for qapi-code-gen.txt will provide more complete
>> documentation for 'if' usage.
>>
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> Reviewed-by: Markus Armbruster <armbru@redhat.com>
> [...]
>> diff --git a/tests/Makefile.include b/tests/Makefile.include
>> index 0b277036df..f77ad2ba3b 100644
>> --- a/tests/Makefile.include
>> +++ b/tests/Makefile.include
>> @@ -436,6 +436,10 @@ qapi-schema += args-unknown.json
>>  qapi-schema += bad-base.json
>>  qapi-schema += bad-data.json
>>  qapi-schema += bad-ident.json
>> +qapi-schema += bad-if.json
>> +qapi-schema += bad-if-empty.json
>> +qapi-schema += bad-if-empty-list.json
>> +qapi-schema += bad-if-list.json
>>  qapi-schema += bad-type-bool.json
>>  qapi-schema += bad-type-dict.json
>>  qapi-schema += bad-type-int.json
>> @@ -933,6 +937,8 @@ $(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json
>>               "TEST","$*.out")
>>       @# Sanitize error messages (make them independent of build directory)
>>       @perl -p -e 's|\Q$(SRC_PATH)\E/||g' $*.test.err | diff -u $(SRC_PATH)/$*.err -
>> +     @if test "$(QAPI_REGENERATE)" == 1 ; then cp $*.test.out $(SRC_PATH)/$*.out ; fi
>> +     @if test "$(QAPI_REGENERATE)" == 1 ; then cp $*.test.err $(SRC_PATH)/$*.err ; fi
>>       @diff -u $(SRC_PATH)/$*.out $*.test.out
>>       @diff -u $(SRC_PATH)/$*.exit $*.test.exit
>>
>
> Huh?

Oops, leftover. Do you have an alternative? I could propose it as a
seperate patch if it's generally useful.

-- 
Marc-André Lureau

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 05/49] qapi: leave the ifcond attribute undefined until check()
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 05/49] qapi: leave the ifcond attribute undefined until check() Marc-André Lureau
@ 2018-06-19  9:06   ` Markus Armbruster
  2018-06-26 13:39     ` Marc-André Lureau
  0 siblings, 1 reply; 95+ messages in thread
From: Markus Armbruster @ 2018-06-19  9:06 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, armbru

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> We commonly initialize attributes to None in .init(), then set their
> real value in .check().  Accessing the attribute before .check()
> yields None.  If we're lucky, the code that accesses the attribute
> prematurely chokes on None.
>
> It won't for .ifcond, because None is a legitimate value.
>
> Leave the ifcond attribute undefined until check().

Drawback: pylint complains.  We'll live.

>
> Suggested-by: Markus Armbruster <armbru@redhat.com>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> Reviewed-by: Markus Armbruster <armbru@redhat.com>

Shouldn't this be squashed into the previous patch?

> ---
>  scripts/qapi/common.py | 21 +++++++++++++++++----
>  1 file changed, 17 insertions(+), 4 deletions(-)
>
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index d8ab3d8f7f..eb07d641ab 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -1026,13 +1026,19 @@ class QAPISchemaEntity(object):
>          # such place).
>          self.info = info
>          self.doc = doc
> -        self.ifcond = listify_cond(ifcond)
> +        self._ifcond = ifcond  # self.ifcond is set only after .check()
>  
>      def c_name(self):
>          return c_name(self.name)
>  
>      def check(self, schema):
> -        pass
> +        if isinstance(self._ifcond, QAPISchemaType):
> +            # inherit the condition from a type
> +            typ = self._ifcond
> +            typ.check(schema)
> +            self.ifcond = typ.ifcond
> +        else:
> +            self.ifcond = listify_cond(self._ifcond)

Whenever we add a .check(), we need to prove QAPISchema.check()'s
recursion still terminates, and terminates the right way.

Argument before this patch: we recurse only into types contained in
types, e.g. an object type's base type, and we detect and report cycles
as "Object %s contains itself", in QAPISchemaObjectType.check().

The .check() added here recurses into a type.  If this creates a cycle,
it'll be caught and reported as "contains itself".  We still need to
show that the error message remains accurate.

We .check() here to inherit .ifcond from a type.  As far as I can tell,
we use this inheritance feature only to inherit an array's condition
from its element type.  That's safe, because an array does contain its
elements.

This is hardly a rigorous proof.  Just enough to make me believe your
code works.

However, I suspect adding the inheritance feature at the entity level
complicates the correctness argument without real need.  Can we restrict
it to array elements?  Have QAPISchemaArrayType.check() resolve
type-valued ._ifcond, and all the others choke on it?

>  
>      def is_implicit(self):
>          return not self.info
> @@ -1169,6 +1175,7 @@ class QAPISchemaEnumType(QAPISchemaType):
>          self.prefix = prefix
>  
>      def check(self, schema):
> +        QAPISchemaType.check(self, schema)
>          seen = {}
>          for v in self.values:
>              v.check_clash(self.info, seen)
> @@ -1201,8 +1208,10 @@ class QAPISchemaArrayType(QAPISchemaType):
>          self.element_type = None
>  
>      def check(self, schema):
> +        QAPISchemaType.check(self, schema)
>          self.element_type = schema.lookup_type(self._element_type_name)
>          assert self.element_type
> +        self.element_type.check(schema)
>          self.ifcond = self.element_type.ifcond
>  
>      def is_implicit(self):
> @@ -1245,6 +1254,7 @@ class QAPISchemaObjectType(QAPISchemaType):
>          self.members = None
>  
>      def check(self, schema):
> +        QAPISchemaType.check(self, schema)
>          if self.members is False:               # check for cycles
>              raise QAPISemError(self.info,
>                                 "Object %s contains itself" % self.name)
> @@ -1427,6 +1437,7 @@ class QAPISchemaAlternateType(QAPISchemaType):
>          self.variants = variants
>  
>      def check(self, schema):
> +        QAPISchemaType.check(self, schema)
>          self.variants.tag_member.check(schema)
>          # Not calling self.variants.check_clash(), because there's nothing
>          # to clash with
> @@ -1470,6 +1481,7 @@ class QAPISchemaCommand(QAPISchemaEntity):
>          self.allow_oob = allow_oob
>  
>      def check(self, schema):
> +        QAPISchemaEntity.check(self, schema)
>          if self._arg_type_name:
>              self.arg_type = schema.lookup_type(self._arg_type_name)
>              assert (isinstance(self.arg_type, QAPISchemaObjectType) or
> @@ -1504,6 +1516,7 @@ class QAPISchemaEvent(QAPISchemaEntity):
>          self.boxed = boxed
>  
>      def check(self, schema):
> +        QAPISchemaEntity.check(self, schema)
>          if self._arg_type_name:
>              self.arg_type = schema.lookup_type(self._arg_type_name)
>              assert (isinstance(self.arg_type, QAPISchemaObjectType) or
> @@ -1633,7 +1646,7 @@ class QAPISchema(object):
>              # But it's not tight: the disjunction need not imply it.  We
>              # may end up compiling useless wrapper types.
>              # TODO kill simple unions or implement the disjunction
> -            assert ifcond == typ.ifcond
> +            assert ifcond == typ._ifcond

pylint complains

    W:1649,29: Access to a protected member _ifcond of a client class (protected-access)

Layering violation.  Tolerable, I think.

>          else:
>              self._def_entity(QAPISchemaObjectType(name, info, doc, ifcond,
>                                                    None, members, None))
> @@ -1679,7 +1692,7 @@ class QAPISchema(object):
>              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).ifcond,
> +            typ, info, None, self.lookup_type(typ),
>              'wrapper', [self._make_member('data', typ, info)])
>          return QAPISchemaObjectTypeVariant(case, typ)

Perhaps other attributes that become valid only at .check() time should
receive the same treatment.  Not necessarily in this series, not
necessarily by you.  A TODO comment wouldn't hurt, though.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 03/49] qapi: add 'if' to top-level expressions
  2018-06-19  8:41     ` Marc-André Lureau
@ 2018-06-19 11:35       ` Markus Armbruster
  0 siblings, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-19 11:35 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: Markus Armbruster, QEMU

Marc-André Lureau <marcandre.lureau@gmail.com> writes:

> On Tue, Jun 19, 2018 at 9:57 AM, Markus Armbruster <armbru@redhat.com> wrote:
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>
>>> Accept 'if' key in top-level elements, accepted as string or list of
>>> string type. The following patches will modify the test visitor to
>>> check the value is correctly saved, and generate #if/#endif code (as a
>>> single #if/endif line or a series for a list).
>>>
>>> Example of 'if' key:
>>> { 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
>>>   'if': 'defined(TEST_IF_STRUCT)' }
>>>
>>> The generated code is for now *unconditional*. Later patches generate
>>> the conditionals.
>>>
>>> A following patch for qapi-code-gen.txt will provide more complete
>>> documentation for 'if' usage.
>>>
>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>>> Reviewed-by: Markus Armbruster <armbru@redhat.com>
>> [...]
>>> diff --git a/tests/Makefile.include b/tests/Makefile.include
>>> index 0b277036df..f77ad2ba3b 100644
>>> --- a/tests/Makefile.include
>>> +++ b/tests/Makefile.include
>>> @@ -436,6 +436,10 @@ qapi-schema += args-unknown.json
>>>  qapi-schema += bad-base.json
>>>  qapi-schema += bad-data.json
>>>  qapi-schema += bad-ident.json
>>> +qapi-schema += bad-if.json
>>> +qapi-schema += bad-if-empty.json
>>> +qapi-schema += bad-if-empty-list.json
>>> +qapi-schema += bad-if-list.json
>>>  qapi-schema += bad-type-bool.json
>>>  qapi-schema += bad-type-dict.json
>>>  qapi-schema += bad-type-int.json
>>> @@ -933,6 +937,8 @@ $(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json
>>>               "TEST","$*.out")
>>>       @# Sanitize error messages (make them independent of build directory)
>>>       @perl -p -e 's|\Q$(SRC_PATH)\E/||g' $*.test.err | diff -u $(SRC_PATH)/$*.err -
>>> +     @if test "$(QAPI_REGENERATE)" == 1 ; then cp $*.test.out $(SRC_PATH)/$*.out ; fi
>>> +     @if test "$(QAPI_REGENERATE)" == 1 ; then cp $*.test.err $(SRC_PATH)/$*.err ; fi
>>>       @diff -u $(SRC_PATH)/$*.out $*.test.out
>>>       @diff -u $(SRC_PATH)/$*.exit $*.test.exit
>>>
>>
>> Huh?
>
> Oops, leftover. Do you have an alternative? I could propose it as a
> seperate patch if it's generally useful.

I guess what you're trying to do here is updating expected test output.
So far, everybody does that by hand.

A make target to do that (check-accept?) would be nice.  Trivial to do
if we had a single test harness, but of course we have many.

My R-by stands with this hunk dropped.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 24/49] qapi: add a dictionary form with 'type' key for members
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 24/49] qapi: add a dictionary form with 'type' key for members Marc-André Lureau
@ 2018-06-20 11:13   ` Markus Armbruster
  0 siblings, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-20 11:13 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, armbru

No review, just a short note.

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>
> ---
[...]
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index 9eb2b0cc37..3f46ed5530 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
[...]
> @@ -952,6 +967,10 @@ def check_exprs(exprs):
>          info = expr_elem['info']
>          if 'enum' in expr:
>              normalize_enum(expr, info)
> +        elif 'union' in expr:
> +            normalize_members(expr, 'base')
> +        if {'union', 'alternate', 'struct', 'command', 'event'} & set(expr):
> +            normalize_members(expr, 'data')

You've since changed this to

  +        if set(['union', 'alternate', 'struct', 'command', 'event']) & set(expr):
  +            normalize_members(expr, 'data')

in your git branch.

>  
>      # Learn the types and check for valid expression keys
>      for expr_elem in exprs:
[...]

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 07/49] qapi: mcgen() shouldn't indent # lines
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 07/49] qapi: mcgen() shouldn't indent # lines Marc-André Lureau
@ 2018-06-20 15:14   ` Markus Armbruster
  0 siblings, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-20 15:14 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, armbru

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Skip preprocessor lines when adding indentation, since that would
> likely result in invalid code.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi/common.py | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index bc4ecd6c76..47efe79758 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -1931,8 +1931,8 @@ def cgen(code, **kwds):
>      if indent_level:
>          indent = genindent(indent_level)
>          # re.subn() lacks flags support before Python 2.7, use re.compile()
> -        raw = re.subn(re.compile(r'^.', re.MULTILINE),
> -                      indent + r'\g<0>', raw)
> +        raw = re.subn(re.compile(r'^(?!(#|$))', re.MULTILINE),
> +                      indent, raw)
>          raw = raw[0]
>      return re.sub(re.escape(eatspace) + r' *', '', raw)

Reviewed-by: Markus Armbruster <armbru@redhat.com>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 08/49] qapi: add #if/#endif helpers
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 08/49] qapi: add #if/#endif helpers Marc-André Lureau
@ 2018-06-20 16:01   ` Markus Armbruster
  2018-06-21  7:06   ` Markus Armbruster
  1 sibling, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-20 16:01 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, armbru

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Add helpers to wrap generated code with #if/#endif lines.
>
> Add QAPIGenCSnippet class to write C snippet code, make QAPIGenC
> inherit from it, for full C files with copyright headers etc.
>
> Add a 'with' statement context manager that will be used to wrap
> generator visitor methods.  The manager will check if code was
> generated before adding #if/#endif lines on QAPIGenCSnippet
> objects. Used in the following patches.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi/common.py | 82 +++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 78 insertions(+), 4 deletions(-)
>
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index 47efe79758..60c1d0a783 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -12,6 +12,7 @@
>  # See the COPYING file in the top-level directory.
>  
>  from __future__ import print_function
> +from contextlib import contextmanager
>  import errno
>  import os
>  import re
> @@ -1964,6 +1965,40 @@ def guardend(name):
>                   name=guardname(name))
>  
>  
> +def gen_if(ifcond):
> +    ret = ''
> +    for ifc in ifcond:
> +        ret += mcgen('''
> +#if %(cond)s
> +''', cond=ifc)
> +    return ret
> +
> +
> +def gen_endif(ifcond):
> +    ret = ''
> +    for ifc in reversed(ifcond):
> +        ret += mcgen('''
> +#endif /* %(cond)s */
> +''', cond=ifc)
> +    return ret
> +
> +
> +def wrap_ifcond(ifcond, before, after):

Looks like a helper method.  Name it _wrap_ifcond?

> +    if ifcond is None or before == after:
> +        return after

The before == after part suppresses empty conditionals.  We'll see later
how we end up with them.

The ifcond is None part is suppresses "non-conditionals".  I wonder how
that can happen.

Another non-conditional is [].  Can that happen?

Questions like these indicate the function needs a contract.

> +
> +    assert after.startswith(before)
> +    out = before
> +    added = after[len(before):]
> +    if added[0] == '\n':
> +        out += '\n'
> +        added = added[1:]

The conditional adjusts vertical space around #if.  This might need
tweaking, but let's not worry about that now.

> +    out += gen_if(ifcond)
> +    out += added
> +    out += gen_endif(ifcond)

There's no similar adjustment for #endif.  Again, let's not worry about
that now.

> +    return out
> +
> +
>  def gen_enum_lookup(name, values, prefix=None):
>      ret = mcgen('''
>  
> @@ -2054,6 +2089,7 @@ class QAPIGen(object):
>      def __init__(self):
>          self._preamble = ''
>          self._body = ''
> +        self._ifcond = None
>  
>      def preamble_add(self, text):
>          self._preamble += text
> @@ -2061,6 +2097,23 @@ class QAPIGen(object):
>      def add(self, text):
>          self._body += text
>  
> +    def start_if(self, ifcond):

What are @ifcond's legal values?  In particular, is it okay to pass
None?

If not, then we have an easy way to check whether we're between
.start_if() and .end_if(): ._ifcond is not None.

> +        self._ifcond = ifcond

What if self._ifcond is not None?

Can happen only when you call .start_if within .start_if() ... .endif().
If that's not supposed to work, let's assert self._ifcond is None here,
and add a function contract spelling out the restriction.

> +        self._start_if_body = self._body
> +        self._start_if_preamble = self._preamble
> +
> +    def _wrap_ifcond(self):
> +        pass
> +
> +    def end_if(self):

If .start_if() doesn't take None, then we can catch misuse of .end_if()
by asserting ._ifcond is not None here.

> +        self._wrap_ifcond()
> +        self._ifcond = None

I'd zap ._start_if_body and ._start_if_preamble here.

Note for later: use of .start_if() ... .end_if() has no effect unless
._wrap_ifcond() is overridden.

> +
> +    def get_content(self, fname=None):
> +        assert self._ifcond is None
> +        return (self._top(fname) + self._preamble + self._body
> +                + self._bottom(fname))
> +
>      def _top(self, fname):
>          return ''
>  
> @@ -2078,8 +2131,7 @@ class QAPIGen(object):
>                      raise
>          fd = os.open(pathname, os.O_RDWR | os.O_CREAT, 0o666)
>          f = os.fdopen(fd, 'r+')
> -        text = (self._top(fname) + self._preamble + self._body
> -                + self._bottom(fname))
> +        text = self.get_content(fname)
>          oldtext = f.read(len(text) + 1)
>          if text != oldtext:
>              f.seek(0)
> @@ -2088,10 +2140,32 @@ class QAPIGen(object):
>          f.close()
>  
>  
> -class QAPIGenC(QAPIGen):
> +@contextmanager
> +def ifcontext(ifcond, *args):
> +    saved = []
> +    for arg in args:
> +        arg.start_if(ifcond)
> +    yield
> +    for arg in args:
> +        arg.end_if()

@saved is write-only.

How to use the function isn't immediately obvious[*]; I had to glance at
later patches to be sure.  Please add a function comment.

>  
> -    def __init__(self, blurb, pydoc):
> +
> +class QAPIGenCSnippet(QAPIGen):
> +
> +    def __init__(self):
>          QAPIGen.__init__(self)
> +
> +    def _wrap_ifcond(self):
> +        self._body = wrap_ifcond(self._ifcond,
> +                                 self._start_if_body, self._body)
> +        self._preamble = wrap_ifcond(self._ifcond,
> +                                     self._start_if_preamble, self._preamble)
> +
> +
> +class QAPIGenC(QAPIGenCSnippet):
> +
> +    def __init__(self, blurb, pydoc):
> +        QAPIGenCSnippet.__init__(self)
>          self._blurb = blurb
>          self._copyright = '\n * '.join(re.findall(r'^Copyright .*', pydoc,
>                                                    re.MULTILINE))

Why do you need the intermediary class QAPIGenCSnippet?

As far as I can see, only one subclass overrides ._wrap_ifcond().  Why
is the general machinery in the superclass, where it does nothing, and
not in the subclass that makes it do something?


[*] Compared to the decorator you had in v4, it's simple as pie.
There *had* to be a better way, and it looks like you found one.
Appreciated!

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 08/49] qapi: add #if/#endif helpers
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 08/49] qapi: add #if/#endif helpers Marc-André Lureau
  2018-06-20 16:01   ` Markus Armbruster
@ 2018-06-21  7:06   ` Markus Armbruster
  1 sibling, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-21  7:06 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, armbru

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Add helpers to wrap generated code with #if/#endif lines.
>
> Add QAPIGenCSnippet class to write C snippet code, make QAPIGenC
> inherit from it, for full C files with copyright headers etc.
>
> Add a 'with' statement context manager that will be used to wrap
> generator visitor methods.  The manager will check if code was
> generated before adding #if/#endif lines on QAPIGenCSnippet
> objects. Used in the following patches.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi/common.py | 82 +++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 78 insertions(+), 4 deletions(-)
>
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index 47efe79758..60c1d0a783 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
[...]
> @@ -2061,6 +2097,23 @@ class QAPIGen(object):
>      def add(self, text):
>          self._body += text
>  
> +    def start_if(self, ifcond):
> +        self._ifcond = ifcond
> +        self._start_if_body = self._body
> +        self._start_if_preamble = self._preamble

pylint gripes:

+W:2102, 8: Attribute '_start_if_body' defined outside __init__ (attribute-defined-outside-init)
+W:2103, 8: Attribute '_start_if_preamble' defined outside __init__ (attribute-defined-outside-init)

We generally define in .__init__(), except when we want to catch
premature use, such as in PATCH 05.  Let's define these two in
.__init__().

[...]

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 06/49] qapi: add 'ifcond' to visitor methods
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 06/49] qapi: add 'ifcond' to visitor methods Marc-André Lureau
@ 2018-06-21  8:18   ` Markus Armbruster
  0 siblings, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-21  8:18 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, armbru

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Modify the test visitor to check correct passing of values.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
> ---
[...]
> diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
> index 10e68b01d9..6d25a37dda 100644
> --- a/tests/qapi-schema/test-qapi.py
> +++ b/tests/qapi-schema/test-qapi.py
> @@ -23,12 +23,13 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
>      def visit_include(self, name, info):
>          print('include %s' % name)
>  
> -    def visit_enum_type(self, name, info, values, prefix):
> +    def visit_enum_type(self, name, info, ifcond, values, prefix):
>          print('enum %s %s' % (name, values))
>          if prefix:
>              print('    prefix %s' % prefix)
> +        self._print_if(ifcond)
>  
> -    def visit_object_type(self, name, info, base, members, variants):
> +    def visit_object_type(self, name, info, ifcond, base, members, variants):
>          print('object %s' % name)
>          if base:
>              print('    base %s' % base.name)
> @@ -36,21 +37,25 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
>              print('    member %s: %s optional=%s' % \
>                    (m.name, m.type.name, m.optional))
>          self._print_variants(variants)
> +        self._print_if(ifcond)
>  
> -    def visit_alternate_type(self, name, info, variants):
> +    def visit_alternate_type(self, name, info, ifcond, variants):
>          print('alternate %s' % name)
>          self._print_variants(variants)
> +        self._print_if(ifcond)
>  
> -    def visit_command(self, name, info, arg_type, ret_type,
> +    def visit_command(self, name, info, ifcond, arg_type, ret_type,
>                        gen, success_response, boxed, allow_oob):
>          print('command %s %s -> %s' % \
>                (name, arg_type and arg_type.name, ret_type and ret_type.name))
>          print('   gen=%s success_response=%s boxed=%s' % \
>                (gen, success_response, boxed))
> +        self._print_if(ifcond)
>  
> -    def visit_event(self, name, info, arg_type, boxed):
> +    def visit_event(self, name, info, ifcond, arg_type, boxed):
>          print('event %s %s' % (name, arg_type and arg_type.name))
>          print('   boxed=%s' % boxed)
> +        self._print_if(ifcond)
>  
>      @staticmethod
>      def _print_variants(variants):
> @@ -59,6 +64,10 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
>              for v in variants.variants:
>                  print('    case %s: %s' % (v.name, v.type.name))
>  
> +    @staticmethod
> +    def _print_if(ifcond, indent=4):
> +        if ifcond:
> +            print('%sif %s' % (' ' * indent, ifcond))
>  

pycodestyle points out:

    tests/qapi-schema/test-qapi.py:72:1: E305 expected 2 blank lines after class or function definition, found 1

Can touch up when I apply.

>  try:
>      schema = QAPISchema(sys.argv[1])

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 10/49] qapi-introspect: add preprocessor conditions to generated QLit
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 10/49] qapi-introspect: add preprocessor conditions to generated QLit Marc-André Lureau
@ 2018-06-21 13:05   ` Markus Armbruster
  0 siblings, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-21 13:05 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, armbru

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> The generator will take (obj, condition) tuples to wrap generated QLit
> objects for 'obj' with #if/#endif conditions.
>
> This commit adds 'ifcond' condition to top-level QLit objects.
>
> See generated tests/test-qmp-introspect.c. Example diff after this patch:
>
>     --- before	2018-01-08 11:55:24.757083654 +0100
>     +++ tests/test-qmp-introspect.c	2018-01-08 13:08:44.477641629 +0100
>     @@ -51,6 +51,8 @@
>              { "name", QLIT_QSTR("EVENT_F"), },
>              {}
>          })),
>     +#if defined(TEST_IF_CMD)
>     +#if defined(TEST_IF_STRUCT)
>          QLIT_QDICT(((QLitDictEntry[]) {
>              { "arg-type", QLIT_QSTR("5"), },
>              { "meta-type", QLIT_QSTR("command"), },
>     @@ -58,12 +60,16 @@
>              { "ret-type", QLIT_QSTR("0"), },
>              {}
>          })),
>     +#endif /* defined(TEST_IF_STRUCT) */
>     +#endif /* defined(TEST_IF_CMD) */
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi/introspect.py | 31 +++++++++++++++++++++----------
>  1 file changed, 21 insertions(+), 10 deletions(-)
>
> diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
> index 1a8eb9e33e..cb4825f134 100644
> --- a/scripts/qapi/introspect.py
> +++ b/scripts/qapi/introspect.py
> @@ -18,6 +18,15 @@ def to_qlit(obj, level=0, suppress_first_indent=False):
>      def indent(level):
>          return level * 4 * ' '
>  
> +    if isinstance(obj, tuple):
> +        ifobj, ifcond = obj
> +        ret = gen_if(ifcond)
> +        ret += to_qlit(ifobj, level)
> +        endif = gen_endif(ifcond)
> +        if endif:
> +            ret += '\n' + endif
> +        return ret
> +
>      ret = ''
>      if not suppress_first_indent:
>          ret += indent(level)

@obj represents a JSON object.  It consists of dictionaries, lists,
strings, booleans and None.  Numbers aren't implemented.  Your patch
splices in tuples to represent conditionals at any level.

So far, tuples occur only as elements of the outermost list (see
._gen_qlit() below), but to_qlit() supports them anywhere.  I figure
that will be needed later.  If yes, the whole thing is a bit of a hack,
but at least it's a simple hack.  If no, I'd look for a solution that
feels less hackish.

By the way, this hunk makes my pylint die with "RecursionError: maximum
recursion depth exceeded".  If I comment out the line with the
recursion, it survives.  Latest git survives, too.  Oh well, python3
setup.py install.

> @@ -26,7 +35,7 @@ def to_qlit(obj, level=0, suppress_first_indent=False):
>      elif isinstance(obj, str):
>          ret += 'QLIT_QSTR(' + to_c_string(obj) + ')'
>      elif isinstance(obj, list):
> -        elts = [to_qlit(elt, level + 1)
> +        elts = [to_qlit(elt, level + 1).strip('\n')
>                  for elt in obj]
>          elts.append(indent(level + 1) + "{}")
>          ret += 'QLIT_QLIST(((QLitObject[]) {\n'

The .strip('\n') looks odd.  Reminds me of the asymmetry I noted in
PATCH 08: you take care to adjust vertical space around #if there, but
not around #endif.  Let's not worry about it now.

> @@ -131,12 +140,12 @@ const QLitObject %(c_name)s = %(c_string)s;
>              return '[' + self._use_type(typ.element_type) + ']'
>          return self._name(typ.name)
>  
> -    def _gen_qlit(self, name, mtype, obj):
> +    def _gen_qlit(self, name, mtype, obj, ifcond):
>          if mtype not in ('command', 'event', 'builtin', 'array'):
>              name = self._name(name)
>          obj['name'] = name
>          obj['meta-type'] = mtype
> -        self._qlits.append(obj)
> +        self._qlits.append((obj, ifcond))

This is where we produce ._qlits.  It's also the only place where we
create tuples.  Thus, all elements of ._qlits are tuples, and no tuples
occur at deeper levels.

>  
>      def _gen_member(self, member):
>          ret = {'name': member.name, 'type': self._use_type(member.type)}
> @@ -152,26 +161,27 @@ const QLitObject %(c_name)s = %(c_string)s;
>          return {'case': variant.name, 'type': self._use_type(variant.type)}
>  
>      def visit_builtin_type(self, name, info, json_type):
> -        self._gen_qlit(name, 'builtin', {'json-type': json_type})
> +        self._gen_qlit(name, 'builtin', {'json-type': json_type}, [])
>  
>      def visit_enum_type(self, name, info, ifcond, values, prefix):
> -        self._gen_qlit(name, 'enum', {'values': values})
> +        self._gen_qlit(name, 'enum', {'values': values}, ifcond)
>  
>      def visit_array_type(self, name, info, ifcond, element_type):
>          element = self._use_type(element_type)
> -        self._gen_qlit('[' + element + ']', 'array', {'element-type': element})
> +        self._gen_qlit('[' + element + ']', 'array', {'element-type': element},
> +                       ifcond)
>  
>      def visit_object_type_flat(self, name, info, ifcond, members, variants):
>          obj = {'members': [self._gen_member(m) for m in members]}
>          if variants:
>              obj.update(self._gen_variants(variants.tag_member.name,
>                                            variants.variants))
> -        self._gen_qlit(name, 'object', obj)
> +        self._gen_qlit(name, 'object', obj, ifcond)
>  
>      def visit_alternate_type(self, name, info, ifcond, variants):
>          self._gen_qlit(name, 'alternate',
>                         {'members': [{'type': self._use_type(m.type)}
> -                                    for m in variants.variants]})
> +                                    for m in variants.variants]}, ifcond)
>  
>      def visit_command(self, name, info, ifcond, arg_type, ret_type,
>                        gen, success_response, boxed, allow_oob):
> @@ -180,11 +190,12 @@ const QLitObject %(c_name)s = %(c_string)s;
>          self._gen_qlit(name, 'command',
>                         {'arg-type': self._use_type(arg_type),
>                          'ret-type': self._use_type(ret_type),
> -                        'allow-oob': allow_oob})
> +                        'allow-oob': allow_oob}, ifcond)
>  
>      def visit_event(self, name, info, ifcond, arg_type, boxed):
>          arg_type = arg_type or self._schema.the_empty_object_type
> -        self._gen_qlit(name, 'event', {'arg-type': self._use_type(arg_type)})
> +        self._gen_qlit(name, 'event', {'arg-type': self._use_type(arg_type)},
> +                       ifcond)
>  
>  
>  def gen_introspect(schema, output_dir, prefix, opt_unmask):

I still prefer the approach I explored in

    [PATCH RFC 09/14] qapi: Pass ifcond to visitors
    [PATCH RFC 13/14] qapi-introspect: Add #if conditions to introspection value

because it separates the concerns.  I'd love to complete my exploration
so we can compare apples to apples.  However, with the soft freeze
closing in, I'll probably have to take the solution that's already
complete, regardless of my preference.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 11/49] qapi/commands: add #if conditions to commands
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 11/49] qapi/commands: add #if conditions to commands Marc-André Lureau
@ 2018-06-21 14:35   ` Markus Armbruster
  2018-06-22  8:34   ` Markus Armbruster
  1 sibling, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-21 14:35 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, armbru

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Wrap generated code with #if/#endif using an 'ifcontext' on
> QAPIGenCSnippet objects.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi/commands.py | 19 ++++++++++---------
>  tests/test-qmp-cmds.c    |  4 ++--
>  2 files changed, 12 insertions(+), 11 deletions(-)
>
> diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
> index e2366b4801..40bb680b7c 100644
> --- a/scripts/qapi/commands.py
> +++ b/scripts/qapi/commands.py
> @@ -237,7 +237,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
>          QAPISchemaModularCVisitor.__init__(
>              self, prefix, 'qapi-commands',
>              ' * Schema-defined QAPI/QMP commands', __doc__)
> -        self._regy = ''
> +        self._regy = QAPIGenCSnippet()

Aha, here's the answer to my question on PATCH 08: you need
QAPIGenCSnippet...

>          self._visited_ret_types = {}
>  
>      def _begin_module(self, name):
> @@ -273,19 +273,20 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
>  void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
>  ''',
>                         c_prefix=c_name(self._prefix, protect=False)))
> -        genc.add(gen_registry(self._regy, self._prefix))
> +        genc.add(gen_registry(self._regy.get_content(), self._prefix))
>  
>      def visit_command(self, name, info, ifcond, arg_type, ret_type,
>                        gen, success_response, boxed, allow_oob):
>          if not gen:
>              return
> -        self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type))
> -        if ret_type and ret_type not in self._visited_ret_types[self._genc]:
> -            self._visited_ret_types[self._genc].add(ret_type)
> -            self._genc.add(gen_marshal_output(ret_type))
> -        self._genh.add(gen_marshal_decl(name))
> -        self._genc.add(gen_marshal(name, arg_type, boxed, ret_type))
> -        self._regy += gen_register_command(name, success_response, allow_oob)
> +        with ifcontext(ifcond, self._genh, self._genc, self._regy):

... so you can pass ._regy  to with ifcontext.

The name QAPIGenCSnippet makes sense for this role.  Less so for its
role as base class of QAPIGenC.  Dunno...  QAPIGenCCode?

> +            self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type))
> +            if ret_type and ret_type not in self._visited_ret_types[self._genc]:

pycodestyle-3 reports
    commands.py:284:80: E501 line too long (80 > 79 characters)

> +                self._visited_ret_types[self._genc].add(ret_type)
> +                self._genc.add(gen_marshal_output(ret_type))
> +            self._genh.add(gen_marshal_decl(name))
> +            self._genc.add(gen_marshal(name, arg_type, boxed, ret_type))
> +            self._regy.add(gen_register_command(name, success_response, allow_oob))

pycodestyle-3 reports
    commands.py:289:80: E501 line too long (83 > 79 characters)

>  
>  
>  def gen_commands(schema, output_dir, prefix):
> diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c
> index c25fc2100a..e675722593 100644
> --- a/tests/test-qmp-cmds.c
> +++ b/tests/test-qmp-cmds.c
> @@ -12,11 +12,11 @@
>  
>  static QmpCommandList qmp_commands;
>  
> -/* #if defined(TEST_IF_STRUCT) && defined(TEST_IF_CMD) */
> +#if defined(TEST_IF_STRUCT) && defined(TEST_IF_CMD)
>  void qmp_TestIfCmd(TestIfStruct *foo, Error **errp)
>  {
>  }
> -/* #endif */
> +#endif
>  
>  void qmp_user_def_cmd(Error **errp)
>  {

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 12/49] qapi/events: add #if conditions to events
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 12/49] qapi/events: add #if conditions to events Marc-André Lureau
@ 2018-06-21 14:40   ` Markus Armbruster
  2018-06-22  9:02   ` Markus Armbruster
  1 sibling, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-21 14:40 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, armbru

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Wrap generated code with #if/#endif using an 'ifcontext' on
> QAPIGenCSnippet objects.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi/events.py | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
> index 26ae00f6f7..dae03e3d88 100644
> --- a/scripts/qapi/events.py
> +++ b/scripts/qapi/events.py
> @@ -185,8 +185,9 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
>          genc.add(gen_enum_lookup(self._enum_name, self._event_names))
>  
>      def visit_event(self, name, info, ifcond, arg_type, boxed):
> -        self._genh.add(gen_event_send_decl(name, arg_type, boxed))
> -        self._genc.add(gen_event_send(name, arg_type, boxed, self._enum_name))
> +        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))

events.py:190:80: E501 line too long (82 > 79 characters)

>          self._event_names.append(name)

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 13/49] qapi-types: refactor variants handling
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 13/49] qapi-types: refactor variants handling Marc-André Lureau
@ 2018-06-21 15:54   ` Markus Armbruster
  0 siblings, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-21 15:54 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, armbru

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Generate variants objects outside gen_object(). This will allow to
> easily wrap gen_object() with ifcond_decorator in the following patch.

ifcond_decorator is no more, please update your commit message.

>
> gen_variants_objects() calls gen_object() for each variants, so it

s/for each variants/for each variant/

> remains guarded for each generated variant object.
>
> self._gen_type_cleanup(name) is factored out in _gen_object(), helping
> generated code to be wrapped by the same condition in the following
> patch.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

I read this thrice, and I still fail to understand the second and third
paragraph.

I'm skipping this patch for now, because we might not need it; see
review of next patch.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 14/49] qapi-types: add #if conditions to types & visitors
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 14/49] qapi-types: add #if conditions to types & visitors Marc-André Lureau
@ 2018-06-21 16:12   ` Markus Armbruster
  2018-06-27 11:59     ` Marc-André Lureau
  0 siblings, 1 reply; 95+ messages in thread
From: Markus Armbruster @ 2018-06-21 16:12 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Types & visitors are coupled and must be handled together to avoid
> temporary build regression.
>
> Wrap generated types/visitor code with #if/#endif using the context
> helpers.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi/types.py | 46 ++++++++++++++++++++++++++-----------------
>  scripts/qapi/visit.py | 33 ++++++++++++++++++-------------
>  2 files changed, 47 insertions(+), 32 deletions(-)
>
> diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
> index 3d9b0f9a07..ce4c91206c 100644
> --- a/scripts/qapi/types.py
> +++ b/scripts/qapi/types.py
> @@ -61,8 +61,10 @@ def gen_variants_objects(variants):
>          for v in variants.variants:
>              if isinstance(v.type, QAPISchemaObjectType):
>                  ret += gen_variants_objects(v.type.variants)
> +                ret += gen_if(v.type.ifcond)
>                  ret += gen_object(v.type.name, v.type.base,
>                                    v.type.local_members, v.type.variants)
> +                ret += gen_endif(v.type.ifcond)

Ignorant question out of curiosity, why is with ifcontext() not usable
here?

>      return ret
>  
>  
> @@ -206,41 +208,49 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
>          # gen_object() is recursive, ensure it doesn't visit the empty type
>          objects_seen.add(schema.the_empty_object_type.name)
>  
> -    def _gen_type_cleanup(self, name):
> -        self._genh.add(gen_type_cleanup_decl(name))
> -        self._genc.add(gen_type_cleanup(name))
> +    def _gen_type_cleanup(self, name, ifcond):
> +        with ifcontext(ifcond, self._genh, self._genc):
> +            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):
> -        self._genh.preamble_add(gen_enum(name, values, prefix))
> -        self._genc.add(gen_enum_lookup(name, values, prefix))
> +        with ifcontext(ifcond, self._genh, self._genc):
> +            self._genh.preamble_add(gen_enum(name, values, prefix))
> +            self._genc.add(gen_enum_lookup(name, values, prefix))
>  
>      def visit_array_type(self, name, info, ifcond, element_type):
> -        self._genh.preamble_add(gen_fwd_object_or_array(name))
> -        self._genh.add(gen_array(name, element_type))
> -        self._gen_type_cleanup(name)
> +        with ifcontext(ifcond, self._genh):
> +            self._genh.preamble_add(gen_fwd_object_or_array(name))
> +            self._genh.add(gen_array(name, element_type))
> +        self._gen_type_cleanup(name, ifcond)
>  
>      def _gen_object(self, name, info, ifcond, base, members, variants):
> -        self._genh.add(gen_object(name, base, members, variants))
> -        if base and not base.is_implicit():
> -            self._genh.add(gen_upcast(name, base))
> -        # TODO Worth changing the visitor signature, so we could
> -        # directly use rather than repeat type.is_implicit()?
> +        with ifcontext(ifcond, self._genh):
> +            self._genh.add(gen_object(name, base, members, variants))
> +            if base and not base.is_implicit():
> +                self._genh.add(gen_upcast(name, base))
> +            # TODO Worth changing the visitor signature, so we could
> +            # directly use rather than repeat type.is_implicit()?
>          if not name.startswith('q_'):
>              # implicit types won't be directly allocated/freed
> -            self._gen_type_cleanup(name)
> +            self._gen_type_cleanup(name, ifcond)
> +
> +    def _gen_fwd_object_or_array(self, name, ifcond):
> +        with ifcontext(ifcond, self._genh):
> +            self._genh.preamble_add(gen_fwd_object_or_array(name))
>  
>      def visit_object_type(self, name, info, ifcond, base, members, variants):
>          # Nothing to do for the special empty builtin
>          if name == 'q_empty':
>              return
> -        self._genh.preamble_add(gen_fwd_object_or_array(name))
> +        self._gen_fwd_object_or_array(name, ifcond)
>          self._genh.add(gen_variants_objects(variants))
> -        self._gen_object(name, info, None, base, members, variants)
> +        self._gen_object(name, info, ifcond, base, members, variants)
>  
>      def visit_alternate_type(self, name, info, ifcond, variants):
> -        self._genh.preamble_add(gen_fwd_object_or_array(name))
> +        self._gen_fwd_object_or_array(name, ifcond)
>          self._genh.add(gen_variants_objects(variants))
> -        self._gen_object(name, info, None, None,
> +        self._gen_object(name, info, ifcond, None,
>                           [variants.tag_member], variants)
>  
>  
> diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
> index 9ea2e04f81..e4a62ce030 100644
> --- a/scripts/qapi/visit.py
> +++ b/scripts/qapi/visit.py
> @@ -302,29 +302,34 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
>                                        types=types))
>  
>      def visit_enum_type(self, name, info, ifcond, values, prefix):
> -        self._genh.add(gen_visit_decl(name, scalar=True))
> -        self._genc.add(gen_visit_enum(name))
> +        with ifcontext(ifcond, self._genh, self._genc):
> +            self._genh.add(gen_visit_decl(name, scalar=True))
> +            self._genc.add(gen_visit_enum(name))
>  
>      def visit_array_type(self, name, info, ifcond, element_type):
> -        self._genh.add(gen_visit_decl(name))
> -        self._genc.add(gen_visit_list(name, element_type))
> +        with ifcontext(ifcond, self._genh, self._genc):
> +            self._genh.add(gen_visit_decl(name))
> +            self._genc.add(gen_visit_list(name, element_type))
>  
>      def visit_object_type(self, name, info, ifcond, base, members, variants):
>          # Nothing to do for the special empty builtin
>          if name == 'q_empty':
>              return
> -        self._genh.add(gen_visit_members_decl(name))
> -        self._genc.add(gen_visit_object_members(name, base, members, variants))
> -        # TODO Worth changing the visitor signature, so we could
> -        # directly use rather than repeat type.is_implicit()?
> -        if not name.startswith('q_'):
> -            # only explicit types need an allocating visit
> -            self._genh.add(gen_visit_decl(name))
> -            self._genc.add(gen_visit_object(name, base, members, variants))
> +        with ifcontext(ifcond, self._genh, self._genc):
> +            self._genh.add(gen_visit_members_decl(name))
> +            self._genc.add(gen_visit_object_members(name, base,
> +                                                    members, variants))
> +            # TODO Worth changing the visitor signature, so we could
> +            # directly use rather than repeat type.is_implicit()?
> +            if not name.startswith('q_'):
> +                # only explicit types need an allocating visit
> +                self._genh.add(gen_visit_decl(name))
> +                self._genc.add(gen_visit_object(name, base, members, variants))
>  
>      def visit_alternate_type(self, name, info, ifcond, variants):
> -        self._genh.add(gen_visit_decl(name))
> -        self._genc.add(gen_visit_alternate(name, variants))
> +        with ifcontext(ifcond, self._genh, self._genc):
> +            self._genh.add(gen_visit_decl(name))
> +            self._genc.add(gen_visit_alternate(name, variants))
>  
>  
>  def gen_visit(schema, output_dir, prefix, opt_builtins):

The visit part is straightforward: wrap code generation in with
ifcontext().

The type part is more involved.  First, it passes ifcond to a bunch of
helpers, which muddies the waters a bit.  Second, you can't just wrap
object types generation, because it's recursive.  You move the recursion
out of gen_object() (previous patch), so you can wrap that.  But you
still can't wrap its new home, gen_variants_objects().  Instead, you
bracket its call of gen_object() with gen_if() ... gen_endif().  Works,
but is there a more direct path to the same result?

I append my attempt.  Its basic idea is to wrap code generation right
where it is.  Requires passing ifcond to gen_object().  The patch to
visit.py is identical.

Less churn, and I it saves me reviewing the previous patch.  Opinions?


>From d6f26abe5a81b10aaff5c75db3bfc60c05203f05 Mon Sep 17 00:00:00 2001
From: Markus Armbruster <armbru@redhat.com>
Date: Thu, 21 Jun 2018 18:03:41 +0200
Subject: [PATCH] qapi-types: add #if conditions to types & visitors

Types & visitors are coupled and must be handled together to avoid
temporary build regression.

Wrap generated types/visitor code with #if/#endif using the context
helpers.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 scripts/qapi/types.py | 48 ++++++++++++++++++++++++++-----------------
 scripts/qapi/visit.py | 33 ++++++++++++++++-------------
 2 files changed, 48 insertions(+), 33 deletions(-)

diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index 298a80db62..e43138bfd7 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -55,7 +55,7 @@ def gen_struct_members(members):
     return ret
 
 
-def gen_object(name, base, members, variants):
+def gen_object(name, ifcond, base, members, variants):
     if name in objects_seen:
         return ''
     objects_seen.add(name)
@@ -64,11 +64,14 @@ def gen_object(name, base, members, variants):
     if variants:
         for v in variants.variants:
             if isinstance(v.type, QAPISchemaObjectType):
-                ret += gen_object(v.type.name, v.type.base,
+                ret += gen_object(v.type.name, v.type.ifcond, v.type.base,
                                   v.type.local_members, v.type.variants)
 
     ret += mcgen('''
 
+''')
+    ret += gen_if(ifcond)
+    ret += mcgen('''
 struct %(c_name)s {
 ''',
                  c_name=c_name(name))
@@ -101,6 +104,7 @@ struct %(c_name)s {
     ret += mcgen('''
 };
 ''')
+    ret += gen_endif(ifcond)
 
     return ret
 
@@ -207,33 +211,39 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
         self._genc.add(gen_type_cleanup(name))
 
     def visit_enum_type(self, name, info, ifcond, values, prefix):
-        self._genh.preamble_add(gen_enum(name, values, prefix))
-        self._genc.add(gen_enum_lookup(name, values, prefix))
+        with ifcontext(ifcond, self._genh, self._genc):
+            self._genh.preamble_add(gen_enum(name, values, prefix))
+            self._genc.add(gen_enum_lookup(name, values, prefix))
 
     def visit_array_type(self, name, info, ifcond, element_type):
-        self._genh.preamble_add(gen_fwd_object_or_array(name))
-        self._genh.add(gen_array(name, element_type))
-        self._gen_type_cleanup(name)
+        with ifcontext(ifcond, self._genh, self._genc):
+            self._genh.preamble_add(gen_fwd_object_or_array(name))
+            self._genh.add(gen_array(name, element_type))
+            self._gen_type_cleanup(name)
 
     def visit_object_type(self, name, info, ifcond, base, members, variants):
         # Nothing to do for the special empty builtin
         if name == 'q_empty':
             return
-        self._genh.preamble_add(gen_fwd_object_or_array(name))
-        self._genh.add(gen_object(name, base, members, variants))
-        if base and not base.is_implicit():
-            self._genh.add(gen_upcast(name, base))
-        # TODO Worth changing the visitor signature, so we could
-        # directly use rather than repeat type.is_implicit()?
-        if not name.startswith('q_'):
-            # implicit types won't be directly allocated/freed
-            self._gen_type_cleanup(name)
+        with ifcontext(ifcond, self._genh):
+            self._genh.preamble_add(gen_fwd_object_or_array(name))
+        self._genh.add(gen_object(name, ifcond, base, members, variants))
+        with ifcontext(ifcond, self._genh, self._genc):
+            if base and not base.is_implicit():
+                self._genh.add(gen_upcast(name, base))
+            # TODO Worth changing the visitor signature, so we could
+            # directly use rather than repeat type.is_implicit()?
+            if not name.startswith('q_'):
+                # implicit types won't be directly allocated/freed
+                self._gen_type_cleanup(name)
 
     def visit_alternate_type(self, name, info, ifcond, variants):
-        self._genh.preamble_add(gen_fwd_object_or_array(name))
-        self._genh.add(gen_object(name, None,
+        with ifcontext(ifcond, self._genh):
+            self._genh.preamble_add(gen_fwd_object_or_array(name))
+        self._genh.add(gen_object(name, ifcond, None,
                                   [variants.tag_member], variants))
-        self._gen_type_cleanup(name)
+        with ifcontext(ifcond, self._genh, self._genc):
+            self._gen_type_cleanup(name)
 
 
 def gen_types(schema, output_dir, prefix, opt_builtins):
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index 9ea2e04f81..e4a62ce030 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -302,29 +302,34 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
                                       types=types))
 
     def visit_enum_type(self, name, info, ifcond, values, prefix):
-        self._genh.add(gen_visit_decl(name, scalar=True))
-        self._genc.add(gen_visit_enum(name))
+        with ifcontext(ifcond, self._genh, self._genc):
+            self._genh.add(gen_visit_decl(name, scalar=True))
+            self._genc.add(gen_visit_enum(name))
 
     def visit_array_type(self, name, info, ifcond, element_type):
-        self._genh.add(gen_visit_decl(name))
-        self._genc.add(gen_visit_list(name, element_type))
+        with ifcontext(ifcond, self._genh, self._genc):
+            self._genh.add(gen_visit_decl(name))
+            self._genc.add(gen_visit_list(name, element_type))
 
     def visit_object_type(self, name, info, ifcond, base, members, variants):
         # Nothing to do for the special empty builtin
         if name == 'q_empty':
             return
-        self._genh.add(gen_visit_members_decl(name))
-        self._genc.add(gen_visit_object_members(name, base, members, variants))
-        # TODO Worth changing the visitor signature, so we could
-        # directly use rather than repeat type.is_implicit()?
-        if not name.startswith('q_'):
-            # only explicit types need an allocating visit
-            self._genh.add(gen_visit_decl(name))
-            self._genc.add(gen_visit_object(name, base, members, variants))
+        with ifcontext(ifcond, self._genh, self._genc):
+            self._genh.add(gen_visit_members_decl(name))
+            self._genc.add(gen_visit_object_members(name, base,
+                                                    members, variants))
+            # TODO Worth changing the visitor signature, so we could
+            # directly use rather than repeat type.is_implicit()?
+            if not name.startswith('q_'):
+                # only explicit types need an allocating visit
+                self._genh.add(gen_visit_decl(name))
+                self._genc.add(gen_visit_object(name, base, members, variants))
 
     def visit_alternate_type(self, name, info, ifcond, variants):
-        self._genh.add(gen_visit_decl(name))
-        self._genc.add(gen_visit_alternate(name, variants))
+        with ifcontext(ifcond, self._genh, self._genc):
+            self._genh.add(gen_visit_decl(name))
+            self._genc.add(gen_visit_alternate(name, variants))
 
 
 def gen_visit(schema, output_dir, prefix, opt_builtins):
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 31/49] qapi2texi: add 'If:' section to generated documentation
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 31/49] qapi2texi: add 'If:' section to generated documentation Marc-André Lureau
@ 2018-06-21 16:29   ` Markus Armbruster
  0 siblings, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-21 16:29 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, armbru

Subject needs an update for the move of qapi2texi.py to do qapi/doc.py.
I think just qapi: would be fine.

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> The documentation is generated only once, and doesn't know C
> pre-conditions. Add 'If:' sections for top-level entities.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi/doc.py             | 22 ++++++++++++----------
>  tests/qapi-schema/doc-good.json |  2 +-
>  tests/qapi-schema/doc-good.out  |  1 +
>  tests/qapi-schema/doc-good.texi |  2 ++
>  4 files changed, 16 insertions(+), 11 deletions(-)
>
> diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
> index 6c2bf98e1d..783b13303a 100755
> --- a/scripts/qapi/doc.py
> +++ b/scripts/qapi/doc.py
> @@ -174,7 +174,7 @@ def texi_members(doc, what, base, variants, member_func):
>      return '\n@b{%s:}\n@table @asis\n%s@end table\n' % (what, items)
>  
>  
> -def texi_sections(doc):
> +def texi_sections(doc, ifcond):
>      """Format additional sections following arguments"""
>      body = ''
>      for section in doc.sections:
> @@ -185,14 +185,16 @@ def texi_sections(doc):
>              body += texi_example(section.text)
>          else:
>              body += texi_format(section.text)
> +    if ifcond:
> +        body += '\n\n@b{If:} @code{%s}' % ", ".join(ifcond)

This is the actual change.  The other hunks for this file are about
passing @ifcond to this spot.

I figure we should explain 'If:' in the introduction, i.e. the big
comment in qapi-schema.json.  Since we fail to explain any of the other
tags there, this is somebody else's problem.

>      return body
>  
>  
> -def texi_entity(doc, what, base=None, variants=None,
> +def texi_entity(doc, what, ifcond, base=None, variants=None,
>                  member_func=texi_member):
>      return (texi_body(doc)
>              + texi_members(doc, what, base, variants, member_func)
> -            + texi_sections(doc))
> +            + texi_sections(doc, ifcond))
>  
>  
>  class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
> @@ -208,7 +210,7 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
>          doc = self.cur_doc
>          self._gen.add(TYPE_FMT(type='Enum',
>                                 name=doc.symbol,
> -                               body=texi_entity(doc, 'Values',
> +                               body=texi_entity(doc, 'Values', ifcond,
>                                                  member_func=texi_enum_value)))
>  
>      def visit_object_type(self, name, info, ifcond, base, members, variants):
> @@ -217,14 +219,14 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
>              base = None
>          self._gen.add(TYPE_FMT(type='Object',
>                                 name=doc.symbol,
> -                               body=texi_entity(doc, 'Members',
> +                               body=texi_entity(doc, 'Members', ifcond,
>                                                  base, variants)))
>  
>      def visit_alternate_type(self, name, info, ifcond, variants):
>          doc = self.cur_doc
>          self._gen.add(TYPE_FMT(type='Alternate',
>                                 name=doc.symbol,
> -                               body=texi_entity(doc, 'Members')))
> +                               body=texi_entity(doc, 'Members', ifcond)))
>  
>      def visit_command(self, name, info, ifcond, arg_type, ret_type,
>                        gen, success_response, boxed, allow_oob):
> @@ -233,9 +235,9 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
>              body = texi_body(doc)
>              body += ('\n@b{Arguments:} the members of @code{%s}\n'
>                       % arg_type.name)
> -            body += texi_sections(doc)
> +            body += texi_sections(doc, ifcond)
>          else:
> -            body = texi_entity(doc, 'Arguments')
> +            body = texi_entity(doc, 'Arguments', ifcond)
>          self._gen.add(MSG_FMT(type='Command',
>                                name=doc.symbol,
>                                body=body))
> @@ -244,7 +246,7 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
>          doc = self.cur_doc
>          self._gen.add(MSG_FMT(type='Event',
>                                name=doc.symbol,
> -                              body=texi_entity(doc, 'Arguments')))
> +                              body=texi_entity(doc, 'Arguments', ifcond)))
>  
>      def symbol(self, doc, entity):
>          if self._gen._body:
> @@ -257,7 +259,7 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
>          assert not doc.args
>          if self._gen._body:
>              self._gen.add('\n')
> -        self._gen.add(texi_body(doc) + texi_sections(doc))
> +        self._gen.add(texi_body(doc) + texi_sections(doc, None))
>  
>  
>  def gen_doc(schema, output_dir, prefix):
> diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json
> index 97ab4625ff..984cd8ed06 100644
> --- a/tests/qapi-schema/doc-good.json
> +++ b/tests/qapi-schema/doc-good.json
> @@ -55,7 +55,7 @@
>  #
>  # @two is undocumented
>  ##
> -{ 'enum': 'Enum', 'data': [ 'one', 'two' ] }
> +{ 'enum': 'Enum', 'data': [ 'one', 'two' ], 'if': 'defined(IFCOND)' }
>  
>  ##
>  # @Base:
> diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
> index 3cd5c094aa..e4054e293c 100644
> --- a/tests/qapi-schema/doc-good.out
> +++ b/tests/qapi-schema/doc-good.out
> @@ -12,6 +12,7 @@ module doc-good.json
>  enum Enum
>      member one
>      member two
> +    if ['defined(IFCOND)']
>  object Base
>      member base1: Enum optional=False
>  object Variant1
> diff --git a/tests/qapi-schema/doc-good.texi b/tests/qapi-schema/doc-good.texi
> index 0aed2300a5..e42eace474 100644
> --- a/tests/qapi-schema/doc-good.texi
> +++ b/tests/qapi-schema/doc-good.texi
> @@ -89,6 +89,8 @@ Not documented
>  @end table
>  @code{two} is undocumented
>  
> +
> +@b{If:} @code{defined(IFCOND)}
>  @end deftp

Test coverage is a bit sparse, but it'll do for now.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code
  2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (52 preceding siblings ...)
  2018-03-22  5:11 ` no-reply
@ 2018-06-21 16:47 ` Markus Armbruster
  2018-06-21 17:18   ` Marc-André Lureau
  53 siblings, 1 reply; 95+ messages in thread
From: Markus Armbruster @ 2018-06-21 16:47 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

I think we can bite off a digestible part of this series:
target-independent top-level conditionals.  I think that's PATCH
01-14,31 and applicable parts of 35-37.  The idea is to merge that part
quickly, then deal with the (less daunting) remainder.  Marc-André, if
you agree with that plan, please respin just that part.  I can continue
review of the remainder without a rebase.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code
  2018-06-21 16:47 ` Markus Armbruster
@ 2018-06-21 17:18   ` Marc-André Lureau
  2018-06-22  6:56     ` Markus Armbruster
  2018-06-22  9:06     ` Markus Armbruster
  0 siblings, 2 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-06-21 17:18 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: QEMU

Hi

On Thu, Jun 21, 2018 at 6:47 PM, Markus Armbruster <armbru@redhat.com> wrote:
> I think we can bite off a digestible part of this series:
> target-independent top-level conditionals.  I think that's PATCH
> 01-14,31 and applicable parts of 35-37.  The idea is to merge that part
> quickly, then deal with the (less daunting) remainder.  Marc-André, if
> you agree with that plan, please respin just that part.  I can continue
> review of the remainder without a rebase.
>

That's ok with me, I'll work on it.
thanks


-- 
Marc-André Lureau

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code
  2018-06-21 17:18   ` Marc-André Lureau
@ 2018-06-22  6:56     ` Markus Armbruster
  2018-06-22  9:06     ` Markus Armbruster
  1 sibling, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-22  6:56 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: Markus Armbruster, QEMU

Marc-André Lureau <marcandre.lureau@gmail.com> writes:

> Hi
>
> On Thu, Jun 21, 2018 at 6:47 PM, Markus Armbruster <armbru@redhat.com> wrote:
>> I think we can bite off a digestible part of this series:
>> target-independent top-level conditionals.  I think that's PATCH
>> 01-14,31 and applicable parts of 35-37.  The idea is to merge that part
>> quickly, then deal with the (less daunting) remainder.  Marc-André, if
>> you agree with that plan, please respin just that part.  I can continue
>> review of the remainder without a rebase.
>>
>
> That's ok with me, I'll work on it.
> thanks

Great!

The next part could be target-dependend top-level conditionals, or
member conditionals (enum members are tied to union variants, which may
make further splitting impractical).  This series does members first.  I
guess we stick to that order to avoid unnecessary patch reordering work.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 15/49] qapi: do not define enumeration value explicitely
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 15/49] qapi: do not define enumeration value explicitely Marc-André Lureau
@ 2018-06-22  8:08   ` Markus Armbruster
  2018-06-27 12:13     ` Marc-André Lureau
  0 siblings, 1 reply; 95+ messages in thread
From: Markus Armbruster @ 2018-06-22  8:08 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, armbru

Subject: explicitly

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.
>
> 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 60c1d0a783..68a567f53f 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -2032,14 +2032,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;

What excactly in your series depends on this?

What safeguards do you propose to ensure an enumeration with
conditionals is compiled only with the exact same conditionals within
the same program?

Example of the kind of deathtrap to guard against: compile

    typedef enum Color {
        COLOR_WHITE,
#if defined(NEED_CPU_H)
#if defined(TARGET_S390X)
        COLOR_BLUE,
#endif /* defined(TARGET_S390X) */
#endif /* defined(NEED_CPU_H) */
        COLOR_BLACK,
    } Color;

in s390x-code (COLOR_BLACK = 2) and in target-independent code
(COLOR_BLACK = 1), then linking the two together.

Yes, I know a similar deathtrap will be set up for struct and union
types.  No excuse for ignoring either of the two.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 11/49] qapi/commands: add #if conditions to commands
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 11/49] qapi/commands: add #if conditions to commands Marc-André Lureau
  2018-06-21 14:35   ` Markus Armbruster
@ 2018-06-22  8:34   ` Markus Armbruster
  2018-06-25 13:15     ` Markus Armbruster
  1 sibling, 1 reply; 95+ messages in thread
From: Markus Armbruster @ 2018-06-22  8:34 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, armbru

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Wrap generated code with #if/#endif using an 'ifcontext' on
> QAPIGenCSnippet objects.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi/commands.py | 19 ++++++++++---------
>  tests/test-qmp-cmds.c    |  4 ++--
>  2 files changed, 12 insertions(+), 11 deletions(-)
>
> diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
> index e2366b4801..40bb680b7c 100644
> --- a/scripts/qapi/commands.py
> +++ b/scripts/qapi/commands.py
> @@ -237,7 +237,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
>          QAPISchemaModularCVisitor.__init__(
>              self, prefix, 'qapi-commands',
>              ' * Schema-defined QAPI/QMP commands', __doc__)
> -        self._regy = ''
> +        self._regy = QAPIGenCSnippet()
>          self._visited_ret_types = {}
>  
>      def _begin_module(self, name):
> @@ -273,19 +273,20 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
>  void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
>  ''',
>                         c_prefix=c_name(self._prefix, protect=False)))
> -        genc.add(gen_registry(self._regy, self._prefix))
> +        genc.add(gen_registry(self._regy.get_content(), self._prefix))
>  
>      def visit_command(self, name, info, ifcond, arg_type, ret_type,
>                        gen, success_response, boxed, allow_oob):
>          if not gen:
>              return
> -        self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type))
> -        if ret_type and ret_type not in self._visited_ret_types[self._genc]:
> -            self._visited_ret_types[self._genc].add(ret_type)
> -            self._genc.add(gen_marshal_output(ret_type))
> -        self._genh.add(gen_marshal_decl(name))
> -        self._genc.add(gen_marshal(name, arg_type, boxed, ret_type))
> -        self._regy += gen_register_command(name, success_response, allow_oob)
> +        with ifcontext(ifcond, self._genh, self._genc, self._regy):
> +            self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type))
> +            if ret_type and ret_type not in self._visited_ret_types[self._genc]:
> +                self._visited_ret_types[self._genc].add(ret_type)
> +                self._genc.add(gen_marshal_output(ret_type))

I'm afraid this falls apart when multiple commands with different
conditions share a return type.

That case needs test coverage.

Aside: the qmp_marshal_FOO() should be static.  I can see just two uses
preventing that:

    monitor.c:1146:                         qmp_marshal_qmp_capabilities, QCO_NO_OPTIONS);
    monitor.c:4312:    qmp_marshal_query_version(NULL, &ver, NULL);

Would be nice to get rid of those.  Not necessarily in this series, of
course.

> +            self._genh.add(gen_marshal_decl(name))
> +            self._genc.add(gen_marshal(name, arg_type, boxed, ret_type))
> +            self._regy.add(gen_register_command(name, success_response, allow_oob))
>  
>  
>  def gen_commands(schema, output_dir, prefix):
> diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c
> index c25fc2100a..e675722593 100644
> --- a/tests/test-qmp-cmds.c
> +++ b/tests/test-qmp-cmds.c
> @@ -12,11 +12,11 @@
>  
>  static QmpCommandList qmp_commands;
>  
> -/* #if defined(TEST_IF_STRUCT) && defined(TEST_IF_CMD) */
> +#if defined(TEST_IF_STRUCT) && defined(TEST_IF_CMD)
>  void qmp_TestIfCmd(TestIfStruct *foo, Error **errp)
>  {
>  }
> -/* #endif */
> +#endif
>  
>  void qmp_user_def_cmd(Error **errp)
>  {

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 12/49] qapi/events: add #if conditions to events
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 12/49] qapi/events: add #if conditions to events Marc-André Lureau
  2018-06-21 14:40   ` Markus Armbruster
@ 2018-06-22  9:02   ` Markus Armbruster
  1 sibling, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-22  9:02 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, armbru

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Wrap generated code with #if/#endif using an 'ifcontext' on
> QAPIGenCSnippet objects.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi/events.py | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
> index 26ae00f6f7..dae03e3d88 100644
> --- a/scripts/qapi/events.py
> +++ b/scripts/qapi/events.py
> @@ -185,8 +185,9 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
>          genc.add(gen_enum_lookup(self._enum_name, self._event_names))
>  
>      def visit_event(self, name, info, ifcond, arg_type, boxed):
> -        self._genh.add(gen_event_send_decl(name, arg_type, boxed))
> -        self._genc.add(gen_event_send(name, arg_type, boxed, self._enum_name))
> +        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)

This makes a conditional event's qapi_event_send_FOO() compile-time
conditional, but its enum QAPIEvent member remains unconditional for
now.  I figure it'll get its #if in PATCH 29.  Please mention this in
your commit message.  You do in PATCH 22.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code
  2018-06-21 17:18   ` Marc-André Lureau
  2018-06-22  6:56     ` Markus Armbruster
@ 2018-06-22  9:06     ` Markus Armbruster
  1 sibling, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-22  9:06 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: Markus Armbruster, QEMU

Marc-André Lureau <marcandre.lureau@gmail.com> writes:

> Hi
>
> On Thu, Jun 21, 2018 at 6:47 PM, Markus Armbruster <armbru@redhat.com> wrote:
>> I think we can bite off a digestible part of this series:
>> target-independent top-level conditionals.  I think that's PATCH
>> 01-14,31 and applicable parts of 35-37.  The idea is to merge that part
>> quickly, then deal with the (less daunting) remainder.  Marc-André, if
>> you agree with that plan, please respin just that part.  I can continue
>> review of the remainder without a rebase.
>>
>
> That's ok with me, I'll work on it.
> thanks

Please include the relevant part of PATCH 30 "docs: document schema
configuration".  Consider squashing it into PATCH 03.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 30/49] docs: document schema configuration
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 30/49] docs: document schema configuration Marc-André Lureau
@ 2018-06-22 11:10   ` Markus Armbruster
  0 siblings, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-22 11:10 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  docs/devel/qapi-code-gen.txt | 38 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 38 insertions(+)
>
> diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
> index a569d24745..eec52e63e5 100644
> --- a/docs/devel/qapi-code-gen.txt
> +++ b/docs/devel/qapi-code-gen.txt
> @@ -728,6 +728,44 @@ Example: Red Hat, Inc. controls redhat.com, and may therefore add a
>  downstream command __com.redhat_drive-mirror.
>  
>  
> +=== Configuring the schema ===
> +
> +Top-level QAPI expressions and various type expressions listed below

Not sure about "and various type expressions listed below".  Perhaps
it's better to start with explaining just top-level conditionals, then
explain member conditionals separately.

> +can take an 'if' key.  The value must be a string or a list of
> +string.  The corresponding generated code will then guard the inclusion

s/string/strings/

> +of that member in the larger struct or function with #if IFCOND
> +(or several #if lines for a list), where IFCOND is the value of the
> +'if' key.
> +
> +'struct', 'enum', 'union', 'alternate', 'command' and 'event'
> +top-level QAPI expressions can take an 'if' keyword like:
> +
> +{ 'struct': 'IfStruct', 'data': { 'foo': 'int' },
> +  'if': 'defined(IFCOND)' }
> +
> +Where a member can normally be defined with a single string value as its
> +type, it is also possible to supply a dictionary with both 'type' and
> +'if' keys.
> +
> +{ '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:
> +
> +{ '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.
> +
> +The presence of 'if' keys in the schema is reflected through to the
> +introspection output depending on the build configuration.
> +
> +
>  == Client JSON Protocol introspection ==
>  
>  Clients of a Client JSON Protocol commonly need to figure out what

Missing: how 'if' affects generated code.

Want me to try my hand at a fixup?

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 17/49] qapi: change enum visitor to take QAPISchemaMember
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 17/49] qapi: change enum visitor to take QAPISchemaMember Marc-André Lureau
@ 2018-06-22 12:24   ` Markus Armbruster
  0 siblings, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-22 12:24 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, armbru

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> 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.
>
> Suggested-by: Markus Armbruster <armbru@redhat.com>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi/common.py         | 12 ++++++------
>  scripts/qapi/events.py         |  2 +-
>  scripts/qapi/introspect.py     |  3 ++-
>  tests/qapi-schema/test-qapi.py |  2 +-
>  4 files changed, 10 insertions(+), 9 deletions(-)
>
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index ea5cdfe3be..4d19146064 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -1198,7 +1198,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):
> @@ -2007,11 +2007,11 @@ const QEnumLookup %(c_name)s_lookup = {
>  ''',
>                  c_name=c_name(name))
>      for m in members:
> -        index = c_enum_const(name, m, prefix)
> +        index = c_enum_const(name, m.name, prefix)
>          ret += mcgen('''
> -        [%(index)s] = "%(value)s",
> +        [%(index)s] = "%(name)s",
>  ''',
> -                     index=index, value=m)
> +                     index=index, name=m.name)
>  
>      ret += mcgen('''
>      },
> @@ -2024,7 +2024,7 @@ const QEnumLookup %(c_name)s_lookup = {
>  
>  def gen_enum(name, members, prefix=None):
>      # append automatically generated _MAX value
> -    enum_members = members + ['_MAX']
> +    enum_members = members + [QAPISchemaMember('_MAX')]
>  
>      ret = mcgen('''
>  

This hunk gave me pause...

> @@ -2036,7 +2036,7 @@ typedef enum %(c_name)s {
>          ret += mcgen('''
>      %(c_enum)s,
>  ''',
> -                     c_enum=c_enum_const(name, m, prefix))
> +                     c_enum=c_enum_const(name, m.name, prefix))
>  
>      ret += mcgen('''
>  } %(c_name)s;
> diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
> index dae03e3d88..233c27a6c8 100644
> --- a/scripts/qapi/events.py
> +++ b/scripts/qapi/events.py
> @@ -188,7 +188,7 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
>          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_names.append(QAPISchemaMember(name))
>  
>  

... and this one as well, until I realized that you're *also* changing
gen_enum_lookup() and gen_enum().  And then I realized that I missed
something about the previous patch.  Going to explain it there.

Anyway, let's mention the change to gen_enum_lookup() and gen_enum() in
the commit message.

>  def gen_events(schema, output_dir, prefix):
> diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
> index 66f7fd00a9..d62fca84de 100644
> --- a/scripts/qapi/introspect.py
> +++ b/scripts/qapi/introspect.py
> @@ -164,7 +164,8 @@ const QLitObject %(c_name)s = %(c_string)s;
>          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': members}, ifcond)
> +        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/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
> index f4b8feb9bc..3623deae62 100644
> --- a/tests/qapi-schema/test-qapi.py
> +++ b/tests/qapi-schema/test-qapi.py
> @@ -24,7 +24,7 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
>          print('include %s' % name)
>  
>      def visit_enum_type(self, name, info, ifcond, members, prefix):
> -        print('enum %s %s' % (name, members))
> +        print('enum %s %s' % (name, [m.name for m in members]))
>          if prefix:
>              print('    prefix %s' % prefix)
>          self._print_if(ifcond)

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 16/49] qapi: rename QAPISchemaEnumType.values to .members
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 16/49] qapi: rename QAPISchemaEnumType.values to .members Marc-André Lureau
@ 2018-06-22 12:24   ` Markus Armbruster
  0 siblings, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-22 12:24 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, armbru

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> 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>

I agree with renaming @values to @members where it's a list of
QAPISchemaMembers.

> ---
>  scripts/qapi/common.py         | 36 +++++++++++++++++-----------------
>  scripts/qapi/doc.py            |  2 +-
>  scripts/qapi/introspect.py     |  4 ++--
>  scripts/qapi/types.py          |  6 +++---
>  scripts/qapi/visit.py          |  2 +-
>  tests/qapi-schema/test-qapi.py |  4 ++--
>  6 files changed, 27 insertions(+), 27 deletions(-)
>
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index 68a567f53f..ea5cdfe3be 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -1068,7 +1068,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):

This one is still a list of strings.  The next patch changes it to list
of QAPISchemaMembers, and that's when it should be renamed.

>          pass
>  
>      def visit_array_type(self, name, info, ifcond, element_type):
> @@ -1166,22 +1166,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()
> @@ -1191,7 +1191,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'
> @@ -1999,19 +1999,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):

Likewise.

>      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, prefix)
>          ret += mcgen('''
>          [%(index)s] = "%(value)s",
>  ''',
> -                     index=index, value=value)
> +                     index=index, value=m)
>  
>      ret += mcgen('''
>      },
> @@ -2022,9 +2022,9 @@ const QEnumLookup %(c_name)s_lookup = {
>      return ret
>  
>  
> -def gen_enum(name, values, prefix=None):
> +def gen_enum(name, members, prefix=None):

Likewise.

>      # append automatically generated _MAX value
> -    enum_values = values + ['_MAX']
> +    enum_members = members + ['_MAX']
>  
>      ret = mcgen('''
>  
> @@ -2032,11 +2032,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, prefix))
>  
>      ret += mcgen('''
>  } %(c_name)s;
> diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
> index d5cfd2336b..6c2bf98e1d 100755
> --- a/scripts/qapi/doc.py
> +++ b/scripts/qapi/doc.py
> @@ -204,7 +204,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,

Likewise.  More of the same below.

> diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
> index cb4825f134..66f7fd00a9 100644
> --- a/scripts/qapi/introspect.py
> +++ b/scripts/qapi/introspect.py
> @@ -163,8 +163,8 @@ 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': 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 ce4c91206c..5b790cb41d 100644
> --- a/scripts/qapi/types.py
> +++ b/scripts/qapi/types.py
> @@ -213,10 +213,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):
> diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
> index e4a62ce030..ee776386ae 100644
> --- a/scripts/qapi/visit.py
> +++ b/scripts/qapi/visit.py
> @@ -301,7 +301,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 6d25a37dda..f4b8feb9bc 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, members))
>          if prefix:
>              print('    prefix %s' % prefix)
>          self._print_if(ifcond)

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 18/49] tests: modify visit_enum_type() in test-qapi to print members
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 18/49] tests: modify visit_enum_type() in test-qapi to print members Marc-André Lureau
@ 2018-06-22 14:10   ` Markus Armbruster
  0 siblings, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-22 14:10 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, armbru

The subject is misleading: visit_enum_type() prints members even before
this patch already.

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Use a common self._print_members() to print enum members details.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@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   | 49 +++++++++++++++++++-----
>  tests/qapi-schema/test-qapi.py           | 18 ++++++---
>  12 files changed, 158 insertions(+), 31 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
[More of the same...]
> diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
> index 3623deae62..7e7b8f9f0f 100644
> --- a/tests/qapi-schema/test-qapi.py
> +++ b/tests/qapi-schema/test-qapi.py
> @@ -12,7 +12,8 @@
>  
>  from __future__ import print_function
>  import sys
> -from qapi.common import QAPIError, QAPISchema, QAPISchemaVisitor
> +from qapi.common import QAPIError, QAPISchema, QAPISchemaVisitor, \
> +    QAPISchemaObjectTypeMember
>  
>  
>  class QAPISchemaTestVisitor(QAPISchemaVisitor):
> @@ -24,18 +25,17 @@ 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)
> +        self._print_members(members)
>          self._print_if(ifcond)
>  
>      def visit_object_type(self, name, info, ifcond, base, members, variants):
>          print('object %s' % name)
>          if base:
>              print('    base %s' % base.name)
> -        for m in members:
> -            print('    member %s: %s optional=%s' % \
> -                  (m.name, m.type.name, m.optional))
> +        self._print_members(members)
>          self._print_variants(variants)
>          self._print_if(ifcond)
>  
> @@ -57,6 +57,14 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
>          print('   boxed=%s' % boxed)
>          self._print_if(ifcond)
>  
> +    @staticmethod
> +    def _print_members(members):
> +        for m in members:
> +            print('    member %s%s' % (
> +                m.name,
> +                ': %s optional=%s' % (m.type.name, m.optional)
> +                if isinstance(m, QAPISchemaObjectTypeMember) else ''))
> +
>      @staticmethod
>      def _print_variants(variants):
>          if variants:

I don't think the de-duplication is worth the isinstance() ugliness,
even with PATCH 21's additional line.

Compare the stupidest possible solution:

   diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
   index 3623deae62..37547dc233 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):

PATCH 21 will then add two lines instead of one.  Still less code, and
simpler, too.

Revised commit message could be:

    tests: Print enum type members more like object type members

    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.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 11/49] qapi/commands: add #if conditions to commands
  2018-06-22  8:34   ` Markus Armbruster
@ 2018-06-25 13:15     ` Markus Armbruster
  0 siblings, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-25 13:15 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Markus Armbruster <armbru@redhat.com> writes:

> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
>> Wrap generated code with #if/#endif using an 'ifcontext' on
>> QAPIGenCSnippet objects.
>>
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> ---
>>  scripts/qapi/commands.py | 19 ++++++++++---------
>>  tests/test-qmp-cmds.c    |  4 ++--
>>  2 files changed, 12 insertions(+), 11 deletions(-)
>>
>> diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
>> index e2366b4801..40bb680b7c 100644
>> --- a/scripts/qapi/commands.py
>> +++ b/scripts/qapi/commands.py
>> @@ -237,7 +237,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
>>          QAPISchemaModularCVisitor.__init__(
>>              self, prefix, 'qapi-commands',
>>              ' * Schema-defined QAPI/QMP commands', __doc__)
>> -        self._regy = ''
>> +        self._regy = QAPIGenCSnippet()
>>          self._visited_ret_types = {}
>>  
>>      def _begin_module(self, name):
>> @@ -273,19 +273,20 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
>>  void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
>>  ''',
>>                         c_prefix=c_name(self._prefix, protect=False)))
>> -        genc.add(gen_registry(self._regy, self._prefix))
>> +        genc.add(gen_registry(self._regy.get_content(), self._prefix))
>>  
>>      def visit_command(self, name, info, ifcond, arg_type, ret_type,
>>                        gen, success_response, boxed, allow_oob):
>>          if not gen:
>>              return
>> -        self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type))
>> -        if ret_type and ret_type not in self._visited_ret_types[self._genc]:
>> -            self._visited_ret_types[self._genc].add(ret_type)
>> -            self._genc.add(gen_marshal_output(ret_type))
>> -        self._genh.add(gen_marshal_decl(name))
>> -        self._genc.add(gen_marshal(name, arg_type, boxed, ret_type))
>> -        self._regy += gen_register_command(name, success_response, allow_oob)
>> +        with ifcontext(ifcond, self._genh, self._genc, self._regy):
>> +            self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type))
>> +            if ret_type and ret_type not in self._visited_ret_types[self._genc]:
>> +                self._visited_ret_types[self._genc].add(ret_type)
>> +                self._genc.add(gen_marshal_output(ret_type))
>
> I'm afraid this falls apart when multiple commands with different
> conditions share a return type.

If you'd rather fix this later, we can consider just documenting the bug
for now.

> That case needs test coverage.

Needed regardless.

[...]

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 19/49] qapi: factor out check_known_keys()
  2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 19/49] qapi: factor out check_known_keys() Marc-André Lureau
@ 2018-06-25 14:10   ` Markus Armbruster
  0 siblings, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-25 14:10 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, armbru

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> The following patches are going to need similar checks from various
> code path. This refactoring will report all conflicting keys (instead
> of the first one encountered).
>
> Modify unknown-expr-key to check plural form.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi/common.py                  | 27 ++++++++++++++++++-------
>  tests/qapi-schema/alternate-base.err    |  2 +-
>  tests/qapi-schema/double-type.err       |  2 +-
>  tests/qapi-schema/enum-missing-data.err |  2 +-
>  tests/qapi-schema/unknown-expr-key.err  |  2 +-
>  tests/qapi-schema/unknown-expr-key.json |  2 +-
>  6 files changed, 25 insertions(+), 12 deletions(-)
>
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index 4d19146064..fdbb5f1823 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -879,6 +879,24 @@ def check_struct(expr, info):
>                 allow_metas=['struct'])
>  
>  
> +def check_known_keys(info, source, keys, required, optional):
> +
> +    def pprint(elems):
> +        return ', '.join("'" + e + "'" for e in sorted(elems))
> +
> +    missing = set(required) - set(keys)
> +    if missing:
> +        raise QAPISemError(info, "%s must have %s key%s"
> +                           % (source, pprint(missing),
> +                              's' if len(missing) > 1 else ''))
> +    allowed = set(required + optional)
> +    unknown = set(keys) - allowed
> +    if unknown:
> +        raise QAPISemError(info, "%s has unknown key%s %s (allowed: %s)"
> +                           % (source, 's' if len(unknown) > 1 else '',
> +                              pprint(unknown), pprint(allowed)))
> +
> +
>  def check_keys(expr_elem, meta, required, optional=[]):
>      expr = expr_elem['expr']
>      info = expr_elem['info']
> @@ -886,10 +904,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, 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 == 'gen' or key == 'success-response') and value is not False:
>              raise QAPISemError(info,
>                                 "'%s' of %s '%s' should only use false value"
> @@ -900,10 +917,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):
> diff --git a/tests/qapi-schema/alternate-base.err b/tests/qapi-schema/alternate-base.err
> index 30d8a34373..2b09c4c7a3 100644
> --- a/tests/qapi-schema/alternate-base.err
> +++ b/tests/qapi-schema/alternate-base.err
> @@ -1 +1 @@
> -tests/qapi-schema/alternate-base.json:4: Unknown key 'base' in alternate 'Alt'
> +tests/qapi-schema/alternate-base.json:4: alternate 'Alt' has unknown key 'base' (allowed: 'alternate', 'data', 'if')

The change in the error message proper, i.e. up to the parenthesis,
doesn't feel like an improvment to me.  The old message starts with
what's wrong.  The new one starts with where's something wrong.

I'd do the parenthesis with error_append_hint(), and say something like
"Valid keys are ...".  See below for a more complete example.

> diff --git a/tests/qapi-schema/double-type.err b/tests/qapi-schema/double-type.err
> index f9613c6d6b..a8c5637659 100644
> --- a/tests/qapi-schema/double-type.err
> +++ b/tests/qapi-schema/double-type.err
> @@ -1 +1 @@
> -tests/qapi-schema/double-type.json:2: Unknown key 'command' in struct 'bar'
> +tests/qapi-schema/double-type.json:2: struct 'bar' has unknown key 'command' (allowed: 'base', 'data', 'if', 'struct')
> diff --git a/tests/qapi-schema/enum-missing-data.err b/tests/qapi-schema/enum-missing-data.err
> index ba4873ae69..68e286badc 100644
> --- a/tests/qapi-schema/enum-missing-data.err
> +++ b/tests/qapi-schema/enum-missing-data.err
> @@ -1 +1 @@
> -tests/qapi-schema/enum-missing-data.json:2: Key 'data' is missing from enum 'MyEnum'
> +tests/qapi-schema/enum-missing-data.json:2: enum 'MyEnum' must have 'data' key

Again, the error message change doesn't feel like an improvement to me.

> diff --git a/tests/qapi-schema/unknown-expr-key.err b/tests/qapi-schema/unknown-expr-key.err
> index 12f5ed5b43..d9f4e41cac 100644
> --- a/tests/qapi-schema/unknown-expr-key.err
> +++ b/tests/qapi-schema/unknown-expr-key.err
> @@ -1 +1 @@
> -tests/qapi-schema/unknown-expr-key.json:2: Unknown key 'bogus' in struct 'bar'
> +tests/qapi-schema/unknown-expr-key.json:2: struct 'bar' has unknown keys 'bogus', 'foo' (allowed: 'base', 'data', 'if', 'struct')
> diff --git a/tests/qapi-schema/unknown-expr-key.json b/tests/qapi-schema/unknown-expr-key.json

Suggest something like

    tests/qapi-schema/unknown-expr-key.json:2: Unknown keys 'bogus', 'foo' in struct 'bar'
    Valid keys are 'base', 'data', 'if', 'struct'.

> index 3b2be00cc4..5bcb8efd1d 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': { }, 'foo': { } }

The patch does two things: 1. factor out a helper for later use in other
places, 2. report all offending keys instead of just the first one.
Split it up, please.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 05/49] qapi: leave the ifcond attribute undefined until check()
  2018-06-19  9:06   ` Markus Armbruster
@ 2018-06-26 13:39     ` Marc-André Lureau
  2018-06-27  5:26       ` Markus Armbruster
  0 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-06-26 13:39 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: QEMU

Hi

On Tue, Jun 19, 2018 at 11:06 AM, Markus Armbruster <armbru@redhat.com> wrote:
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
>> We commonly initialize attributes to None in .init(), then set their
>> real value in .check().  Accessing the attribute before .check()
>> yields None.  If we're lucky, the code that accesses the attribute
>> prematurely chokes on None.
>>
>> It won't for .ifcond, because None is a legitimate value.
>>
>> Leave the ifcond attribute undefined until check().
>
> Drawback: pylint complains.  We'll live.
>
>>
>> Suggested-by: Markus Armbruster <armbru@redhat.com>
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> Reviewed-by: Markus Armbruster <armbru@redhat.com>
>
> Shouldn't this be squashed into the previous patch?

I would rather keep it seperate, as it makes reviewing both a bit
easier to me. But feel free to squash on commit.

>
>> ---
>>  scripts/qapi/common.py | 21 +++++++++++++++++----
>>  1 file changed, 17 insertions(+), 4 deletions(-)
>>
>> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
>> index d8ab3d8f7f..eb07d641ab 100644
>> --- a/scripts/qapi/common.py
>> +++ b/scripts/qapi/common.py
>> @@ -1026,13 +1026,19 @@ class QAPISchemaEntity(object):
>>          # such place).
>>          self.info = info
>>          self.doc = doc
>> -        self.ifcond = listify_cond(ifcond)
>> +        self._ifcond = ifcond  # self.ifcond is set only after .check()
>>
>>      def c_name(self):
>>          return c_name(self.name)
>>
>>      def check(self, schema):
>> -        pass
>> +        if isinstance(self._ifcond, QAPISchemaType):
>> +            # inherit the condition from a type
>> +            typ = self._ifcond
>> +            typ.check(schema)
>> +            self.ifcond = typ.ifcond
>> +        else:
>> +            self.ifcond = listify_cond(self._ifcond)
>
> Whenever we add a .check(), we need to prove QAPISchema.check()'s
> recursion still terminates, and terminates the right way.
>
> Argument before this patch: we recurse only into types contained in
> types, e.g. an object type's base type, and we detect and report cycles
> as "Object %s contains itself", in QAPISchemaObjectType.check().
>
> The .check() added here recurses into a type.  If this creates a cycle,
> it'll be caught and reported as "contains itself".  We still need to
> show that the error message remains accurate.
>
> We .check() here to inherit .ifcond from a type.  As far as I can tell,
> we use this inheritance feature only to inherit an array's condition
> from its element type.  That's safe, because an array does contain its
> elements.
>
> This is hardly a rigorous proof.  Just enough to make me believe your
> code works.
>
> However, I suspect adding the inheritance feature at the entity level
> complicates the correctness argument without real need.  Can we restrict
> it to array elements?  Have QAPISchemaArrayType.check() resolve
> type-valued ._ifcond, and all the others choke on it?

There is also implicit object types.

>
>>
>>      def is_implicit(self):
>>          return not self.info
>> @@ -1169,6 +1175,7 @@ class QAPISchemaEnumType(QAPISchemaType):
>>          self.prefix = prefix
>>
>>      def check(self, schema):
>> +        QAPISchemaType.check(self, schema)
>>          seen = {}
>>          for v in self.values:
>>              v.check_clash(self.info, seen)
>> @@ -1201,8 +1208,10 @@ class QAPISchemaArrayType(QAPISchemaType):
>>          self.element_type = None
>>
>>      def check(self, schema):
>> +        QAPISchemaType.check(self, schema)
>>          self.element_type = schema.lookup_type(self._element_type_name)
>>          assert self.element_type
>> +        self.element_type.check(schema)
>>          self.ifcond = self.element_type.ifcond
>>
>>      def is_implicit(self):
>> @@ -1245,6 +1254,7 @@ class QAPISchemaObjectType(QAPISchemaType):
>>          self.members = None
>>
>>      def check(self, schema):
>> +        QAPISchemaType.check(self, schema)
>>          if self.members is False:               # check for cycles
>>              raise QAPISemError(self.info,
>>                                 "Object %s contains itself" % self.name)
>> @@ -1427,6 +1437,7 @@ class QAPISchemaAlternateType(QAPISchemaType):
>>          self.variants = variants
>>
>>      def check(self, schema):
>> +        QAPISchemaType.check(self, schema)
>>          self.variants.tag_member.check(schema)
>>          # Not calling self.variants.check_clash(), because there's nothing
>>          # to clash with
>> @@ -1470,6 +1481,7 @@ class QAPISchemaCommand(QAPISchemaEntity):
>>          self.allow_oob = allow_oob
>>
>>      def check(self, schema):
>> +        QAPISchemaEntity.check(self, schema)
>>          if self._arg_type_name:
>>              self.arg_type = schema.lookup_type(self._arg_type_name)
>>              assert (isinstance(self.arg_type, QAPISchemaObjectType) or
>> @@ -1504,6 +1516,7 @@ class QAPISchemaEvent(QAPISchemaEntity):
>>          self.boxed = boxed
>>
>>      def check(self, schema):
>> +        QAPISchemaEntity.check(self, schema)
>>          if self._arg_type_name:
>>              self.arg_type = schema.lookup_type(self._arg_type_name)
>>              assert (isinstance(self.arg_type, QAPISchemaObjectType) or
>> @@ -1633,7 +1646,7 @@ class QAPISchema(object):
>>              # But it's not tight: the disjunction need not imply it.  We
>>              # may end up compiling useless wrapper types.
>>              # TODO kill simple unions or implement the disjunction
>> -            assert ifcond == typ.ifcond
>> +            assert ifcond == typ._ifcond
>
> pylint complains
>
>     W:1649,29: Access to a protected member _ifcond of a client class (protected-access)
>
> Layering violation.  Tolerable, I think.
>

yeah, alternative would be to add an assert_ifcond() method in type..?
I'll add a # pylint: disable=protected-access for now

>>              self._def_entity(QAPISchemaObjectType(name, info, doc, ifcond,
>>                                                    None, members, None))
>> @@ -1679,7 +1692,7 @@ class QAPISchema(object):
>>              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).ifcond,
>> +            typ, info, None, self.lookup_type(typ),
>>              'wrapper', [self._make_member('data', typ, info)])
>>          return QAPISchemaObjectTypeVariant(case, typ)
>
> Perhaps other attributes that become valid only at .check() time should
> receive the same treatment.  Not necessarily in this series, not
> necessarily by you.  A TODO comment wouldn't hurt, though.
>

It doesn't look obvious to me which should receive the same
treatement. I'll leave that to you to figure out :)


-- 
Marc-André Lureau

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 05/49] qapi: leave the ifcond attribute undefined until check()
  2018-06-26 13:39     ` Marc-André Lureau
@ 2018-06-27  5:26       ` Markus Armbruster
  2018-06-29 10:30         ` Marc-André Lureau
  0 siblings, 1 reply; 95+ messages in thread
From: Markus Armbruster @ 2018-06-27  5:26 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: Markus Armbruster, QEMU

Marc-André Lureau <marcandre.lureau@gmail.com> writes:

> Hi
>
> On Tue, Jun 19, 2018 at 11:06 AM, Markus Armbruster <armbru@redhat.com> wrote:
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>
>>> We commonly initialize attributes to None in .init(), then set their
>>> real value in .check().  Accessing the attribute before .check()
>>> yields None.  If we're lucky, the code that accesses the attribute
>>> prematurely chokes on None.
>>>
>>> It won't for .ifcond, because None is a legitimate value.
>>>
>>> Leave the ifcond attribute undefined until check().
>>
>> Drawback: pylint complains.  We'll live.
>>
>>>
>>> Suggested-by: Markus Armbruster <armbru@redhat.com>
>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>>> Reviewed-by: Markus Armbruster <armbru@redhat.com>
>>
>> Shouldn't this be squashed into the previous patch?
>
> I would rather keep it seperate, as it makes reviewing both a bit
> easier to me. But feel free to squash on commit.

No need to decide right now.

>>
>>> ---
>>>  scripts/qapi/common.py | 21 +++++++++++++++++----
>>>  1 file changed, 17 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
>>> index d8ab3d8f7f..eb07d641ab 100644
>>> --- a/scripts/qapi/common.py
>>> +++ b/scripts/qapi/common.py
>>> @@ -1026,13 +1026,19 @@ class QAPISchemaEntity(object):
>>>          # such place).
>>>          self.info = info
>>>          self.doc = doc
>>> -        self.ifcond = listify_cond(ifcond)
>>> +        self._ifcond = ifcond  # self.ifcond is set only after .check()
>>>
>>>      def c_name(self):
>>>          return c_name(self.name)
>>>
>>>      def check(self, schema):
>>> -        pass
>>> +        if isinstance(self._ifcond, QAPISchemaType):
>>> +            # inherit the condition from a type
>>> +            typ = self._ifcond
>>> +            typ.check(schema)
>>> +            self.ifcond = typ.ifcond
>>> +        else:
>>> +            self.ifcond = listify_cond(self._ifcond)
>>
>> Whenever we add a .check(), we need to prove QAPISchema.check()'s
>> recursion still terminates, and terminates the right way.
>>
>> Argument before this patch: we recurse only into types contained in
>> types, e.g. an object type's base type, and we detect and report cycles
>> as "Object %s contains itself", in QAPISchemaObjectType.check().
>>
>> The .check() added here recurses into a type.  If this creates a cycle,
>> it'll be caught and reported as "contains itself".  We still need to
>> show that the error message remains accurate.
>>
>> We .check() here to inherit .ifcond from a type.  As far as I can tell,
>> we use this inheritance feature only to inherit an array's condition
>> from its element type.  That's safe, because an array does contain its
>> elements.
>>
>> This is hardly a rigorous proof.  Just enough to make me believe your
>> code works.
>>
>> However, I suspect adding the inheritance feature at the entity level
>> complicates the correctness argument without real need.  Can we restrict
>> it to array elements?  Have QAPISchemaArrayType.check() resolve
>> type-valued ._ifcond, and all the others choke on it?
>
> There is also implicit object types.

Can you give an example?

>>>
>>>      def is_implicit(self):
>>>          return not self.info
>>> @@ -1169,6 +1175,7 @@ class QAPISchemaEnumType(QAPISchemaType):
>>>          self.prefix = prefix
>>>
>>>      def check(self, schema):
>>> +        QAPISchemaType.check(self, schema)
>>>          seen = {}
>>>          for v in self.values:
>>>              v.check_clash(self.info, seen)
>>> @@ -1201,8 +1208,10 @@ class QAPISchemaArrayType(QAPISchemaType):
>>>          self.element_type = None
>>>
>>>      def check(self, schema):
>>> +        QAPISchemaType.check(self, schema)
>>>          self.element_type = schema.lookup_type(self._element_type_name)
>>>          assert self.element_type
>>> +        self.element_type.check(schema)
>>>          self.ifcond = self.element_type.ifcond
>>>
>>>      def is_implicit(self):
>>> @@ -1245,6 +1254,7 @@ class QAPISchemaObjectType(QAPISchemaType):
>>>          self.members = None
>>>
>>>      def check(self, schema):
>>> +        QAPISchemaType.check(self, schema)
>>>          if self.members is False:               # check for cycles
>>>              raise QAPISemError(self.info,
>>>                                 "Object %s contains itself" % self.name)
>>> @@ -1427,6 +1437,7 @@ class QAPISchemaAlternateType(QAPISchemaType):
>>>          self.variants = variants
>>>
>>>      def check(self, schema):
>>> +        QAPISchemaType.check(self, schema)
>>>          self.variants.tag_member.check(schema)
>>>          # Not calling self.variants.check_clash(), because there's nothing
>>>          # to clash with
>>> @@ -1470,6 +1481,7 @@ class QAPISchemaCommand(QAPISchemaEntity):
>>>          self.allow_oob = allow_oob
>>>
>>>      def check(self, schema):
>>> +        QAPISchemaEntity.check(self, schema)
>>>          if self._arg_type_name:
>>>              self.arg_type = schema.lookup_type(self._arg_type_name)
>>>              assert (isinstance(self.arg_type, QAPISchemaObjectType) or
>>> @@ -1504,6 +1516,7 @@ class QAPISchemaEvent(QAPISchemaEntity):
>>>          self.boxed = boxed
>>>
>>>      def check(self, schema):
>>> +        QAPISchemaEntity.check(self, schema)
>>>          if self._arg_type_name:
>>>              self.arg_type = schema.lookup_type(self._arg_type_name)
>>>              assert (isinstance(self.arg_type, QAPISchemaObjectType) or
>>> @@ -1633,7 +1646,7 @@ class QAPISchema(object):
>>>              # But it's not tight: the disjunction need not imply it.  We
>>>              # may end up compiling useless wrapper types.
>>>              # TODO kill simple unions or implement the disjunction
>>> -            assert ifcond == typ.ifcond
>>> +            assert ifcond == typ._ifcond
>>
>> pylint complains
>>
>>     W:1649,29: Access to a protected member _ifcond of a client class (protected-access)
>>
>> Layering violation.  Tolerable, I think.
>>
>
> yeah, alternative would be to add an assert_ifcond() method in type..?
> I'll add a # pylint: disable=protected-access for now

Wortwhile only if we make an effort to clean up or suppress the other
pylint gripes.  I'll look into it.  Go ahead and add the directive
meanwhile; easily dropped it if we decide we don't want it.

>>>              self._def_entity(QAPISchemaObjectType(name, info, doc, ifcond,
>>>                                                    None, members, None))
>>> @@ -1679,7 +1692,7 @@ class QAPISchema(object):
>>>              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).ifcond,
>>> +            typ, info, None, self.lookup_type(typ),
>>>              'wrapper', [self._make_member('data', typ, info)])
>>>          return QAPISchemaObjectTypeVariant(case, typ)
>>
>> Perhaps other attributes that become valid only at .check() time should
>> receive the same treatment.  Not necessarily in this series, not
>> necessarily by you.  A TODO comment wouldn't hurt, though.
>>
>
> It doesn't look obvious to me which should receive the same
> treatement. I'll leave that to you to figure out :)

Fair enough.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 14/49] qapi-types: add #if conditions to types & visitors
  2018-06-21 16:12   ` Markus Armbruster
@ 2018-06-27 11:59     ` Marc-André Lureau
  2018-06-28  6:27       ` Markus Armbruster
  0 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-06-27 11:59 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: QEMU

Hi

On Thu, Jun 21, 2018 at 6:12 PM, Markus Armbruster <armbru@redhat.com> wrote:
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
>> Types & visitors are coupled and must be handled together to avoid
>> temporary build regression.
>>
>> Wrap generated types/visitor code with #if/#endif using the context
>> helpers.
>>
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> ---
>>  scripts/qapi/types.py | 46 ++++++++++++++++++++++++++-----------------
>>  scripts/qapi/visit.py | 33 ++++++++++++++++++-------------
>>  2 files changed, 47 insertions(+), 32 deletions(-)
>>
>> diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
>> index 3d9b0f9a07..ce4c91206c 100644
>> --- a/scripts/qapi/types.py
>> +++ b/scripts/qapi/types.py
>> @@ -61,8 +61,10 @@ def gen_variants_objects(variants):
>>          for v in variants.variants:
>>              if isinstance(v.type, QAPISchemaObjectType):
>>                  ret += gen_variants_objects(v.type.variants)
>> +                ret += gen_if(v.type.ifcond)
>>                  ret += gen_object(v.type.name, v.type.base,
>>                                    v.type.local_members, v.type.variants)
>> +                ret += gen_endif(v.type.ifcond)
>
> Ignorant question out of curiosity, why is with ifcontext() not usable
> here?
>

ifcontext() works on QAPIGen objects. We could make it work on strings
too, but I don't think it's necessary.

>>      return ret
>>
>>
>> @@ -206,41 +208,49 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
>>          # gen_object() is recursive, ensure it doesn't visit the empty type
>>          objects_seen.add(schema.the_empty_object_type.name)
>>
>> -    def _gen_type_cleanup(self, name):
>> -        self._genh.add(gen_type_cleanup_decl(name))
>> -        self._genc.add(gen_type_cleanup(name))
>> +    def _gen_type_cleanup(self, name, ifcond):
>> +        with ifcontext(ifcond, self._genh, self._genc):
>> +            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):
>> -        self._genh.preamble_add(gen_enum(name, values, prefix))
>> -        self._genc.add(gen_enum_lookup(name, values, prefix))
>> +        with ifcontext(ifcond, self._genh, self._genc):
>> +            self._genh.preamble_add(gen_enum(name, values, prefix))
>> +            self._genc.add(gen_enum_lookup(name, values, prefix))
>>
>>      def visit_array_type(self, name, info, ifcond, element_type):
>> -        self._genh.preamble_add(gen_fwd_object_or_array(name))
>> -        self._genh.add(gen_array(name, element_type))
>> -        self._gen_type_cleanup(name)
>> +        with ifcontext(ifcond, self._genh):
>> +            self._genh.preamble_add(gen_fwd_object_or_array(name))
>> +            self._genh.add(gen_array(name, element_type))
>> +        self._gen_type_cleanup(name, ifcond)
>>
>>      def _gen_object(self, name, info, ifcond, base, members, variants):
>> -        self._genh.add(gen_object(name, base, members, variants))
>> -        if base and not base.is_implicit():
>> -            self._genh.add(gen_upcast(name, base))
>> -        # TODO Worth changing the visitor signature, so we could
>> -        # directly use rather than repeat type.is_implicit()?
>> +        with ifcontext(ifcond, self._genh):
>> +            self._genh.add(gen_object(name, base, members, variants))
>> +            if base and not base.is_implicit():
>> +                self._genh.add(gen_upcast(name, base))
>> +            # TODO Worth changing the visitor signature, so we could
>> +            # directly use rather than repeat type.is_implicit()?
>>          if not name.startswith('q_'):
>>              # implicit types won't be directly allocated/freed
>> -            self._gen_type_cleanup(name)
>> +            self._gen_type_cleanup(name, ifcond)
>> +
>> +    def _gen_fwd_object_or_array(self, name, ifcond):
>> +        with ifcontext(ifcond, self._genh):
>> +            self._genh.preamble_add(gen_fwd_object_or_array(name))
>>
>>      def visit_object_type(self, name, info, ifcond, base, members, variants):
>>          # Nothing to do for the special empty builtin
>>          if name == 'q_empty':
>>              return
>> -        self._genh.preamble_add(gen_fwd_object_or_array(name))
>> +        self._gen_fwd_object_or_array(name, ifcond)
>>          self._genh.add(gen_variants_objects(variants))
>> -        self._gen_object(name, info, None, base, members, variants)
>> +        self._gen_object(name, info, ifcond, base, members, variants)
>>
>>      def visit_alternate_type(self, name, info, ifcond, variants):
>> -        self._genh.preamble_add(gen_fwd_object_or_array(name))
>> +        self._gen_fwd_object_or_array(name, ifcond)
>>          self._genh.add(gen_variants_objects(variants))
>> -        self._gen_object(name, info, None, None,
>> +        self._gen_object(name, info, ifcond, None,
>>                           [variants.tag_member], variants)
>>
>>
>> diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
>> index 9ea2e04f81..e4a62ce030 100644
>> --- a/scripts/qapi/visit.py
>> +++ b/scripts/qapi/visit.py
>> @@ -302,29 +302,34 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
>>                                        types=types))
>>
>>      def visit_enum_type(self, name, info, ifcond, values, prefix):
>> -        self._genh.add(gen_visit_decl(name, scalar=True))
>> -        self._genc.add(gen_visit_enum(name))
>> +        with ifcontext(ifcond, self._genh, self._genc):
>> +            self._genh.add(gen_visit_decl(name, scalar=True))
>> +            self._genc.add(gen_visit_enum(name))
>>
>>      def visit_array_type(self, name, info, ifcond, element_type):
>> -        self._genh.add(gen_visit_decl(name))
>> -        self._genc.add(gen_visit_list(name, element_type))
>> +        with ifcontext(ifcond, self._genh, self._genc):
>> +            self._genh.add(gen_visit_decl(name))
>> +            self._genc.add(gen_visit_list(name, element_type))
>>
>>      def visit_object_type(self, name, info, ifcond, base, members, variants):
>>          # Nothing to do for the special empty builtin
>>          if name == 'q_empty':
>>              return
>> -        self._genh.add(gen_visit_members_decl(name))
>> -        self._genc.add(gen_visit_object_members(name, base, members, variants))
>> -        # TODO Worth changing the visitor signature, so we could
>> -        # directly use rather than repeat type.is_implicit()?
>> -        if not name.startswith('q_'):
>> -            # only explicit types need an allocating visit
>> -            self._genh.add(gen_visit_decl(name))
>> -            self._genc.add(gen_visit_object(name, base, members, variants))
>> +        with ifcontext(ifcond, self._genh, self._genc):
>> +            self._genh.add(gen_visit_members_decl(name))
>> +            self._genc.add(gen_visit_object_members(name, base,
>> +                                                    members, variants))
>> +            # TODO Worth changing the visitor signature, so we could
>> +            # directly use rather than repeat type.is_implicit()?
>> +            if not name.startswith('q_'):
>> +                # only explicit types need an allocating visit
>> +                self._genh.add(gen_visit_decl(name))
>> +                self._genc.add(gen_visit_object(name, base, members, variants))
>>
>>      def visit_alternate_type(self, name, info, ifcond, variants):
>> -        self._genh.add(gen_visit_decl(name))
>> -        self._genc.add(gen_visit_alternate(name, variants))
>> +        with ifcontext(ifcond, self._genh, self._genc):
>> +            self._genh.add(gen_visit_decl(name))
>> +            self._genc.add(gen_visit_alternate(name, variants))
>>
>>
>>  def gen_visit(schema, output_dir, prefix, opt_builtins):
>
> The visit part is straightforward: wrap code generation in with
> ifcontext().
>
> The type part is more involved.  First, it passes ifcond to a bunch of
> helpers, which muddies the waters a bit.  Second, you can't just wrap
> object types generation, because it's recursive.  You move the recursion
> out of gen_object() (previous patch), so you can wrap that.  But you
> still can't wrap its new home, gen_variants_objects().  Instead, you
> bracket its call of gen_object() with gen_if() ... gen_endif().  Works,
> but is there a more direct path to the same result?
>
> I append my attempt.  Its basic idea is to wrap code generation right
> where it is.  Requires passing ifcond to gen_object().  The patch to
> visit.py is identical.
>
> Less churn, and I it saves me reviewing the previous patch.  Opinions?


Looks good to me. I think the churn was necessary before, when we used
the function decorator. Now that we can scope the if/endif at the
block level, we don't need it anymore.

>
>
> From d6f26abe5a81b10aaff5c75db3bfc60c05203f05 Mon Sep 17 00:00:00 2001
> From: Markus Armbruster <armbru@redhat.com>
> Date: Thu, 21 Jun 2018 18:03:41 +0200
> Subject: [PATCH] qapi-types: add #if conditions to types & visitors
>
> Types & visitors are coupled and must be handled together to avoid
> temporary build regression.
>
> Wrap generated types/visitor code with #if/#endif using the context
> helpers.
>
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

I'll take it with my signed-off, since it shares a lot of similarities
with my patch.

thanks!

> ---
>  scripts/qapi/types.py | 48 ++++++++++++++++++++++++++-----------------
>  scripts/qapi/visit.py | 33 ++++++++++++++++-------------
>  2 files changed, 48 insertions(+), 33 deletions(-)
>
> diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
> index 298a80db62..e43138bfd7 100644
> --- a/scripts/qapi/types.py
> +++ b/scripts/qapi/types.py
> @@ -55,7 +55,7 @@ def gen_struct_members(members):
>      return ret
>
>
> -def gen_object(name, base, members, variants):
> +def gen_object(name, ifcond, base, members, variants):
>      if name in objects_seen:
>          return ''
>      objects_seen.add(name)
> @@ -64,11 +64,14 @@ def gen_object(name, base, members, variants):
>      if variants:
>          for v in variants.variants:
>              if isinstance(v.type, QAPISchemaObjectType):
> -                ret += gen_object(v.type.name, v.type.base,
> +                ret += gen_object(v.type.name, v.type.ifcond, v.type.base,
>                                    v.type.local_members, v.type.variants)
>
>      ret += mcgen('''
>
> +''')
> +    ret += gen_if(ifcond)
> +    ret += mcgen('''
>  struct %(c_name)s {
>  ''',
>                   c_name=c_name(name))
> @@ -101,6 +104,7 @@ struct %(c_name)s {
>      ret += mcgen('''
>  };
>  ''')
> +    ret += gen_endif(ifcond)
>
>      return ret
>
> @@ -207,33 +211,39 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
>          self._genc.add(gen_type_cleanup(name))
>
>      def visit_enum_type(self, name, info, ifcond, values, prefix):
> -        self._genh.preamble_add(gen_enum(name, values, prefix))
> -        self._genc.add(gen_enum_lookup(name, values, prefix))
> +        with ifcontext(ifcond, self._genh, self._genc):
> +            self._genh.preamble_add(gen_enum(name, values, prefix))
> +            self._genc.add(gen_enum_lookup(name, values, prefix))
>
>      def visit_array_type(self, name, info, ifcond, element_type):
> -        self._genh.preamble_add(gen_fwd_object_or_array(name))
> -        self._genh.add(gen_array(name, element_type))
> -        self._gen_type_cleanup(name)
> +        with ifcontext(ifcond, self._genh, self._genc):
> +            self._genh.preamble_add(gen_fwd_object_or_array(name))
> +            self._genh.add(gen_array(name, element_type))
> +            self._gen_type_cleanup(name)
>
>      def visit_object_type(self, name, info, ifcond, base, members, variants):
>          # Nothing to do for the special empty builtin
>          if name == 'q_empty':
>              return
> -        self._genh.preamble_add(gen_fwd_object_or_array(name))
> -        self._genh.add(gen_object(name, base, members, variants))
> -        if base and not base.is_implicit():
> -            self._genh.add(gen_upcast(name, base))
> -        # TODO Worth changing the visitor signature, so we could
> -        # directly use rather than repeat type.is_implicit()?
> -        if not name.startswith('q_'):
> -            # implicit types won't be directly allocated/freed
> -            self._gen_type_cleanup(name)
> +        with ifcontext(ifcond, self._genh):
> +            self._genh.preamble_add(gen_fwd_object_or_array(name))
> +        self._genh.add(gen_object(name, ifcond, base, members, variants))
> +        with ifcontext(ifcond, self._genh, self._genc):
> +            if base and not base.is_implicit():
> +                self._genh.add(gen_upcast(name, base))
> +            # TODO Worth changing the visitor signature, so we could
> +            # directly use rather than repeat type.is_implicit()?
> +            if not name.startswith('q_'):
> +                # implicit types won't be directly allocated/freed
> +                self._gen_type_cleanup(name)
>
>      def visit_alternate_type(self, name, info, ifcond, variants):
> -        self._genh.preamble_add(gen_fwd_object_or_array(name))
> -        self._genh.add(gen_object(name, None,
> +        with ifcontext(ifcond, self._genh):
> +            self._genh.preamble_add(gen_fwd_object_or_array(name))
> +        self._genh.add(gen_object(name, ifcond, None,
>                                    [variants.tag_member], variants))
> -        self._gen_type_cleanup(name)
> +        with ifcontext(ifcond, self._genh, self._genc):
> +            self._gen_type_cleanup(name)
>
>
>  def gen_types(schema, output_dir, prefix, opt_builtins):
> diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
> index 9ea2e04f81..e4a62ce030 100644
> --- a/scripts/qapi/visit.py
> +++ b/scripts/qapi/visit.py
> @@ -302,29 +302,34 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
>                                        types=types))
>
>      def visit_enum_type(self, name, info, ifcond, values, prefix):
> -        self._genh.add(gen_visit_decl(name, scalar=True))
> -        self._genc.add(gen_visit_enum(name))
> +        with ifcontext(ifcond, self._genh, self._genc):
> +            self._genh.add(gen_visit_decl(name, scalar=True))
> +            self._genc.add(gen_visit_enum(name))
>
>      def visit_array_type(self, name, info, ifcond, element_type):
> -        self._genh.add(gen_visit_decl(name))
> -        self._genc.add(gen_visit_list(name, element_type))
> +        with ifcontext(ifcond, self._genh, self._genc):
> +            self._genh.add(gen_visit_decl(name))
> +            self._genc.add(gen_visit_list(name, element_type))
>
>      def visit_object_type(self, name, info, ifcond, base, members, variants):
>          # Nothing to do for the special empty builtin
>          if name == 'q_empty':
>              return
> -        self._genh.add(gen_visit_members_decl(name))
> -        self._genc.add(gen_visit_object_members(name, base, members, variants))
> -        # TODO Worth changing the visitor signature, so we could
> -        # directly use rather than repeat type.is_implicit()?
> -        if not name.startswith('q_'):
> -            # only explicit types need an allocating visit
> -            self._genh.add(gen_visit_decl(name))
> -            self._genc.add(gen_visit_object(name, base, members, variants))
> +        with ifcontext(ifcond, self._genh, self._genc):
> +            self._genh.add(gen_visit_members_decl(name))
> +            self._genc.add(gen_visit_object_members(name, base,
> +                                                    members, variants))
> +            # TODO Worth changing the visitor signature, so we could
> +            # directly use rather than repeat type.is_implicit()?
> +            if not name.startswith('q_'):
> +                # only explicit types need an allocating visit
> +                self._genh.add(gen_visit_decl(name))
> +                self._genc.add(gen_visit_object(name, base, members, variants))
>
>      def visit_alternate_type(self, name, info, ifcond, variants):
> -        self._genh.add(gen_visit_decl(name))
> -        self._genc.add(gen_visit_alternate(name, variants))
> +        with ifcontext(ifcond, self._genh, self._genc):
> +            self._genh.add(gen_visit_decl(name))
> +            self._genc.add(gen_visit_alternate(name, variants))
>
>
>  def gen_visit(schema, output_dir, prefix, opt_builtins):
> --
> 2.17.1
>
>



-- 
Marc-André Lureau

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 15/49] qapi: do not define enumeration value explicitely
  2018-06-22  8:08   ` Markus Armbruster
@ 2018-06-27 12:13     ` Marc-André Lureau
  2018-06-28  6:34       ` Markus Armbruster
  0 siblings, 1 reply; 95+ messages in thread
From: Marc-André Lureau @ 2018-06-27 12:13 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: QEMU

Hi

On Fri, Jun 22, 2018 at 10:08 AM, Markus Armbruster <armbru@redhat.com> wrote:
> Subject: explicitly
>
> 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.
>>
>> 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 60c1d0a783..68a567f53f 100644
>> --- a/scripts/qapi/common.py
>> +++ b/scripts/qapi/common.py
>> @@ -2032,14 +2032,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;
>
> What excactly in your series depends on this?
>
> What safeguards do you propose to ensure an enumeration with
> conditionals is compiled only with the exact same conditionals within
> the same program?
>
> Example of the kind of deathtrap to guard against: compile
>
>     typedef enum Color {
>         COLOR_WHITE,
> #if defined(NEED_CPU_H)
> #if defined(TARGET_S390X)
>         COLOR_BLUE,
> #endif /* defined(TARGET_S390X) */
> #endif /* defined(NEED_CPU_H) */
>         COLOR_BLACK,
>     } Color;
>
> in s390x-code (COLOR_BLACK = 2) and in target-independent code
> (COLOR_BLACK = 1), then linking the two together.

This was a trick used in previous iterations. Now that we have a
separate target schema and generated code/headers, and since we have
poisoned identifiers, this should never happen.

> Yes, I know a similar deathtrap will be set up for struct and union
> types.  No excuse for ignoring either of the two.

Having gaps in the enums makes it harder to iterate over all values,
and we use more memory than necessary when allocating based on MAX
value.

It's not a big problem, but I consider this more important than this
artificially made up broken build example.

-- 
Marc-André Lureau

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 14/49] qapi-types: add #if conditions to types & visitors
  2018-06-27 11:59     ` Marc-André Lureau
@ 2018-06-28  6:27       ` Markus Armbruster
  0 siblings, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-28  6:27 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: Markus Armbruster, QEMU

Marc-André Lureau <marcandre.lureau@gmail.com> writes:

> Hi
>
> On Thu, Jun 21, 2018 at 6:12 PM, Markus Armbruster <armbru@redhat.com> wrote:
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>
>>> Types & visitors are coupled and must be handled together to avoid
>>> temporary build regression.
>>>
>>> Wrap generated types/visitor code with #if/#endif using the context
>>> helpers.
>>>
>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>>> ---
>>>  scripts/qapi/types.py | 46 ++++++++++++++++++++++++++-----------------
>>>  scripts/qapi/visit.py | 33 ++++++++++++++++++-------------
>>>  2 files changed, 47 insertions(+), 32 deletions(-)
>>>
>>> diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
>>> index 3d9b0f9a07..ce4c91206c 100644
>>> --- a/scripts/qapi/types.py
>>> +++ b/scripts/qapi/types.py
>>> @@ -61,8 +61,10 @@ def gen_variants_objects(variants):
>>>          for v in variants.variants:
>>>              if isinstance(v.type, QAPISchemaObjectType):
>>>                  ret += gen_variants_objects(v.type.variants)
>>> +                ret += gen_if(v.type.ifcond)
>>>                  ret += gen_object(v.type.name, v.type.base,
>>>                                    v.type.local_members, v.type.variants)
>>> +                ret += gen_endif(v.type.ifcond)
>>
>> Ignorant question out of curiosity, why is with ifcontext() not usable
>> here?
>>
>
> ifcontext() works on QAPIGen objects. We could make it work on strings
> too, but I don't think it's necessary.

I see.

>>>      return ret
>>>
>>>
>>> @@ -206,41 +208,49 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
>>>          # gen_object() is recursive, ensure it doesn't visit the empty type
>>>          objects_seen.add(schema.the_empty_object_type.name)
>>>
>>> -    def _gen_type_cleanup(self, name):
>>> -        self._genh.add(gen_type_cleanup_decl(name))
>>> -        self._genc.add(gen_type_cleanup(name))
>>> +    def _gen_type_cleanup(self, name, ifcond):
>>> +        with ifcontext(ifcond, self._genh, self._genc):
>>> +            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):
>>> -        self._genh.preamble_add(gen_enum(name, values, prefix))
>>> -        self._genc.add(gen_enum_lookup(name, values, prefix))
>>> +        with ifcontext(ifcond, self._genh, self._genc):
>>> +            self._genh.preamble_add(gen_enum(name, values, prefix))
>>> +            self._genc.add(gen_enum_lookup(name, values, prefix))
>>>
>>>      def visit_array_type(self, name, info, ifcond, element_type):
>>> -        self._genh.preamble_add(gen_fwd_object_or_array(name))
>>> -        self._genh.add(gen_array(name, element_type))
>>> -        self._gen_type_cleanup(name)
>>> +        with ifcontext(ifcond, self._genh):
>>> +            self._genh.preamble_add(gen_fwd_object_or_array(name))
>>> +            self._genh.add(gen_array(name, element_type))
>>> +        self._gen_type_cleanup(name, ifcond)
>>>
>>>      def _gen_object(self, name, info, ifcond, base, members, variants):
>>> -        self._genh.add(gen_object(name, base, members, variants))
>>> -        if base and not base.is_implicit():
>>> -            self._genh.add(gen_upcast(name, base))
>>> -        # TODO Worth changing the visitor signature, so we could
>>> -        # directly use rather than repeat type.is_implicit()?
>>> +        with ifcontext(ifcond, self._genh):
>>> +            self._genh.add(gen_object(name, base, members, variants))
>>> +            if base and not base.is_implicit():
>>> +                self._genh.add(gen_upcast(name, base))
>>> +            # TODO Worth changing the visitor signature, so we could
>>> +            # directly use rather than repeat type.is_implicit()?
>>>          if not name.startswith('q_'):
>>>              # implicit types won't be directly allocated/freed
>>> -            self._gen_type_cleanup(name)
>>> +            self._gen_type_cleanup(name, ifcond)
>>> +
>>> +    def _gen_fwd_object_or_array(self, name, ifcond):
>>> +        with ifcontext(ifcond, self._genh):
>>> +            self._genh.preamble_add(gen_fwd_object_or_array(name))
>>>
>>>      def visit_object_type(self, name, info, ifcond, base, members, variants):
>>>          # Nothing to do for the special empty builtin
>>>          if name == 'q_empty':
>>>              return
>>> -        self._genh.preamble_add(gen_fwd_object_or_array(name))
>>> +        self._gen_fwd_object_or_array(name, ifcond)
>>>          self._genh.add(gen_variants_objects(variants))
>>> -        self._gen_object(name, info, None, base, members, variants)
>>> +        self._gen_object(name, info, ifcond, base, members, variants)
>>>
>>>      def visit_alternate_type(self, name, info, ifcond, variants):
>>> -        self._genh.preamble_add(gen_fwd_object_or_array(name))
>>> +        self._gen_fwd_object_or_array(name, ifcond)
>>>          self._genh.add(gen_variants_objects(variants))
>>> -        self._gen_object(name, info, None, None,
>>> +        self._gen_object(name, info, ifcond, None,
>>>                           [variants.tag_member], variants)
>>>
>>>
>>> diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
>>> index 9ea2e04f81..e4a62ce030 100644
>>> --- a/scripts/qapi/visit.py
>>> +++ b/scripts/qapi/visit.py
>>> @@ -302,29 +302,34 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
>>>                                        types=types))
>>>
>>>      def visit_enum_type(self, name, info, ifcond, values, prefix):
>>> -        self._genh.add(gen_visit_decl(name, scalar=True))
>>> -        self._genc.add(gen_visit_enum(name))
>>> +        with ifcontext(ifcond, self._genh, self._genc):
>>> +            self._genh.add(gen_visit_decl(name, scalar=True))
>>> +            self._genc.add(gen_visit_enum(name))
>>>
>>>      def visit_array_type(self, name, info, ifcond, element_type):
>>> -        self._genh.add(gen_visit_decl(name))
>>> -        self._genc.add(gen_visit_list(name, element_type))
>>> +        with ifcontext(ifcond, self._genh, self._genc):
>>> +            self._genh.add(gen_visit_decl(name))
>>> +            self._genc.add(gen_visit_list(name, element_type))
>>>
>>>      def visit_object_type(self, name, info, ifcond, base, members, variants):
>>>          # Nothing to do for the special empty builtin
>>>          if name == 'q_empty':
>>>              return
>>> -        self._genh.add(gen_visit_members_decl(name))
>>> -        self._genc.add(gen_visit_object_members(name, base, members, variants))
>>> -        # TODO Worth changing the visitor signature, so we could
>>> -        # directly use rather than repeat type.is_implicit()?
>>> -        if not name.startswith('q_'):
>>> -            # only explicit types need an allocating visit
>>> -            self._genh.add(gen_visit_decl(name))
>>> -            self._genc.add(gen_visit_object(name, base, members, variants))
>>> +        with ifcontext(ifcond, self._genh, self._genc):
>>> +            self._genh.add(gen_visit_members_decl(name))
>>> +            self._genc.add(gen_visit_object_members(name, base,
>>> +                                                    members, variants))
>>> +            # TODO Worth changing the visitor signature, so we could
>>> +            # directly use rather than repeat type.is_implicit()?
>>> +            if not name.startswith('q_'):
>>> +                # only explicit types need an allocating visit
>>> +                self._genh.add(gen_visit_decl(name))
>>> +                self._genc.add(gen_visit_object(name, base, members, variants))
>>>
>>>      def visit_alternate_type(self, name, info, ifcond, variants):
>>> -        self._genh.add(gen_visit_decl(name))
>>> -        self._genc.add(gen_visit_alternate(name, variants))
>>> +        with ifcontext(ifcond, self._genh, self._genc):
>>> +            self._genh.add(gen_visit_decl(name))
>>> +            self._genc.add(gen_visit_alternate(name, variants))
>>>
>>>
>>>  def gen_visit(schema, output_dir, prefix, opt_builtins):
>>
>> The visit part is straightforward: wrap code generation in with
>> ifcontext().
>>
>> The type part is more involved.  First, it passes ifcond to a bunch of
>> helpers, which muddies the waters a bit.  Second, you can't just wrap
>> object types generation, because it's recursive.  You move the recursion
>> out of gen_object() (previous patch), so you can wrap that.  But you
>> still can't wrap its new home, gen_variants_objects().  Instead, you
>> bracket its call of gen_object() with gen_if() ... gen_endif().  Works,
>> but is there a more direct path to the same result?
>>
>> I append my attempt.  Its basic idea is to wrap code generation right
>> where it is.  Requires passing ifcond to gen_object().  The patch to
>> visit.py is identical.
>>
>> Less churn, and I it saves me reviewing the previous patch.  Opinions?
>
>
> Looks good to me. I think the churn was necessary before, when we used
> the function decorator. Now that we can scope the if/endif at the
> block level, we don't need it anymore.

Makes sense.

>> From d6f26abe5a81b10aaff5c75db3bfc60c05203f05 Mon Sep 17 00:00:00 2001
>> From: Markus Armbruster <armbru@redhat.com>
>> Date: Thu, 21 Jun 2018 18:03:41 +0200
>> Subject: [PATCH] qapi-types: add #if conditions to types & visitors
>>
>> Types & visitors are coupled and must be handled together to avoid
>> temporary build regression.
>>
>> Wrap generated types/visitor code with #if/#endif using the context
>> helpers.
>>
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>
> I'll take it with my signed-off, since it shares a lot of similarities
> with my patch.

Of course.  git-commit -avs comes from muscle memory :)

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 15/49] qapi: do not define enumeration value explicitely
  2018-06-27 12:13     ` Marc-André Lureau
@ 2018-06-28  6:34       ` Markus Armbruster
  0 siblings, 0 replies; 95+ messages in thread
From: Markus Armbruster @ 2018-06-28  6:34 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: Markus Armbruster, QEMU

Marc-André Lureau <marcandre.lureau@gmail.com> writes:

> Hi
>
> On Fri, Jun 22, 2018 at 10:08 AM, Markus Armbruster <armbru@redhat.com> wrote:
>> Subject: explicitly
>>
>> 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.
>>>
>>> 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 60c1d0a783..68a567f53f 100644
>>> --- a/scripts/qapi/common.py
>>> +++ b/scripts/qapi/common.py
>>> @@ -2032,14 +2032,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;
>>
>> What excactly in your series depends on this?
>>
>> What safeguards do you propose to ensure an enumeration with
>> conditionals is compiled only with the exact same conditionals within
>> the same program?
>>
>> Example of the kind of deathtrap to guard against: compile
>>
>>     typedef enum Color {
>>         COLOR_WHITE,
>> #if defined(NEED_CPU_H)
>> #if defined(TARGET_S390X)
>>         COLOR_BLUE,
>> #endif /* defined(TARGET_S390X) */
>> #endif /* defined(NEED_CPU_H) */
>>         COLOR_BLACK,
>>     } Color;
>>
>> in s390x-code (COLOR_BLACK = 2) and in target-independent code
>> (COLOR_BLACK = 1), then linking the two together.
>
> This was a trick used in previous iterations. Now that we have a
> separate target schema and generated code/headers, and since we have
> poisoned identifiers, this should never happen.
>
>> Yes, I know a similar deathtrap will be set up for struct and union
>> types.  No excuse for ignoring either of the two.
>
> Having gaps in the enums makes it harder to iterate over all values,
> and we use more memory than necessary when allocating based on MAX
> value.
>
> It's not a big problem, but I consider this more important than this
> artificially made up broken build example.

Made up yes, but the making up comes from painful experience debugging
real programs :)

I'm not at all opposed to "contracting" enums.  I just want to be
persuaded it's safe.  I think your argument is "Now that we have a
separate target schema and generated code/headers, and since we have
poisoned identifiers, this should never happen."  Can you elaborate?

If that goes as I expect it to go, the next request will be "now put
that into your commit message" :)

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [Qemu-devel] [PATCH v3 05/49] qapi: leave the ifcond attribute undefined until check()
  2018-06-27  5:26       ` Markus Armbruster
@ 2018-06-29 10:30         ` Marc-André Lureau
  0 siblings, 0 replies; 95+ messages in thread
From: Marc-André Lureau @ 2018-06-29 10:30 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: QEMU

Hi

On Wed, Jun 27, 2018 at 7:26 AM, Markus Armbruster <armbru@redhat.com> wrote:
>>> This is hardly a rigorous proof.  Just enough to make me believe your
>>> code works.
>>>
>>> However, I suspect adding the inheritance feature at the entity level
>>> complicates the correctness argument without real need.  Can we restrict
>>> it to array elements?  Have QAPISchemaArrayType.check() resolve
>>> type-valued ._ifcond, and all the others choke on it?
>>
>> There is also implicit object types.
>
> Can you give an example?
>

{ 'union': 'Foo', 'data': { 'foo': 'Test' } }

will create implicit QAPISchemaObjectType q_obj_Test-wrapper in
_make_simple_variant()

This happens before check(), so we pass the Test type as ifcond.

-- 
Marc-André Lureau

^ permalink raw reply	[flat|nested] 95+ messages in thread

end of thread, other threads:[~2018-06-29 10:30 UTC | newest]

Thread overview: 95+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 01/49] qapi/visit: remove useless prefix argument Marc-André Lureau
2018-06-18 14:29   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 02/49] qapi/events: generate event enum in main module Marc-André Lureau
2018-06-18 14:33   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 03/49] qapi: add 'if' to top-level expressions Marc-André Lureau
2018-06-19  7:57   ` Markus Armbruster
2018-06-19  8:41     ` Marc-André Lureau
2018-06-19 11:35       ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 04/49] qapi: pass 'if' condition into QAPISchemaEntity objects Marc-André Lureau
2018-06-19  8:09   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 05/49] qapi: leave the ifcond attribute undefined until check() Marc-André Lureau
2018-06-19  9:06   ` Markus Armbruster
2018-06-26 13:39     ` Marc-André Lureau
2018-06-27  5:26       ` Markus Armbruster
2018-06-29 10:30         ` Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 06/49] qapi: add 'ifcond' to visitor methods Marc-André Lureau
2018-06-21  8:18   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 07/49] qapi: mcgen() shouldn't indent # lines Marc-André Lureau
2018-06-20 15:14   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 08/49] qapi: add #if/#endif helpers Marc-André Lureau
2018-06-20 16:01   ` Markus Armbruster
2018-06-21  7:06   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 09/49] qapi-introspect: modify to_qlit() to append ', ' on level > 0 Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 10/49] qapi-introspect: add preprocessor conditions to generated QLit Marc-André Lureau
2018-06-21 13:05   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 11/49] qapi/commands: add #if conditions to commands Marc-André Lureau
2018-06-21 14:35   ` Markus Armbruster
2018-06-22  8:34   ` Markus Armbruster
2018-06-25 13:15     ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 12/49] qapi/events: add #if conditions to events Marc-André Lureau
2018-06-21 14:40   ` Markus Armbruster
2018-06-22  9:02   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 13/49] qapi-types: refactor variants handling Marc-André Lureau
2018-06-21 15:54   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 14/49] qapi-types: add #if conditions to types & visitors Marc-André Lureau
2018-06-21 16:12   ` Markus Armbruster
2018-06-27 11:59     ` Marc-André Lureau
2018-06-28  6:27       ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 15/49] qapi: do not define enumeration value explicitely Marc-André Lureau
2018-06-22  8:08   ` Markus Armbruster
2018-06-27 12:13     ` Marc-André Lureau
2018-06-28  6:34       ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 16/49] qapi: rename QAPISchemaEnumType.values to .members Marc-André Lureau
2018-06-22 12:24   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 17/49] qapi: change enum visitor to take QAPISchemaMember Marc-André Lureau
2018-06-22 12:24   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 18/49] tests: modify visit_enum_type() in test-qapi to print members Marc-André Lureau
2018-06-22 14:10   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 19/49] qapi: factor out check_known_keys() Marc-André Lureau
2018-06-25 14:10   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 20/49] qapi: add a dictionnary form with 'name' key for enum members Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 21/49] qapi: add 'if' to " Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 22/49] qapi-event: add 'if' condition to implicit event enum Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 23/49] qapi: rename allow_dict to allow_implicit Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 24/49] qapi: add a dictionary form with 'type' key for members Marc-André Lureau
2018-06-20 11:13   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 25/49] qapi: add 'if' to implicit struct members Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 26/49] qapi: add an error in case a discriminator is conditionnal Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 27/49] qapi: add 'if' on union members Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 28/49] qapi: add 'if' to alternate members Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 29/49] qapi: add #if conditions to generated code members Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 30/49] docs: document schema configuration Marc-André Lureau
2018-06-22 11:10   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 31/49] qapi2texi: add 'If:' section to generated documentation Marc-André Lureau
2018-06-21 16:29   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 32/49] qapi2texi: add 'If:' condition to enum values Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 33/49] qapi2texi: add 'If:' condition to struct members Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 34/49] qapi2texi: add condition to variants Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 35/49] qapi: add conditions to VNC type/commands/events on the schema Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 36/49] qapi: add conditions to SPICE " Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 37/49] qapi: add conditions to REPLICATION type/commands " Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 38/49] build-sys: move qmp-introspect per target Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 39/49] qapi-commands: don't initialize command list in qmp_init_marshall() Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 40/49] RFC: qapi: learn to split schema by 'top-unit' Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 41/49] qapi: add a top-unit 'target' schema Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 42/49] qapi: make rtc-reset-reinjection and SEV depend on TARGET_I386 Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 43/49] qapi: make s390 commands depend on TARGET_S390X Marc-André Lureau
2018-03-22  5:42   ` Thomas Huth
2018-03-22  9:41     ` Marc-André Lureau
2018-03-22 16:10       ` Thomas Huth
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 44/49] target.json: add a note about query-cpu* not being s390x-specific Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 45/49] qapi: make query-gic-capabilities depend on TARGET_ARM Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 46/49] qapi: make query-cpu-model-expansion depend on s390 or x86 Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 47/49] qapi: make query-cpu-definitions depend on specific targets Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 48/49] qapi: remove qmp_unregister_command() Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 49/49] RFC: make RTC_CHANGE per-target Marc-André Lureau
2018-03-21 12:47 ` [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code no-reply
2018-03-21 14:20 ` no-reply
2018-03-21 22:08 ` no-reply
2018-03-22  5:11 ` no-reply
2018-06-21 16:47 ` Markus Armbruster
2018-06-21 17:18   ` Marc-André Lureau
2018-06-22  6:56     ` Markus Armbruster
2018-06-22  9:06     ` 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.