All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code
@ 2017-08-22 13:22 Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 01/54] qapi: fix type_seen key error Marc-André Lureau
                   ` (55 more replies)
  0 siblings, 56 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: 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 good 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 demonstrate adding conditions, in order to
remove qmp_unregister_commands_hack(). However, it feels like I
cheated a little bit by using per-target NEED_CPU_H in the headers to
avoid #define poison. The alternative could be to split the headers in
common/target?

There are a lot more things we could 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,

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 (54):
  qapi: fix type_seen key error
  qdict: add qdict_put_null() helper
  qobject: add literal qobject type
  qlit: add qobject_form_qlit()
  qapi: generate a literal qobject for introspection
  qapi: introduce qapi_enum_lookup()
  tpm: simplify driver registration & lookup
  hmp: use qapi_enum_parse() in hmp_migrate_set_capability
  hmp: use qapi_enum_parse() in hmp_migrate_set_parameter
  block: use qemu_enum_parse() in blkdebug_debug_breakpoint
  quorum: use qapi_enum_parse() in quorum_open
  qapi: change enum lookup structure
  qapi: drop the sentinel in enum array
  qapi2texi: minor python code simplification
  qapi: add 'if' to top-level expressions
  qapi: add a test for invalid 'if'
  qapi: add 'if' condition on entity objects
  qapi: add 'ifcond' to visitor methods
  qapi: add #if/#endif helpers
  qapi-introspect: modify to_qlit() to take an optional suffix
  qapi-introspect: modify to_qlit() to generate #if code
  qapi-introspect: add preprocessor conditions to generated QLit
  qapi-commands: add #if conditions to commands
  qapi-event: add #if conditions to events
  qapi-visit: add #if conditions to visitors
  qapi-types: refactor variants handling
  qapi-types: add #if conditions to types
  qapi: do not define enumeration value explicitely
  qapi: add 'if' to enum members
  qapi: add #if conditions on generated enum values
  tests: add some enum members tests
  qapi: add 'if' to struct members
  qapi: add some struct member tests
  qapi: add #if conditions to generated struct members
  qapi: add 'if' on union variants
  qapi: add #if conditions to generated variants
  qapi: 'if' to alternate variant
  qapi: add tests for invalid alternate
  qapi: add #if conditions to generated alternate variants
  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
  tests/qmp-test: add query-qmp-schema test
  build-sys: make qemu qapi objects per-target
  qapi: make rtc-reset-reinjection depend on TARGET_I386
  qapi: make s390 commands depend on TARGET_S390X
  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-schema.json                                 |  98 +++++---
 qapi/block-core.json                             |  13 +-
 qapi/crypto.json                                 |   3 +-
 qapi/event.json                                  |  21 +-
 include/qapi/visitor.h                           |   2 +-
 scripts/qapi.py                                  | 279 +++++++++++++++++------
 scripts/qapi-commands.py                         |   4 +-
 scripts/qapi-event.py                            |   4 +-
 scripts/qapi-introspect.py                       | 124 ++++++----
 scripts/qapi-types.py                            |  62 +++--
 scripts/qapi-visit.py                            |  21 +-
 scripts/qapi2texi.py                             |  51 +++--
 include/hw/qdev-core.h                           |   2 +-
 include/qapi/qmp/qdict.h                         |   2 +
 include/qapi/qmp/qlit.h                          |  56 +++++
 include/qapi/util.h                              |   6 +-
 include/qom/object.h                             |   4 +-
 include/sysemu/arch_init.h                       |  11 -
 include/sysemu/tpm_backend.h                     |   2 +-
 qapi/qapi-visit-core.c                           |  24 +-
 backends/hostmem.c                               |   5 +-
 block.c                                          |   3 +-
 block/backup.c                                   |   3 +-
 block/blkdebug.c                                 |  28 +--
 block/file-posix.c                               |  18 +-
 block/file-win32.c                               |   6 +-
 block/gluster.c                                  |  12 +-
 block/iscsi.c                                    |   3 +-
 block/nfs.c                                      |   3 +-
 block/parallels.c                                |  11 +-
 block/qcow2.c                                    |  15 +-
 block/qed.c                                      |   3 +-
 block/quorum.c                                   |  27 +--
 block/rbd.c                                      |   3 +-
 block/sheepdog.c                                 |   3 +-
 blockdev.c                                       |   9 +-
 blockjob.c                                       |   9 +-
 chardev/char.c                                   |   7 +-
 crypto/block-luks.c                              |  43 ++--
 crypto/block.c                                   |   5 +-
 crypto/cipher-afalg.c                            |   2 +-
 crypto/cipher-builtin.c                          |  17 +-
 crypto/cipher-gcrypt.c                           |  14 +-
 crypto/cipher-nettle.c                           |  22 +-
 crypto/cipher.c                                  |  14 +-
 crypto/hmac-gcrypt.c                             |   2 +-
 crypto/hmac-glib.c                               |   3 +-
 crypto/hmac-nettle.c                             |   3 +-
 crypto/pbkdf-gcrypt.c                            |   3 +-
 crypto/pbkdf-nettle.c                            |   4 +-
 crypto/secret.c                                  |   2 +-
 crypto/tlscreds.c                                |   2 +-
 hmp.c                                            | 252 ++++++++++----------
 hw/block/fdc.c                                   |   9 +-
 hw/char/escc.c                                   |   3 +-
 hw/core/qdev-properties.c                        |  19 +-
 hw/input/virtio-input-hid.c                      |   5 +-
 migration/colo-failover.c                        |   6 +-
 migration/colo.c                                 |  31 +--
 migration/global_state.c                         |   5 +-
 monitor.c                                        |  94 ++------
 net/filter.c                                     |   2 +-
 net/net.c                                        |   5 +-
 qapi/qapi-util.c                                 |  16 +-
 qapi/qmp-dispatch.c                              |   4 +-
 qemu-img.c                                       |   6 +-
 qemu-nbd.c                                       |   3 +-
 qmp.c                                            |  72 +-----
 qobject/qlit.c                                   | 143 ++++++++++++
 qom/object.c                                     |  16 +-
 stubs/arch-query-cpu-def.c                       |  10 -
 stubs/arch-query-cpu-model-baseline.c            |  12 -
 stubs/arch-query-cpu-model-comparison.c          |  12 -
 stubs/arch-query-cpu-model-expansion.c           |  12 -
 stubs/qapi-event.c                               |  74 ++++++
 target/arm/helper.c                              |   3 +-
 target/i386/cpu.c                                |   5 +-
 target/ppc/translate_init.c                      |   3 +-
 target/s390x/cpu_models.c                        |   9 +-
 tests/check-qjson.c                              | 150 +++---------
 tests/check-qlit.c                               |  94 ++++++++
 tests/check-qom-proplist.c                       |   7 +-
 tests/qmp-test.c                                 |  21 ++
 tests/test-qapi-util.c                           |  17 +-
 tests/test-qmp-commands.c                        |   6 +
 tests/test-qobject-input-visitor.c               |  18 +-
 tests/test-qobject-output-visitor.c              |   4 +-
 tests/test-string-input-visitor.c                |   4 +-
 tests/test-string-output-visitor.c               |   6 +-
 tpm.c                                            |  44 ++--
 ui/input-legacy.c                                |   6 +-
 ui/input.c                                       |  13 +-
 ui/vnc.c                                         |   8 +-
 vl.c                                             |   7 +-
 Makefile.objs                                    |   9 +-
 Makefile.target                                  |   4 +
 docs/devel/qapi-code-gen.txt                     |  76 +++++-
 hmp-commands-info.hx                             |   2 +
 qobject/Makefile.objs                            |   2 +-
 stubs/Makefile.objs                              |   5 +-
 tests/Makefile.include                           |  11 +-
 tests/qapi-schema/alternate-conflict-string.json |   4 +-
 tests/qapi-schema/alternate-dict-invalid.err     |   1 +
 tests/qapi-schema/alternate-dict-invalid.exit    |   1 +
 tests/qapi-schema/alternate-dict-invalid.json    |   4 +
 tests/qapi-schema/alternate-dict-invalid.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/enum-dict-member-invalid.err   |   1 +
 tests/qapi-schema/enum-dict-member-invalid.exit  |   1 +
 tests/qapi-schema/enum-dict-member-invalid.json  |   2 +
 tests/qapi-schema/enum-dict-member-invalid.out   |   0
 tests/qapi-schema/enum-dict-member.err           |   1 -
 tests/qapi-schema/enum-dict-member.exit          |   2 +-
 tests/qapi-schema/enum-dict-member.json          |   3 +-
 tests/qapi-schema/enum-dict-member.out           |   4 +
 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          |  32 +++
 tests/qapi-schema/qapi-schema-test.out           |  47 ++++
 tests/qapi-schema/struct-if-invalid.err          |   1 +
 tests/qapi-schema/struct-if-invalid.exit         |   1 +
 tests/qapi-schema/struct-if-invalid.json         |   3 +
 tests/qapi-schema/struct-if-invalid.out          |   0
 tests/qapi-schema/struct-member-type.err         |   0
 tests/qapi-schema/struct-member-type.exit        |   1 +
 tests/qapi-schema/struct-member-type.json        |   1 +
 tests/qapi-schema/struct-member-type.out         |   5 +
 tests/qapi-schema/test-qapi.py                   |  31 ++-
 trace/Makefile.objs                              |   2 +-
 134 files changed, 1606 insertions(+), 990 deletions(-)
 create mode 100644 include/qapi/qmp/qlit.h
 create mode 100644 qobject/qlit.c
 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 stubs/qapi-event.c
 create mode 100644 tests/check-qlit.c
 create mode 100644 tests/qapi-schema/alternate-dict-invalid.err
 create mode 100644 tests/qapi-schema/alternate-dict-invalid.exit
 create mode 100644 tests/qapi-schema/alternate-dict-invalid.json
 create mode 100644 tests/qapi-schema/alternate-dict-invalid.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-dict-member-invalid.err
 create mode 100644 tests/qapi-schema/enum-dict-member-invalid.exit
 create mode 100644 tests/qapi-schema/enum-dict-member-invalid.json
 create mode 100644 tests/qapi-schema/enum-dict-member-invalid.out
 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/struct-if-invalid.err
 create mode 100644 tests/qapi-schema/struct-if-invalid.exit
 create mode 100644 tests/qapi-schema/struct-if-invalid.json
 create mode 100644 tests/qapi-schema/struct-if-invalid.out
 create mode 100644 tests/qapi-schema/struct-member-type.err
 create mode 100644 tests/qapi-schema/struct-member-type.exit
 create mode 100644 tests/qapi-schema/struct-member-type.json
 create mode 100644 tests/qapi-schema/struct-member-type.out

-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 01/54] qapi: fix type_seen key error
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 15:00   ` Markus Armbruster
  2017-08-25  6:02   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 02/54] qdict: add qdict_put_null() helper Marc-André Lureau
                   ` (54 subsequent siblings)
  55 siblings, 2 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

The type_seen member can be of a different type than the 'qtype' being
checked, since a string create several conflicts. Lookup the real
conflicting type in the conflict set, that one must be present in
type_seen.

This fixes the following error, reproducible with the modified test:

Traceback (most recent call last):
  File "/home/elmarco/src/qq/tests/qapi-schema/test-qapi.py", line 56, in <module>
    schema = QAPISchema(sys.argv[1])
  File "/home/elmarco/src/qq/scripts/qapi.py", line 1470, in __init__
    self.exprs = check_exprs(parser.exprs)
  File "/home/elmarco/src/qq/scripts/qapi.py", line 959, in check_exprs
    check_alternate(expr, info)
  File "/home/elmarco/src/qq/scripts/qapi.py", line 831, in check_alternate
    % (name, key, types_seen[qtype]))
KeyError: 'QTYPE_QSTRING'

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi.py                                  | 6 ++++--
 tests/qapi-schema/alternate-conflict-string.json | 4 ++--
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/scripts/qapi.py b/scripts/qapi.py
index 8aa2775f12..a3ac799535 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -825,10 +825,12 @@ def check_alternate(expr, info):
             else:
                 conflicting.add('QTYPE_QNUM')
                 conflicting.add('QTYPE_QBOOL')
-        if conflicting & set(types_seen):
+        conflict = conflicting & set(types_seen)
+        if conflict:
+            conflict_qtype = list(conflict)[0]
             raise QAPISemError(info, "Alternate '%s' member '%s' can't "
                                "be distinguished from member '%s'"
-                               % (name, key, types_seen[qtype]))
+                               % (name, key, types_seen[conflict_qtype]))
         for qt in conflicting:
             types_seen[qt] = key
 
diff --git a/tests/qapi-schema/alternate-conflict-string.json b/tests/qapi-schema/alternate-conflict-string.json
index 85adbd4adc..bb2702978e 100644
--- a/tests/qapi-schema/alternate-conflict-string.json
+++ b/tests/qapi-schema/alternate-conflict-string.json
@@ -1,4 +1,4 @@
 # alternate branches of 'str' type conflict with all scalar types
 { 'alternate': 'Alt',
-  'data': { 'one': 'str',
-            'two': 'int' } }
+  'data': { 'one': 'int',
+            'two': 'str' } }
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 02/54] qdict: add qdict_put_null() helper
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 01/54] qapi: fix type_seen key error Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 15:09   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 03/54] qobject: add literal qobject type Marc-André Lureau
                   ` (53 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/qapi/qmp/qdict.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
index 363e431106..a35bed9f16 100644
--- a/include/qapi/qmp/qdict.h
+++ b/include/qapi/qmp/qdict.h
@@ -60,6 +60,8 @@ void qdict_destroy_obj(QObject *obj);
         qdict_put(qdict, key, qbool_from_bool(value))
 #define qdict_put_str(qdict, key, value) \
         qdict_put(qdict, key, qstring_from_str(value))
+#define qdict_put_null(qdict, key) \
+        qdict_put(qdict, key, qnull())
 
 /* High level helpers */
 double qdict_get_double(const QDict *qdict, const char *key);
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 03/54] qobject: add literal qobject type
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 01/54] qapi: fix type_seen key error Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 02/54] qdict: add qdict_put_null() helper Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 15:31   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 04/54] qlit: add qobject_form_qlit() Marc-André Lureau
                   ` (52 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster

Promote LiteralQObject from tests/check-qjson.c to qobject/qlit.c,
allowing to statically declare complex qobjects.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/qapi/qmp/qlit.h |  54 +++++++++++++++++
 qobject/qlit.c          | 106 ++++++++++++++++++++++++++++++++++
 tests/check-qjson.c     | 150 +++++++++---------------------------------------
 tests/check-qlit.c      |  68 ++++++++++++++++++++++
 qobject/Makefile.objs   |   2 +-
 tests/Makefile.include  |   5 +-
 6 files changed, 261 insertions(+), 124 deletions(-)
 create mode 100644 include/qapi/qmp/qlit.h
 create mode 100644 qobject/qlit.c
 create mode 100644 tests/check-qlit.c

diff --git a/include/qapi/qmp/qlit.h b/include/qapi/qmp/qlit.h
new file mode 100644
index 0000000000..2cdceb448d
--- /dev/null
+++ b/include/qapi/qmp/qlit.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright IBM, Corp. 2009
+ * Copyright (c) 2013, 2015, 2017 Red Hat Inc.
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *  Markus Armbruster <armbru@redhat.com>
+ *  Marc-André Lureau <marcandre.lureau@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+#ifndef QLIT_H_
+#define QLIT_H_
+
+#include "qapi-types.h"
+#include "qobject.h"
+
+typedef struct QLitDictEntry QLitDictEntry;
+typedef struct QLitObject QLitObject;
+
+struct QLitObject {
+    int type;
+    union {
+        bool qbool;
+        int64_t qnum;
+        const char *qstr;
+        QLitDictEntry *qdict;
+        QLitObject *qlist;
+    } value;
+};
+
+struct QLitDictEntry {
+    const char *key;
+    QLitObject value;
+};
+
+#define QLIT_QNULL \
+    { .type = QTYPE_QNULL }
+#define QLIT_QBOOL(val) \
+    { .type = QTYPE_QBOOL, .value.qbool = (val) }
+#define QLIT_QNUM(val) \
+    { .type = QTYPE_QNUM, .value.qnum = (val) }
+#define QLIT_QSTR(val) \
+    { .type = QTYPE_QSTRING, .value.qstr = (val) }
+#define QLIT_QDICT(val) \
+    { .type = QTYPE_QDICT, .value.qdict = (val) }
+#define QLIT_QLIST(val) \
+    { .type = QTYPE_QLIST, .value.qlist = (val) }
+
+bool qlit_equal_qobject(QLitObject *lhs, QObject *rhs);
+
+#endif /* QLIT_H_ */
diff --git a/qobject/qlit.c b/qobject/qlit.c
new file mode 100644
index 0000000000..f4ebeb6259
--- /dev/null
+++ b/qobject/qlit.c
@@ -0,0 +1,106 @@
+/*
+ * QLit literal qobject
+ *
+ * Copyright IBM, Corp. 2009
+ * Copyright (c) 2013, 2015, 2017 Red Hat Inc.
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *  Markus Armbruster <armbru@redhat.com>
+ *  Marc-André Lureau <marcandre.lureau@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+
+#include "qapi/qmp/qlit.h"
+#include "qapi/qmp/types.h"
+
+typedef struct QListCompareHelper {
+    int index;
+    QLitObject *objs;
+    bool result;
+} QListCompareHelper;
+
+static void compare_helper(QObject *obj, void *opaque)
+{
+    QListCompareHelper *helper = opaque;
+
+    if (!helper->result) {
+        return;
+    }
+
+    if (helper->objs[helper->index].type == QTYPE_NONE) {
+        helper->result = false;
+        return;
+    }
+
+    helper->result =
+        qlit_equal_qobject(&helper->objs[helper->index++], obj);
+}
+
+bool qlit_equal_qobject(QLitObject *lhs, QObject *rhs)
+{
+    int64_t val;
+
+    if (!rhs || lhs->type != qobject_type(rhs)) {
+        return false;
+    }
+
+    switch (lhs->type) {
+    case QTYPE_QBOOL:
+        return lhs->value.qbool == qbool_get_bool(qobject_to_qbool(rhs));
+    case QTYPE_QNUM:
+        val = qnum_get_int(qobject_to_qnum(rhs));
+        return lhs->value.qnum == val;
+    case QTYPE_QSTRING:
+        return g_str_equal(lhs->value.qstr,
+                           qstring_get_str(qobject_to_qstring(rhs)));
+    case QTYPE_QDICT: {
+        int i;
+
+        for (i = 0; lhs->value.qdict[i].key; i++) {
+            QObject *obj = qdict_get(qobject_to_qdict(rhs),
+                                     lhs->value.qdict[i].key);
+
+            if (!qlit_equal_qobject(&lhs->value.qdict[i].value, obj)) {
+                return false;
+            }
+        }
+
+        if (qdict_size(qobject_to_qdict(rhs)) != i) {
+            return false;
+        }
+
+        return true;
+    }
+    case QTYPE_QLIST: {
+        QListCompareHelper helper;
+        int i;
+
+        for (i = 0; lhs->value.qlist[i].type != QTYPE_NONE; i++) {
+            continue;
+        }
+
+        if (qlist_size(qobject_to_qlist(rhs)) != i) {
+            return false;
+        }
+
+        helper.index = 0;
+        helper.objs = lhs->value.qlist;
+        helper.result = true;
+
+        qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
+
+        return helper.result;
+    }
+    case QTYPE_QNULL:
+        return true;
+    default:
+        break;
+    }
+
+    return false;
+}
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
index a3a97b0d99..59227934ce 100644
--- a/tests/check-qjson.c
+++ b/tests/check-qjson.c
@@ -16,6 +16,7 @@
 #include "qapi/error.h"
 #include "qapi/qmp/types.h"
 #include "qapi/qmp/qjson.h"
+#include "qapi/qmp/qlit.h"
 #include "qemu-common.h"
 
 static void escaped_string(void)
@@ -1059,123 +1060,28 @@ static void keyword_literal(void)
     QDECREF(null);
 }
 
-typedef struct LiteralQDictEntry LiteralQDictEntry;
-typedef struct LiteralQObject LiteralQObject;
-
-struct LiteralQObject
-{
-    int type;
-    union {
-        int64_t qnum;
-        const char *qstr;
-        LiteralQDictEntry *qdict;
-        LiteralQObject *qlist;
-    } value;
-};
-
-struct LiteralQDictEntry
-{
-    const char *key;
-    LiteralQObject value;
-};
-
-#define QLIT_QNUM(val) (LiteralQObject){.type = QTYPE_QNUM, .value.qnum = (val)}
-#define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
-#define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
-#define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
-
-typedef struct QListCompareHelper
-{
-    int index;
-    LiteralQObject *objs;
-    int result;
-} QListCompareHelper;
-
-static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
-
-static void compare_helper(QObject *obj, void *opaque)
-{
-    QListCompareHelper *helper = opaque;
-
-    if (helper->result == 0) {
-        return;
-    }
-
-    if (helper->objs[helper->index].type == QTYPE_NONE) {
-        helper->result = 0;
-        return;
-    }
-
-    helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
-}
-
-static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
-{
-    int64_t val;
-
-    if (!rhs || lhs->type != qobject_type(rhs)) {
-        return 0;
-    }
-
-    switch (lhs->type) {
-    case QTYPE_QNUM:
-        g_assert(qnum_get_try_int(qobject_to_qnum(rhs), &val));
-        return lhs->value.qnum == val;
-    case QTYPE_QSTRING:
-        return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
-    case QTYPE_QDICT: {
-        int i;
-
-        for (i = 0; lhs->value.qdict[i].key; i++) {
-            QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
-
-            if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
-                return 0;
-            }
-        }
-
-        return 1;
-    }
-    case QTYPE_QLIST: {
-        QListCompareHelper helper;
-
-        helper.index = 0;
-        helper.objs = lhs->value.qlist;
-        helper.result = 1;
-        
-        qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
-
-        return helper.result;
-    }
-    default:
-        break;
-    }
-
-    return 0;
-}
-
 static void simple_dict(void)
 {
     int i;
     struct {
         const char *encoded;
-        LiteralQObject decoded;
+        QLitObject decoded;
     } test_cases[] = {
         {
             .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
-            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
+            .decoded = QLIT_QDICT(((QLitDictEntry[]){
                         { "foo", QLIT_QNUM(42) },
                         { "bar", QLIT_QSTR("hello world") },
                         { }
                     })),
         }, {
             .encoded = "{}",
-            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
+            .decoded = QLIT_QDICT(((QLitDictEntry[]){
                         { }
                     })),
         }, {
             .encoded = "{\"foo\": 43}",
-            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
+            .decoded = QLIT_QDICT(((QLitDictEntry[]){
                         { "foo", QLIT_QNUM(43) },
                         { }
                     })),
@@ -1188,13 +1094,13 @@ static void simple_dict(void)
         QString *str;
 
         obj = qobject_from_json(test_cases[i].encoded, &error_abort);
-        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+        g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
 
         str = qobject_to_json(obj);
         qobject_decref(obj);
 
         obj = qobject_from_json(qstring_get_str(str), &error_abort);
-        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+        g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
         qobject_decref(obj);
         QDECREF(str);
     }
@@ -1257,11 +1163,11 @@ static void simple_list(void)
     int i;
     struct {
         const char *encoded;
-        LiteralQObject decoded;
+        QLitObject decoded;
     } test_cases[] = {
         {
             .encoded = "[43,42]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
+            .decoded = QLIT_QLIST(((QLitObject[]){
                         QLIT_QNUM(43),
                         QLIT_QNUM(42),
                         { }
@@ -1269,21 +1175,21 @@ static void simple_list(void)
         },
         {
             .encoded = "[43]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
+            .decoded = QLIT_QLIST(((QLitObject[]){
                         QLIT_QNUM(43),
                         { }
                     })),
         },
         {
             .encoded = "[]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
+            .decoded = QLIT_QLIST(((QLitObject[]){
                         { }
                     })),
         },
         {
             .encoded = "[{}]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QDICT(((LiteralQDictEntry[]){
+            .decoded = QLIT_QLIST(((QLitObject[]){
+                        QLIT_QDICT(((QLitDictEntry[]){
                                     {},
                                         })),
                         {},
@@ -1297,13 +1203,13 @@ static void simple_list(void)
         QString *str;
 
         obj = qobject_from_json(test_cases[i].encoded, &error_abort);
-        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+        g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
 
         str = qobject_to_json(obj);
         qobject_decref(obj);
 
         obj = qobject_from_json(qstring_get_str(str), &error_abort);
-        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+        g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
         qobject_decref(obj);
         QDECREF(str);
     }
@@ -1314,11 +1220,11 @@ static void simple_whitespace(void)
     int i;
     struct {
         const char *encoded;
-        LiteralQObject decoded;
+        QLitObject decoded;
     } test_cases[] = {
         {
             .encoded = " [ 43 , 42 ]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
+            .decoded = QLIT_QLIST(((QLitObject[]){
                         QLIT_QNUM(43),
                         QLIT_QNUM(42),
                         { }
@@ -1326,12 +1232,12 @@ static void simple_whitespace(void)
         },
         {
             .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
+            .decoded = QLIT_QLIST(((QLitObject[]){
                         QLIT_QNUM(43),
-                        QLIT_QDICT(((LiteralQDictEntry[]){
+                        QLIT_QDICT(((QLitDictEntry[]){
                                     { "h", QLIT_QSTR("b") },
                                     { }})),
-                        QLIT_QLIST(((LiteralQObject[]){
+                        QLIT_QLIST(((QLitObject[]){
                                     { }})),
                         QLIT_QNUM(42),
                         { }
@@ -1339,13 +1245,13 @@ static void simple_whitespace(void)
         },
         {
             .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
+            .decoded = QLIT_QLIST(((QLitObject[]){
                         QLIT_QNUM(43),
-                        QLIT_QDICT(((LiteralQDictEntry[]){
+                        QLIT_QDICT(((QLitDictEntry[]){
                                     { "h", QLIT_QSTR("b") },
                                     { "a", QLIT_QNUM(32) },
                                     { }})),
-                        QLIT_QLIST(((LiteralQObject[]){
+                        QLIT_QLIST(((QLitObject[]){
                                     { }})),
                         QLIT_QNUM(42),
                         { }
@@ -1359,13 +1265,13 @@ static void simple_whitespace(void)
         QString *str;
 
         obj = qobject_from_json(test_cases[i].encoded, &error_abort);
-        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+        g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
 
         str = qobject_to_json(obj);
         qobject_decref(obj);
 
         obj = qobject_from_json(qstring_get_str(str), &error_abort);
-        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+        g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
 
         qobject_decref(obj);
         QDECREF(str);
@@ -1376,10 +1282,10 @@ static void simple_varargs(void)
 {
     QObject *embedded_obj;
     QObject *obj;
-    LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
+    QLitObject decoded = QLIT_QLIST(((QLitObject[]){
             QLIT_QNUM(1),
             QLIT_QNUM(2),
-            QLIT_QLIST(((LiteralQObject[]){
+            QLIT_QLIST(((QLitObject[]){
                         QLIT_QNUM(32),
                         QLIT_QNUM(42),
                         {}})),
@@ -1389,7 +1295,7 @@ static void simple_varargs(void)
     g_assert(embedded_obj != NULL);
 
     obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
-    g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
+    g_assert(qlit_equal_qobject(&decoded, obj));
 
     qobject_decref(obj);
 }
diff --git a/tests/check-qlit.c b/tests/check-qlit.c
new file mode 100644
index 0000000000..5736b61ebf
--- /dev/null
+++ b/tests/check-qlit.c
@@ -0,0 +1,68 @@
+/*
+ * QLit unit-tests.
+ *
+ * Copyright (C) 2017 Red Hat Inc.
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+
+#include "qapi/qmp/qbool.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qlit.h"
+#include "qapi/qmp/qnum.h"
+#include "qapi/qmp/qstring.h"
+
+static QLitObject qlit = QLIT_QDICT(((QLitDictEntry[]) {
+    { "foo", QLIT_QNUM(42) },
+    { "bar", QLIT_QSTR("hello world") },
+    { "baz", QLIT_QNULL },
+    { "bee", QLIT_QLIST(((QLitObject[]) {
+        QLIT_QNUM(43),
+        QLIT_QNUM(44),
+        QLIT_QBOOL(true),
+        { },
+    }))},
+    { },
+}));
+
+static QObject *make_qobject(void)
+{
+    QDict *qdict = qdict_new();
+    QList *list = qlist_new();
+
+    qdict_put_int(qdict, "foo", 42);
+    qdict_put_str(qdict, "bar", "hello world");
+    qdict_put_null(qdict, "baz");
+
+    qlist_append_int(list, 43);
+    qlist_append_int(list, 44);
+    qlist_append_bool(list, true);
+    qdict_put(qdict, "bee", list);
+
+    return QOBJECT(qdict);
+}
+
+static void qlit_equal_qobject_test(void)
+{
+    QObject *qobj = make_qobject();
+    QList *list = qlist_new();
+
+    g_assert(qlit_equal_qobject(&qlit, qobj));
+
+    qdict_put(qobject_to_qdict(qobj), "bee", list);
+    g_assert(!qlit_equal_qobject(&qlit, qobj));
+
+    qobject_decref(qobj);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    g_test_add_func("/qlit/equal_qobject", qlit_equal_qobject_test);
+
+    return g_test_run();
+}
diff --git a/qobject/Makefile.objs b/qobject/Makefile.objs
index fc8885c9a4..002d25873a 100644
--- a/qobject/Makefile.objs
+++ b/qobject/Makefile.objs
@@ -1,2 +1,2 @@
-util-obj-y = qnull.o qnum.o qstring.o qdict.o qlist.o qbool.o
+util-obj-y = qnull.o qnum.o qstring.o qdict.o qlist.o qbool.o qlit.o
 util-obj-y += qjson.o qobject.o json-lexer.o json-streamer.o json-parser.o
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 37c1bed683..3653c7b40a 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -43,6 +43,8 @@ check-unit-y += tests/check-qnull$(EXESUF)
 gcov-files-check-qnull-y = qobject/qnull.c
 check-unit-y += tests/check-qjson$(EXESUF)
 gcov-files-check-qjson-y = qobject/qjson.c
+check-unit-y += tests/check-qlit$(EXESUF)
+gcov-files-check-qlit-y = qobject/qlit.c
 check-unit-y += tests/test-qobject-output-visitor$(EXESUF)
 gcov-files-test-qobject-output-visitor-y = qapi/qobject-output-visitor.c
 check-unit-y += tests/test-clone-visitor$(EXESUF)
@@ -535,7 +537,7 @@ GENERATED_FILES += tests/test-qapi-types.h tests/test-qapi-visit.h \
 
 test-obj-y = tests/check-qnum.o tests/check-qstring.o tests/check-qdict.o \
 	tests/check-qlist.o tests/check-qnull.o \
-	tests/check-qjson.o \
+	tests/check-qjson.o tests/check-qlit.o \
 	tests/test-coroutine.o tests/test-string-output-visitor.o \
 	tests/test-string-input-visitor.o tests/test-qobject-output-visitor.o \
 	tests/test-clone-visitor.o \
@@ -569,6 +571,7 @@ tests/check-qdict$(EXESUF): tests/check-qdict.o $(test-util-obj-y)
 tests/check-qlist$(EXESUF): tests/check-qlist.o $(test-util-obj-y)
 tests/check-qnull$(EXESUF): tests/check-qnull.o $(test-util-obj-y)
 tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y)
+tests/check-qlit$(EXESUF): tests/check-qlit.o $(test-util-obj-y)
 tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y)
 tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(test-qom-obj-y)
 
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 04/54] qlit: add qobject_form_qlit()
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (2 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 03/54] qobject: add literal qobject type Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 15:40   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 05/54] qapi: generate a literal qobject for introspection Marc-André Lureau
                   ` (51 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/qapi/qmp/qlit.h |  2 ++
 qobject/qlit.c          | 37 +++++++++++++++++++++++++++++++++++++
 tests/check-qlit.c      | 26 ++++++++++++++++++++++++++
 3 files changed, 65 insertions(+)

diff --git a/include/qapi/qmp/qlit.h b/include/qapi/qmp/qlit.h
index 2cdceb448d..dd562b7d69 100644
--- a/include/qapi/qmp/qlit.h
+++ b/include/qapi/qmp/qlit.h
@@ -51,4 +51,6 @@ struct QLitDictEntry {
 
 bool qlit_equal_qobject(QLitObject *lhs, QObject *rhs);
 
+QObject *qobject_from_qlit(const QLitObject *qlit);
+
 #endif /* QLIT_H_ */
diff --git a/qobject/qlit.c b/qobject/qlit.c
index f4ebeb6259..5a2aa44355 100644
--- a/qobject/qlit.c
+++ b/qobject/qlit.c
@@ -104,3 +104,40 @@ bool qlit_equal_qobject(QLitObject *lhs, QObject *rhs)
 
     return false;
 }
+
+QObject *qobject_from_qlit(const QLitObject *qlit)
+{
+    int i;
+
+    switch (qlit->type) {
+    case QTYPE_QNULL:
+        return QOBJECT(qnull());
+    case QTYPE_QNUM:
+        return QOBJECT(qnum_from_int(qlit->value.qnum));
+    case QTYPE_QSTRING:
+        return QOBJECT(qstring_from_str(qlit->value.qstr));
+    case QTYPE_QDICT: {
+        QDict *qdict = qdict_new();
+        for (i = 0; qlit->value.qdict[i].value.type != QTYPE_NONE; i++) {
+            QLitDictEntry *e = &qlit->value.qdict[i];
+
+            qdict_put_obj(qdict, e->key, qobject_from_qlit(&e->value));
+        }
+        return QOBJECT(qdict);
+    }
+    case QTYPE_QLIST: {
+        QList *qlist = qlist_new();
+
+        for (i = 0; qlit->value.qlist[i].type != QTYPE_NONE; i++) {
+            qlist_append_obj(qlist, qobject_from_qlit(&qlit->value.qlist[i]));
+        }
+        return QOBJECT(qlist);
+    }
+    case QTYPE_QBOOL:
+        return QOBJECT(qbool_from_bool(qlit->value.qbool));
+    case QTYPE_NONE:
+        assert(0);
+    }
+
+    return NULL;
+}
diff --git a/tests/check-qlit.c b/tests/check-qlit.c
index 5736b61ebf..f25f3d9633 100644
--- a/tests/check-qlit.c
+++ b/tests/check-qlit.c
@@ -58,11 +58,37 @@ static void qlit_equal_qobject_test(void)
     qobject_decref(qobj);
 }
 
+static void qobject_from_qlit_test(void)
+{
+    QObject *obj, *qobj = qobject_from_qlit(&qlit);
+    QDict *qdict;
+    QList *bee;
+
+    qdict = qobject_to_qdict(qobj);
+    g_assert_cmpint(qdict_get_int(qdict, "foo"), ==, 42);
+    g_assert_cmpstr(qdict_get_str(qdict, "bar"), ==, "hello world");
+    g_assert(qobject_type(qdict_get(qdict, "baz")) == QTYPE_QNULL);
+
+    bee = qdict_get_qlist(qdict, "bee");
+    obj = qlist_pop(bee);
+    g_assert_cmpint(qnum_get_int(qobject_to_qnum(obj)), ==, 43);
+    qobject_decref(obj);
+    obj = qlist_pop(bee);
+    g_assert_cmpint(qnum_get_int(qobject_to_qnum(obj)), ==, 44);
+    qobject_decref(obj);
+    obj = qlist_pop(bee);
+    g_assert(qbool_get_bool(qobject_to_qbool(obj)));
+    qobject_decref(obj);
+
+    qobject_decref(qobj);
+}
+
 int main(int argc, char **argv)
 {
     g_test_init(&argc, &argv, NULL);
 
     g_test_add_func("/qlit/equal_qobject", qlit_equal_qobject_test);
+    g_test_add_func("/qlit/qobject_from_qlit", qobject_from_qlit_test);
 
     return g_test_run();
 }
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 05/54] qapi: generate a literal qobject for introspection
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (3 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 04/54] qlit: add qobject_form_qlit() Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 16:33   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 06/54] qapi: introduce qapi_enum_lookup() Marc-André Lureau
                   ` (50 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Dr. David Alan Gilbert,
	Markus Armbruster, Michael Roth

Replace the generated json string with a literal qobject. The later is
easier to deal with, at run time as well as compile time: adding #if
conditionals will be easier than in a json string.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi-introspect.py         | 91 ++++++++++++++++++++++----------------
 monitor.c                          |  2 +-
 tests/test-qobject-input-visitor.c | 11 +++--
 docs/devel/qapi-code-gen.txt       | 29 +++++++-----
 4 files changed, 80 insertions(+), 53 deletions(-)

diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index 032bcea491..1b96926fa7 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -12,72 +12,80 @@
 from qapi import *
 
 
-# Caveman's json.dumps() replacement (we're stuck at Python 2.4)
-# TODO try to use json.dumps() once we get unstuck
-def to_json(obj, level=0):
+def to_c_string(s):
+    return '"' + s.replace('\\', r'\\').replace('"', r'\"') + '"'
+
+
+def to_qlit(obj, level=0, first_indent=True):
+
+    def indent(level):
+        return level * 4 * ' '
+
+    ret = ''
+    if first_indent:
+        ret += indent(level)
     if obj is None:
-        ret = 'null'
+        ret += 'QLIT_QNULL'
     elif isinstance(obj, str):
-        ret = '"' + obj.replace('"', r'\"') + '"'
+        ret += 'QLIT_QSTR(' + to_c_string(obj) + ')'
     elif isinstance(obj, list):
-        elts = [to_json(elt, level + 1)
+        elts = [to_qlit(elt, level + 1)
                 for elt in obj]
-        ret = '[' + ', '.join(elts) + ']'
+        elts.append(indent(level + 1) + "{}")
+        ret += 'QLIT_QLIST(((QLitObject[]) {\n'
+        ret += ',\n'.join(elts) + '\n'
+        ret += indent(level) + '}))'
     elif isinstance(obj, dict):
-        elts = ['"%s": %s' % (key.replace('"', r'\"'),
-                              to_json(obj[key], level + 1))
-                for key in sorted(obj.keys())]
-        ret = '{' + ', '.join(elts) + '}'
+        elts = []
+        for key, value in sorted(obj.iteritems()):
+            elts.append(indent(level + 1) + '{ %s, %s }' %
+                        (to_c_string(key), to_qlit(value, level + 1, False)))
+        elts.append(indent(level + 1) + '{}')
+        ret += 'QLIT_QDICT(((QLitDictEntry[]) {\n'
+        ret += ',\n'.join(elts) + '\n'
+        ret += indent(level) + '}))'
     else:
         assert False                # not implemented
-    if level == 1:
-        ret = '\n' + ret
     return ret
 
 
-def to_c_string(string):
-    return '"' + string.replace('\\', r'\\').replace('"', r'\"') + '"'
-
-
 class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor):
     def __init__(self, unmask):
         self._unmask = unmask
         self.defn = None
         self.decl = None
         self._schema = None
-        self._jsons = None
+        self._qlits = None
         self._used_types = None
         self._name_map = None
 
     def visit_begin(self, schema):
         self._schema = schema
-        self._jsons = []
+        self._qlits = []
         self._used_types = []
         self._name_map = {}
 
     def visit_end(self):
         # visit the types that are actually used
-        jsons = self._jsons
-        self._jsons = []
+        qlits = self._qlits
+        self._qlits = []
         for typ in self._used_types:
             typ.visit(self)
         # generate C
         # TODO can generate awfully long lines
-        jsons.extend(self._jsons)
-        name = c_name(prefix, protect=False) + 'qmp_schema_json'
+        qlits.extend(self._qlits)
+        name = c_name(prefix, protect=False) + 'qmp_schema_qlit'
         self.decl = mcgen('''
-extern const char %(c_name)s[];
+extern const QLitObject %(c_name)s;
 ''',
                           c_name=c_name(name))
-        lines = to_json(jsons).split('\n')
-        c_string = '\n    '.join([to_c_string(line) for line in lines])
         self.defn = mcgen('''
-const char %(c_name)s[] = %(c_string)s;
+const QLitObject %(c_name)s = %(c_string)s;
 ''',
                           c_name=c_name(name),
-                          c_string=c_string)
+                          c_string=to_qlit(qlits))
         self._schema = None
-        self._jsons = None
+        self._qlits = None
         self._used_types = None
         self._name_map = None
 
@@ -111,12 +119,12 @@ const char %(c_name)s[] = %(c_string)s;
             return '[' + self._use_type(typ.element_type) + ']'
         return self._name(typ.name)
 
-    def _gen_json(self, name, mtype, obj):
+    def _gen_qlit(self, name, mtype, obj):
         if mtype not in ('command', 'event', 'builtin', 'array'):
             name = self._name(name)
         obj['name'] = name
         obj['meta-type'] = mtype
-        self._jsons.append(obj)
+        self._qlits.append(obj)
 
     def _gen_member(self, member):
         ret = {'name': member.name, 'type': self._use_type(member.type)}
@@ -132,24 +140,24 @@ const char %(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_json(name, 'builtin', {'json-type': json_type})
+        self._gen_qlit(name, 'builtin', {'json-type': json_type})
 
     def visit_enum_type(self, name, info, values, prefix):
-        self._gen_json(name, 'enum', {'values': values})
+        self._gen_qlit(name, 'enum', {'values': values})
 
     def visit_array_type(self, name, info, element_type):
         element = self._use_type(element_type)
-        self._gen_json('[' + element + ']', 'array', {'element-type': element})
+        self._gen_qlit('[' + element + ']', 'array', {'element-type': element})
 
     def visit_object_type_flat(self, name, info, 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_json(name, 'object', obj)
+        self._gen_qlit(name, 'object', obj)
 
     def visit_alternate_type(self, name, info, variants):
-        self._gen_json(name, 'alternate',
+        self._gen_qlit(name, 'alternate',
                        {'members': [{'type': self._use_type(m.type)}
                                     for m in variants.variants]})
 
@@ -157,13 +165,13 @@ const char %(c_name)s[] = %(c_string)s;
                       gen, success_response, boxed):
         arg_type = arg_type or self._schema.the_empty_object_type
         ret_type = ret_type or self._schema.the_empty_object_type
-        self._gen_json(name, 'command',
+        self._gen_qlit(name, 'command',
                        {'arg-type': self._use_type(arg_type),
                         'ret-type': self._use_type(ret_type)})
 
     def visit_event(self, name, info, arg_type, boxed):
         arg_type = arg_type or self._schema.the_empty_object_type
-        self._gen_json(name, 'event', {'arg-type': self._use_type(arg_type)})
+        self._gen_qlit(name, 'event', {'arg-type': self._use_type(arg_type)})
 
 # Debugging aid: unmask QAPI schema's type names
 # We normally mask them, because they're not QMP wire ABI
@@ -205,11 +213,18 @@ h_comment = '''
 
 fdef.write(mcgen('''
 #include "qemu/osdep.h"
+#include "qapi/qmp/qlit.h"
 #include "%(prefix)sqmp-introspect.h"
 
 ''',
                  prefix=prefix))
 
+fdecl.write(mcgen('''
+#include "qemu/osdep.h"
+#include "qapi/qmp/qlit.h"
+
+'''))
+
 schema = QAPISchema(input_file)
 gen = QAPISchemaGenIntrospectVisitor(opt_unmask)
 schema.visit(gen)
diff --git a/monitor.c b/monitor.c
index e0f880107f..14c27d4b6f 100644
--- a/monitor.c
+++ b/monitor.c
@@ -953,7 +953,7 @@ EventInfoList *qmp_query_events(Error **errp)
 static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
                                  Error **errp)
 {
-    *ret_data = qobject_from_json(qmp_schema_json, &error_abort);
+    *ret_data = qobject_from_qlit(&qmp_schema_qlit);
 }
 
 /*
diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
index bcf02617dc..bdd00f6bd8 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -1247,24 +1247,27 @@ static void test_visitor_in_fail_alternate(TestInputVisitorData *data,
 }
 
 static void do_test_visitor_in_qmp_introspect(TestInputVisitorData *data,
-                                              const char *schema_json)
+                                              const QLitObject *qlit)
 {
     SchemaInfoList *schema = NULL;
+    QObject *obj = qobject_from_qlit(qlit);
     Visitor *v;
 
-    v = visitor_input_test_init_raw(data, schema_json);
+    v = qobject_input_visitor_new(obj);
 
     visit_type_SchemaInfoList(v, NULL, &schema, &error_abort);
     g_assert(schema);
 
     qapi_free_SchemaInfoList(schema);
+    qobject_decref(obj);
+    visit_free(v);
 }
 
 static void test_visitor_in_qmp_introspect(TestInputVisitorData *data,
                                            const void *unused)
 {
-    do_test_visitor_in_qmp_introspect(data, test_qmp_schema_json);
-    do_test_visitor_in_qmp_introspect(data, qmp_schema_json);
+    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/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
index 9903ac4c19..b653e86bff 100644
--- a/docs/devel/qapi-code-gen.txt
+++ b/docs/devel/qapi-code-gen.txt
@@ -1295,18 +1295,27 @@ Example:
     #ifndef EXAMPLE_QMP_INTROSPECT_H
     #define EXAMPLE_QMP_INTROSPECT_H
 
-    extern const char example_qmp_schema_json[];
+    extern const QLitObject qmp_schema_qlit;
 
     #endif
     $ cat qapi-generated/example-qmp-introspect.c
 [Uninteresting stuff omitted...]
 
-    const char example_qmp_schema_json[] = "["
-        "{\"arg-type\": \"0\", \"meta-type\": \"event\", \"name\": \"MY_EVENT\"}, "
-        "{\"arg-type\": \"1\", \"meta-type\": \"command\", \"name\": \"my-command\", \"ret-type\": \"2\"}, "
-        "{\"members\": [], \"meta-type\": \"object\", \"name\": \"0\"}, "
-        "{\"members\": [{\"name\": \"arg1\", \"type\": \"[2]\"}], \"meta-type\": \"object\", \"name\": \"1\"}, "
-        "{\"members\": [{\"name\": \"integer\", \"type\": \"int\"}, {\"default\": null, \"name\": \"string\", \"type\": \"str\"}], \"meta-type\": \"object\", \"name\": \"2\"}, "
-        "{\"element-type\": \"2\", \"meta-type\": \"array\", \"name\": \"[2]\"}, "
-        "{\"json-type\": \"int\", \"meta-type\": \"builtin\", \"name\": \"int\"}, "
-        "{\"json-type\": \"string\", \"meta-type\": \"builtin\", \"name\": \"str\"}]";
+    const QLitObject example_qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
+        QLIT_QDICT(((QLitDictEntry[]) {
+            { "arg-type", QLIT_QSTR("0") },
+            { "meta-type", QLIT_QSTR("event") },
+            { "name", QLIT_QSTR("Event") },
+            { }
+        })),
+        QLIT_QDICT(((QLitDictEntry[]) {
+            { "members", QLIT_QLIST(((QLitObject[]) {
+                { }
+            })) },
+            { "meta-type", QLIT_QSTR("object") },
+            { "name", QLIT_QSTR("0") },
+            { }
+        })),
+        ...
+        { }
+    }));
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 06/54] qapi: introduce qapi_enum_lookup()
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (4 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 05/54] qapi: generate a literal qobject for introspection Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 18:10   ` John Snow
  2017-08-23  8:02   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 07/54] tpm: simplify driver registration & lookup Marc-André Lureau
                   ` (49 subsequent siblings)
  55 siblings, 2 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Eduardo Habkost, Igor Mammedov,
	Jeff Cody, Kevin Wolf, Max Reitz, Stefan Weil, Ronnie Sahlberg,
	Paolo Bonzini, Peter Lieven, Stefan Hajnoczi, Josh Durgin,
	Hitoshi Mitake, Liu Yuan, Markus Armbruster, Daniel P. Berrange,
	Dr. David Alan Gilbert, John Snow, Gerd Hoffmann,
	Michael S. Tsirkin, Michael Roth, zhanghailiang, Juan Quintela,
	Jason Wang, open list:Block Jobs, open list:Sheepdog

This will help with the introduction of a new structure to handle
enum lookup.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/qapi/util.h                 |  2 +
 backends/hostmem.c                  |  3 +-
 block/backup.c                      |  3 +-
 block/file-posix.c                  |  5 ++-
 block/file-win32.c                  |  2 +-
 block/gluster.c                     |  4 +-
 block/iscsi.c                       |  3 +-
 block/nfs.c                         |  3 +-
 block/qcow2.c                       |  5 ++-
 block/qed.c                         |  3 +-
 block/rbd.c                         |  3 +-
 block/sheepdog.c                    |  3 +-
 blockdev.c                          |  6 ++-
 blockjob.c                          |  9 +++--
 chardev/char.c                      |  7 +++-
 crypto/block-luks.c                 | 17 ++++++---
 crypto/block.c                      |  5 ++-
 crypto/cipher-afalg.c               |  2 +-
 crypto/cipher-builtin.c             |  8 ++--
 crypto/cipher-gcrypt.c              |  4 +-
 crypto/cipher-nettle.c              |  8 ++--
 crypto/cipher.c                     |  1 +
 crypto/hmac-gcrypt.c                |  2 +-
 crypto/hmac-glib.c                  |  3 +-
 crypto/hmac-nettle.c                |  3 +-
 crypto/pbkdf-gcrypt.c               |  3 +-
 crypto/pbkdf-nettle.c               |  4 +-
 hmp.c                               | 74 +++++++++++++++++++++++--------------
 hw/block/fdc.c                      |  9 +++--
 hw/char/escc.c                      |  3 +-
 hw/core/qdev-properties.c           |  9 +++--
 hw/input/virtio-input-hid.c         |  5 ++-
 migration/colo-failover.c           |  6 ++-
 migration/colo.c                    | 17 +++++----
 migration/global_state.c            |  2 +-
 monitor.c                           | 24 +++++++-----
 net/net.c                           |  5 ++-
 qapi/qapi-util.c                    |  7 ++++
 qapi/qmp-dispatch.c                 |  4 +-
 tests/test-qobject-output-visitor.c |  4 +-
 tests/test-string-output-visitor.c  |  6 ++-
 tpm.c                               |  4 +-
 ui/input.c                          | 13 ++++---
 ui/vnc.c                            |  8 ++--
 vl.c                                |  7 ++--
 45 files changed, 206 insertions(+), 122 deletions(-)

diff --git a/include/qapi/util.h b/include/qapi/util.h
index 7436ed815c..60733b6a80 100644
--- a/include/qapi/util.h
+++ b/include/qapi/util.h
@@ -11,6 +11,8 @@
 #ifndef QAPI_UTIL_H
 #define QAPI_UTIL_H
 
+const char *qapi_enum_lookup(const char * const lookup[], int val);
+
 int qapi_enum_parse(const char * const lookup[], const char *buf,
                     int max, int def, Error **errp);
 
diff --git a/backends/hostmem.c b/backends/hostmem.c
index 4606b73849..c4f795475c 100644
--- a/backends/hostmem.c
+++ b/backends/hostmem.c
@@ -13,6 +13,7 @@
 #include "sysemu/hostmem.h"
 #include "hw/boards.h"
 #include "qapi/error.h"
+#include "qapi/util.h"
 #include "qapi/visitor.h"
 #include "qapi-types.h"
 #include "qapi-visit.h"
@@ -304,7 +305,7 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
             return;
         } else if (maxnode == 0 && backend->policy != MPOL_DEFAULT) {
             error_setg(errp, "host-nodes must be set for policy %s",
-                       HostMemPolicy_lookup[backend->policy]);
+                qapi_enum_lookup(HostMemPolicy_lookup, backend->policy));
             return;
         }
 
diff --git a/block/backup.c b/block/backup.c
index 504a089150..a700cc0315 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -19,6 +19,7 @@
 #include "block/blockjob_int.h"
 #include "block/block_backup.h"
 #include "qapi/error.h"
+#include "qapi/util.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/ratelimit.h"
 #include "qemu/cutils.h"
@@ -596,7 +597,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
         error_setg(errp,
                    "a sync_bitmap was provided to backup_run, "
                    "but received an incompatible sync_mode (%s)",
-                   MirrorSyncMode_lookup[sync_mode]);
+                   qapi_enum_lookup(MirrorSyncMode_lookup, sync_mode));
         return NULL;
     }
 
diff --git a/block/file-posix.c b/block/file-posix.c
index cb3bfce147..48200aef0b 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -1725,7 +1725,7 @@ static int raw_regular_truncate(int fd, int64_t offset, PreallocMode prealloc,
     default:
         result = -ENOTSUP;
         error_setg(errp, "Unsupported preallocation mode: %s",
-                   PreallocMode_lookup[prealloc]);
+                   qapi_enum_lookup(PreallocMode_lookup, prealloc));
         return result;
     }
 
@@ -1760,7 +1760,8 @@ static int raw_truncate(BlockDriverState *bs, int64_t offset,
 
     if (prealloc != PREALLOC_MODE_OFF) {
         error_setg(errp, "Preallocation mode '%s' unsupported for this "
-                   "non-regular file", PreallocMode_lookup[prealloc]);
+                   "non-regular file", qapi_enum_lookup(PreallocMode_lookup,
+                                                        prealloc));
         return -ENOTSUP;
     }
 
diff --git a/block/file-win32.c b/block/file-win32.c
index 4706335cff..2f3975f040 100644
--- a/block/file-win32.c
+++ b/block/file-win32.c
@@ -470,7 +470,7 @@ static int raw_truncate(BlockDriverState *bs, int64_t offset,
 
     if (prealloc != PREALLOC_MODE_OFF) {
         error_setg(errp, "Unsupported preallocation mode '%s'",
-                   PreallocMode_lookup[prealloc]);
+                   qapi_enum_lookup(reallocMode_lookup, prealloc));
         return -ENOTSUP;
     }
 
diff --git a/block/gluster.c b/block/gluster.c
index 3064a45047..934f459014 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -1050,7 +1050,7 @@ static int qemu_gluster_create(const char *filename,
     default:
         ret = -EINVAL;
         error_setg(errp, "Unsupported preallocation mode: %s",
-                   PreallocMode_lookup[prealloc]);
+                   qapi_enum_lookup(PreallocMode_lookup, prealloc));
         break;
     }
 
@@ -1102,7 +1102,7 @@ static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset,
 
     if (prealloc != PREALLOC_MODE_OFF) {
         error_setg(errp, "Unsupported preallocation mode '%s'",
-                   PreallocMode_lookup[prealloc]);
+                   qapi_enum_lookup(PreallocMode_lookup, prealloc));
         return -ENOTSUP;
     }
 
diff --git a/block/iscsi.c b/block/iscsi.c
index d557c99668..5c1870340b 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -39,6 +39,7 @@
 #include "qemu/uuid.h"
 #include "qmp-commands.h"
 #include "qapi/qmp/qstring.h"
+#include "qapi/util.h"
 #include "crypto/secret.h"
 
 #include <iscsi/iscsi.h>
@@ -2087,7 +2088,7 @@ static int iscsi_truncate(BlockDriverState *bs, int64_t offset,
 
     if (prealloc != PREALLOC_MODE_OFF) {
         error_setg(errp, "Unsupported preallocation mode '%s'",
-                   PreallocMode_lookup[prealloc]);
+                   qapi_enum_lookup(PreallocMode_lookup, prealloc));
         return -ENOTSUP;
     }
 
diff --git a/block/nfs.c b/block/nfs.c
index bec16b72a6..953728ae31 100644
--- a/block/nfs.c
+++ b/block/nfs.c
@@ -40,6 +40,7 @@
 #include "qapi-visit.h"
 #include "qapi/qobject-input-visitor.h"
 #include "qapi/qobject-output-visitor.h"
+#include "qapi/util.h"
 #include <nfsc/libnfs.h>
 
 
@@ -772,7 +773,7 @@ static int nfs_file_truncate(BlockDriverState *bs, int64_t offset,
 
     if (prealloc != PREALLOC_MODE_OFF) {
         error_setg(errp, "Unsupported preallocation mode '%s'",
-                   PreallocMode_lookup[prealloc]);
+                   qapi_enum_lookup(PreallocMode_lookup, prealloc));
         return -ENOTSUP;
     }
 
diff --git a/block/qcow2.c b/block/qcow2.c
index 40ba26c111..45b0579caa 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2732,7 +2732,8 @@ static int qcow2_create2(const char *filename, int64_t total_size,
         int64_t prealloc_size =
             qcow2_calc_prealloc_size(total_size, cluster_size, refcount_order);
         qemu_opt_set_number(opts, BLOCK_OPT_SIZE, prealloc_size, &error_abort);
-        qemu_opt_set(opts, BLOCK_OPT_PREALLOC, PreallocMode_lookup[prealloc],
+        qemu_opt_set(opts, BLOCK_OPT_PREALLOC,
+                     qapi_enum_lookup(PreallocMode_lookup, prealloc),
                      &error_abort);
     }
 
@@ -3098,7 +3099,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
         prealloc != PREALLOC_MODE_FALLOC && prealloc != PREALLOC_MODE_FULL)
     {
         error_setg(errp, "Unsupported preallocation mode '%s'",
-                   PreallocMode_lookup[prealloc]);
+                   qapi_enum_lookup(PreallocMode_lookup, prealloc));
         return -ENOTSUP;
     }
 
diff --git a/block/qed.c b/block/qed.c
index dc54bf4a93..756fcb85a7 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -19,6 +19,7 @@
 #include "trace.h"
 #include "qed.h"
 #include "qapi/qmp/qerror.h"
+#include "qapi/util.h"
 #include "sysemu/block-backend.h"
 
 static int bdrv_qed_probe(const uint8_t *buf, int buf_size,
@@ -1399,7 +1400,7 @@ static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset,
 
     if (prealloc != PREALLOC_MODE_OFF) {
         error_setg(errp, "Unsupported preallocation mode '%s'",
-                   PreallocMode_lookup[prealloc]);
+                   qapi_enum_lookup(PreallocMode_lookup, prealloc));
         return -ENOTSUP;
     }
 
diff --git a/block/rbd.c b/block/rbd.c
index 9c3aa638e7..09f8d18d1b 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -21,6 +21,7 @@
 #include "qemu/cutils.h"
 #include "qapi/qmp/qstring.h"
 #include "qapi/qmp/qjson.h"
+#include "qapi/util.h"
 
 /*
  * When specifying the image filename use:
@@ -944,7 +945,7 @@ static int qemu_rbd_truncate(BlockDriverState *bs, int64_t offset,
 
     if (prealloc != PREALLOC_MODE_OFF) {
         error_setg(errp, "Unsupported preallocation mode '%s'",
-                   PreallocMode_lookup[prealloc]);
+                   qapi_enum_lookup(PreallocMode_lookup, prealloc));
         return -ENOTSUP;
     }
 
diff --git a/block/sheepdog.c b/block/sheepdog.c
index abb2e79065..69d49fb720 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -17,6 +17,7 @@
 #include "qapi/error.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qobject-input-visitor.h"
+#include "qapi/util.h"
 #include "qemu/uri.h"
 #include "qemu/error-report.h"
 #include "qemu/sockets.h"
@@ -2176,7 +2177,7 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset,
 
     if (prealloc != PREALLOC_MODE_OFF) {
         error_setg(errp, "Unsupported preallocation mode '%s'",
-                   PreallocMode_lookup[prealloc]);
+                   qapi_enum_lookup(PreallocMode_lookup, prealloc));
         return -ENOTSUP;
     }
 
diff --git a/blockdev.c b/blockdev.c
index 02cd69bc21..6a067e81bf 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1468,8 +1468,10 @@ static int action_check_completion_mode(BlkActionState *s, Error **errp)
         error_setg(errp,
                    "Action '%s' does not support Transaction property "
                    "completion-mode = %s",
-                   TransactionActionKind_lookup[s->action->type],
-                   ActionCompletionMode_lookup[s->txn_props->completion_mode]);
+                   qapi_enum_lookup(TransactionActionKind_lookup,
+                                    s->action->type),
+                   qapi_enum_lookup(ActionCompletionMode_lookup,
+                                    s->txn_props->completion_mode));
         return -1;
     }
     return 0;
diff --git a/blockjob.c b/blockjob.c
index 70a78188b7..fca71123e0 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -31,6 +31,7 @@
 #include "sysemu/block-backend.h"
 #include "qapi/qmp/qerror.h"
 #include "qapi/qmp/qjson.h"
+#include "qapi/util.h"
 #include "qemu/coroutine.h"
 #include "qemu/id.h"
 #include "qmp-commands.h"
@@ -208,7 +209,8 @@ static char *child_job_get_parent_desc(BdrvChild *c)
 {
     BlockJob *job = c->opaque;
     return g_strdup_printf("%s job '%s'",
-                           BlockJobType_lookup[job->driver->job_type],
+                           qapi_enum_lookup(BlockJobType_lookup,
+                                            job->driver->job_type),
                            job->id);
 }
 
@@ -553,7 +555,8 @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
         return NULL;
     }
     info = g_new0(BlockJobInfo, 1);
-    info->type      = g_strdup(BlockJobType_lookup[job->driver->job_type]);
+    info->type      = g_strdup(qapi_enum_lookup(BlockJobType_lookup,
+                                                job->driver->job_type));
     info->device    = g_strdup(job->id);
     info->len       = job->len;
     info->busy      = job->busy;
@@ -666,7 +669,7 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
     job->refcnt        = 1;
 
     error_setg(&job->blocker, "block device is in use by block job: %s",
-               BlockJobType_lookup[driver->job_type]);
+               qapi_enum_lookup(BlockJobType_lookup, driver->job_type));
     block_job_add_bdrv(job, "main node", bs, 0, BLK_PERM_ALL, &error_abort);
     bs->job = job;
 
diff --git a/chardev/char.c b/chardev/char.c
index 5d283b90d3..4408d12a08 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -30,6 +30,7 @@
 #include "chardev/char.h"
 #include "qmp-commands.h"
 #include "qapi-visit.h"
+#include "qapi/util.h"
 #include "sysemu/replay.h"
 #include "qemu/help_option.h"
 
@@ -931,7 +932,8 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
     ChardevReturn *ret;
     Chardev *chr;
 
-    cc = char_get_class(ChardevBackendKind_lookup[backend->type], errp);
+    cc = char_get_class(qapi_enum_lookup(ChardevBackendKind_lookup,
+                                         backend->type), errp);
     if (!cc) {
         return NULL;
     }
@@ -989,7 +991,8 @@ ChardevReturn *qmp_chardev_change(const char *id, ChardevBackend *backend,
         return NULL;
     }
 
-    cc = char_get_class(ChardevBackendKind_lookup[backend->type], errp);
+    cc = char_get_class(qapi_enum_lookup(ChardevBackendKind_lookup,
+                                         backend->type), errp);
     if (!cc) {
         return NULL;
     }
diff --git a/crypto/block-luks.c b/crypto/block-luks.c
index afb8543108..b78a6345f3 100644
--- a/crypto/block-luks.c
+++ b/crypto/block-luks.c
@@ -20,6 +20,7 @@
 
 #include "qemu/osdep.h"
 #include "qapi/error.h"
+#include "qapi/util.h"
 #include "qemu/bswap.h"
 
 #include "crypto/block-luks.h"
@@ -257,7 +258,7 @@ qcrypto_block_luks_cipher_alg_lookup(QCryptoCipherAlgorithm alg,
     }
 
     error_setg(errp, "Algorithm '%s' not supported",
-               QCryptoCipherAlgorithm_lookup[alg]);
+               qapi_enum_lookup(QCryptoCipherAlgorithm_lookup, alg));
     return NULL;
 }
 
@@ -398,7 +399,7 @@ qcrypto_block_luks_essiv_cipher(QCryptoCipherAlgorithm cipher,
         break;
     default:
         error_setg(errp, "Cipher %s not supported with essiv",
-                   QCryptoCipherAlgorithm_lookup[cipher]);
+                   qapi_enum_lookup(QCryptoCipherAlgorithm_lookup, cipher));
         return 0;
     }
 }
@@ -968,16 +969,20 @@ qcrypto_block_luks_create(QCryptoBlock *block,
         goto error;
     }
 
-    cipher_mode = QCryptoCipherMode_lookup[luks_opts.cipher_mode];
-    ivgen_alg = QCryptoIVGenAlgorithm_lookup[luks_opts.ivgen_alg];
+    cipher_mode = qapi_enum_lookup(QCryptoCipherMode_lookup,
+                                   luks_opts.cipher_mode);
+    ivgen_alg = qapi_enum_lookup(QCryptoIVGenAlgorithm_lookup,
+                                 luks_opts.ivgen_alg);
     if (luks_opts.has_ivgen_hash_alg) {
-        ivgen_hash_alg = QCryptoHashAlgorithm_lookup[luks_opts.ivgen_hash_alg];
+        ivgen_hash_alg = qapi_enum_lookup(QCryptoHashAlgorithm_lookup,
+                                          luks_opts.ivgen_hash_alg);
         cipher_mode_spec = g_strdup_printf("%s-%s:%s", cipher_mode, ivgen_alg,
                                            ivgen_hash_alg);
     } else {
         cipher_mode_spec = g_strdup_printf("%s-%s", cipher_mode, ivgen_alg);
     }
-    hash_alg = QCryptoHashAlgorithm_lookup[luks_opts.hash_alg];
+    hash_alg = qapi_enum_lookup(QCryptoHashAlgorithm_lookup,
+                                luks_opts.hash_alg);
 
 
     if (strlen(cipher_alg) >= QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN) {
diff --git a/crypto/block.c b/crypto/block.c
index b097d451af..2140e55426 100644
--- a/crypto/block.c
+++ b/crypto/block.c
@@ -20,6 +20,7 @@
 
 #include "qemu/osdep.h"
 #include "qapi/error.h"
+#include "qapi/util.h"
 #include "crypto/blockpriv.h"
 #include "crypto/block-qcow.h"
 #include "crypto/block-luks.h"
@@ -61,7 +62,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
     if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
         !qcrypto_block_drivers[options->format]) {
         error_setg(errp, "Unsupported block driver %s",
-                   QCryptoBlockFormat_lookup[options->format]);
+            qapi_enum_lookup(QCryptoBlockFormat_lookup, options->format));
         g_free(block);
         return NULL;
     }
@@ -92,7 +93,7 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
     if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
         !qcrypto_block_drivers[options->format]) {
         error_setg(errp, "Unsupported block driver %s",
-                   QCryptoBlockFormat_lookup[options->format]);
+            qapi_enum_lookup(QCryptoBlockFormat_lookup, options->format));
         g_free(block);
         return NULL;
     }
diff --git a/crypto/cipher-afalg.c b/crypto/cipher-afalg.c
index 01343b2b7c..24d7ba8277 100644
--- a/crypto/cipher-afalg.c
+++ b/crypto/cipher-afalg.c
@@ -52,7 +52,7 @@ qcrypto_afalg_cipher_format_name(QCryptoCipherAlgorithm alg,
         return NULL;
     }
 
-    mode_name = QCryptoCipherMode_lookup[mode];
+    mode_name = qapi_enum_lookup(QCryptoCipherMode_lookup, mode);
     name = g_strdup_printf("%s(%s)", mode_name, alg_name);
 
     return name;
diff --git a/crypto/cipher-builtin.c b/crypto/cipher-builtin.c
index 16a36d4532..76c76fb05b 100644
--- a/crypto/cipher-builtin.c
+++ b/crypto/cipher-builtin.c
@@ -247,7 +247,7 @@ qcrypto_cipher_init_aes(QCryptoCipherMode mode,
         mode != QCRYPTO_CIPHER_MODE_ECB &&
         mode != QCRYPTO_CIPHER_MODE_XTS) {
         error_setg(errp, "Unsupported cipher mode %s",
-                   QCryptoCipherMode_lookup[mode]);
+                   qapi_enum_lookup(QCryptoCipherMode_lookup, mode));
         return NULL;
     }
 
@@ -379,7 +379,7 @@ qcrypto_cipher_init_des_rfb(QCryptoCipherMode mode,
 
     if (mode != QCRYPTO_CIPHER_MODE_ECB) {
         error_setg(errp, "Unsupported cipher mode %s",
-                   QCryptoCipherMode_lookup[mode]);
+                   qapi_enum_lookup(QCryptoCipherMode_lookup, mode));
         return NULL;
     }
 
@@ -440,7 +440,7 @@ static QCryptoCipherBuiltin *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
         break;
     default:
         error_setg(errp, "Unsupported cipher mode %s",
-                   QCryptoCipherMode_lookup[mode]);
+                   qapi_enum_lookup(QCryptoCipherMode_lookup, mode));
         return NULL;
     }
 
@@ -460,7 +460,7 @@ static QCryptoCipherBuiltin *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
     default:
         error_setg(errp,
                    "Unsupported cipher algorithm %s",
-                   QCryptoCipherAlgorithm_lookup[alg]);
+                   qapi_enum_lookup(QCryptoCipherAlgorithm_lookup, alg));
         return NULL;
     }
 
diff --git a/crypto/cipher-gcrypt.c b/crypto/cipher-gcrypt.c
index 0489147398..09210195a4 100644
--- a/crypto/cipher-gcrypt.c
+++ b/crypto/cipher-gcrypt.c
@@ -105,7 +105,7 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
         break;
     default:
         error_setg(errp, "Unsupported cipher mode %s",
-                   QCryptoCipherMode_lookup[mode]);
+                   qapi_enum_lookup(QCryptoCipherMode_lookup, mode));
         return NULL;
     }
 
@@ -160,7 +160,7 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
 
     default:
         error_setg(errp, "Unsupported cipher algorithm %s",
-                   QCryptoCipherAlgorithm_lookup[alg]);
+                   qapi_enum_lookup(QCryptoCipherAlgorithm_lookup, alg));
         return NULL;
     }
 
diff --git a/crypto/cipher-nettle.c b/crypto/cipher-nettle.c
index c51f119cbc..7c02b3e7a2 100644
--- a/crypto/cipher-nettle.c
+++ b/crypto/cipher-nettle.c
@@ -281,7 +281,7 @@ static QCryptoCipherNettle *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
         break;
     default:
         error_setg(errp, "Unsupported cipher mode %s",
-                   QCryptoCipherMode_lookup[mode]);
+                   qapi_enum_lookup(QCryptoCipherMode_lookup, mode));
         return NULL;
     }
 
@@ -420,7 +420,7 @@ static QCryptoCipherNettle *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
 
     default:
         error_setg(errp, "Unsupported cipher algorithm %s",
-                   QCryptoCipherAlgorithm_lookup[alg]);
+                   qapi_enum_lookup(QCryptoCipherAlgorithm_lookup, alg));
         goto error;
     }
 
@@ -491,7 +491,7 @@ qcrypto_nettle_cipher_encrypt(QCryptoCipher *cipher,
 
     default:
         error_setg(errp, "Unsupported cipher mode %s",
-                   QCryptoCipherMode_lookup[cipher->mode]);
+                   qapi_enum_lookup(QCryptoCipherMode_lookup, cipher->mode));
         return -1;
     }
     return 0;
@@ -537,7 +537,7 @@ qcrypto_nettle_cipher_decrypt(QCryptoCipher *cipher,
 
     default:
         error_setg(errp, "Unsupported cipher mode %s",
-                   QCryptoCipherMode_lookup[cipher->mode]);
+                   qapi_enum_lookup(QCryptoCipherMode_lookup, cipher->mode));
         return -1;
     }
     return 0;
diff --git a/crypto/cipher.c b/crypto/cipher.c
index 0aad9d6d79..43291cba7e 100644
--- a/crypto/cipher.c
+++ b/crypto/cipher.c
@@ -22,6 +22,7 @@
 #include "qapi/error.h"
 #include "crypto/cipher.h"
 #include "cipherpriv.h"
+#include "qapi/util.h"
 
 
 static size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = {
diff --git a/crypto/hmac-gcrypt.c b/crypto/hmac-gcrypt.c
index 76ca61ba24..0784795269 100644
--- a/crypto/hmac-gcrypt.c
+++ b/crypto/hmac-gcrypt.c
@@ -52,7 +52,7 @@ void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
 
     if (!qcrypto_hmac_supports(alg)) {
         error_setg(errp, "Unsupported hmac algorithm %s",
-                   QCryptoHashAlgorithm_lookup[alg]);
+                   qapi_enum_lookup(QCryptoHashAlgorithm_lookup, alg));
         return NULL;
     }
 
diff --git a/crypto/hmac-glib.c b/crypto/hmac-glib.c
index 8cf6b221ed..56b71dbf85 100644
--- a/crypto/hmac-glib.c
+++ b/crypto/hmac-glib.c
@@ -14,6 +14,7 @@
 
 #include "qemu/osdep.h"
 #include "qapi/error.h"
+#include "qapi/util.h"
 #include "crypto/hmac.h"
 #include "hmacpriv.h"
 
@@ -58,7 +59,7 @@ void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
 
     if (!qcrypto_hmac_supports(alg)) {
         error_setg(errp, "Unsupported hmac algorithm %s",
-                   QCryptoHashAlgorithm_lookup[alg]);
+                   qapi_enum_lookup(QCryptoHashAlgorithm_lookup, alg));
         return NULL;
     }
 
diff --git a/crypto/hmac-nettle.c b/crypto/hmac-nettle.c
index 1d5a915f03..be43511252 100644
--- a/crypto/hmac-nettle.c
+++ b/crypto/hmac-nettle.c
@@ -14,6 +14,7 @@
 
 #include "qemu/osdep.h"
 #include "qapi/error.h"
+#include "qapi/util.h"
 #include "crypto/hmac.h"
 #include "hmacpriv.h"
 #include <nettle/hmac.h>
@@ -106,7 +107,7 @@ void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
 
     if (!qcrypto_hmac_supports(alg)) {
         error_setg(errp, "Unsupported hmac algorithm %s",
-                   QCryptoHashAlgorithm_lookup[alg]);
+                   qapi_enum_lookup(QCryptoHashAlgorithm_lookup, alg));
         return NULL;
     }
 
diff --git a/crypto/pbkdf-gcrypt.c b/crypto/pbkdf-gcrypt.c
index 40289858bf..a815138c46 100644
--- a/crypto/pbkdf-gcrypt.c
+++ b/crypto/pbkdf-gcrypt.c
@@ -22,6 +22,7 @@
 #include <gcrypt.h>
 #include "qapi/error.h"
 #include "crypto/pbkdf.h"
+#include "qapi/util.h"
 
 bool qcrypto_pbkdf2_supports(QCryptoHashAlgorithm hash)
 {
@@ -68,7 +69,7 @@ int qcrypto_pbkdf2(QCryptoHashAlgorithm hash,
         hash_map[hash] == GCRY_MD_NONE) {
         error_setg_errno(errp, ENOSYS,
                          "PBKDF does not support hash algorithm %s",
-                         QCryptoHashAlgorithm_lookup[hash]);
+                         qapi_enum_lookup(QCryptoHashAlgorithm_lookup, hash));
         return -1;
     }
 
diff --git a/crypto/pbkdf-nettle.c b/crypto/pbkdf-nettle.c
index 6fb2671656..84977fdd69 100644
--- a/crypto/pbkdf-nettle.c
+++ b/crypto/pbkdf-nettle.c
@@ -23,7 +23,7 @@
 #include <nettle/hmac.h>
 #include "qapi/error.h"
 #include "crypto/pbkdf.h"
-
+#include "qapi/util.h"
 
 bool qcrypto_pbkdf2_supports(QCryptoHashAlgorithm hash)
 {
@@ -110,7 +110,7 @@ int qcrypto_pbkdf2(QCryptoHashAlgorithm hash,
     default:
         error_setg_errno(errp, ENOSYS,
                          "PBKDF does not support hash algorithm %s",
-                         QCryptoHashAlgorithm_lookup[hash]);
+                         qapi_enum_lookup(QCryptoHashAlgorithm_lookup, hash));
         return -1;
     }
     return 0;
diff --git a/hmp.c b/hmp.c
index fd80dce758..29e42ab661 100644
--- a/hmp.c
+++ b/hmp.c
@@ -107,7 +107,8 @@ void hmp_info_status(Monitor *mon, const QDict *qdict)
                    info->singlestep ? " (single step mode)" : "");
 
     if (!info->running && info->status != RUN_STATE_PAUSED) {
-        monitor_printf(mon, " (%s)", RunState_lookup[info->status]);
+        monitor_printf(mon, " (%s)",
+                       qapi_enum_lookup(RunState_lookup, info->status));
     }
 
     monitor_printf(mon, "\n");
@@ -172,7 +173,8 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
         monitor_printf(mon, "capabilities: ");
         for (cap = caps; cap; cap = cap->next) {
             monitor_printf(mon, "%s: %s ",
-                           MigrationCapability_lookup[cap->value->capability],
+                           qapi_enum_lookup(MigrationCapability_lookup,
+                                            cap->value->capability),
                            cap->value->state ? "on" : "off");
         }
         monitor_printf(mon, "\n");
@@ -180,7 +182,7 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
 
     if (info->has_status) {
         monitor_printf(mon, "Migration status: %s",
-                       MigrationStatus_lookup[info->status]);
+                       qapi_enum_lookup(MigrationStatus_lookup, info->status));
         if (info->status == MIGRATION_STATUS_FAILED &&
             info->has_error_desc) {
             monitor_printf(mon, " (%s)\n", info->error_desc);
@@ -278,7 +280,8 @@ void hmp_info_migrate_capabilities(Monitor *mon, const QDict *qdict)
     if (caps) {
         for (cap = caps; cap; cap = cap->next) {
             monitor_printf(mon, "%s: %s\n",
-                           MigrationCapability_lookup[cap->value->capability],
+                           qapi_enum_lookup(MigrationCapability_lookup,
+                                            cap->value->capability),
                            cap->value->state ? "on" : "off");
         }
     }
@@ -295,48 +298,59 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict)
     if (params) {
         assert(params->has_compress_level);
         monitor_printf(mon, "%s: %" PRId64 "\n",
-            MigrationParameter_lookup[MIGRATION_PARAMETER_COMPRESS_LEVEL],
+            qapi_enum_lookup(MigrationParameter_lookup,
+                             MIGRATION_PARAMETER_COMPRESS_LEVEL),
             params->compress_level);
         assert(params->has_compress_threads);
         monitor_printf(mon, "%s: %" PRId64 "\n",
-            MigrationParameter_lookup[MIGRATION_PARAMETER_COMPRESS_THREADS],
+            qapi_enum_lookup(MigrationParameter_lookup,
+                             MIGRATION_PARAMETER_COMPRESS_THREADS),
             params->compress_threads);
         assert(params->has_decompress_threads);
         monitor_printf(mon, "%s: %" PRId64 "\n",
-            MigrationParameter_lookup[MIGRATION_PARAMETER_DECOMPRESS_THREADS],
+            qapi_enum_lookup(MigrationParameter_lookup,
+                             MIGRATION_PARAMETER_DECOMPRESS_THREADS),
             params->decompress_threads);
         assert(params->has_cpu_throttle_initial);
         monitor_printf(mon, "%s: %" PRId64 "\n",
-            MigrationParameter_lookup[MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL],
+            qapi_enum_lookup(MigrationParameter_lookup,
+                             MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL),
             params->cpu_throttle_initial);
         assert(params->has_cpu_throttle_increment);
         monitor_printf(mon, "%s: %" PRId64 "\n",
-            MigrationParameter_lookup[MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT],
+            qapi_enum_lookup(MigrationParameter_lookup,
+                             MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT),
             params->cpu_throttle_increment);
         assert(params->has_tls_creds);
         monitor_printf(mon, "%s: '%s'\n",
-            MigrationParameter_lookup[MIGRATION_PARAMETER_TLS_CREDS],
+            qapi_enum_lookup(MigrationParameter_lookup,
+                             MIGRATION_PARAMETER_TLS_CREDS),
             params->tls_creds);
         assert(params->has_tls_hostname);
         monitor_printf(mon, "%s: '%s'\n",
-            MigrationParameter_lookup[MIGRATION_PARAMETER_TLS_HOSTNAME],
+            qapi_enum_lookup(MigrationParameter_lookup,
+                             MIGRATION_PARAMETER_TLS_HOSTNAME),
             params->tls_hostname);
         assert(params->has_max_bandwidth);
         monitor_printf(mon, "%s: %" PRId64 " bytes/second\n",
-            MigrationParameter_lookup[MIGRATION_PARAMETER_MAX_BANDWIDTH],
+            qapi_enum_lookup(MigrationParameter_lookup,
+                             MIGRATION_PARAMETER_MAX_BANDWIDTH),
             params->max_bandwidth);
         assert(params->has_downtime_limit);
         monitor_printf(mon, "%s: %" PRId64 " milliseconds\n",
-            MigrationParameter_lookup[MIGRATION_PARAMETER_DOWNTIME_LIMIT],
+            qapi_enum_lookup(MigrationParameter_lookup,
+                             MIGRATION_PARAMETER_DOWNTIME_LIMIT),
             params->downtime_limit);
         assert(params->has_x_checkpoint_delay);
         monitor_printf(mon, "%s: %" PRId64 "\n",
-            MigrationParameter_lookup[MIGRATION_PARAMETER_X_CHECKPOINT_DELAY],
+            qapi_enum_lookup(MigrationParameter_lookup,
+                             MIGRATION_PARAMETER_X_CHECKPOINT_DELAY),
             params->x_checkpoint_delay);
         assert(params->has_block_incremental);
         monitor_printf(mon, "%s: %s\n",
-            MigrationParameter_lookup[MIGRATION_PARAMETER_BLOCK_INCREMENTAL],
-                       params->block_incremental ? "on" : "off");
+            qapi_enum_lookup(MigrationParameter_lookup,
+                             MIGRATION_PARAMETER_BLOCK_INCREMENTAL),
+            params->block_incremental ? "on" : "off");
     }
 
     qapi_free_MigrationParameters(params);
@@ -432,7 +446,7 @@ static void print_block_info(Monitor *mon, BlockInfo *info,
         }
         if (info->has_io_status && info->io_status != BLOCK_DEVICE_IO_STATUS_OK) {
             monitor_printf(mon, "    I/O status:       %s\n",
-                           BlockDeviceIoStatus_lookup[info->io_status]);
+                qapi_enum_lookup(BlockDeviceIoStatus_lookup, info->io_status));
         }
 
         if (info->removable) {
@@ -462,7 +476,8 @@ static void print_block_info(Monitor *mon, BlockInfo *info,
 
     if (inserted->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF) {
         monitor_printf(mon, "    Detect zeroes:    %s\n",
-                       BlockdevDetectZeroesOptions_lookup[inserted->detect_zeroes]);
+            qapi_enum_lookup(BlockdevDetectZeroesOptions_lookup,
+                             inserted->detect_zeroes));
     }
 
     if (inserted->bps  || inserted->bps_rd  || inserted->bps_wr  ||
@@ -613,7 +628,7 @@ static void hmp_info_VncBasicInfo(Monitor *mon, VncBasicInfo *info,
                    name,
                    info->host,
                    info->service,
-                   NetworkAddressFamily_lookup[info->family],
+                   qapi_enum_lookup(NetworkAddressFamily_lookup, info->family),
                    info->websocket ? " (Websocket)" : "");
 }
 
@@ -623,8 +638,9 @@ static void hmp_info_vnc_authcrypt(Monitor *mon, const char *indent,
                                    VncVencryptSubAuth *vencrypt)
 {
     monitor_printf(mon, "%sAuth: %s (Sub: %s)\n", indent,
-                   VncPrimaryAuth_lookup[auth],
-                   vencrypt ? VncVencryptSubAuth_lookup[*vencrypt] : "none");
+        qapi_enum_lookup(VncPrimaryAuth_lookup, auth),
+        vencrypt ? qapi_enum_lookup(VncVencryptSubAuth_lookup, *vencrypt)
+                   : "none");
 }
 
 static void hmp_info_vnc_clients(Monitor *mon, VncClientInfoList *client)
@@ -739,7 +755,7 @@ void hmp_info_spice(Monitor *mon, const QDict *qdict)
     monitor_printf(mon, "        auth: %s\n", info->auth);
     monitor_printf(mon, "    compiled: %s\n", info->compiled_version);
     monitor_printf(mon, "  mouse-mode: %s\n",
-                   SpiceQueryMouseMode_lookup[info->mouse_mode]);
+        qapi_enum_lookup(SpiceQueryMouseMode_lookup, info->mouse_mode));
 
     if (!info->has_channels || info->channels == NULL) {
         monitor_printf(mon, "Channels: none\n");
@@ -1010,10 +1026,11 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
     for (info = info_list; info; info = info->next) {
         TPMInfo *ti = info->value;
         monitor_printf(mon, " tpm%d: model=%s\n",
-                       c, TpmModel_lookup[ti->model]);
+                       c, qapi_enum_lookup(TpmModel_lookup, ti->model));
 
         monitor_printf(mon, "  \\ %s: type=%s",
-                       ti->id, TpmTypeOptionsKind_lookup[ti->options->type]);
+                       ti->id, qapi_enum_lookup(TpmTypeOptionsKind_lookup,
+                                                ti->options->type));
 
         switch (ti->options->type) {
         case TPM_TYPE_OPTIONS_KIND_PASSTHROUGH:
@@ -2374,7 +2391,7 @@ void hmp_info_memdev(Monitor *mon, const QDict *qdict)
         monitor_printf(mon, "  prealloc: %s\n",
                        m->value->prealloc ? "true" : "false");
         monitor_printf(mon, "  policy: %s\n",
-                       HostMemPolicy_lookup[m->value->policy]);
+            qapi_enum_lookup(HostMemPolicy_lookup, m->value->policy));
         visit_complete(v, &str);
         monitor_printf(mon, "  host nodes: %s\n", str);
 
@@ -2405,8 +2422,8 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)
                 di = value->u.dimm.data;
 
                 monitor_printf(mon, "Memory device [%s]: \"%s\"\n",
-                               MemoryDeviceInfoKind_lookup[value->type],
-                               di->id ? di->id : "");
+                    qapi_enum_lookup(MemoryDeviceInfoKind_lookup, value->type),
+                    di->id ? di->id : "");
                 monitor_printf(mon, "  addr: 0x%" PRIx64 "\n", di->addr);
                 monitor_printf(mon, "  slot: %" PRId64 "\n", di->slot);
                 monitor_printf(mon, "  node: %" PRId64 "\n", di->node);
@@ -2799,7 +2816,8 @@ void hmp_info_dump(Monitor *mon, const QDict *qdict)
     DumpQueryResult *result = qmp_query_dump(NULL);
 
     assert(result && result->status < DUMP_STATUS__MAX);
-    monitor_printf(mon, "Status: %s\n", DumpStatus_lookup[result->status]);
+    monitor_printf(mon, "Status: %s\n",
+                   qapi_enum_lookup(DumpStatus_lookup, result->status));
 
     if (result->status == DUMP_STATUS_ACTIVE) {
         float percent = 0;
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index 401129073b..8ebe08d1af 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -31,6 +31,7 @@
 #include "hw/hw.h"
 #include "hw/block/fdc.h"
 #include "qapi/error.h"
+#include "qapi/util.h"
 #include "qemu/error-report.h"
 #include "qemu/timer.h"
 #include "hw/isa/isa.h"
@@ -392,9 +393,11 @@ static int pick_geometry(FDrive *drv)
             FLOPPY_DPRINTF("User requested floppy drive type '%s', "
                            "but inserted medium appears to be a "
                            "%"PRId64" sector '%s' type\n",
-                           FloppyDriveType_lookup[drv->drive],
+                           qapi_enum_lookup(FloppyDriveType_lookup,
+                                            drv->drive),
                            nb_sectors,
-                           FloppyDriveType_lookup[parse->drive]);
+                           qapi_enum_lookup(FloppyDriveType_lookup,
+                                            parse->drive));
         }
         match = type_match;
     }
@@ -403,7 +406,7 @@ static int pick_geometry(FDrive *drv)
     if (match == -1) {
         error_setg(&error_abort, "No candidate geometries present in table "
                    " for floppy drive type '%s'",
-                   FloppyDriveType_lookup[drv->drive]);
+                   qapi_enum_lookup(FloppyDriveType_lookup, drv->drive));
     }
 
     parse = &(fd_formats[match]);
diff --git a/hw/char/escc.c b/hw/char/escc.c
index 1aca564e33..5c1d7b0e29 100644
--- a/hw/char/escc.c
+++ b/hw/char/escc.c
@@ -31,6 +31,7 @@
 #include "ui/console.h"
 #include "ui/input.h"
 #include "trace.h"
+#include "qapi/util.h"
 
 /*
  * Chipset docs:
@@ -848,7 +849,7 @@ static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
     assert(evt->type == INPUT_EVENT_KIND_KEY);
     key = evt->u.key.data;
     qcode = qemu_input_key_value_to_qcode(key->key);
-    trace_escc_sunkbd_event_in(qcode, QKeyCode_lookup[qcode],
+    trace_escc_sunkbd_event_in(qcode, qapi_enum_lookup(QKeyCode_lookup, qcode),
                                key->down);
 
     if (qcode == Q_KEY_CODE_CAPS_LOCK) {
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 078fc5d239..c82c693bca 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -2,6 +2,7 @@
 #include "net/net.h"
 #include "hw/qdev.h"
 #include "qapi/error.h"
+#include "qapi/util.h"
 #include "hw/pci/pci.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/error-report.h"
@@ -72,8 +73,9 @@ static void set_enum(Object *obj, Visitor *v, const char *name, void *opaque,
 
 static void set_default_value_enum(Object *obj, const Property *prop)
 {
-    object_property_set_str(obj, prop->info->enum_table[prop->defval.i],
-                            prop->name, &error_abort);
+    object_property_set_str(obj,
+        qapi_enum_lookup(prop->info->enum_table, prop->defval.i),
+        prop->name, &error_abort);
 }
 
 /* Bit */
@@ -1095,7 +1097,8 @@ void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
     Property *prop;
 
     prop = qdev_prop_find(dev, name);
-    object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
+    object_property_set_str(OBJECT(dev),
+                            qapi_enum_lookup(prop->info->enum_table, value),
                             name, &error_abort);
 }
 
diff --git a/hw/input/virtio-input-hid.c b/hw/input/virtio-input-hid.c
index 46c038110c..64039236f1 100644
--- a/hw/input/virtio-input-hid.c
+++ b/hw/input/virtio-input-hid.c
@@ -15,6 +15,7 @@
 #include "ui/console.h"
 
 #include "standard-headers/linux/input.h"
+#include "qapi/util.h"
 
 #define VIRTIO_ID_NAME_KEYBOARD "QEMU Virtio Keyboard"
 #define VIRTIO_ID_NAME_MOUSE    "QEMU Virtio Mouse"
@@ -209,7 +210,7 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
         } else {
             if (key->down) {
                 fprintf(stderr, "%s: unmapped key: %d [%s]\n", __func__,
-                        qcode, QKeyCode_lookup[qcode]);
+                        qcode, qapi_enum_lookup(QKeyCode_lookup, qcode));
             }
         }
         break;
@@ -224,7 +225,7 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
             if (btn->down) {
                 fprintf(stderr, "%s: unmapped button: %d [%s]\n", __func__,
                         btn->button,
-                        InputButton_lookup[btn->button]);
+                        qapi_enum_lookup(InputButton_lookup, btn->button));
             }
         }
         break;
diff --git a/migration/colo-failover.c b/migration/colo-failover.c
index f9914869c5..e5394ba631 100644
--- a/migration/colo-failover.c
+++ b/migration/colo-failover.c
@@ -17,6 +17,7 @@
 #include "migration.h"
 #include "qmp-commands.h"
 #include "qapi/qmp/qerror.h"
+#include "qapi/util.h"
 #include "qemu/error-report.h"
 #include "trace.h"
 
@@ -34,7 +35,7 @@ static void colo_failover_bh(void *opaque)
                                    FAILOVER_STATUS_ACTIVE);
     if (old_state != FAILOVER_STATUS_REQUIRE) {
         error_report("Unknown error for failover, old_state = %s",
-                    FailoverStatus_lookup[old_state]);
+                     qapi_enum_lookup(FailoverStatus_lookup, old_state));
         return;
     }
 
@@ -64,7 +65,8 @@ FailoverStatus failover_set_state(FailoverStatus old_state,
 
     old = atomic_cmpxchg(&failover_state, old_state, new_state);
     if (old == old_state) {
-        trace_colo_failover_set_state(FailoverStatus_lookup[new_state]);
+        trace_colo_failover_set_state(qapi_enum_lookup(FailoverStatus_lookup,
+                                                       new_state));
     }
     return old;
 }
diff --git a/migration/colo.c b/migration/colo.c
index a4255432ac..2b683a0afc 100644
--- a/migration/colo.c
+++ b/migration/colo.c
@@ -24,6 +24,7 @@
 #include "migration/failover.h"
 #include "replication.h"
 #include "qmp-commands.h"
+#include "qapi/util.h"
 
 static bool vmstate_loading;
 
@@ -61,7 +62,8 @@ static void secondary_vm_do_failover(void)
                         FAILOVER_STATUS_RELAUNCH);
         if (old_state != FAILOVER_STATUS_ACTIVE) {
             error_report("Unknown error while do failover for secondary VM,"
-                         "old_state: %s", FailoverStatus_lookup[old_state]);
+                         "old_state: %s",
+                         qapi_enum_lookup(FailoverStatus_lookup, old_state));
         }
         return;
     }
@@ -91,7 +93,8 @@ static void secondary_vm_do_failover(void)
                                    FAILOVER_STATUS_COMPLETED);
     if (old_state != FAILOVER_STATUS_ACTIVE) {
         error_report("Incorrect state (%s) while doing failover for "
-                     "secondary VM", FailoverStatus_lookup[old_state]);
+                     "secondary VM",
+                     qapi_enum_lookup(FailoverStatus_lookup, old_state));
         return;
     }
     /* Notify COLO incoming thread that failover work is finished */
@@ -126,7 +129,7 @@ static void primary_vm_do_failover(void)
                                    FAILOVER_STATUS_COMPLETED);
     if (old_state != FAILOVER_STATUS_ACTIVE) {
         error_report("Incorrect state (%s) while doing failover for Primary VM",
-                     FailoverStatus_lookup[old_state]);
+                     qapi_enum_lookup(FailoverStatus_lookup, old_state));
         return;
     }
     /* Notify COLO thread that failover work is finished */
@@ -222,7 +225,7 @@ static void colo_send_message(QEMUFile *f, COLOMessage msg,
     if (ret < 0) {
         error_setg_errno(errp, -ret, "Can't send COLO message");
     }
-    trace_colo_send_message(COLOMessage_lookup[msg]);
+    trace_colo_send_message(qapi_enum_lookup(COLOMessage_lookup, msg));
 }
 
 static void colo_send_message_value(QEMUFile *f, COLOMessage msg,
@@ -242,7 +245,7 @@ static void colo_send_message_value(QEMUFile *f, COLOMessage msg,
     ret = qemu_file_get_error(f);
     if (ret < 0) {
         error_setg_errno(errp, -ret, "Failed to send value for message:%s",
-                         COLOMessage_lookup[msg]);
+                         qapi_enum_lookup(COLOMessage_lookup, msg));
     }
 }
 
@@ -261,7 +264,7 @@ static COLOMessage colo_receive_message(QEMUFile *f, Error **errp)
         error_setg(errp, "%s: Invalid message", __func__);
         return msg;
     }
-    trace_colo_receive_message(COLOMessage_lookup[msg]);
+    trace_colo_receive_message(qapi_enum_lookup(COLOMessage_lookup, msg));
     return msg;
 }
 
@@ -299,7 +302,7 @@ static uint64_t colo_receive_message_value(QEMUFile *f, uint32_t expect_msg,
     ret = qemu_file_get_error(f);
     if (ret < 0) {
         error_setg_errno(errp, -ret, "Failed to get value for COLO message: %s",
-                         COLOMessage_lookup[expect_msg]);
+                         qapi_enum_lookup(COLOMessage_lookup, expect_msg));
     }
     return value;
 }
diff --git a/migration/global_state.c b/migration/global_state.c
index dcbbcb28be..4d57a9c5f2 100644
--- a/migration/global_state.c
+++ b/migration/global_state.c
@@ -42,7 +42,7 @@ int global_state_store(void)
 
 void global_state_store_running(void)
 {
-    const char *state = RunState_lookup[RUN_STATE_RUNNING];
+    const char *state = qapi_enum_lookup(RunState_lookup, RUN_STATE_RUNNING);
     strncpy((char *)global_state.runstate,
            state, sizeof(global_state.runstate));
 }
diff --git a/monitor.c b/monitor.c
index 14c27d4b6f..ee2fdfd4f1 100644
--- a/monitor.c
+++ b/monitor.c
@@ -78,6 +78,7 @@
 #include "sysemu/cpus.h"
 #include "qemu/cutils.h"
 #include "qapi/qmp/dispatch.h"
+#include "qapi/util.h"
 
 #if defined(TARGET_S390X)
 #include "hw/s390x/storage-keys.h"
@@ -928,7 +929,7 @@ EventInfoList *qmp_query_events(Error **errp)
     QAPIEvent e;
 
     for (e = 0 ; e < QAPI_EVENT__MAX ; e++) {
-        const char *event_name = QAPIEvent_lookup[e];
+        const char *event_name = qapi_enum_lookup(QAPIEvent_lookup, e);
         assert(event_name != NULL);
         info = g_malloc0(sizeof(*info));
         info->value = g_malloc0(sizeof(*info->value));
@@ -3249,8 +3250,9 @@ void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str)
     }
     len = strlen(str);
     readline_set_completion_index(rs, len);
-    for (i = 0; NetClientDriver_lookup[i]; i++) {
-        add_completion_option(rs, str, NetClientDriver_lookup[i]);
+    for (i = 0; qapi_enum_lookup(NetClientDriver_lookup, i); i++) {
+        add_completion_option(rs, str,
+                              qapi_enum_lookup(NetClientDriver_lookup, i));
     }
 }
 
@@ -3434,8 +3436,8 @@ void sendkey_completion(ReadLineState *rs, int nb_args, const char *str)
     len = strlen(str);
     readline_set_completion_index(rs, len);
     for (i = 0; i < Q_KEY_CODE__MAX; i++) {
-        if (!strncmp(str, QKeyCode_lookup[i], len)) {
-            readline_add_completion(rs, QKeyCode_lookup[i]);
+        if (!strncmp(str, qapi_enum_lookup(QKeyCode_lookup, i), len)) {
+            readline_add_completion(rs, qapi_enum_lookup(QKeyCode_lookup, i));
         }
     }
 }
@@ -3537,8 +3539,9 @@ void watchdog_action_completion(ReadLineState *rs, int nb_args, const char *str)
         return;
     }
     readline_set_completion_index(rs, strlen(str));
-    for (i = 0; WatchdogExpirationAction_lookup[i]; i++) {
-        add_completion_option(rs, str, WatchdogExpirationAction_lookup[i]);
+    for (i = 0; qapi_enum_lookup(WatchdogExpirationAction_lookup, i); i++) {
+        add_completion_option(rs, str,
+            qapi_enum_lookup(WatchdogExpirationAction_lookup, i));
     }
 }
 
@@ -3552,7 +3555,7 @@ void migrate_set_capability_completion(ReadLineState *rs, int nb_args,
     if (nb_args == 2) {
         int i;
         for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
-            const char *name = MigrationCapability_lookup[i];
+            const char *name = qapi_enum_lookup(MigrationCapability_lookup, i);
             if (!strncmp(str, name, len)) {
                 readline_add_completion(rs, name);
             }
@@ -3573,7 +3576,7 @@ void migrate_set_parameter_completion(ReadLineState *rs, int nb_args,
     if (nb_args == 2) {
         int i;
         for (i = 0; i < MIGRATION_PARAMETER__MAX; i++) {
-            const char *name = MigrationParameter_lookup[i];
+            const char *name = qapi_enum_lookup(MigrationParameter_lookup, i);
             if (!strncmp(str, name, len)) {
                 readline_add_completion(rs, name);
             }
@@ -3852,7 +3855,8 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
         qdict = qdict_get_qdict(qobject_to_qdict(rsp), "error");
         if (qdict
             && !g_strcmp0(qdict_get_try_str(qdict, "class"),
-                    QapiErrorClass_lookup[ERROR_CLASS_COMMAND_NOT_FOUND])) {
+                          qapi_enum_lookup(QapiErrorClass_lookup,
+                                           ERROR_CLASS_COMMAND_NOT_FOUND))) {
             /* Provide a more useful error message */
             qdict_del(qdict, "desc");
             qdict_put_str(qdict, "desc", "Expecting capabilities negotiation"
diff --git a/net/net.c b/net/net.c
index 0e28099554..efe2252c59 100644
--- a/net/net.c
+++ b/net/net.c
@@ -48,6 +48,7 @@
 #include "sysemu/qtest.h"
 #include "net/filter.h"
 #include "qapi/string-output-visitor.h"
+#include "qapi/util.h"
 
 /* Net bridge is currently not supported for W32. */
 #if !defined(_WIN32)
@@ -1064,7 +1065,7 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
         /* FIXME drop when all init functions store an Error */
         if (errp && !*errp) {
             error_setg(errp, QERR_DEVICE_INIT_FAILED,
-                       NetClientDriver_lookup[netdev->type]);
+                       qapi_enum_lookup(NetClientDriver_lookup, netdev->type));
         }
         return -1;
     }
@@ -1288,7 +1289,7 @@ void print_net_client(Monitor *mon, NetClientState *nc)
 
     monitor_printf(mon, "%s: index=%d,type=%s,%s\n", nc->name,
                    nc->queue_index,
-                   NetClientDriver_lookup[nc->info->type],
+                   qapi_enum_lookup(NetClientDriver_lookup, nc->info->type),
                    nc->info_str);
     if (!QTAILQ_EMPTY(&nc->filters)) {
         monitor_printf(mon, "filters:\n");
diff --git a/qapi/qapi-util.c b/qapi/qapi-util.c
index 46eda7d196..7677caa51e 100644
--- a/qapi/qapi-util.c
+++ b/qapi/qapi-util.c
@@ -34,6 +34,13 @@ int qapi_enum_parse(const char * const lookup[], const char *buf,
     return def;
 }
 
+const char *qapi_enum_lookup(const char * const lookup[], int val)
+{
+    assert(val >= 0);
+
+    return lookup[val];
+}
+
 /*
  * Parse a valid QAPI name from @str.
  * A valid name consists of letters, digits, hyphen and underscore.
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index 5ad36f8a09..06f1470516 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -19,6 +19,7 @@
 #include "qapi/qmp/qjson.h"
 #include "qapi-types.h"
 #include "qapi/qmp/qerror.h"
+#include "qapi/util.h"
 
 static QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp)
 {
@@ -118,7 +119,8 @@ static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request,
 QObject *qmp_build_error_object(Error *err)
 {
     return qobject_from_jsonf("{ 'class': %s, 'desc': %s }",
-                              QapiErrorClass_lookup[error_get_class(err)],
+                              qapi_enum_lookup(QapiErrorClass_lookup,
+                                               error_get_class(err)),
                               error_get_pretty(err));
 }
 
diff --git a/tests/test-qobject-output-visitor.c b/tests/test-qobject-output-visitor.c
index 7eb162059c..bb2d66b666 100644
--- a/tests/test-qobject-output-visitor.c
+++ b/tests/test-qobject-output-visitor.c
@@ -19,6 +19,7 @@
 #include "test-qapi-visit.h"
 #include "qapi/qmp/types.h"
 #include "qapi/qmp/qjson.h"
+#include "qapi/util.h"
 
 typedef struct TestOutputVisitorData {
     Visitor *ov;
@@ -133,7 +134,8 @@ static void test_visitor_out_enum(TestOutputVisitorData *data,
 
         qstr = qobject_to_qstring(visitor_get(data));
         g_assert(qstr);
-        g_assert_cmpstr(qstring_get_str(qstr), ==, EnumOne_lookup[i]);
+        g_assert_cmpstr(qstring_get_str(qstr), ==,
+                        qapi_enum_lookup(EnumOne_lookup, i));
         visitor_reset(data);
     }
 }
diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c
index e736db3af8..0b2087d312 100644
--- a/tests/test-string-output-visitor.c
+++ b/tests/test-string-output-visitor.c
@@ -14,6 +14,7 @@
 
 #include "qemu-common.h"
 #include "qapi/error.h"
+#include "qapi/util.h"
 #include "qapi/string-output-visitor.h"
 #include "test-qapi-types.h"
 #include "test-qapi-visit.h"
@@ -194,12 +195,13 @@ static void test_visitor_out_enum(TestOutputVisitorData *data,
 
         str = visitor_get(data);
         if (data->human) {
-            char *str_human = g_strdup_printf("\"%s\"", EnumOne_lookup[i]);
+            char *str_human =
+                g_strdup_printf("\"%s\"", qapi_enum_lookup(EnumOne_lookup, i));
 
             g_assert_cmpstr(str, ==, str_human);
             g_free(str_human);
         } else {
-            g_assert_cmpstr(str, ==, EnumOne_lookup[i]);
+            g_assert_cmpstr(str, ==, qapi_enum_lookup(EnumOne_lookup, i));
         }
         visitor_reset(data);
     }
diff --git a/tpm.c b/tpm.c
index 9a7c7114d3..c3b731b3f2 100644
--- a/tpm.c
+++ b/tpm.c
@@ -19,6 +19,7 @@
 #include "qemu/config-file.h"
 #include "qemu/error-report.h"
 #include "qmp-commands.h"
+#include "qapi/util.h"
 
 static QLIST_HEAD(, TPMBackend) tpm_backends =
     QLIST_HEAD_INITIALIZER(tpm_backends);
@@ -102,7 +103,8 @@ static void tpm_display_backend_drivers(void)
 
     for (i = 0; i < TPM_MAX_DRIVERS && be_drivers[i] != NULL; i++) {
         fprintf(stderr, "%12s   %s\n",
-                TpmType_lookup[be_drivers[i]->type], be_drivers[i]->desc());
+                qapi_enum_lookup(TpmType_lookup, be_drivers[i]->type),
+                be_drivers[i]->desc());
     }
     fprintf(stderr, "\n");
 }
diff --git a/ui/input.c b/ui/input.c
index af05f06368..6bceb6b825 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -7,6 +7,7 @@
 #include "ui/input.h"
 #include "ui/console.h"
 #include "sysemu/replay.h"
+#include "qapi/util.h"
 
 struct QemuInputHandlerState {
     DeviceState       *dev;
@@ -151,7 +152,7 @@ void qmp_input_send_event(bool has_device, const char *device,
         if (!qemu_input_find_handler(1 << event->type, con)) {
             error_setg(errp, "Input handler not found for "
                              "event type %s",
-                            InputEventKind_lookup[event->type]);
+                       qapi_enum_lookup(InputEventKind_lookup, event->type));
             return;
         }
     }
@@ -213,12 +214,12 @@ static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
         switch (key->key->type) {
         case KEY_VALUE_KIND_NUMBER:
             qcode = qemu_input_key_number_to_qcode(key->key->u.number.data);
-            name = QKeyCode_lookup[qcode];
+            name = qapi_enum_lookup(QKeyCode_lookup, qcode);
             trace_input_event_key_number(idx, key->key->u.number.data,
                                          name, key->down);
             break;
         case KEY_VALUE_KIND_QCODE:
-            name = QKeyCode_lookup[key->key->u.qcode.data];
+            name = qapi_enum_lookup(QKeyCode_lookup, key->key->u.qcode.data);
             trace_input_event_key_qcode(idx, name, key->down);
             break;
         case KEY_VALUE_KIND__MAX:
@@ -228,17 +229,17 @@ static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
         break;
     case INPUT_EVENT_KIND_BTN:
         btn = evt->u.btn.data;
-        name = InputButton_lookup[btn->button];
+        name = qapi_enum_lookup(InputButton_lookup, btn->button);
         trace_input_event_btn(idx, name, btn->down);
         break;
     case INPUT_EVENT_KIND_REL:
         move = evt->u.rel.data;
-        name = InputAxis_lookup[move->axis];
+        name = qapi_enum_lookup(InputAxis_lookup, move->axis);
         trace_input_event_rel(idx, name, move->value);
         break;
     case INPUT_EVENT_KIND_ABS:
         move = evt->u.abs.data;
-        name = InputAxis_lookup[move->axis];
+        name = qapi_enum_lookup(InputAxis_lookup, move->axis);
         trace_input_event_abs(idx, name, move->value);
         break;
     case INPUT_EVENT_KIND__MAX:
diff --git a/ui/vnc.c b/ui/vnc.c
index 651cbb8606..20a45a7241 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -36,6 +36,7 @@
 #include "qemu/config-file.h"
 #include "qapi/qmp/qerror.h"
 #include "qapi/qmp/types.h"
+#include "qapi/util.h"
 #include "qmp-commands.h"
 #include "ui/input.h"
 #include "qapi-event.h"
@@ -131,7 +132,7 @@ static void vnc_init_basic_info(SocketAddress *addr,
     case SOCKET_ADDRESS_TYPE_VSOCK:
     case SOCKET_ADDRESS_TYPE_FD:
         error_setg(errp, "Unsupported socket address type %s",
-                   SocketAddressType_lookup[addr->type]);
+                   qapi_enum_lookup(SocketAddressType_lookup, addr->type));
         break;
     default:
         abort();
@@ -416,7 +417,7 @@ VncInfo *qmp_query_vnc(Error **errp)
         case SOCKET_ADDRESS_TYPE_VSOCK:
         case SOCKET_ADDRESS_TYPE_FD:
             error_setg(errp, "Unsupported socket address type %s",
-                       SocketAddressType_lookup[addr->type]);
+                       qapi_enum_lookup(SocketAddressType_lookup, addr->type));
             goto out_error;
         default:
             abort();
@@ -1839,7 +1840,8 @@ static void vnc_release_modifiers(VncState *vs)
 
 static const char *code2name(int keycode)
 {
-    return QKeyCode_lookup[qemu_input_key_number_to_qcode(keycode)];
+    return qapi_enum_lookup(QKeyCode_lookup,
+                            qemu_input_key_number_to_qcode(keycode));
 }
 
 static void key_event(VncState *vs, int down, uint32_t sym)
diff --git a/vl.c b/vl.c
index 8e247cc2a2..def4f5f05f 100644
--- a/vl.c
+++ b/vl.c
@@ -99,6 +99,7 @@ int main(int argc, char **argv)
 #include "sysemu/hax.h"
 #include "qapi/qobject-input-visitor.h"
 #include "qapi/qobject-input-visitor.h"
+#include "qapi/util.h"
 #include "qapi-visit.h"
 #include "qapi/qmp/qjson.h"
 #include "qemu/option.h"
@@ -688,7 +689,7 @@ bool runstate_check(RunState state)
 
 bool runstate_store(char *str, size_t size)
 {
-    const char *state = RunState_lookup[current_run_state];
+    const char *state = qapi_enum_lookup(RunState_lookup, current_run_state);
     size_t len = strlen(state) + 1;
 
     if (len > size) {
@@ -721,8 +722,8 @@ void runstate_set(RunState new_state)
 
     if (!runstate_valid_transitions[current_run_state][new_state]) {
         error_report("invalid runstate transition: '%s' -> '%s'",
-                     RunState_lookup[current_run_state],
-                     RunState_lookup[new_state]);
+                     qapi_enum_lookup(RunState_lookup, current_run_state),
+                     qapi_enum_lookup(RunState_lookup, new_state));
         abort();
     }
     trace_runstate_set(new_state);
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 07/54] tpm: simplify driver registration & lookup
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (5 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 06/54] qapi: introduce qapi_enum_lookup() Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-23  9:04   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 08/54] hmp: use qapi_enum_parse() in hmp_migrate_set_capability Marc-André Lureau
                   ` (48 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau

Make be_drivers[n] match order of TpmType enum.

Use qapi_enum_parse() in tpm_get_backend_driver.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/sysemu/tpm_backend.h |  2 +-
 tpm.c                        | 42 ++++++++++++------------------------------
 2 files changed, 13 insertions(+), 31 deletions(-)

diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
index b58f52d39f..1d21c6b19b 100644
--- a/include/sysemu/tpm_backend.h
+++ b/include/sysemu/tpm_backend.h
@@ -227,6 +227,6 @@ TPMBackend *qemu_find_tpm(const char *id);
 
 const TPMDriverOps *tpm_get_backend_driver(const char *type);
 int tpm_register_model(enum TpmModel model);
-int tpm_register_driver(const TPMDriverOps *tdo);
+void tpm_register_driver(const TPMDriverOps *tdo);
 
 #endif
diff --git a/tpm.c b/tpm.c
index c3b731b3f2..f175661bfe 100644
--- a/tpm.c
+++ b/tpm.c
@@ -26,9 +26,8 @@ static QLIST_HEAD(, TPMBackend) tpm_backends =
 
 
 #define TPM_MAX_MODELS      1
-#define TPM_MAX_DRIVERS     1
 
-static TPMDriverOps const *be_drivers[TPM_MAX_DRIVERS] = {
+static TPMDriverOps const *be_drivers[TPM_TYPE__MAX] = {
     NULL,
 };
 
@@ -64,31 +63,18 @@ static bool tpm_model_is_registered(enum TpmModel model)
 
 const TPMDriverOps *tpm_get_backend_driver(const char *type)
 {
-    int i;
+    int i = qapi_enum_parse(TpmType_lookup, type, TPM_TYPE__MAX, -1, NULL);
 
-    for (i = 0; i < TPM_MAX_DRIVERS && be_drivers[i] != NULL; i++) {
-        if (!strcmp(TpmType_lookup[be_drivers[i]->type], type)) {
-            return be_drivers[i];
-        }
-    }
-
-    return NULL;
+    return i >= 0 ? be_drivers[i] : NULL;
 }
 
 #ifdef CONFIG_TPM
 
-int tpm_register_driver(const TPMDriverOps *tdo)
+void tpm_register_driver(const TPMDriverOps *tdo)
 {
-    int i;
+    assert(!be_drivers[tdo->type]);
 
-    for (i = 0; i < TPM_MAX_DRIVERS; i++) {
-        if (!be_drivers[i]) {
-            be_drivers[i] = tdo;
-            return 0;
-        }
-    }
-    error_report("Could not register TPM driver");
-    return 1;
+    be_drivers[tdo->type] = tdo;
 }
 
 /*
@@ -101,9 +87,12 @@ static void tpm_display_backend_drivers(void)
 
     fprintf(stderr, "Supported TPM types (choose only one):\n");
 
-    for (i = 0; i < TPM_MAX_DRIVERS && be_drivers[i] != NULL; i++) {
+    for (i = 0; i < TPM_TYPE__MAX; i++) {
+        if (be_drivers[i] == NULL) {
+            continue;
+        }
         fprintf(stderr, "%12s   %s\n",
-                qapi_enum_lookup(TpmType_lookup, be_drivers[i]->type),
+                qapi_enum_lookup(TpmType_lookup, i),
                 be_drivers[i]->desc());
     }
     fprintf(stderr, "\n");
@@ -241,14 +230,7 @@ int tpm_config_parse(QemuOptsList *opts_list, const char *optarg)
 
 static const TPMDriverOps *tpm_driver_find_by_type(enum TpmType type)
 {
-    int i;
-
-    for (i = 0; i < TPM_MAX_DRIVERS && be_drivers[i] != NULL; i++) {
-        if (be_drivers[i]->type == type) {
-            return be_drivers[i];
-        }
-    }
-    return NULL;
+    return be_drivers[type];
 }
 
 static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv)
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 08/54] hmp: use qapi_enum_parse() in hmp_migrate_set_capability
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (6 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 07/54] tpm: simplify driver registration & lookup Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-23  9:34   ` Markus Armbruster
  2017-08-24 11:29   ` Dr. David Alan Gilbert
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 09/54] hmp: use qapi_enum_parse() in hmp_migrate_set_parameter Marc-André Lureau
                   ` (47 subsequent siblings)
  55 siblings, 2 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Dr. David Alan Gilbert

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hmp.c | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/hmp.c b/hmp.c
index 29e42ab661..4ba50e8e26 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1544,23 +1544,21 @@ void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict)
     bool state = qdict_get_bool(qdict, "state");
     Error *err = NULL;
     MigrationCapabilityStatusList *caps = g_malloc0(sizeof(*caps));
-    int i;
+    int val;
 
-    for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
-        if (strcmp(cap, MigrationCapability_lookup[i]) == 0) {
-            caps->value = g_malloc0(sizeof(*caps->value));
-            caps->value->capability = i;
-            caps->value->state = state;
-            caps->next = NULL;
-            qmp_migrate_set_capabilities(caps, &err);
-            break;
-        }
+    val = qapi_enum_parse(MigrationCapability_lookup, cap,
+                          MIGRATION_CAPABILITY__MAX, -1, &err);
+    if (val < 0) {
+        goto end;
     }
 
-    if (i == MIGRATION_CAPABILITY__MAX) {
-        error_setg(&err, QERR_INVALID_PARAMETER, cap);
-    }
+    caps->value = g_malloc0(sizeof(*caps->value));
+    caps->value->capability = val;
+    caps->value->state = state;
+    caps->next = NULL;
+    qmp_migrate_set_capabilities(caps, &err);
 
+end:
     qapi_free_MigrationCapabilityStatusList(caps);
 
     if (err) {
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 09/54] hmp: use qapi_enum_parse() in hmp_migrate_set_parameter
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (7 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 08/54] hmp: use qapi_enum_parse() in hmp_migrate_set_capability Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-23  9:43   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 10/54] block: use qemu_enum_parse() in blkdebug_debug_breakpoint Marc-André Lureau
                   ` (46 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Dr. David Alan Gilbert

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hmp.c | 139 ++++++++++++++++++++++++++++++++----------------------------------
 1 file changed, 68 insertions(+), 71 deletions(-)

diff --git a/hmp.c b/hmp.c
index 4ba50e8e26..ccc58e6d88 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1574,84 +1574,81 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
     MigrateSetParameters *p = g_new0(MigrateSetParameters, 1);
     uint64_t valuebw = 0;
     Error *err = NULL;
-    int i, ret;
-
-    for (i = 0; i < MIGRATION_PARAMETER__MAX; i++) {
-        if (strcmp(param, MigrationParameter_lookup[i]) == 0) {
-            switch (i) {
-            case MIGRATION_PARAMETER_COMPRESS_LEVEL:
-                p->has_compress_level = true;
-                visit_type_int(v, param, &p->compress_level, &err);
-                break;
-            case MIGRATION_PARAMETER_COMPRESS_THREADS:
-                p->has_compress_threads = true;
-                visit_type_int(v, param, &p->compress_threads, &err);
-                break;
-            case MIGRATION_PARAMETER_DECOMPRESS_THREADS:
-                p->has_decompress_threads = true;
-                visit_type_int(v, param, &p->decompress_threads, &err);
-                break;
-            case MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL:
-                p->has_cpu_throttle_initial = true;
-                visit_type_int(v, param, &p->cpu_throttle_initial, &err);
-                break;
-            case MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT:
-                p->has_cpu_throttle_increment = true;
-                visit_type_int(v, param, &p->cpu_throttle_increment, &err);
-                break;
-            case MIGRATION_PARAMETER_TLS_CREDS:
-                p->has_tls_creds = true;
-                p->tls_creds = g_new0(StrOrNull, 1);
-                p->tls_creds->type = QTYPE_QSTRING;
-                visit_type_str(v, param, &p->tls_creds->u.s, &err);
-                break;
-            case MIGRATION_PARAMETER_TLS_HOSTNAME:
-                p->has_tls_hostname = true;
-                p->tls_hostname = g_new0(StrOrNull, 1);
-                p->tls_hostname->type = QTYPE_QSTRING;
-                visit_type_str(v, param, &p->tls_hostname->u.s, &err);
-                break;
-            case MIGRATION_PARAMETER_MAX_BANDWIDTH:
-                p->has_max_bandwidth = true;
-                /*
-                 * Can't use visit_type_size() here, because it
-                 * defaults to Bytes rather than Mebibytes.
-                 */
-                ret = qemu_strtosz_MiB(valuestr, NULL, &valuebw);
-                if (ret < 0 || valuebw > INT64_MAX
-                    || (size_t)valuebw != valuebw) {
-                    error_setg(&err, "Invalid size %s", valuestr);
-                    break;
-                }
-                p->max_bandwidth = valuebw;
-                break;
-            case MIGRATION_PARAMETER_DOWNTIME_LIMIT:
-                p->has_downtime_limit = true;
-                visit_type_int(v, param, &p->downtime_limit, &err);
-                break;
-            case MIGRATION_PARAMETER_X_CHECKPOINT_DELAY:
-                p->has_x_checkpoint_delay = true;
-                visit_type_int(v, param, &p->x_checkpoint_delay, &err);
-                break;
-            case MIGRATION_PARAMETER_BLOCK_INCREMENTAL:
-                p->has_block_incremental = true;
-                visit_type_bool(v, param, &p->block_incremental, &err);
-                break;
-            }
+    int val, ret;
 
-            if (err) {
-                goto cleanup;
-            }
-
-            qmp_migrate_set_parameters(p, &err);
+    val = qapi_enum_parse(MigrationParameter_lookup, param,
+                          MIGRATION_PARAMETER__MAX,  -1, &err);
+    if (val < 0) {
+        goto cleanup;
+    }
+
+    switch (val) {
+    case MIGRATION_PARAMETER_COMPRESS_LEVEL:
+        p->has_compress_level = true;
+        visit_type_int(v, param, &p->compress_level, &err);
+        break;
+    case MIGRATION_PARAMETER_COMPRESS_THREADS:
+        p->has_compress_threads = true;
+        visit_type_int(v, param, &p->compress_threads, &err);
+        break;
+    case MIGRATION_PARAMETER_DECOMPRESS_THREADS:
+        p->has_decompress_threads = true;
+        visit_type_int(v, param, &p->decompress_threads, &err);
+        break;
+    case MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL:
+        p->has_cpu_throttle_initial = true;
+        visit_type_int(v, param, &p->cpu_throttle_initial, &err);
+        break;
+    case MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT:
+        p->has_cpu_throttle_increment = true;
+        visit_type_int(v, param, &p->cpu_throttle_increment, &err);
+        break;
+    case MIGRATION_PARAMETER_TLS_CREDS:
+        p->has_tls_creds = true;
+        p->tls_creds = g_new0(StrOrNull, 1);
+        p->tls_creds->type = QTYPE_QSTRING;
+        visit_type_str(v, param, &p->tls_creds->u.s, &err);
+        break;
+    case MIGRATION_PARAMETER_TLS_HOSTNAME:
+        p->has_tls_hostname = true;
+        p->tls_hostname = g_new0(StrOrNull, 1);
+        p->tls_hostname->type = QTYPE_QSTRING;
+        visit_type_str(v, param, &p->tls_hostname->u.s, &err);
+        break;
+    case MIGRATION_PARAMETER_MAX_BANDWIDTH:
+        p->has_max_bandwidth = true;
+        /*
+         * Can't use visit_type_size() here, because it
+         * defaults to Bytes rather than Mebibytes.
+         */
+        ret = qemu_strtosz_MiB(valuestr, NULL, &valuebw);
+        if (ret < 0 || valuebw > INT64_MAX
+            || (size_t)valuebw != valuebw) {
+            error_setg(&err, "Invalid size %s", valuestr);
             break;
         }
+        p->max_bandwidth = valuebw;
+        break;
+    case MIGRATION_PARAMETER_DOWNTIME_LIMIT:
+        p->has_downtime_limit = true;
+        visit_type_int(v, param, &p->downtime_limit, &err);
+        break;
+    case MIGRATION_PARAMETER_X_CHECKPOINT_DELAY:
+        p->has_x_checkpoint_delay = true;
+        visit_type_int(v, param, &p->x_checkpoint_delay, &err);
+        break;
+    case MIGRATION_PARAMETER_BLOCK_INCREMENTAL:
+        p->has_block_incremental = true;
+        visit_type_bool(v, param, &p->block_incremental, &err);
+        break;
     }
 
-    if (i == MIGRATION_PARAMETER__MAX) {
-        error_setg(&err, QERR_INVALID_PARAMETER, param);
+    if (err) {
+        goto cleanup;
     }
 
+    qmp_migrate_set_parameters(p, &err);
+
  cleanup:
     qapi_free_MigrateSetParameters(p);
     visit_free(v);
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 10/54] block: use qemu_enum_parse() in blkdebug_debug_breakpoint
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (8 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 09/54] hmp: use qapi_enum_parse() in hmp_migrate_set_parameter Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-23 10:05   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 11/54] quorum: use qapi_enum_parse() in quorum_open Marc-André Lureau
                   ` (45 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Kevin Wolf, Max Reitz, open list:blkdebug

This slightly change the error report message from "Invalid event
name" to "Invalid parameter".

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 block/blkdebug.c | 28 ++++++++--------------------
 1 file changed, 8 insertions(+), 20 deletions(-)

diff --git a/block/blkdebug.c b/block/blkdebug.c
index c19ab28f07..50edda2a31 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -32,6 +32,7 @@
 #include "qapi/qmp/qbool.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qstring.h"
+#include "qapi/util.h"
 #include "sysemu/qtest.h"
 
 typedef struct BDRVBlkdebugState {
@@ -149,20 +150,6 @@ static QemuOptsList *config_groups[] = {
     NULL
 };
 
-static int get_event_by_name(const char *name, BlkdebugEvent *event)
-{
-    int i;
-
-    for (i = 0; i < BLKDBG__MAX; i++) {
-        if (!strcmp(BlkdebugEvent_lookup[i], name)) {
-            *event = i;
-            return 0;
-        }
-    }
-
-    return -1;
-}
-
 struct add_rule_data {
     BDRVBlkdebugState *s;
     int action;
@@ -173,7 +160,7 @@ static int add_rule(void *opaque, QemuOpts *opts, Error **errp)
     struct add_rule_data *d = opaque;
     BDRVBlkdebugState *s = d->s;
     const char* event_name;
-    BlkdebugEvent event;
+    int event;
     struct BlkdebugRule *rule;
     int64_t sector;
 
@@ -182,8 +169,9 @@ static int add_rule(void *opaque, QemuOpts *opts, Error **errp)
     if (!event_name) {
         error_setg(errp, "Missing event name for rule");
         return -1;
-    } else if (get_event_by_name(event_name, &event) < 0) {
-        error_setg(errp, "Invalid event name \"%s\"", event_name);
+    }
+    event = qapi_enum_parse(BlkdebugEvent_lookup, event_name, BLKDBG__MAX, -1, errp);
+    if (event < 0) {
         return -1;
     }
 
@@ -743,13 +731,13 @@ static int blkdebug_debug_breakpoint(BlockDriverState *bs, const char *event,
 {
     BDRVBlkdebugState *s = bs->opaque;
     struct BlkdebugRule *rule;
-    BlkdebugEvent blkdebug_event;
+    int blkdebug_event;
 
-    if (get_event_by_name(event, &blkdebug_event) < 0) {
+    blkdebug_event = qapi_enum_parse(BlkdebugEvent_lookup, event, BLKDBG__MAX, -1, NULL);
+    if (blkdebug_event < 0) {
         return -ENOENT;
     }
 
-
     rule = g_malloc(sizeof(*rule));
     *rule = (struct BlkdebugRule) {
         .event  = blkdebug_event,
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 11/54] quorum: use qapi_enum_parse() in quorum_open
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (9 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 10/54] block: use qemu_enum_parse() in blkdebug_debug_breakpoint Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:40   ` Alberto Garcia
  2017-08-23 11:24   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 12/54] qapi: change enum lookup structure Marc-André Lureau
                   ` (44 subsequent siblings)
  55 siblings, 2 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Alberto Garcia, Kevin Wolf, Max Reitz,
	open list:Quorum

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 block/quorum.c | 27 ++++++++-------------------
 1 file changed, 8 insertions(+), 19 deletions(-)

diff --git a/block/quorum.c b/block/quorum.c
index d04da4f430..e4271caa7a 100644
--- a/block/quorum.c
+++ b/block/quorum.c
@@ -22,6 +22,7 @@
 #include "qapi/qmp/qjson.h"
 #include "qapi/qmp/qlist.h"
 #include "qapi/qmp/qstring.h"
+#include "qapi/util.h"
 #include "qapi-event.h"
 #include "crypto/hash.h"
 
@@ -867,24 +868,6 @@ static QemuOptsList quorum_runtime_opts = {
     },
 };
 
-static int parse_read_pattern(const char *opt)
-{
-    int i;
-
-    if (!opt) {
-        /* Set quorum as default */
-        return QUORUM_READ_PATTERN_QUORUM;
-    }
-
-    for (i = 0; i < QUORUM_READ_PATTERN__MAX; i++) {
-        if (!strcmp(opt, QuorumReadPattern_lookup[i])) {
-            return i;
-        }
-    }
-
-    return -EINVAL;
-}
-
 static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
                        Error **errp)
 {
@@ -925,7 +908,13 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
         goto exit;
     }
 
-    ret = parse_read_pattern(qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN));
+    if (!qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN)) {
+        ret = QUORUM_READ_PATTERN_QUORUM;
+    } else {
+        ret = qapi_enum_parse(QuorumReadPattern_lookup,
+                              qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN),
+                              QUORUM_READ_PATTERN__MAX, -EINVAL, NULL);
+    }
     if (ret < 0) {
         error_setg(&local_err, "Please set read-pattern as fifo or quorum");
         goto exit;
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 12/54] qapi: change enum lookup structure
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (10 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 11/54] quorum: use qapi_enum_parse() in quorum_open Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-23 12:09   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 13/54] qapi: drop the sentinel in enum array Marc-André Lureau
                   ` (43 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Eduardo Habkost, Igor Mammedov,
	Kevin Wolf, Max Reitz, Jeff Cody, Stefan Weil, Ronnie Sahlberg,
	Paolo Bonzini, Peter Lieven, Stefan Hajnoczi, Denis V. Lunev,
	Alberto Garcia, Josh Durgin, Hitoshi Mitake, Liu Yuan,
	Markus Armbruster, Daniel P. Berrange, Dr. David Alan Gilbert,
	John Snow, Michael S. Tsirkin, Gerd Hoffmann, Michael Roth,
	Andreas Färber, zhanghailiang, Juan Quintela, Jason Wang,
	Eric Blake, open list:Block layer core, open list:Sheepdog

Store the length in the lookup table, i.e. change it from
const char *const[] to struct { int n, const char *const s[] }.

The following conditional enum entry change will create "hole"
elements in the generated lookup array, that should be skipped.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/qapi/visitor.h              |  2 +-
 scripts/qapi.py                     | 11 +++++--
 scripts/qapi-types.py               |  6 ++++
 scripts/qapi-visit.py               |  2 +-
 include/hw/qdev-core.h              |  2 +-
 include/qapi/util.h                 |  6 ++--
 include/qom/object.h                |  4 +--
 qapi/qapi-visit-core.c              | 24 +++++++-------
 backends/hostmem.c                  |  4 +--
 block.c                             |  3 +-
 block/backup.c                      |  2 +-
 block/blkdebug.c                    |  4 +--
 block/file-posix.c                  | 17 +++++-----
 block/file-win32.c                  |  6 ++--
 block/gluster.c                     | 12 +++----
 block/iscsi.c                       |  2 +-
 block/nfs.c                         |  2 +-
 block/parallels.c                   | 10 ++++--
 block/qcow2.c                       | 14 ++++----
 block/qed.c                         |  2 +-
 block/quorum.c                      |  4 +--
 block/rbd.c                         |  2 +-
 block/sheepdog.c                    |  2 +-
 blockdev.c                          |  7 ++--
 blockjob.c                          |  6 ++--
 chardev/char.c                      |  4 +--
 crypto/block-luks.c                 | 38 +++++++++-------------
 crypto/block.c                      |  4 +--
 crypto/cipher-afalg.c               |  2 +-
 crypto/cipher-builtin.c             |  8 ++---
 crypto/cipher-gcrypt.c              |  4 +--
 crypto/cipher-nettle.c              |  8 ++---
 crypto/hmac-gcrypt.c                |  2 +-
 crypto/hmac-glib.c                  |  2 +-
 crypto/hmac-nettle.c                |  2 +-
 crypto/pbkdf-gcrypt.c               |  2 +-
 crypto/pbkdf-nettle.c               |  2 +-
 crypto/secret.c                     |  2 +-
 crypto/tlscreds.c                   |  2 +-
 hmp.c                               | 64 +++++++++++++++++--------------------
 hw/block/fdc.c                      |  6 ++--
 hw/char/escc.c                      |  2 +-
 hw/core/qdev-properties.c           | 10 +++---
 hw/input/virtio-input-hid.c         |  4 +--
 migration/colo-failover.c           |  4 +--
 migration/colo.c                    | 14 ++++----
 migration/global_state.c            |  5 ++-
 monitor.c                           | 20 ++++++------
 net/filter.c                        |  2 +-
 net/net.c                           |  4 +--
 qapi/qapi-util.c                    | 13 ++++----
 qapi/qmp-dispatch.c                 |  2 +-
 qemu-img.c                          |  6 ++--
 qemu-nbd.c                          |  3 +-
 qom/object.c                        | 16 +++++-----
 tests/check-qom-proplist.c          |  7 +++-
 tests/test-qapi-util.c              | 17 ++++------
 tests/test-qobject-input-visitor.c  |  8 ++---
 tests/test-qobject-output-visitor.c |  2 +-
 tests/test-string-input-visitor.c   |  4 +--
 tests/test-string-output-visitor.c  |  4 +--
 tpm.c                               |  4 +--
 ui/input-legacy.c                   |  6 ++--
 ui/input.c                          | 12 +++----
 ui/vnc.c                            |  6 ++--
 vl.c                                |  6 ++--
 66 files changed, 241 insertions(+), 248 deletions(-)

diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index 0f3b8cb459..62a51a54cb 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -469,7 +469,7 @@ bool visit_optional(Visitor *v, const char *name, bool *present);
  * that visit_type_str() must have no unwelcome side effects.
  */
 void visit_type_enum(Visitor *v, const char *name, int *obj,
-                     const char *const strings[], Error **errp);
+                     const QEnumLookup *lookup, Error **errp);
 
 /*
  * Check if visitor is an input visitor.
diff --git a/scripts/qapi.py b/scripts/qapi.py
index a3ac799535..314d7e0365 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -1851,7 +1851,7 @@ def guardend(name):
 def gen_enum_lookup(name, values, prefix=None):
     ret = mcgen('''
 
-const char *const %(c_name)s_lookup[] = {
+static const char *const %(c_name)s_array[] = {
 ''',
                 c_name=c_name(name))
     for value in values:
@@ -1865,8 +1865,13 @@ const char *const %(c_name)s_lookup[] = {
     ret += mcgen('''
     [%(max_index)s] = NULL,
 };
+
+const QEnumLookup %(c_name)s_lookup = {
+    .array = %(c_name)s_array,
+    .size = %(max_index)s
+};
 ''',
-                 max_index=max_index)
+                 max_index=max_index, c_name=c_name(name))
     return ret
 
 
@@ -1896,7 +1901,7 @@ typedef enum %(c_name)s {
 
     ret += mcgen('''
 
-extern const char *const %(c_name)s_lookup[];
+extern const QEnumLookup %(c_name)s_lookup;
 ''',
                  c_name=c_name(name))
     return ret
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index b45e7b5634..dc05268917 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -179,6 +179,12 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
         self.defn = ''
         self._fwdecl = ''
         self._btin = guardstart('QAPI_TYPES_BUILTIN')
+        self._btin += '''
+typedef struct QEnumLookup {
+    const char *const *array;
+    int size;
+} QEnumLookup;
+'''
 
     def visit_end(self):
         self.decl = self._fwdecl + self.decl
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index bd0b742236..7e1cfc13f0 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -153,7 +153,7 @@ def gen_visit_enum(name):
 void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s *obj, Error **errp)
 {
     int value = *obj;
-    visit_type_enum(v, name, &value, %(c_name)s_lookup, errp);
+    visit_type_enum(v, name, &value, &%(c_name)s_lookup, errp);
     *obj = value;
 }
 ''',
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index ae317286a4..089146197f 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -249,7 +249,7 @@ struct Property {
 struct PropertyInfo {
     const char *name;
     const char *description;
-    const char * const *enum_table;
+    const QEnumLookup *enum_table;
     int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
     void (*set_default_value)(Object *obj, const Property *prop);
     void (*create)(Object *obj, Property *prop, Error **errp);
diff --git a/include/qapi/util.h b/include/qapi/util.h
index 60733b6a80..613f82bdcd 100644
--- a/include/qapi/util.h
+++ b/include/qapi/util.h
@@ -11,10 +11,10 @@
 #ifndef QAPI_UTIL_H
 #define QAPI_UTIL_H
 
-const char *qapi_enum_lookup(const char * const lookup[], int val);
+const char *qapi_enum_lookup(const QEnumLookup *lookup, int val);
 
-int qapi_enum_parse(const char * const lookup[], const char *buf,
-                    int max, int def, Error **errp);
+int qapi_enum_parse(const QEnumLookup *lookup, const char *buf,
+                    int def, Error **errp);
 
 int parse_qapi_name(const char *name, bool complete);
 
diff --git a/include/qom/object.h b/include/qom/object.h
index 1b828994fa..f3e5cff37a 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -1415,14 +1415,14 @@ void object_class_property_add_bool(ObjectClass *klass, const char *name,
  */
 void object_property_add_enum(Object *obj, const char *name,
                               const char *typename,
-                              const char * const *strings,
+                              const QEnumLookup *lookup,
                               int (*get)(Object *, Error **),
                               void (*set)(Object *, int, Error **),
                               Error **errp);
 
 void object_class_property_add_enum(ObjectClass *klass, const char *name,
                                     const char *typename,
-                                    const char * const *strings,
+                                    const QEnumLookup *lookup,
                                     int (*get)(Object *, Error **),
                                     void (*set)(Object *, int, Error **),
                                     Error **errp);
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index ed6d2af462..8876ecf0cd 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -333,24 +333,22 @@ void visit_type_null(Visitor *v, const char *name, QNull **obj,
 }
 
 static void output_type_enum(Visitor *v, const char *name, int *obj,
-                             const char *const strings[], Error **errp)
+                             const QEnumLookup *lookup, Error **errp)
 {
-    int i = 0;
     int value = *obj;
     char *enum_str;
 
-    while (strings[i++] != NULL);
-    if (value < 0 || value >= i - 1) {
+    if (value < 0 || value > lookup->size || !lookup->array[value]) {
         error_setg(errp, QERR_INVALID_PARAMETER, name ? name : "null");
         return;
     }
 
-    enum_str = (char *)strings[value];
+    enum_str = (char *)lookup->array[value];
     visit_type_str(v, name, &enum_str, errp);
 }
 
 static void input_type_enum(Visitor *v, const char *name, int *obj,
-                            const char *const strings[], Error **errp)
+                            const QEnumLookup *lookup, Error **errp)
 {
     Error *local_err = NULL;
     int64_t value = 0;
@@ -362,14 +360,14 @@ static void input_type_enum(Visitor *v, const char *name, int *obj,
         return;
     }
 
-    while (strings[value] != NULL) {
-        if (strcmp(strings[value], enum_str) == 0) {
+    while (value < lookup->size) {
+        if (!g_strcmp0(lookup->array[value], enum_str)) {
             break;
         }
         value++;
     }
 
-    if (strings[value] == NULL) {
+    if (value == lookup->size) {
         error_setg(errp, QERR_INVALID_PARAMETER, enum_str);
         g_free(enum_str);
         return;
@@ -380,16 +378,16 @@ static void input_type_enum(Visitor *v, const char *name, int *obj,
 }
 
 void visit_type_enum(Visitor *v, const char *name, int *obj,
-                     const char *const strings[], Error **errp)
+                     const QEnumLookup *lookup, Error **errp)
 {
-    assert(obj && strings);
+    assert(obj && lookup);
     trace_visit_type_enum(v, name, obj);
     switch (v->type) {
     case VISITOR_INPUT:
-        input_type_enum(v, name, obj, strings, errp);
+        input_type_enum(v, name, obj, lookup, errp);
         break;
     case VISITOR_OUTPUT:
-        output_type_enum(v, name, obj, strings, errp);
+        output_type_enum(v, name, obj, lookup, errp);
         break;
     case VISITOR_CLONE:
         /* nothing further to do, scalar value was already copied by
diff --git a/backends/hostmem.c b/backends/hostmem.c
index c4f795475c..ce430f1d14 100644
--- a/backends/hostmem.c
+++ b/backends/hostmem.c
@@ -305,7 +305,7 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
             return;
         } else if (maxnode == 0 && backend->policy != MPOL_DEFAULT) {
             error_setg(errp, "host-nodes must be set for policy %s",
-                qapi_enum_lookup(HostMemPolicy_lookup, backend->policy));
+                qapi_enum_lookup(&HostMemPolicy_lookup, backend->policy));
             return;
         }
 
@@ -396,7 +396,7 @@ host_memory_backend_class_init(ObjectClass *oc, void *data)
         host_memory_backend_set_host_nodes,
         NULL, NULL, &error_abort);
     object_class_property_add_enum(oc, "policy", "HostMemPolicy",
-        HostMemPolicy_lookup,
+        &HostMemPolicy_lookup,
         host_memory_backend_get_policy,
         host_memory_backend_set_policy, &error_abort);
     object_class_property_add_str(oc, "id", get_id, set_id, &error_abort);
diff --git a/block.c b/block.c
index 3615a6809e..ffb1f8db13 100644
--- a/block.c
+++ b/block.c
@@ -1333,9 +1333,8 @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
     detect_zeroes = qemu_opt_get(opts, "detect-zeroes");
     if (detect_zeroes) {
         BlockdevDetectZeroesOptions value =
-            qapi_enum_parse(BlockdevDetectZeroesOptions_lookup,
+            qapi_enum_parse(&BlockdevDetectZeroesOptions_lookup,
                             detect_zeroes,
-                            BLOCKDEV_DETECT_ZEROES_OPTIONS__MAX,
                             BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF,
                             &local_err);
         if (local_err) {
diff --git a/block/backup.c b/block/backup.c
index a700cc0315..8d4f3bcc13 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -597,7 +597,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
         error_setg(errp,
                    "a sync_bitmap was provided to backup_run, "
                    "but received an incompatible sync_mode (%s)",
-                   qapi_enum_lookup(MirrorSyncMode_lookup, sync_mode));
+                   qapi_enum_lookup(&MirrorSyncMode_lookup, sync_mode));
         return NULL;
     }
 
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 50edda2a31..94068156dc 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -170,7 +170,7 @@ static int add_rule(void *opaque, QemuOpts *opts, Error **errp)
         error_setg(errp, "Missing event name for rule");
         return -1;
     }
-    event = qapi_enum_parse(BlkdebugEvent_lookup, event_name, BLKDBG__MAX, -1, errp);
+    event = qapi_enum_parse(&BlkdebugEvent_lookup, event_name, -1, errp);
     if (event < 0) {
         return -1;
     }
@@ -733,7 +733,7 @@ static int blkdebug_debug_breakpoint(BlockDriverState *bs, const char *event,
     struct BlkdebugRule *rule;
     int blkdebug_event;
 
-    blkdebug_event = qapi_enum_parse(BlkdebugEvent_lookup, event, BLKDBG__MAX, -1, NULL);
+    blkdebug_event = qapi_enum_parse(&BlkdebugEvent_lookup, event, -1, NULL);
     if (blkdebug_event < 0) {
         return -ENOENT;
     }
diff --git a/block/file-posix.c b/block/file-posix.c
index 48200aef0b..578f9aae39 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -438,8 +438,8 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
     aio_default = (bdrv_flags & BDRV_O_NATIVE_AIO)
                   ? BLOCKDEV_AIO_OPTIONS_NATIVE
                   : BLOCKDEV_AIO_OPTIONS_THREADS;
-    aio = qapi_enum_parse(BlockdevAioOptions_lookup, qemu_opt_get(opts, "aio"),
-                          BLOCKDEV_AIO_OPTIONS__MAX, aio_default, &local_err);
+    aio = qapi_enum_parse(&BlockdevAioOptions_lookup, qemu_opt_get(opts, "aio"),
+                          aio_default, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         ret = -EINVAL;
@@ -447,8 +447,8 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
     }
     s->use_linux_aio = (aio == BLOCKDEV_AIO_OPTIONS_NATIVE);
 
-    locking = qapi_enum_parse(OnOffAuto_lookup, qemu_opt_get(opts, "locking"),
-                              ON_OFF_AUTO__MAX, ON_OFF_AUTO_AUTO, &local_err);
+    locking = qapi_enum_parse(&OnOffAuto_lookup, qemu_opt_get(opts, "locking"),
+                              ON_OFF_AUTO_AUTO, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         ret = -EINVAL;
@@ -1725,7 +1725,7 @@ static int raw_regular_truncate(int fd, int64_t offset, PreallocMode prealloc,
     default:
         result = -ENOTSUP;
         error_setg(errp, "Unsupported preallocation mode: %s",
-                   qapi_enum_lookup(PreallocMode_lookup, prealloc));
+                   qapi_enum_lookup(&PreallocMode_lookup, prealloc));
         return result;
     }
 
@@ -1760,7 +1760,7 @@ static int raw_truncate(BlockDriverState *bs, int64_t offset,
 
     if (prealloc != PREALLOC_MODE_OFF) {
         error_setg(errp, "Preallocation mode '%s' unsupported for this "
-                   "non-regular file", qapi_enum_lookup(PreallocMode_lookup,
+                   "non-regular file", qapi_enum_lookup(&PreallocMode_lookup,
                                                         prealloc));
         return -ENOTSUP;
     }
@@ -1975,9 +1975,8 @@ static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
                           BDRV_SECTOR_SIZE);
     nocow = qemu_opt_get_bool(opts, BLOCK_OPT_NOCOW, false);
     buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
-    prealloc = qapi_enum_parse(PreallocMode_lookup, buf,
-                               PREALLOC_MODE__MAX, PREALLOC_MODE_OFF,
-                               &local_err);
+    prealloc = qapi_enum_parse(&PreallocMode_lookup, buf,
+                               PREALLOC_MODE_OFF, &local_err);
     g_free(buf);
     if (local_err) {
         error_propagate(errp, local_err);
diff --git a/block/file-win32.c b/block/file-win32.c
index 2f3975f040..be4146e030 100644
--- a/block/file-win32.c
+++ b/block/file-win32.c
@@ -303,8 +303,8 @@ static bool get_aio_option(QemuOpts *opts, int flags, Error **errp)
 
     aio_default = (flags & BDRV_O_NATIVE_AIO) ? BLOCKDEV_AIO_OPTIONS_NATIVE
                                               : BLOCKDEV_AIO_OPTIONS_THREADS;
-    aio = qapi_enum_parse(BlockdevAioOptions_lookup, qemu_opt_get(opts, "aio"),
-                          BLOCKDEV_AIO_OPTIONS__MAX, aio_default, errp);
+    aio = qapi_enum_parse(&BlockdevAioOptions_lookup, qemu_opt_get(opts, "aio"),
+                          aio_default, errp);
 
     switch (aio) {
     case BLOCKDEV_AIO_OPTIONS_NATIVE:
@@ -470,7 +470,7 @@ static int raw_truncate(BlockDriverState *bs, int64_t offset,
 
     if (prealloc != PREALLOC_MODE_OFF) {
         error_setg(errp, "Unsupported preallocation mode '%s'",
-                   qapi_enum_lookup(reallocMode_lookup, prealloc));
+                   qapi_enum_lookup(&reallocMode_lookup, prealloc));
         return -ENOTSUP;
     }
 
diff --git a/block/gluster.c b/block/gluster.c
index 934f459014..bc8eff5dd3 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -544,8 +544,7 @@ static int qemu_gluster_parse_json(BlockdevOptionsGluster *gconf,
         if (!strcmp(ptr, "tcp")) {
             ptr = "inet";       /* accept legacy "tcp" */
         }
-        type = qapi_enum_parse(SocketAddressType_lookup, ptr,
-                               SOCKET_ADDRESS_TYPE__MAX, -1, NULL);
+        type = qapi_enum_parse(&SocketAddressType_lookup, ptr, -1, NULL);
         if (type != SOCKET_ADDRESS_TYPE_INET
             && type != SOCKET_ADDRESS_TYPE_UNIX) {
             error_setg(&local_err,
@@ -1002,9 +1001,8 @@ static int qemu_gluster_create(const char *filename,
                           BDRV_SECTOR_SIZE);
 
     tmp = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
-    prealloc = qapi_enum_parse(PreallocMode_lookup, tmp,
-                               PREALLOC_MODE__MAX, PREALLOC_MODE_OFF,
-                               &local_err);
+    prealloc = qapi_enum_parse(&PreallocMode_lookup, tmp,
+                               PREALLOC_MODE_OFF, &local_err);
     g_free(tmp);
     if (local_err) {
         error_propagate(errp, local_err);
@@ -1050,7 +1048,7 @@ static int qemu_gluster_create(const char *filename,
     default:
         ret = -EINVAL;
         error_setg(errp, "Unsupported preallocation mode: %s",
-                   qapi_enum_lookup(PreallocMode_lookup, prealloc));
+                   qapi_enum_lookup(&PreallocMode_lookup, prealloc));
         break;
     }
 
@@ -1102,7 +1100,7 @@ static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset,
 
     if (prealloc != PREALLOC_MODE_OFF) {
         error_setg(errp, "Unsupported preallocation mode '%s'",
-                   qapi_enum_lookup(PreallocMode_lookup, prealloc));
+                   qapi_enum_lookup(&PreallocMode_lookup, prealloc));
         return -ENOTSUP;
     }
 
diff --git a/block/iscsi.c b/block/iscsi.c
index 5c1870340b..c6bb0049bf 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -2088,7 +2088,7 @@ static int iscsi_truncate(BlockDriverState *bs, int64_t offset,
 
     if (prealloc != PREALLOC_MODE_OFF) {
         error_setg(errp, "Unsupported preallocation mode '%s'",
-                   qapi_enum_lookup(PreallocMode_lookup, prealloc));
+                   qapi_enum_lookup(&PreallocMode_lookup, prealloc));
         return -ENOTSUP;
     }
 
diff --git a/block/nfs.c b/block/nfs.c
index 953728ae31..f0ac050169 100644
--- a/block/nfs.c
+++ b/block/nfs.c
@@ -773,7 +773,7 @@ static int nfs_file_truncate(BlockDriverState *bs, int64_t offset,
 
     if (prealloc != PREALLOC_MODE_OFF) {
         error_setg(errp, "Unsupported preallocation mode '%s'",
-                   qapi_enum_lookup(PreallocMode_lookup, prealloc));
+                   qapi_enum_lookup(&PreallocMode_lookup, prealloc));
         return -ENOTSUP;
     }
 
diff --git a/block/parallels.c b/block/parallels.c
index e1e06d23cc..f870bbac3e 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -69,12 +69,16 @@ typedef enum ParallelsPreallocMode {
     PRL_PREALLOC_MODE__MAX = 2,
 } ParallelsPreallocMode;
 
-static const char *prealloc_mode_lookup[] = {
+static const char *prealloc_mode_array[] = {
     "falloc",
     "truncate",
     NULL,
 };
 
+static QEnumLookup prealloc_mode_lookup = {
+    .array = prealloc_mode_array,
+    .size = G_N_ELEMENTS(prealloc_mode_array),
+};
 
 typedef struct BDRVParallelsState {
     /** Locking is conservative, the lock protects
@@ -696,8 +700,8 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
         qemu_opt_get_size_del(opts, PARALLELS_OPT_PREALLOC_SIZE, 0);
     s->prealloc_size = MAX(s->tracks, s->prealloc_size >> BDRV_SECTOR_BITS);
     buf = qemu_opt_get_del(opts, PARALLELS_OPT_PREALLOC_MODE);
-    s->prealloc_mode = qapi_enum_parse(prealloc_mode_lookup, buf,
-            PRL_PREALLOC_MODE__MAX, PRL_PREALLOC_MODE_FALLOCATE, &local_err);
+    s->prealloc_mode = qapi_enum_parse(&prealloc_mode_lookup, buf,
+                                       PRL_PREALLOC_MODE_FALLOCATE, &local_err);
     g_free(buf);
     if (local_err != NULL) {
         goto fail_options;
diff --git a/block/qcow2.c b/block/qcow2.c
index 45b0579caa..c72fa2b476 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2733,7 +2733,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
             qcow2_calc_prealloc_size(total_size, cluster_size, refcount_order);
         qemu_opt_set_number(opts, BLOCK_OPT_SIZE, prealloc_size, &error_abort);
         qemu_opt_set(opts, BLOCK_OPT_PREALLOC,
-                     qapi_enum_lookup(PreallocMode_lookup, prealloc),
+                     qapi_enum_lookup(&PreallocMode_lookup, prealloc),
                      &error_abort);
     }
 
@@ -2933,9 +2933,8 @@ static int qcow2_create(const char *filename, QemuOpts *opts, Error **errp)
         goto finish;
     }
     buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
-    prealloc = qapi_enum_parse(PreallocMode_lookup, buf,
-                               PREALLOC_MODE__MAX, PREALLOC_MODE_OFF,
-                               &local_err);
+    prealloc = qapi_enum_parse(&PreallocMode_lookup, buf,
+                               PREALLOC_MODE_OFF, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         ret = -EINVAL;
@@ -3099,7 +3098,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
         prealloc != PREALLOC_MODE_FALLOC && prealloc != PREALLOC_MODE_FULL)
     {
         error_setg(errp, "Unsupported preallocation mode '%s'",
-                   qapi_enum_lookup(PreallocMode_lookup, prealloc));
+                   qapi_enum_lookup(&PreallocMode_lookup, prealloc));
         return -ENOTSUP;
     }
 
@@ -3624,9 +3623,8 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
     }
 
     optstr = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
-    prealloc = qapi_enum_parse(PreallocMode_lookup, optstr,
-                               PREALLOC_MODE__MAX, PREALLOC_MODE_OFF,
-                               &local_err);
+    prealloc = qapi_enum_parse(&PreallocMode_lookup, optstr,
+                               PREALLOC_MODE_OFF, &local_err);
     g_free(optstr);
     if (local_err) {
         goto err;
diff --git a/block/qed.c b/block/qed.c
index 756fcb85a7..aec2a559ce 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -1400,7 +1400,7 @@ static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset,
 
     if (prealloc != PREALLOC_MODE_OFF) {
         error_setg(errp, "Unsupported preallocation mode '%s'",
-                   qapi_enum_lookup(PreallocMode_lookup, prealloc));
+                   qapi_enum_lookup(&PreallocMode_lookup, prealloc));
         return -ENOTSUP;
     }
 
diff --git a/block/quorum.c b/block/quorum.c
index e4271caa7a..44acd2702c 100644
--- a/block/quorum.c
+++ b/block/quorum.c
@@ -911,9 +911,9 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
     if (!qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN)) {
         ret = QUORUM_READ_PATTERN_QUORUM;
     } else {
-        ret = qapi_enum_parse(QuorumReadPattern_lookup,
+        ret = qapi_enum_parse(&QuorumReadPattern_lookup,
                               qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN),
-                              QUORUM_READ_PATTERN__MAX, -EINVAL, NULL);
+                              -EINVAL, NULL);
     }
     if (ret < 0) {
         error_setg(&local_err, "Please set read-pattern as fifo or quorum");
diff --git a/block/rbd.c b/block/rbd.c
index 09f8d18d1b..ff71259f05 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -945,7 +945,7 @@ static int qemu_rbd_truncate(BlockDriverState *bs, int64_t offset,
 
     if (prealloc != PREALLOC_MODE_OFF) {
         error_setg(errp, "Unsupported preallocation mode '%s'",
-                   qapi_enum_lookup(PreallocMode_lookup, prealloc));
+                   qapi_enum_lookup(&PreallocMode_lookup, prealloc));
         return -ENOTSUP;
     }
 
diff --git a/block/sheepdog.c b/block/sheepdog.c
index 69d49fb720..9eac7c0ec7 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -2177,7 +2177,7 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset,
 
     if (prealloc != PREALLOC_MODE_OFF) {
         error_setg(errp, "Unsupported preallocation mode '%s'",
-                   qapi_enum_lookup(PreallocMode_lookup, prealloc));
+                   qapi_enum_lookup(&PreallocMode_lookup, prealloc));
         return -ENOTSUP;
     }
 
diff --git a/blockdev.c b/blockdev.c
index 6a067e81bf..7834b8830e 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -438,9 +438,8 @@ static void extract_common_blockdev_options(QemuOpts *opts, int *bdrv_flags,
 
     if (detect_zeroes) {
         *detect_zeroes =
-            qapi_enum_parse(BlockdevDetectZeroesOptions_lookup,
+            qapi_enum_parse(&BlockdevDetectZeroesOptions_lookup,
                             qemu_opt_get(opts, "detect-zeroes"),
-                            BLOCKDEV_DETECT_ZEROES_OPTIONS__MAX,
                             BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF,
                             &local_error);
         if (local_error) {
@@ -1468,9 +1467,9 @@ static int action_check_completion_mode(BlkActionState *s, Error **errp)
         error_setg(errp,
                    "Action '%s' does not support Transaction property "
                    "completion-mode = %s",
-                   qapi_enum_lookup(TransactionActionKind_lookup,
+                   qapi_enum_lookup(&TransactionActionKind_lookup,
                                     s->action->type),
-                   qapi_enum_lookup(ActionCompletionMode_lookup,
+                   qapi_enum_lookup(&ActionCompletionMode_lookup,
                                     s->txn_props->completion_mode));
         return -1;
     }
diff --git a/blockjob.c b/blockjob.c
index fca71123e0..3c815b89e4 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -209,7 +209,7 @@ static char *child_job_get_parent_desc(BdrvChild *c)
 {
     BlockJob *job = c->opaque;
     return g_strdup_printf("%s job '%s'",
-                           qapi_enum_lookup(BlockJobType_lookup,
+                           qapi_enum_lookup(&BlockJobType_lookup,
                                             job->driver->job_type),
                            job->id);
 }
@@ -555,7 +555,7 @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
         return NULL;
     }
     info = g_new0(BlockJobInfo, 1);
-    info->type      = g_strdup(qapi_enum_lookup(BlockJobType_lookup,
+    info->type      = g_strdup(qapi_enum_lookup(&BlockJobType_lookup,
                                                 job->driver->job_type));
     info->device    = g_strdup(job->id);
     info->len       = job->len;
@@ -669,7 +669,7 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
     job->refcnt        = 1;
 
     error_setg(&job->blocker, "block device is in use by block job: %s",
-               qapi_enum_lookup(BlockJobType_lookup, driver->job_type));
+               qapi_enum_lookup(&BlockJobType_lookup, driver->job_type));
     block_job_add_bdrv(job, "main node", bs, 0, BLK_PERM_ALL, &error_abort);
     bs->job = job;
 
diff --git a/chardev/char.c b/chardev/char.c
index 4408d12a08..ba2d110ae5 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -932,7 +932,7 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
     ChardevReturn *ret;
     Chardev *chr;
 
-    cc = char_get_class(qapi_enum_lookup(ChardevBackendKind_lookup,
+    cc = char_get_class(qapi_enum_lookup(&ChardevBackendKind_lookup,
                                          backend->type), errp);
     if (!cc) {
         return NULL;
@@ -991,7 +991,7 @@ ChardevReturn *qmp_chardev_change(const char *id, ChardevBackend *backend,
         return NULL;
     }
 
-    cc = char_get_class(qapi_enum_lookup(ChardevBackendKind_lookup,
+    cc = char_get_class(qapi_enum_lookup(&ChardevBackendKind_lookup,
                                          backend->type), errp);
     if (!cc) {
         return NULL;
diff --git a/crypto/block-luks.c b/crypto/block-luks.c
index b78a6345f3..a3c96d768b 100644
--- a/crypto/block-luks.c
+++ b/crypto/block-luks.c
@@ -258,47 +258,39 @@ qcrypto_block_luks_cipher_alg_lookup(QCryptoCipherAlgorithm alg,
     }
 
     error_setg(errp, "Algorithm '%s' not supported",
-               qapi_enum_lookup(QCryptoCipherAlgorithm_lookup, alg));
+               qapi_enum_lookup(&QCryptoCipherAlgorithm_lookup, alg));
     return NULL;
 }
 
-/* XXX replace with qapi_enum_parse() in future, when we can
+/* XXX replace with qapi_enum_parse(&) in future, when we can
  * make that function emit a more friendly error message */
 static int qcrypto_block_luks_name_lookup(const char *name,
-                                          const char *const *map,
-                                          size_t maplen,
+                                          const QEnumLookup *lookup,
                                           const char *type,
                                           Error **errp)
 {
-    size_t i;
-    for (i = 0; i < maplen; i++) {
-        if (g_str_equal(map[i], name)) {
-            return i;
-        }
+    int i = qapi_enum_parse(lookup, name, -1, NULL);
+    if (i < 0) {
+        error_setg(errp, "%s %s not supported", type, name);
     }
-
-    error_setg(errp, "%s %s not supported", type, name);
-    return 0;
+    return i;
 }
 
 #define qcrypto_block_luks_cipher_mode_lookup(name, errp)               \
     qcrypto_block_luks_name_lookup(name,                                \
-                                   QCryptoCipherMode_lookup,            \
-                                   QCRYPTO_CIPHER_MODE__MAX,            \
+                                   &QCryptoCipherMode_lookup,            \
                                    "Cipher mode",                       \
                                    errp)
 
 #define qcrypto_block_luks_hash_name_lookup(name, errp)                 \
     qcrypto_block_luks_name_lookup(name,                                \
-                                   QCryptoHashAlgorithm_lookup,         \
-                                   QCRYPTO_HASH_ALG__MAX,               \
+                                   &QCryptoHashAlgorithm_lookup,         \
                                    "Hash algorithm",                    \
                                    errp)
 
 #define qcrypto_block_luks_ivgen_name_lookup(name, errp)                \
     qcrypto_block_luks_name_lookup(name,                                \
-                                   QCryptoIVGenAlgorithm_lookup,        \
-                                   QCRYPTO_IVGEN_ALG__MAX,              \
+                                   &QCryptoIVGenAlgorithm_lookup,        \
                                    "IV generator",                      \
                                    errp)
 
@@ -399,7 +391,7 @@ qcrypto_block_luks_essiv_cipher(QCryptoCipherAlgorithm cipher,
         break;
     default:
         error_setg(errp, "Cipher %s not supported with essiv",
-                   qapi_enum_lookup(QCryptoCipherAlgorithm_lookup, cipher));
+                   qapi_enum_lookup(&QCryptoCipherAlgorithm_lookup, cipher));
         return 0;
     }
 }
@@ -969,19 +961,19 @@ qcrypto_block_luks_create(QCryptoBlock *block,
         goto error;
     }
 
-    cipher_mode = qapi_enum_lookup(QCryptoCipherMode_lookup,
+    cipher_mode = qapi_enum_lookup(&QCryptoCipherMode_lookup,
                                    luks_opts.cipher_mode);
-    ivgen_alg = qapi_enum_lookup(QCryptoIVGenAlgorithm_lookup,
+    ivgen_alg = qapi_enum_lookup(&QCryptoIVGenAlgorithm_lookup,
                                  luks_opts.ivgen_alg);
     if (luks_opts.has_ivgen_hash_alg) {
-        ivgen_hash_alg = qapi_enum_lookup(QCryptoHashAlgorithm_lookup,
+        ivgen_hash_alg = qapi_enum_lookup(&QCryptoHashAlgorithm_lookup,
                                           luks_opts.ivgen_hash_alg);
         cipher_mode_spec = g_strdup_printf("%s-%s:%s", cipher_mode, ivgen_alg,
                                            ivgen_hash_alg);
     } else {
         cipher_mode_spec = g_strdup_printf("%s-%s", cipher_mode, ivgen_alg);
     }
-    hash_alg = qapi_enum_lookup(QCryptoHashAlgorithm_lookup,
+    hash_alg = qapi_enum_lookup(&QCryptoHashAlgorithm_lookup,
                                 luks_opts.hash_alg);
 
 
diff --git a/crypto/block.c b/crypto/block.c
index 2140e55426..99606fe63a 100644
--- a/crypto/block.c
+++ b/crypto/block.c
@@ -62,7 +62,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
     if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
         !qcrypto_block_drivers[options->format]) {
         error_setg(errp, "Unsupported block driver %s",
-            qapi_enum_lookup(QCryptoBlockFormat_lookup, options->format));
+            qapi_enum_lookup(&QCryptoBlockFormat_lookup, options->format));
         g_free(block);
         return NULL;
     }
@@ -93,7 +93,7 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
     if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
         !qcrypto_block_drivers[options->format]) {
         error_setg(errp, "Unsupported block driver %s",
-            qapi_enum_lookup(QCryptoBlockFormat_lookup, options->format));
+            qapi_enum_lookup(&QCryptoBlockFormat_lookup, options->format));
         g_free(block);
         return NULL;
     }
diff --git a/crypto/cipher-afalg.c b/crypto/cipher-afalg.c
index 24d7ba8277..f15fb2a9c8 100644
--- a/crypto/cipher-afalg.c
+++ b/crypto/cipher-afalg.c
@@ -52,7 +52,7 @@ qcrypto_afalg_cipher_format_name(QCryptoCipherAlgorithm alg,
         return NULL;
     }
 
-    mode_name = qapi_enum_lookup(QCryptoCipherMode_lookup, mode);
+    mode_name = qapi_enum_lookup(&QCryptoCipherMode_lookup, mode);
     name = g_strdup_printf("%s(%s)", mode_name, alg_name);
 
     return name;
diff --git a/crypto/cipher-builtin.c b/crypto/cipher-builtin.c
index 76c76fb05b..e956cc5a53 100644
--- a/crypto/cipher-builtin.c
+++ b/crypto/cipher-builtin.c
@@ -247,7 +247,7 @@ qcrypto_cipher_init_aes(QCryptoCipherMode mode,
         mode != QCRYPTO_CIPHER_MODE_ECB &&
         mode != QCRYPTO_CIPHER_MODE_XTS) {
         error_setg(errp, "Unsupported cipher mode %s",
-                   qapi_enum_lookup(QCryptoCipherMode_lookup, mode));
+                   qapi_enum_lookup(&QCryptoCipherMode_lookup, mode));
         return NULL;
     }
 
@@ -379,7 +379,7 @@ qcrypto_cipher_init_des_rfb(QCryptoCipherMode mode,
 
     if (mode != QCRYPTO_CIPHER_MODE_ECB) {
         error_setg(errp, "Unsupported cipher mode %s",
-                   qapi_enum_lookup(QCryptoCipherMode_lookup, mode));
+                   qapi_enum_lookup(&QCryptoCipherMode_lookup, mode));
         return NULL;
     }
 
@@ -440,7 +440,7 @@ static QCryptoCipherBuiltin *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
         break;
     default:
         error_setg(errp, "Unsupported cipher mode %s",
-                   qapi_enum_lookup(QCryptoCipherMode_lookup, mode));
+                   qapi_enum_lookup(&QCryptoCipherMode_lookup, mode));
         return NULL;
     }
 
@@ -460,7 +460,7 @@ static QCryptoCipherBuiltin *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
     default:
         error_setg(errp,
                    "Unsupported cipher algorithm %s",
-                   qapi_enum_lookup(QCryptoCipherAlgorithm_lookup, alg));
+                   qapi_enum_lookup(&QCryptoCipherAlgorithm_lookup, alg));
         return NULL;
     }
 
diff --git a/crypto/cipher-gcrypt.c b/crypto/cipher-gcrypt.c
index 09210195a4..3e46ee7502 100644
--- a/crypto/cipher-gcrypt.c
+++ b/crypto/cipher-gcrypt.c
@@ -105,7 +105,7 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
         break;
     default:
         error_setg(errp, "Unsupported cipher mode %s",
-                   qapi_enum_lookup(QCryptoCipherMode_lookup, mode));
+                   qapi_enum_lookup(&QCryptoCipherMode_lookup, mode));
         return NULL;
     }
 
@@ -160,7 +160,7 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
 
     default:
         error_setg(errp, "Unsupported cipher algorithm %s",
-                   qapi_enum_lookup(QCryptoCipherAlgorithm_lookup, alg));
+                   qapi_enum_lookup(&QCryptoCipherAlgorithm_lookup, alg));
         return NULL;
     }
 
diff --git a/crypto/cipher-nettle.c b/crypto/cipher-nettle.c
index 7c02b3e7a2..5e70c7984a 100644
--- a/crypto/cipher-nettle.c
+++ b/crypto/cipher-nettle.c
@@ -281,7 +281,7 @@ static QCryptoCipherNettle *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
         break;
     default:
         error_setg(errp, "Unsupported cipher mode %s",
-                   qapi_enum_lookup(QCryptoCipherMode_lookup, mode));
+                   qapi_enum_lookup(&QCryptoCipherMode_lookup, mode));
         return NULL;
     }
 
@@ -420,7 +420,7 @@ static QCryptoCipherNettle *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
 
     default:
         error_setg(errp, "Unsupported cipher algorithm %s",
-                   qapi_enum_lookup(QCryptoCipherAlgorithm_lookup, alg));
+                   qapi_enum_lookup(&QCryptoCipherAlgorithm_lookup, alg));
         goto error;
     }
 
@@ -491,7 +491,7 @@ qcrypto_nettle_cipher_encrypt(QCryptoCipher *cipher,
 
     default:
         error_setg(errp, "Unsupported cipher mode %s",
-                   qapi_enum_lookup(QCryptoCipherMode_lookup, cipher->mode));
+                   qapi_enum_lookup(&QCryptoCipherMode_lookup, cipher->mode));
         return -1;
     }
     return 0;
@@ -537,7 +537,7 @@ qcrypto_nettle_cipher_decrypt(QCryptoCipher *cipher,
 
     default:
         error_setg(errp, "Unsupported cipher mode %s",
-                   qapi_enum_lookup(QCryptoCipherMode_lookup, cipher->mode));
+                   qapi_enum_lookup(&QCryptoCipherMode_lookup, cipher->mode));
         return -1;
     }
     return 0;
diff --git a/crypto/hmac-gcrypt.c b/crypto/hmac-gcrypt.c
index 0784795269..f24d5a48c2 100644
--- a/crypto/hmac-gcrypt.c
+++ b/crypto/hmac-gcrypt.c
@@ -52,7 +52,7 @@ void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
 
     if (!qcrypto_hmac_supports(alg)) {
         error_setg(errp, "Unsupported hmac algorithm %s",
-                   qapi_enum_lookup(QCryptoHashAlgorithm_lookup, alg));
+                   qapi_enum_lookup(&QCryptoHashAlgorithm_lookup, alg));
         return NULL;
     }
 
diff --git a/crypto/hmac-glib.c b/crypto/hmac-glib.c
index 56b71dbf85..aac4b217c0 100644
--- a/crypto/hmac-glib.c
+++ b/crypto/hmac-glib.c
@@ -59,7 +59,7 @@ void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
 
     if (!qcrypto_hmac_supports(alg)) {
         error_setg(errp, "Unsupported hmac algorithm %s",
-                   qapi_enum_lookup(QCryptoHashAlgorithm_lookup, alg));
+                   qapi_enum_lookup(&QCryptoHashAlgorithm_lookup, alg));
         return NULL;
     }
 
diff --git a/crypto/hmac-nettle.c b/crypto/hmac-nettle.c
index be43511252..07cc8af9b9 100644
--- a/crypto/hmac-nettle.c
+++ b/crypto/hmac-nettle.c
@@ -107,7 +107,7 @@ void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
 
     if (!qcrypto_hmac_supports(alg)) {
         error_setg(errp, "Unsupported hmac algorithm %s",
-                   qapi_enum_lookup(QCryptoHashAlgorithm_lookup, alg));
+                   qapi_enum_lookup(&QCryptoHashAlgorithm_lookup, alg));
         return NULL;
     }
 
diff --git a/crypto/pbkdf-gcrypt.c b/crypto/pbkdf-gcrypt.c
index a815138c46..eff037f08f 100644
--- a/crypto/pbkdf-gcrypt.c
+++ b/crypto/pbkdf-gcrypt.c
@@ -69,7 +69,7 @@ int qcrypto_pbkdf2(QCryptoHashAlgorithm hash,
         hash_map[hash] == GCRY_MD_NONE) {
         error_setg_errno(errp, ENOSYS,
                          "PBKDF does not support hash algorithm %s",
-                         qapi_enum_lookup(QCryptoHashAlgorithm_lookup, hash));
+                         qapi_enum_lookup(&QCryptoHashAlgorithm_lookup, hash));
         return -1;
     }
 
diff --git a/crypto/pbkdf-nettle.c b/crypto/pbkdf-nettle.c
index 84977fdd69..bb6454b80c 100644
--- a/crypto/pbkdf-nettle.c
+++ b/crypto/pbkdf-nettle.c
@@ -110,7 +110,7 @@ int qcrypto_pbkdf2(QCryptoHashAlgorithm hash,
     default:
         error_setg_errno(errp, ENOSYS,
                          "PBKDF does not support hash algorithm %s",
-                         qapi_enum_lookup(QCryptoHashAlgorithm_lookup, hash));
+                         qapi_enum_lookup(&QCryptoHashAlgorithm_lookup, hash));
         return -1;
     }
     return 0;
diff --git a/crypto/secret.c b/crypto/secret.c
index 285ab7a63c..388abd7df5 100644
--- a/crypto/secret.c
+++ b/crypto/secret.c
@@ -378,7 +378,7 @@ qcrypto_secret_class_init(ObjectClass *oc, void *data)
                                    NULL);
     object_class_property_add_enum(oc, "format",
                                    "QCryptoSecretFormat",
-                                   QCryptoSecretFormat_lookup,
+                                   &QCryptoSecretFormat_lookup,
                                    qcrypto_secret_prop_get_format,
                                    qcrypto_secret_prop_set_format,
                                    NULL);
diff --git a/crypto/tlscreds.c b/crypto/tlscreds.c
index a8965531b6..3cd41035bb 100644
--- a/crypto/tlscreds.c
+++ b/crypto/tlscreds.c
@@ -233,7 +233,7 @@ qcrypto_tls_creds_class_init(ObjectClass *oc, void *data)
                                   NULL);
     object_class_property_add_enum(oc, "endpoint",
                                    "QCryptoTLSCredsEndpoint",
-                                   QCryptoTLSCredsEndpoint_lookup,
+                                   &QCryptoTLSCredsEndpoint_lookup,
                                    qcrypto_tls_creds_prop_get_endpoint,
                                    qcrypto_tls_creds_prop_set_endpoint,
                                    NULL);
diff --git a/hmp.c b/hmp.c
index ccc58e6d88..0eb318f938 100644
--- a/hmp.c
+++ b/hmp.c
@@ -108,7 +108,7 @@ void hmp_info_status(Monitor *mon, const QDict *qdict)
 
     if (!info->running && info->status != RUN_STATE_PAUSED) {
         monitor_printf(mon, " (%s)",
-                       qapi_enum_lookup(RunState_lookup, info->status));
+                       qapi_enum_lookup(&RunState_lookup, info->status));
     }
 
     monitor_printf(mon, "\n");
@@ -173,7 +173,7 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
         monitor_printf(mon, "capabilities: ");
         for (cap = caps; cap; cap = cap->next) {
             monitor_printf(mon, "%s: %s ",
-                           qapi_enum_lookup(MigrationCapability_lookup,
+                           qapi_enum_lookup(&MigrationCapability_lookup,
                                             cap->value->capability),
                            cap->value->state ? "on" : "off");
         }
@@ -182,7 +182,7 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
 
     if (info->has_status) {
         monitor_printf(mon, "Migration status: %s",
-                       qapi_enum_lookup(MigrationStatus_lookup, info->status));
+                       qapi_enum_lookup(&MigrationStatus_lookup, info->status));
         if (info->status == MIGRATION_STATUS_FAILED &&
             info->has_error_desc) {
             monitor_printf(mon, " (%s)\n", info->error_desc);
@@ -280,7 +280,7 @@ void hmp_info_migrate_capabilities(Monitor *mon, const QDict *qdict)
     if (caps) {
         for (cap = caps; cap; cap = cap->next) {
             monitor_printf(mon, "%s: %s\n",
-                           qapi_enum_lookup(MigrationCapability_lookup,
+                           qapi_enum_lookup(&MigrationCapability_lookup,
                                             cap->value->capability),
                            cap->value->state ? "on" : "off");
         }
@@ -298,57 +298,57 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict)
     if (params) {
         assert(params->has_compress_level);
         monitor_printf(mon, "%s: %" PRId64 "\n",
-            qapi_enum_lookup(MigrationParameter_lookup,
+            qapi_enum_lookup(&MigrationParameter_lookup,
                              MIGRATION_PARAMETER_COMPRESS_LEVEL),
             params->compress_level);
         assert(params->has_compress_threads);
         monitor_printf(mon, "%s: %" PRId64 "\n",
-            qapi_enum_lookup(MigrationParameter_lookup,
+            qapi_enum_lookup(&MigrationParameter_lookup,
                              MIGRATION_PARAMETER_COMPRESS_THREADS),
             params->compress_threads);
         assert(params->has_decompress_threads);
         monitor_printf(mon, "%s: %" PRId64 "\n",
-            qapi_enum_lookup(MigrationParameter_lookup,
+            qapi_enum_lookup(&MigrationParameter_lookup,
                              MIGRATION_PARAMETER_DECOMPRESS_THREADS),
             params->decompress_threads);
         assert(params->has_cpu_throttle_initial);
         monitor_printf(mon, "%s: %" PRId64 "\n",
-            qapi_enum_lookup(MigrationParameter_lookup,
+            qapi_enum_lookup(&MigrationParameter_lookup,
                              MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL),
             params->cpu_throttle_initial);
         assert(params->has_cpu_throttle_increment);
         monitor_printf(mon, "%s: %" PRId64 "\n",
-            qapi_enum_lookup(MigrationParameter_lookup,
+            qapi_enum_lookup(&MigrationParameter_lookup,
                              MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT),
             params->cpu_throttle_increment);
         assert(params->has_tls_creds);
         monitor_printf(mon, "%s: '%s'\n",
-            qapi_enum_lookup(MigrationParameter_lookup,
+            qapi_enum_lookup(&MigrationParameter_lookup,
                              MIGRATION_PARAMETER_TLS_CREDS),
             params->tls_creds);
         assert(params->has_tls_hostname);
         monitor_printf(mon, "%s: '%s'\n",
-            qapi_enum_lookup(MigrationParameter_lookup,
+            qapi_enum_lookup(&MigrationParameter_lookup,
                              MIGRATION_PARAMETER_TLS_HOSTNAME),
             params->tls_hostname);
         assert(params->has_max_bandwidth);
         monitor_printf(mon, "%s: %" PRId64 " bytes/second\n",
-            qapi_enum_lookup(MigrationParameter_lookup,
+            qapi_enum_lookup(&MigrationParameter_lookup,
                              MIGRATION_PARAMETER_MAX_BANDWIDTH),
             params->max_bandwidth);
         assert(params->has_downtime_limit);
         monitor_printf(mon, "%s: %" PRId64 " milliseconds\n",
-            qapi_enum_lookup(MigrationParameter_lookup,
+            qapi_enum_lookup(&MigrationParameter_lookup,
                              MIGRATION_PARAMETER_DOWNTIME_LIMIT),
             params->downtime_limit);
         assert(params->has_x_checkpoint_delay);
         monitor_printf(mon, "%s: %" PRId64 "\n",
-            qapi_enum_lookup(MigrationParameter_lookup,
+            qapi_enum_lookup(&MigrationParameter_lookup,
                              MIGRATION_PARAMETER_X_CHECKPOINT_DELAY),
             params->x_checkpoint_delay);
         assert(params->has_block_incremental);
         monitor_printf(mon, "%s: %s\n",
-            qapi_enum_lookup(MigrationParameter_lookup,
+            qapi_enum_lookup(&MigrationParameter_lookup,
                              MIGRATION_PARAMETER_BLOCK_INCREMENTAL),
             params->block_incremental ? "on" : "off");
     }
@@ -446,7 +446,7 @@ static void print_block_info(Monitor *mon, BlockInfo *info,
         }
         if (info->has_io_status && info->io_status != BLOCK_DEVICE_IO_STATUS_OK) {
             monitor_printf(mon, "    I/O status:       %s\n",
-                qapi_enum_lookup(BlockDeviceIoStatus_lookup, info->io_status));
+                qapi_enum_lookup(&BlockDeviceIoStatus_lookup, info->io_status));
         }
 
         if (info->removable) {
@@ -476,7 +476,7 @@ static void print_block_info(Monitor *mon, BlockInfo *info,
 
     if (inserted->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF) {
         monitor_printf(mon, "    Detect zeroes:    %s\n",
-            qapi_enum_lookup(BlockdevDetectZeroesOptions_lookup,
+            qapi_enum_lookup(&BlockdevDetectZeroesOptions_lookup,
                              inserted->detect_zeroes));
     }
 
@@ -628,7 +628,7 @@ static void hmp_info_VncBasicInfo(Monitor *mon, VncBasicInfo *info,
                    name,
                    info->host,
                    info->service,
-                   qapi_enum_lookup(NetworkAddressFamily_lookup, info->family),
+                   qapi_enum_lookup(&NetworkAddressFamily_lookup, info->family),
                    info->websocket ? " (Websocket)" : "");
 }
 
@@ -638,8 +638,8 @@ static void hmp_info_vnc_authcrypt(Monitor *mon, const char *indent,
                                    VncVencryptSubAuth *vencrypt)
 {
     monitor_printf(mon, "%sAuth: %s (Sub: %s)\n", indent,
-        qapi_enum_lookup(VncPrimaryAuth_lookup, auth),
-        vencrypt ? qapi_enum_lookup(VncVencryptSubAuth_lookup, *vencrypt)
+        qapi_enum_lookup(&VncPrimaryAuth_lookup, auth),
+        vencrypt ? qapi_enum_lookup(&VncVencryptSubAuth_lookup, *vencrypt)
                    : "none");
 }
 
@@ -755,7 +755,7 @@ void hmp_info_spice(Monitor *mon, const QDict *qdict)
     monitor_printf(mon, "        auth: %s\n", info->auth);
     monitor_printf(mon, "    compiled: %s\n", info->compiled_version);
     monitor_printf(mon, "  mouse-mode: %s\n",
-        qapi_enum_lookup(SpiceQueryMouseMode_lookup, info->mouse_mode));
+        qapi_enum_lookup(&SpiceQueryMouseMode_lookup, info->mouse_mode));
 
     if (!info->has_channels || info->channels == NULL) {
         monitor_printf(mon, "Channels: none\n");
@@ -1026,10 +1026,10 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
     for (info = info_list; info; info = info->next) {
         TPMInfo *ti = info->value;
         monitor_printf(mon, " tpm%d: model=%s\n",
-                       c, qapi_enum_lookup(TpmModel_lookup, ti->model));
+                       c, qapi_enum_lookup(&TpmModel_lookup, ti->model));
 
         monitor_printf(mon, "  \\ %s: type=%s",
-                       ti->id, qapi_enum_lookup(TpmTypeOptionsKind_lookup,
+                       ti->id, qapi_enum_lookup(&TpmTypeOptionsKind_lookup,
                                                 ti->options->type));
 
         switch (ti->options->type) {
@@ -1546,8 +1546,7 @@ void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict)
     MigrationCapabilityStatusList *caps = g_malloc0(sizeof(*caps));
     int val;
 
-    val = qapi_enum_parse(MigrationCapability_lookup, cap,
-                          MIGRATION_CAPABILITY__MAX, -1, &err);
+    val = qapi_enum_parse(&MigrationCapability_lookup, cap, -1, &err);
     if (val < 0) {
         goto end;
     }
@@ -1576,8 +1575,7 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
     Error *err = NULL;
     int val, ret;
 
-    val = qapi_enum_parse(MigrationParameter_lookup, param,
-                          MIGRATION_PARAMETER__MAX,  -1, &err);
+    val = qapi_enum_parse(&MigrationParameter_lookup, param, -1, &err);
     if (val < 0) {
         goto cleanup;
     }
@@ -1752,10 +1750,8 @@ void hmp_change(Monitor *mon, const QDict *qdict)
         qmp_change("vnc", target, !!arg, arg, &err);
     } else {
         if (read_only) {
-            read_only_mode =
-                qapi_enum_parse(BlockdevChangeReadOnlyMode_lookup,
-                                read_only, BLOCKDEV_CHANGE_READ_ONLY_MODE__MAX,
-                                BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN, &err);
+            read_only_mode = qapi_enum_parse(&BlockdevChangeReadOnlyMode_lookup,
+                read_only, BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN, &err);
             if (err) {
                 hmp_handle_error(mon, &err);
                 return;
@@ -2386,7 +2382,7 @@ void hmp_info_memdev(Monitor *mon, const QDict *qdict)
         monitor_printf(mon, "  prealloc: %s\n",
                        m->value->prealloc ? "true" : "false");
         monitor_printf(mon, "  policy: %s\n",
-            qapi_enum_lookup(HostMemPolicy_lookup, m->value->policy));
+            qapi_enum_lookup(&HostMemPolicy_lookup, m->value->policy));
         visit_complete(v, &str);
         monitor_printf(mon, "  host nodes: %s\n", str);
 
@@ -2417,7 +2413,7 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)
                 di = value->u.dimm.data;
 
                 monitor_printf(mon, "Memory device [%s]: \"%s\"\n",
-                    qapi_enum_lookup(MemoryDeviceInfoKind_lookup, value->type),
+                    qapi_enum_lookup(&MemoryDeviceInfoKind_lookup, value->type),
                     di->id ? di->id : "");
                 monitor_printf(mon, "  addr: 0x%" PRIx64 "\n", di->addr);
                 monitor_printf(mon, "  slot: %" PRId64 "\n", di->slot);
@@ -2812,7 +2808,7 @@ void hmp_info_dump(Monitor *mon, const QDict *qdict)
 
     assert(result && result->status < DUMP_STATUS__MAX);
     monitor_printf(mon, "Status: %s\n",
-                   qapi_enum_lookup(DumpStatus_lookup, result->status));
+                   qapi_enum_lookup(&DumpStatus_lookup, result->status));
 
     if (result->status == DUMP_STATUS_ACTIVE) {
         float percent = 0;
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index 8ebe08d1af..df35f3e1cc 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -393,10 +393,10 @@ static int pick_geometry(FDrive *drv)
             FLOPPY_DPRINTF("User requested floppy drive type '%s', "
                            "but inserted medium appears to be a "
                            "%"PRId64" sector '%s' type\n",
-                           qapi_enum_lookup(FloppyDriveType_lookup,
+                           qapi_enum_lookup(&FloppyDriveType_lookup,
                                             drv->drive),
                            nb_sectors,
-                           qapi_enum_lookup(FloppyDriveType_lookup,
+                           qapi_enum_lookup(&FloppyDriveType_lookup,
                                             parse->drive));
         }
         match = type_match;
@@ -406,7 +406,7 @@ static int pick_geometry(FDrive *drv)
     if (match == -1) {
         error_setg(&error_abort, "No candidate geometries present in table "
                    " for floppy drive type '%s'",
-                   qapi_enum_lookup(FloppyDriveType_lookup, drv->drive));
+                   qapi_enum_lookup(&FloppyDriveType_lookup, drv->drive));
     }
 
     parse = &(fd_formats[match]);
diff --git a/hw/char/escc.c b/hw/char/escc.c
index 5c1d7b0e29..d5aba2a8a4 100644
--- a/hw/char/escc.c
+++ b/hw/char/escc.c
@@ -849,7 +849,7 @@ static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
     assert(evt->type == INPUT_EVENT_KIND_KEY);
     key = evt->u.key.data;
     qcode = qemu_input_key_value_to_qcode(key->key);
-    trace_escc_sunkbd_event_in(qcode, qapi_enum_lookup(QKeyCode_lookup, qcode),
+    trace_escc_sunkbd_event_in(qcode, qapi_enum_lookup(&QKeyCode_lookup, qcode),
                                key->down);
 
     if (qcode == Q_KEY_CODE_CAPS_LOCK) {
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index c82c693bca..ee4fc9812b 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -587,7 +587,7 @@ const PropertyInfo qdev_prop_macaddr = {
 const PropertyInfo qdev_prop_on_off_auto = {
     .name = "OnOffAuto",
     .description = "on/off/auto",
-    .enum_table = OnOffAuto_lookup,
+    .enum_table = &OnOffAuto_lookup,
     .get = get_enum,
     .set = set_enum,
     .set_default_value = set_default_value_enum,
@@ -599,7 +599,7 @@ QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
 
 const PropertyInfo qdev_prop_losttickpolicy = {
     .name  = "LostTickPolicy",
-    .enum_table  = LostTickPolicy_lookup,
+    .enum_table  = &LostTickPolicy_lookup,
     .get   = get_enum,
     .set   = set_enum,
     .set_default_value = set_default_value_enum,
@@ -613,7 +613,7 @@ const PropertyInfo qdev_prop_blockdev_on_error = {
     .name = "BlockdevOnError",
     .description = "Error handling policy, "
                    "report/ignore/enospc/stop/auto",
-    .enum_table = BlockdevOnError_lookup,
+    .enum_table = &BlockdevOnError_lookup,
     .get = get_enum,
     .set = set_enum,
     .set_default_value = set_default_value_enum,
@@ -627,7 +627,7 @@ const PropertyInfo qdev_prop_bios_chs_trans = {
     .name = "BiosAtaTranslation",
     .description = "Logical CHS translation algorithm, "
                    "auto/none/lba/large/rechs",
-    .enum_table = BiosAtaTranslation_lookup,
+    .enum_table = &BiosAtaTranslation_lookup,
     .get = get_enum,
     .set = set_enum,
     .set_default_value = set_default_value_enum,
@@ -639,7 +639,7 @@ const PropertyInfo qdev_prop_fdc_drive_type = {
     .name = "FdcDriveType",
     .description = "FDC drive type, "
                    "144/288/120/none/auto",
-    .enum_table = FloppyDriveType_lookup,
+    .enum_table = &FloppyDriveType_lookup,
     .get = get_enum,
     .set = set_enum,
     .set_default_value = set_default_value_enum,
diff --git a/hw/input/virtio-input-hid.c b/hw/input/virtio-input-hid.c
index 64039236f1..235b11082f 100644
--- a/hw/input/virtio-input-hid.c
+++ b/hw/input/virtio-input-hid.c
@@ -210,7 +210,7 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
         } else {
             if (key->down) {
                 fprintf(stderr, "%s: unmapped key: %d [%s]\n", __func__,
-                        qcode, qapi_enum_lookup(QKeyCode_lookup, qcode));
+                        qcode, qapi_enum_lookup(&QKeyCode_lookup, qcode));
             }
         }
         break;
@@ -225,7 +225,7 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
             if (btn->down) {
                 fprintf(stderr, "%s: unmapped button: %d [%s]\n", __func__,
                         btn->button,
-                        qapi_enum_lookup(InputButton_lookup, btn->button));
+                        qapi_enum_lookup(&InputButton_lookup, btn->button));
             }
         }
         break;
diff --git a/migration/colo-failover.c b/migration/colo-failover.c
index e5394ba631..c3dd0969d6 100644
--- a/migration/colo-failover.c
+++ b/migration/colo-failover.c
@@ -35,7 +35,7 @@ static void colo_failover_bh(void *opaque)
                                    FAILOVER_STATUS_ACTIVE);
     if (old_state != FAILOVER_STATUS_REQUIRE) {
         error_report("Unknown error for failover, old_state = %s",
-                     qapi_enum_lookup(FailoverStatus_lookup, old_state));
+                     qapi_enum_lookup(&FailoverStatus_lookup, old_state));
         return;
     }
 
@@ -65,7 +65,7 @@ FailoverStatus failover_set_state(FailoverStatus old_state,
 
     old = atomic_cmpxchg(&failover_state, old_state, new_state);
     if (old == old_state) {
-        trace_colo_failover_set_state(qapi_enum_lookup(FailoverStatus_lookup,
+        trace_colo_failover_set_state(qapi_enum_lookup(&FailoverStatus_lookup,
                                                        new_state));
     }
     return old;
diff --git a/migration/colo.c b/migration/colo.c
index 2b683a0afc..8bd7ef0531 100644
--- a/migration/colo.c
+++ b/migration/colo.c
@@ -63,7 +63,7 @@ static void secondary_vm_do_failover(void)
         if (old_state != FAILOVER_STATUS_ACTIVE) {
             error_report("Unknown error while do failover for secondary VM,"
                          "old_state: %s",
-                         qapi_enum_lookup(FailoverStatus_lookup, old_state));
+                         qapi_enum_lookup(&FailoverStatus_lookup, old_state));
         }
         return;
     }
@@ -94,7 +94,7 @@ static void secondary_vm_do_failover(void)
     if (old_state != FAILOVER_STATUS_ACTIVE) {
         error_report("Incorrect state (%s) while doing failover for "
                      "secondary VM",
-                     qapi_enum_lookup(FailoverStatus_lookup, old_state));
+                     qapi_enum_lookup(&FailoverStatus_lookup, old_state));
         return;
     }
     /* Notify COLO incoming thread that failover work is finished */
@@ -129,7 +129,7 @@ static void primary_vm_do_failover(void)
                                    FAILOVER_STATUS_COMPLETED);
     if (old_state != FAILOVER_STATUS_ACTIVE) {
         error_report("Incorrect state (%s) while doing failover for Primary VM",
-                     qapi_enum_lookup(FailoverStatus_lookup, old_state));
+                     qapi_enum_lookup(&FailoverStatus_lookup, old_state));
         return;
     }
     /* Notify COLO thread that failover work is finished */
@@ -225,7 +225,7 @@ static void colo_send_message(QEMUFile *f, COLOMessage msg,
     if (ret < 0) {
         error_setg_errno(errp, -ret, "Can't send COLO message");
     }
-    trace_colo_send_message(qapi_enum_lookup(COLOMessage_lookup, msg));
+    trace_colo_send_message(qapi_enum_lookup(&COLOMessage_lookup, msg));
 }
 
 static void colo_send_message_value(QEMUFile *f, COLOMessage msg,
@@ -245,7 +245,7 @@ static void colo_send_message_value(QEMUFile *f, COLOMessage msg,
     ret = qemu_file_get_error(f);
     if (ret < 0) {
         error_setg_errno(errp, -ret, "Failed to send value for message:%s",
-                         qapi_enum_lookup(COLOMessage_lookup, msg));
+                         qapi_enum_lookup(&COLOMessage_lookup, msg));
     }
 }
 
@@ -264,7 +264,7 @@ static COLOMessage colo_receive_message(QEMUFile *f, Error **errp)
         error_setg(errp, "%s: Invalid message", __func__);
         return msg;
     }
-    trace_colo_receive_message(qapi_enum_lookup(COLOMessage_lookup, msg));
+    trace_colo_receive_message(qapi_enum_lookup(&COLOMessage_lookup, msg));
     return msg;
 }
 
@@ -302,7 +302,7 @@ static uint64_t colo_receive_message_value(QEMUFile *f, uint32_t expect_msg,
     ret = qemu_file_get_error(f);
     if (ret < 0) {
         error_setg_errno(errp, -ret, "Failed to get value for COLO message: %s",
-                         qapi_enum_lookup(COLOMessage_lookup, expect_msg));
+                         qapi_enum_lookup(&COLOMessage_lookup, expect_msg));
     }
     return value;
 }
diff --git a/migration/global_state.c b/migration/global_state.c
index 4d57a9c5f2..486979c4cc 100644
--- a/migration/global_state.c
+++ b/migration/global_state.c
@@ -42,7 +42,7 @@ int global_state_store(void)
 
 void global_state_store_running(void)
 {
-    const char *state = qapi_enum_lookup(RunState_lookup, RUN_STATE_RUNNING);
+    const char *state = qapi_enum_lookup(&RunState_lookup, RUN_STATE_RUNNING);
     strncpy((char *)global_state.runstate,
            state, sizeof(global_state.runstate));
 }
@@ -89,8 +89,7 @@ static int global_state_post_load(void *opaque, int version_id)
     s->received = true;
     trace_migrate_global_state_post_load(runstate);
 
-    r = qapi_enum_parse(RunState_lookup, runstate, RUN_STATE__MAX,
-                                -1, &local_err);
+    r = qapi_enum_parse(&RunState_lookup, runstate, -1, &local_err);
 
     if (r == -1) {
         if (local_err) {
diff --git a/monitor.c b/monitor.c
index ee2fdfd4f1..228f246fcc 100644
--- a/monitor.c
+++ b/monitor.c
@@ -929,7 +929,7 @@ EventInfoList *qmp_query_events(Error **errp)
     QAPIEvent e;
 
     for (e = 0 ; e < QAPI_EVENT__MAX ; e++) {
-        const char *event_name = qapi_enum_lookup(QAPIEvent_lookup, e);
+        const char *event_name = qapi_enum_lookup(&QAPIEvent_lookup, e);
         assert(event_name != NULL);
         info = g_malloc0(sizeof(*info));
         info->value = g_malloc0(sizeof(*info->value));
@@ -3250,9 +3250,9 @@ void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str)
     }
     len = strlen(str);
     readline_set_completion_index(rs, len);
-    for (i = 0; qapi_enum_lookup(NetClientDriver_lookup, i); i++) {
+    for (i = 0; qapi_enum_lookup(&NetClientDriver_lookup, i); i++) {
         add_completion_option(rs, str,
-                              qapi_enum_lookup(NetClientDriver_lookup, i));
+                              qapi_enum_lookup(&NetClientDriver_lookup, i));
     }
 }
 
@@ -3436,8 +3436,8 @@ void sendkey_completion(ReadLineState *rs, int nb_args, const char *str)
     len = strlen(str);
     readline_set_completion_index(rs, len);
     for (i = 0; i < Q_KEY_CODE__MAX; i++) {
-        if (!strncmp(str, qapi_enum_lookup(QKeyCode_lookup, i), len)) {
-            readline_add_completion(rs, qapi_enum_lookup(QKeyCode_lookup, i));
+        if (!strncmp(str, qapi_enum_lookup(&QKeyCode_lookup, i), len)) {
+            readline_add_completion(rs, qapi_enum_lookup(&QKeyCode_lookup, i));
         }
     }
 }
@@ -3539,9 +3539,9 @@ void watchdog_action_completion(ReadLineState *rs, int nb_args, const char *str)
         return;
     }
     readline_set_completion_index(rs, strlen(str));
-    for (i = 0; qapi_enum_lookup(WatchdogExpirationAction_lookup, i); i++) {
+    for (i = 0; qapi_enum_lookup(&WatchdogExpirationAction_lookup, i); i++) {
         add_completion_option(rs, str,
-            qapi_enum_lookup(WatchdogExpirationAction_lookup, i));
+            qapi_enum_lookup(&WatchdogExpirationAction_lookup, i));
     }
 }
 
@@ -3555,7 +3555,7 @@ void migrate_set_capability_completion(ReadLineState *rs, int nb_args,
     if (nb_args == 2) {
         int i;
         for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
-            const char *name = qapi_enum_lookup(MigrationCapability_lookup, i);
+            const char *name = qapi_enum_lookup(&MigrationCapability_lookup, i);
             if (!strncmp(str, name, len)) {
                 readline_add_completion(rs, name);
             }
@@ -3576,7 +3576,7 @@ void migrate_set_parameter_completion(ReadLineState *rs, int nb_args,
     if (nb_args == 2) {
         int i;
         for (i = 0; i < MIGRATION_PARAMETER__MAX; i++) {
-            const char *name = qapi_enum_lookup(MigrationParameter_lookup, i);
+            const char *name = qapi_enum_lookup(&MigrationParameter_lookup, i);
             if (!strncmp(str, name, len)) {
                 readline_add_completion(rs, name);
             }
@@ -3855,7 +3855,7 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
         qdict = qdict_get_qdict(qobject_to_qdict(rsp), "error");
         if (qdict
             && !g_strcmp0(qdict_get_try_str(qdict, "class"),
-                          qapi_enum_lookup(QapiErrorClass_lookup,
+                          qapi_enum_lookup(&QapiErrorClass_lookup,
                                            ERROR_CLASS_COMMAND_NOT_FOUND))) {
             /* Provide a more useful error message */
             qdict_del(qdict, "desc");
diff --git a/net/filter.c b/net/filter.c
index 1dfd2caa23..2fd7d7d663 100644
--- a/net/filter.c
+++ b/net/filter.c
@@ -179,7 +179,7 @@ static void netfilter_init(Object *obj)
                             netfilter_get_netdev_id, netfilter_set_netdev_id,
                             NULL);
     object_property_add_enum(obj, "queue", "NetFilterDirection",
-                             NetFilterDirection_lookup,
+                             &NetFilterDirection_lookup,
                              netfilter_get_direction, netfilter_set_direction,
                              NULL);
     object_property_add_str(obj, "status",
diff --git a/net/net.c b/net/net.c
index efe2252c59..f4b8739b0b 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1065,7 +1065,7 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
         /* FIXME drop when all init functions store an Error */
         if (errp && !*errp) {
             error_setg(errp, QERR_DEVICE_INIT_FAILED,
-                       qapi_enum_lookup(NetClientDriver_lookup, netdev->type));
+                       qapi_enum_lookup(&NetClientDriver_lookup, netdev->type));
         }
         return -1;
     }
@@ -1289,7 +1289,7 @@ void print_net_client(Monitor *mon, NetClientState *nc)
 
     monitor_printf(mon, "%s: index=%d,type=%s,%s\n", nc->name,
                    nc->queue_index,
-                   qapi_enum_lookup(NetClientDriver_lookup, nc->info->type),
+                   qapi_enum_lookup(&NetClientDriver_lookup, nc->info->type),
                    nc->info_str);
     if (!QTAILQ_EMPTY(&nc->filters)) {
         monitor_printf(mon, "filters:\n");
diff --git a/qapi/qapi-util.c b/qapi/qapi-util.c
index 7677caa51e..363214efb1 100644
--- a/qapi/qapi-util.c
+++ b/qapi/qapi-util.c
@@ -15,8 +15,8 @@
 #include "qemu-common.h"
 #include "qapi/util.h"
 
-int qapi_enum_parse(const char * const lookup[], const char *buf,
-                    int max, int def, Error **errp)
+int qapi_enum_parse(const QEnumLookup *lookup, const char *buf,
+                    int def, Error **errp)
 {
     int i;
 
@@ -24,8 +24,8 @@ int qapi_enum_parse(const char * const lookup[], const char *buf,
         return def;
     }
 
-    for (i = 0; i < max; i++) {
-        if (!strcmp(buf, lookup[i])) {
+    for (i = 0; i < lookup->size; i++) {
+        if (!g_strcmp0(buf, lookup->array[i])) {
             return i;
         }
     }
@@ -34,11 +34,12 @@ int qapi_enum_parse(const char * const lookup[], const char *buf,
     return def;
 }
 
-const char *qapi_enum_lookup(const char * const lookup[], int val)
+const char *qapi_enum_lookup(const QEnumLookup *lookup, int val)
 {
     assert(val >= 0);
+    assert(val < lookup->size);
 
-    return lookup[val];
+    return lookup->array[val];
 }
 
 /*
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index 06f1470516..7f3302ad3c 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -119,7 +119,7 @@ static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request,
 QObject *qmp_build_error_object(Error *err)
 {
     return qobject_from_jsonf("{ 'class': %s, 'desc': %s }",
-                              qapi_enum_lookup(QapiErrorClass_lookup,
+                              qapi_enum_lookup(&QapiErrorClass_lookup,
                                                error_get_class(err)),
                               error_get_pretty(err));
 }
diff --git a/qemu-img.c b/qemu-img.c
index 56ef49e214..19f1996f90 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -3490,10 +3490,8 @@ static int img_resize(int argc, char **argv)
             image_opts = true;
             break;
         case OPTION_PREALLOCATION:
-            prealloc = qapi_enum_parse(PreallocMode_lookup, optarg,
-                                       PREALLOC_MODE__MAX, PREALLOC_MODE__MAX,
-                                       NULL);
-            if (prealloc == PREALLOC_MODE__MAX) {
+            prealloc = qapi_enum_parse(&PreallocMode_lookup, optarg, -1, NULL);
+            if (prealloc == -1) {
                 error_report("Invalid preallocation mode '%s'", optarg);
                 return 1;
             }
diff --git a/qemu-nbd.c b/qemu-nbd.c
index 27164b8205..0dda0cce05 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -639,9 +639,8 @@ int main(int argc, char **argv)
             break;
         case QEMU_NBD_OPT_DETECT_ZEROES:
             detect_zeroes =
-                qapi_enum_parse(BlockdevDetectZeroesOptions_lookup,
+                qapi_enum_parse(&BlockdevDetectZeroesOptions_lookup,
                                 optarg,
-                                BLOCKDEV_DETECT_ZEROES_OPTIONS__MAX,
                                 BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF,
                                 &local_err);
             if (local_err) {
diff --git a/qom/object.c b/qom/object.c
index fe6e744b4d..3e18537e9b 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1246,7 +1246,7 @@ uint64_t object_property_get_uint(Object *obj, const char *name,
 }
 
 typedef struct EnumProperty {
-    const char * const *strings;
+    const QEnumLookup *lookup;
     int (*get)(Object *, Error **);
     void (*set)(Object *, int, Error **);
 } EnumProperty;
@@ -1284,7 +1284,7 @@ int object_property_get_enum(Object *obj, const char *name,
     visit_complete(v, &str);
     visit_free(v);
     v = string_input_visitor_new(str);
-    visit_type_enum(v, name, &ret, enumprop->strings, errp);
+    visit_type_enum(v, name, &ret, enumprop->lookup, errp);
 
     g_free(str);
     visit_free(v);
@@ -1950,7 +1950,7 @@ static void property_get_enum(Object *obj, Visitor *v, const char *name,
         return;
     }
 
-    visit_type_enum(v, name, &value, prop->strings, errp);
+    visit_type_enum(v, name, &value, prop->lookup, errp);
 }
 
 static void property_set_enum(Object *obj, Visitor *v, const char *name,
@@ -1960,7 +1960,7 @@ static void property_set_enum(Object *obj, Visitor *v, const char *name,
     int value;
     Error *err = NULL;
 
-    visit_type_enum(v, name, &value, prop->strings, &err);
+    visit_type_enum(v, name, &value, prop->lookup, &err);
     if (err) {
         error_propagate(errp, err);
         return;
@@ -1977,7 +1977,7 @@ static void property_release_enum(Object *obj, const char *name,
 
 void object_property_add_enum(Object *obj, const char *name,
                               const char *typename,
-                              const char * const *strings,
+                              const QEnumLookup *lookup,
                               int (*get)(Object *, Error **),
                               void (*set)(Object *, int, Error **),
                               Error **errp)
@@ -1985,7 +1985,7 @@ void object_property_add_enum(Object *obj, const char *name,
     Error *local_err = NULL;
     EnumProperty *prop = g_malloc(sizeof(*prop));
 
-    prop->strings = strings;
+    prop->lookup = lookup;
     prop->get = get;
     prop->set = set;
 
@@ -2002,7 +2002,7 @@ void object_property_add_enum(Object *obj, const char *name,
 
 void object_class_property_add_enum(ObjectClass *klass, const char *name,
                                     const char *typename,
-                                    const char * const *strings,
+                                    const QEnumLookup *lookup,
                                     int (*get)(Object *, Error **),
                                     void (*set)(Object *, int, Error **),
                                     Error **errp)
@@ -2010,7 +2010,7 @@ void object_class_property_add_enum(ObjectClass *klass, const char *name,
     Error *local_err = NULL;
     EnumProperty *prop = g_malloc(sizeof(*prop));
 
-    prop->strings = strings;
+    prop->lookup = lookup;
     prop->get = get;
     prop->set = set;
 
diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c
index c51e6e734d..0ba8b55ce1 100644
--- a/tests/check-qom-proplist.c
+++ b/tests/check-qom-proplist.c
@@ -53,6 +53,11 @@ static const char *const dummy_animal_map[DUMMY_LAST + 1] = {
     [DUMMY_LAST] = NULL,
 };
 
+const QEnumLookup dummy_animal_lookup = {
+    .array = dummy_animal_map,
+    .size = DUMMY_LAST
+};
+
 struct DummyObject {
     Object parent_obj;
 
@@ -142,7 +147,7 @@ static void dummy_class_init(ObjectClass *cls, void *data)
                                   NULL);
     object_class_property_add_enum(cls, "av",
                                    "DummyAnimal",
-                                   dummy_animal_map,
+                                   &dummy_animal_lookup,
                                    dummy_get_av,
                                    dummy_set_av,
                                    NULL);
diff --git a/tests/test-qapi-util.c b/tests/test-qapi-util.c
index e8697577a5..fc9436ff94 100644
--- a/tests/test-qapi-util.c
+++ b/tests/test-qapi-util.c
@@ -20,24 +20,21 @@ static void test_qapi_enum_parse(void)
     Error *err = NULL;
     int ret;
 
-    ret = qapi_enum_parse(QType_lookup, NULL, QTYPE__MAX, QTYPE_NONE,
-                          &error_abort);
+    ret = qapi_enum_parse(&QType_lookup, NULL, QTYPE_NONE, &error_abort);
     g_assert_cmpint(ret, ==, QTYPE_NONE);
 
-    ret = qapi_enum_parse(QType_lookup, "junk", QTYPE__MAX, -1,
-                          NULL);
+    ret = qapi_enum_parse(&QType_lookup, "junk", -1, NULL);
     g_assert_cmpint(ret, ==, -1);
 
-    ret = qapi_enum_parse(QType_lookup, "junk", QTYPE__MAX, -1,
-                          &err);
+    ret = qapi_enum_parse(&QType_lookup, "junk", -1, &err);
     error_free_or_abort(&err);
 
-    ret = qapi_enum_parse(QType_lookup, "none", QTYPE__MAX, -1,
-                          &error_abort);
+    ret = qapi_enum_parse(&QType_lookup, "none", -1, &error_abort);
     g_assert_cmpint(ret, ==, QTYPE_NONE);
 
-    ret = qapi_enum_parse(QType_lookup, QType_lookup[QTYPE__MAX - 1],
-                          QTYPE__MAX, QTYPE__MAX - 1,
+    ret = qapi_enum_parse(&QType_lookup,
+                          qapi_enum_lookup(&QType_lookup, QTYPE__MAX - 1),
+                          QTYPE__MAX - 1,
                           &error_abort);
     g_assert_cmpint(ret, ==, QTYPE__MAX - 1);
 }
diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
index bdd00f6bd8..be7d7ea654 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -382,10 +382,10 @@ static void test_visitor_in_enum(TestInputVisitorData *data,
     Visitor *v;
     EnumOne i;
 
-    for (i = 0; EnumOne_lookup[i]; i++) {
+    for (i = 0; i < EnumOne_lookup.size; i++) {
         EnumOne res = -1;
 
-        v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
+        v = visitor_input_test_init(data, "%s", EnumOne_lookup.array[i]);
 
         visit_type_EnumOne(v, NULL, &res, &error_abort);
         g_assert_cmpint(i, ==, res);
@@ -699,7 +699,7 @@ static void test_native_list_integer_helper(TestInputVisitorData *data,
         }
     }
     g_string_append_printf(gstr_union,  "{ 'type': '%s', 'data': [ %s ] }",
-                           UserDefNativeListUnionKind_lookup[kind],
+                           UserDefNativeListUnionKind_lookup.array[kind],
                            gstr_list->str);
     v = visitor_input_test_init_raw(data,  gstr_union->str);
 
@@ -1110,7 +1110,7 @@ static void test_visitor_in_fail_struct_missing(TestInputVisitorData *data,
     error_free_or_abort(&err);
     visit_optional(v, "optional", &present);
     g_assert(!present);
-    visit_type_enum(v, "enum", &en, EnumOne_lookup, &err);
+    visit_type_enum(v, "enum", &en, &EnumOne_lookup, &err);
     error_free_or_abort(&err);
     visit_type_int(v, "i64", &i64, &err);
     error_free_or_abort(&err);
diff --git a/tests/test-qobject-output-visitor.c b/tests/test-qobject-output-visitor.c
index bb2d66b666..55a8c932e0 100644
--- a/tests/test-qobject-output-visitor.c
+++ b/tests/test-qobject-output-visitor.c
@@ -135,7 +135,7 @@ static void test_visitor_out_enum(TestOutputVisitorData *data,
         qstr = qobject_to_qstring(visitor_get(data));
         g_assert(qstr);
         g_assert_cmpstr(qstring_get_str(qstr), ==,
-                        qapi_enum_lookup(EnumOne_lookup, i));
+                        qapi_enum_lookup(&EnumOne_lookup, i));
         visitor_reset(data);
     }
 }
diff --git a/tests/test-string-input-visitor.c b/tests/test-string-input-visitor.c
index 79313a7f7a..5828359830 100644
--- a/tests/test-string-input-visitor.c
+++ b/tests/test-string-input-visitor.c
@@ -279,10 +279,10 @@ static void test_visitor_in_enum(TestInputVisitorData *data,
     Visitor *v;
     EnumOne i;
 
-    for (i = 0; EnumOne_lookup[i]; i++) {
+    for (i = 0; i < EnumOne_lookup.size; i++) {
         EnumOne res = -1;
 
-        v = visitor_input_test_init(data, EnumOne_lookup[i]);
+        v = visitor_input_test_init(data, EnumOne_lookup.array[i]);
 
         visit_type_EnumOne(v, NULL, &res, &err);
         g_assert(!err);
diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c
index 0b2087d312..a5d26ac0ca 100644
--- a/tests/test-string-output-visitor.c
+++ b/tests/test-string-output-visitor.c
@@ -196,12 +196,12 @@ static void test_visitor_out_enum(TestOutputVisitorData *data,
         str = visitor_get(data);
         if (data->human) {
             char *str_human =
-                g_strdup_printf("\"%s\"", qapi_enum_lookup(EnumOne_lookup, i));
+                g_strdup_printf("\"%s\"", qapi_enum_lookup(&EnumOne_lookup, i));
 
             g_assert_cmpstr(str, ==, str_human);
             g_free(str_human);
         } else {
-            g_assert_cmpstr(str, ==, qapi_enum_lookup(EnumOne_lookup, i));
+            g_assert_cmpstr(str, ==, qapi_enum_lookup(&EnumOne_lookup, i));
         }
         visitor_reset(data);
     }
diff --git a/tpm.c b/tpm.c
index f175661bfe..3ddd889906 100644
--- a/tpm.c
+++ b/tpm.c
@@ -63,7 +63,7 @@ static bool tpm_model_is_registered(enum TpmModel model)
 
 const TPMDriverOps *tpm_get_backend_driver(const char *type)
 {
-    int i = qapi_enum_parse(TpmType_lookup, type, TPM_TYPE__MAX, -1, NULL);
+    int i = qapi_enum_parse(&TpmType_lookup, type, -1, NULL);
 
     return i >= 0 ? be_drivers[i] : NULL;
 }
@@ -92,7 +92,7 @@ static void tpm_display_backend_drivers(void)
             continue;
         }
         fprintf(stderr, "%12s   %s\n",
-                qapi_enum_lookup(TpmType_lookup, i),
+                qapi_enum_lookup(&TpmType_lookup, i),
                 be_drivers[i]->desc());
     }
     fprintf(stderr, "\n");
diff --git a/ui/input-legacy.c b/ui/input-legacy.c
index 7159747404..c597bdc711 100644
--- a/ui/input-legacy.c
+++ b/ui/input-legacy.c
@@ -61,9 +61,9 @@ int index_from_key(const char *key, size_t key_length)
 {
     int i;
 
-    for (i = 0; QKeyCode_lookup[i] != NULL; i++) {
-        if (!strncmp(key, QKeyCode_lookup[i], key_length) &&
-            !QKeyCode_lookup[i][key_length]) {
+    for (i = 0; QKeyCode_lookup.array[i] != NULL; i++) {
+        if (!strncmp(key, QKeyCode_lookup.array[i], key_length) &&
+            !QKeyCode_lookup.array[i][key_length]) {
             break;
         }
     }
diff --git a/ui/input.c b/ui/input.c
index 6bceb6b825..dfae347154 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -152,7 +152,7 @@ void qmp_input_send_event(bool has_device, const char *device,
         if (!qemu_input_find_handler(1 << event->type, con)) {
             error_setg(errp, "Input handler not found for "
                              "event type %s",
-                       qapi_enum_lookup(InputEventKind_lookup, event->type));
+                       qapi_enum_lookup(&InputEventKind_lookup, event->type));
             return;
         }
     }
@@ -214,12 +214,12 @@ static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
         switch (key->key->type) {
         case KEY_VALUE_KIND_NUMBER:
             qcode = qemu_input_key_number_to_qcode(key->key->u.number.data);
-            name = qapi_enum_lookup(QKeyCode_lookup, qcode);
+            name = qapi_enum_lookup(&QKeyCode_lookup, qcode);
             trace_input_event_key_number(idx, key->key->u.number.data,
                                          name, key->down);
             break;
         case KEY_VALUE_KIND_QCODE:
-            name = qapi_enum_lookup(QKeyCode_lookup, key->key->u.qcode.data);
+            name = qapi_enum_lookup(&QKeyCode_lookup, key->key->u.qcode.data);
             trace_input_event_key_qcode(idx, name, key->down);
             break;
         case KEY_VALUE_KIND__MAX:
@@ -229,17 +229,17 @@ static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
         break;
     case INPUT_EVENT_KIND_BTN:
         btn = evt->u.btn.data;
-        name = qapi_enum_lookup(InputButton_lookup, btn->button);
+        name = qapi_enum_lookup(&InputButton_lookup, btn->button);
         trace_input_event_btn(idx, name, btn->down);
         break;
     case INPUT_EVENT_KIND_REL:
         move = evt->u.rel.data;
-        name = qapi_enum_lookup(InputAxis_lookup, move->axis);
+        name = qapi_enum_lookup(&InputAxis_lookup, move->axis);
         trace_input_event_rel(idx, name, move->value);
         break;
     case INPUT_EVENT_KIND_ABS:
         move = evt->u.abs.data;
-        name = qapi_enum_lookup(InputAxis_lookup, move->axis);
+        name = qapi_enum_lookup(&InputAxis_lookup, move->axis);
         trace_input_event_abs(idx, name, move->value);
         break;
     case INPUT_EVENT_KIND__MAX:
diff --git a/ui/vnc.c b/ui/vnc.c
index 20a45a7241..afe46dd8ae 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -132,7 +132,7 @@ static void vnc_init_basic_info(SocketAddress *addr,
     case SOCKET_ADDRESS_TYPE_VSOCK:
     case SOCKET_ADDRESS_TYPE_FD:
         error_setg(errp, "Unsupported socket address type %s",
-                   qapi_enum_lookup(SocketAddressType_lookup, addr->type));
+                   qapi_enum_lookup(&SocketAddressType_lookup, addr->type));
         break;
     default:
         abort();
@@ -417,7 +417,7 @@ VncInfo *qmp_query_vnc(Error **errp)
         case SOCKET_ADDRESS_TYPE_VSOCK:
         case SOCKET_ADDRESS_TYPE_FD:
             error_setg(errp, "Unsupported socket address type %s",
-                       qapi_enum_lookup(SocketAddressType_lookup, addr->type));
+                       qapi_enum_lookup(&SocketAddressType_lookup, addr->type));
             goto out_error;
         default:
             abort();
@@ -1840,7 +1840,7 @@ static void vnc_release_modifiers(VncState *vs)
 
 static const char *code2name(int keycode)
 {
-    return qapi_enum_lookup(QKeyCode_lookup,
+    return qapi_enum_lookup(&QKeyCode_lookup,
                             qemu_input_key_number_to_qcode(keycode));
 }
 
diff --git a/vl.c b/vl.c
index def4f5f05f..adeb6ed479 100644
--- a/vl.c
+++ b/vl.c
@@ -689,7 +689,7 @@ bool runstate_check(RunState state)
 
 bool runstate_store(char *str, size_t size)
 {
-    const char *state = qapi_enum_lookup(RunState_lookup, current_run_state);
+    const char *state = qapi_enum_lookup(&RunState_lookup, current_run_state);
     size_t len = strlen(state) + 1;
 
     if (len > size) {
@@ -722,8 +722,8 @@ void runstate_set(RunState new_state)
 
     if (!runstate_valid_transitions[current_run_state][new_state]) {
         error_report("invalid runstate transition: '%s' -> '%s'",
-                     qapi_enum_lookup(RunState_lookup, current_run_state),
-                     qapi_enum_lookup(RunState_lookup, new_state));
+                     qapi_enum_lookup(&RunState_lookup, current_run_state),
+                     qapi_enum_lookup(&RunState_lookup, new_state));
         abort();
     }
     trace_runstate_set(new_state);
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 13/54] qapi: drop the sentinel in enum array
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (11 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 12/54] qapi: change enum lookup structure Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-23 12:37   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 14/54] qapi2texi: minor python code simplification Marc-André Lureau
                   ` (42 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Stefan Hajnoczi, Denis V. Lunev,
	Kevin Wolf, Max Reitz, Markus Armbruster, Michael Roth,
	Gerd Hoffmann, open list:parallels

Now that all usages have been converted to user lookup helpers.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi.py   | 1 -
 block/parallels.c | 1 -
 ui/input-legacy.c | 2 +-
 3 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/scripts/qapi.py b/scripts/qapi.py
index 314d7e0365..73adb90379 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -1863,7 +1863,6 @@ static const char *const %(c_name)s_array[] = {
 
     max_index = c_enum_const(name, '_MAX', prefix)
     ret += mcgen('''
-    [%(max_index)s] = NULL,
 };
 
 const QEnumLookup %(c_name)s_lookup = {
diff --git a/block/parallels.c b/block/parallels.c
index f870bbac3e..d5de692c9c 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -72,7 +72,6 @@ typedef enum ParallelsPreallocMode {
 static const char *prealloc_mode_array[] = {
     "falloc",
     "truncate",
-    NULL,
 };
 
 static QEnumLookup prealloc_mode_lookup = {
diff --git a/ui/input-legacy.c b/ui/input-legacy.c
index c597bdc711..d50a18a505 100644
--- a/ui/input-legacy.c
+++ b/ui/input-legacy.c
@@ -61,7 +61,7 @@ int index_from_key(const char *key, size_t key_length)
 {
     int i;
 
-    for (i = 0; QKeyCode_lookup.array[i] != NULL; i++) {
+    for (i = 0; i < QKeyCode_lookup.size; i++) {
         if (!strncmp(key, QKeyCode_lookup.array[i], key_length) &&
             !QKeyCode_lookup.array[i][key_length]) {
             break;
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 14/54] qapi2texi: minor python code simplification
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (12 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 13/54] qapi: drop the sentinel in enum array Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:56   ` Philippe Mathieu-Daudé
  2017-09-01 15:49   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 15/54] qapi: add 'if' to top-level expressions Marc-André Lureau
                   ` (41 subsequent siblings)
  55 siblings, 2 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

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

diff --git a/scripts/qapi2texi.py b/scripts/qapi2texi.py
index a317526e51..8b542f9fff 100755
--- a/scripts/qapi2texi.py
+++ b/scripts/qapi2texi.py
@@ -136,10 +136,9 @@ def texi_enum_value(value):
 def texi_member(member, suffix=''):
     """Format a table of members item for an object type member"""
     typ = member.type.doc_type()
-    return '@item @code{%s%s%s}%s%s\n' % (
-        member.name,
-        ': ' if typ else '',
-        typ if typ else '',
+    membertype = ': %s' % typ if typ else ''
+    return '@item @code{%s%s}%s%s\n' % (
+        member.name, membertype,
         ' (optional)' if member.optional else '',
         suffix)
 
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 15/54] qapi: add 'if' to top-level expressions
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (13 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 14/54] qapi2texi: minor python code simplification Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-09-04 13:27   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 16/54] qapi: add a test for invalid 'if' Marc-André Lureau
                   ` (40 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

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

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>
---
 scripts/qapi.py                         | 13 +++++++++++++
 tests/test-qmp-commands.c               |  6 ++++++
 tests/qapi-schema/qapi-schema-test.json | 20 ++++++++++++++++++++
 tests/qapi-schema/qapi-schema-test.out  | 22 ++++++++++++++++++++++
 4 files changed, 61 insertions(+)

diff --git a/scripts/qapi.py b/scripts/qapi.py
index 73adb90379..a94d93ada4 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -639,6 +639,16 @@ def add_name(name, info, meta, implicit=False):
     all_names[name] = meta
 
 
+def check_if(expr, info):
+    ifcond = expr.get('if')
+    if not ifcond or isinstance(ifcond, str):
+        return
+    if (not isinstance(ifcond, list) or
+            any([not isinstance(elt, str) for elt in ifcond])):
+        raise QAPISemError(info, "'if' condition requires a string or "
+                           "a list of string")
+
+
 def check_type(info, source, value, allow_array=False,
                allow_dict=False, allow_optional=False,
                allow_metas=[]):
@@ -865,6 +875,7 @@ def check_keys(expr_elem, meta, required, optional=[]):
     expr = expr_elem['expr']
     info = expr_elem['info']
     name = expr[meta]
+    optional = optional + ['if']  # all top-level elem accept if
     if not isinstance(name, str):
         raise QAPISemError(info, "'%s' key must have a string value" % meta)
     required = required + [meta]
@@ -880,6 +891,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'"
diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
index 904c89d4d4..9b9a7ffee7 100644
--- a/tests/test-qmp-commands.c
+++ b/tests/test-qmp-commands.c
@@ -10,6 +10,12 @@
 
 static QmpCommandList qmp_commands;
 
+/* #if defined(TEST_IF_CMD) */
+void qmp_TestIfCmd(TestIfStruct *foo, Error **errp)
+{
+}
+/* #endif */
+
 void qmp_user_def_cmd(Error **errp)
 {
 }
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index c72dbd8050..dc2c444fc1 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 3b1e9082d3..7fbaea19bc 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -52,6 +52,22 @@ enum QEnumTwo ['value1', 'value2']
     prefix QENUM_TWO
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
+alternate TestIfAlternate
+    tag type
+    case foo: int
+    case bar: TestStruct
+command TestIfCmd q_obj_TestIfCmd-arg -> None
+   gen=True success_response=True boxed=False
+enum TestIfEnum ['foo', 'bar']
+event TestIfEvent q_obj_TestIfEvent-arg
+   boxed=False
+object TestIfStruct
+    member foo: int optional=False
+object TestIfUnion
+    member type: TestIfUnionKind optional=False
+    tag type
+    case foo: q_obj_TestStruct-wrapper
+enum TestIfUnionKind ['foo']
 object TestStruct
     member integer: int optional=False
     member boolean: bool optional=False
@@ -172,6 +188,12 @@ object q_obj_EVENT_D-arg
     member b: str optional=False
     member c: str optional=True
     member enum3: EnumOne optional=True
+object q_obj_TestIfCmd-arg
+    member foo: TestIfStruct optional=False
+object q_obj_TestIfEvent-arg
+    member foo: TestIfStruct optional=False
+object q_obj_TestStruct-wrapper
+    member data: TestStruct optional=False
 object q_obj_UserDefFlatUnion2-base
     member integer: int optional=True
     member string: str optional=False
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 16/54] qapi: add a test for invalid 'if'
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (14 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 15/54] qapi: add 'if' to top-level expressions Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-09-04 13:31   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 17/54] qapi: add 'if' condition on entity objects Marc-André Lureau
                   ` (39 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 tests/Makefile.include        | 1 +
 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
 5 files changed, 6 insertions(+)
 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/tests/Makefile.include b/tests/Makefile.include
index 3653c7b40a..1f1d8f075b 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -396,6 +396,7 @@ 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-type-bool.json
 qapi-schema += bad-type-dict.json
 qapi-schema += bad-type-int.json
diff --git a/tests/qapi-schema/bad-if.err b/tests/qapi-schema/bad-if.err
new file mode 100644
index 0000000000..8054fbb143
--- /dev/null
+++ b/tests/qapi-schema/bad-if.err
@@ -0,0 +1 @@
+tests/qapi-schema/bad-if.json:2: 'if' condition requires a string or a list of string
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
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 17/54] qapi: add 'if' condition on entity objects
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (15 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 16/54] qapi: add a test for invalid 'if' Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-09-04 16:13   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 18/54] qapi: add 'ifcond' to visitor methods Marc-André Lureau
                   ` (38 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

Take 'if' from expression, and use it to construct entity objects.
Shared implicit objects must share the same 'if' condition.

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

diff --git a/scripts/qapi.py b/scripts/qapi.py
index a94d93ada4..dc40d74abb 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -992,7 +992,7 @@ def check_exprs(exprs):
 #
 
 class QAPISchemaEntity(object):
-    def __init__(self, name, info, doc):
+    def __init__(self, name, info, doc, ifcond=None):
         assert isinstance(name, str)
         self.name = name
         # For explicitly defined entities, info points to the (explicit)
@@ -1002,6 +1002,7 @@ class QAPISchemaEntity(object):
         # such place).
         self.info = info
         self.doc = doc
+        self.ifcond = ifcond
 
     def c_name(self):
         return c_name(self.name)
@@ -1118,8 +1119,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, values, prefix, ifcond=None):
+        QAPISchemaType.__init__(self, name, info, doc, ifcond)
         for v in values:
             assert isinstance(v, QAPISchemaMember)
             v.set_owner(name)
@@ -1162,6 +1163,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
@@ -1183,11 +1185,12 @@ class QAPISchemaArrayType(QAPISchemaType):
 
 
 class QAPISchemaObjectType(QAPISchemaType):
-    def __init__(self, name, info, doc, base, local_members, variants):
+    def __init__(self, name, info, doc, base, local_members, variants,
+                 ifcond=None):
         # 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)
@@ -1375,8 +1378,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, variants, ifcond):
+        QAPISchemaType.__init__(self, name, info, doc, ifcond)
         assert isinstance(variants, QAPISchemaObjectTypeVariants)
         assert variants.tag_member
         variants.set_owner(name)
@@ -1413,8 +1416,8 @@ class QAPISchemaAlternateType(QAPISchemaType):
 
 class QAPISchemaCommand(QAPISchemaEntity):
     def __init__(self, name, info, doc, arg_type, ret_type,
-                 gen, success_response, boxed):
-        QAPISchemaEntity.__init__(self, name, info, doc)
+                 gen, success_response, boxed, ifcond):
+        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
@@ -1451,8 +1454,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, arg_type, boxed, ifcond):
+        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
@@ -1547,11 +1550,11 @@ class QAPISchema(object):
     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, values, ifcond):
         # 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, self._make_enum_members(values), None, ifcond))
         return name
 
     def _make_array_type(self, element_type, info):
@@ -1560,22 +1563,29 @@ 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, role, members,
+                                   ifcond=None):
         if not members:
             return None
         # See also QAPISchemaObjectTypeMember._pretty_owner()
         name = 'q_obj_%s-%s' % (name, role)
-        if not self.lookup_entity(name, QAPISchemaObjectType):
+        typ = self.lookup_entity(name, QAPISchemaObjectType)
+        if typ:
+            # FIXME: generating the disjunction of all conditions
+            assert ifcond == typ.ifcond
+        else:
             self._def_entity(QAPISchemaObjectType(name, info, doc, None,
-                                                  members, None))
+                                                  members, None, ifcond))
         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, self._make_enum_members(data), prefix,
+            ifcond))
 
     def _make_member(self, name, typ, info):
         optional = False
@@ -1595,9 +1605,10 @@ class QAPISchema(object):
         name = expr['struct']
         base = expr.get('base')
         data = expr['data']
+        ifcond = expr.get('if')
         self._def_entity(QAPISchemaObjectType(name, info, doc, base,
                                               self._make_members(data, info),
-                                              None))
+                                              None, ifcond))
 
     def _make_variant(self, case, typ):
         return QAPISchemaObjectTypeVariant(case, typ)
@@ -1606,19 +1617,23 @@ class QAPISchema(object):
         if isinstance(typ, list):
             assert len(typ) == 1
             typ = self._make_array_type(typ[0], info)
+        type_entity = self.lookup_type(typ)
         typ = self._make_implicit_object_type(
-            typ, info, None, 'wrapper', [self._make_member('data', typ, info)])
+            typ, info, None, 'wrapper',
+            [self._make_member('data', typ, info)], type_entity.ifcond)
         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, 'base', self._make_members(base, info),
+                ifcond)
         if tag_name:
             variants = [self._make_variant(key, value)
                         for (key, value) in data.iteritems()]
@@ -1627,18 +1642,21 @@ class QAPISchema(object):
             variants = [self._make_simple_variant(key, value, info)
                         for (key, value) in data.iteritems()]
             typ = self._make_implicit_enum_type(name, info,
-                                                [v.name for v in variants])
+                                                [v.name for v in variants],
+                                                ifcond)
             tag_member = QAPISchemaObjectTypeMember('type', typ, False)
             members = [tag_member]
         self._def_entity(
             QAPISchemaObjectType(name, info, doc, base, members,
                                  QAPISchemaObjectTypeVariants(tag_name,
                                                               tag_member,
-                                                              variants)))
+                                                              variants),
+                                 ifcond))
 
     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.iteritems()]
         tag_member = QAPISchemaObjectTypeMember('type', 'QType', False)
@@ -1646,7 +1664,8 @@ class QAPISchema(object):
             QAPISchemaAlternateType(name, info, doc,
                                     QAPISchemaObjectTypeVariants(None,
                                                                  tag_member,
-                                                                 variants)))
+                                                                 variants),
+                                    ifcond))
 
     def _def_command(self, expr, info, doc):
         name = expr['command']
@@ -1655,23 +1674,29 @@ class QAPISchema(object):
         gen = expr.get('gen', True)
         success_response = expr.get('success-response', True)
         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))
+                name, info, doc, 'arg', self._make_members(data, info),
+                ifcond)
         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,
-                                           gen, success_response, boxed))
+                                           gen, success_response, boxed,
+                                           ifcond))
 
     def _def_event(self, expr, info, doc):
         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, 'arg', self._make_members(data, info),
+                ifcond)
+        self._def_entity(QAPISchemaEvent(name, info, doc, data, boxed,
+                                         ifcond))
 
     def _def_exprs(self):
         for expr_elem in self.exprs:
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 18/54] qapi: add 'ifcond' to visitor methods
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (16 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 17/54] qapi: add 'if' condition on entity objects Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-09-04 16:47   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 19/54] qapi: add #if/#endif helpers Marc-André Lureau
                   ` (37 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

Modify the test visitor to check correct passing of values.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi.py                        | 34 ++++++++++++++++++++--------------
 scripts/qapi-commands.py               |  2 +-
 scripts/qapi-event.py                  |  2 +-
 scripts/qapi-introspect.py             | 12 ++++++------
 scripts/qapi-types.py                  |  8 ++++----
 scripts/qapi-visit.py                  |  8 ++++----
 scripts/qapi2texi.py                   | 10 +++++-----
 tests/qapi-schema/qapi-schema-test.out |  9 +++++++++
 tests/qapi-schema/test-qapi.py         | 21 ++++++++++++++++-----
 9 files changed, 66 insertions(+), 40 deletions(-)

diff --git a/scripts/qapi.py b/scripts/qapi.py
index dc40d74abb..86845a28f9 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -1031,26 +1031,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, values, prefix, ifcond):
         pass
 
-    def visit_array_type(self, name, info, element_type):
+    def visit_array_type(self, name, info, element_type, ifcond):
         pass
 
-    def visit_object_type(self, name, info, base, members, variants):
+    def visit_object_type(self, name, info, base, members, variants, ifcond):
         pass
 
-    def visit_object_type_flat(self, name, info, members, variants):
+    def visit_object_type_flat(self, name, info, members, variants, ifcond):
         pass
 
-    def visit_alternate_type(self, name, info, variants):
+    def visit_alternate_type(self, name, info, variants, ifcond):
         pass
 
     def visit_command(self, name, info, arg_type, ret_type,
-                      gen, success_response, boxed):
+                      gen, success_response, boxed, ifcond):
         pass
 
-    def visit_event(self, name, info, arg_type, boxed):
+    def visit_event(self, name, info, arg_type, boxed, ifcond):
         pass
 
 
@@ -1150,7 +1150,7 @@ class QAPISchemaEnumType(QAPISchemaType):
 
     def visit(self, visitor):
         visitor.visit_enum_type(self.name, self.info,
-                                self.member_names(), self.prefix)
+                                self.member_names(), self.prefix, self.ifcond)
 
 
 class QAPISchemaArrayType(QAPISchemaType):
@@ -1181,7 +1181,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.element_type,
+                                 self.ifcond)
 
 
 class QAPISchemaObjectType(QAPISchemaType):
@@ -1263,9 +1264,11 @@ class QAPISchemaObjectType(QAPISchemaType):
 
     def visit(self, visitor):
         visitor.visit_object_type(self.name, self.info,
-                                  self.base, self.local_members, self.variants)
+                                  self.base, self.local_members, self.variants,
+                                  self.ifcond)
         visitor.visit_object_type_flat(self.name, self.info,
-                                       self.members, self.variants)
+                                       self.members, self.variants,
+                                       self.ifcond)
 
 
 class QAPISchemaMember(object):
@@ -1408,7 +1411,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.variants, self.ifcond)
 
     def is_empty(self):
         return False
@@ -1450,7 +1454,8 @@ class QAPISchemaCommand(QAPISchemaEntity):
     def visit(self, visitor):
         visitor.visit_command(self.name, self.info,
                               self.arg_type, self.ret_type,
-                              self.gen, self.success_response, self.boxed)
+                              self.gen, self.success_response, self.boxed,
+                              self.ifcond)
 
 
 class QAPISchemaEvent(QAPISchemaEntity):
@@ -1478,7 +1483,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.arg_type, self.boxed,
+                            self.ifcond)
 
 
 class QAPISchema(object):
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index 974d0a4a80..5eb96b2d95 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -241,7 +241,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
         self._visited_ret_types = None
 
     def visit_command(self, name, info, arg_type, ret_type,
-                      gen, success_response, boxed):
+                      gen, success_response, boxed, ifcond):
         if not gen:
             return
         self.decl += gen_command_decl(name, arg_type, boxed, ret_type)
diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
index bcbef1035f..fec27fe2e1 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi-event.py
@@ -163,7 +163,7 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
         self.defn += gen_enum_lookup(event_enum_name, self._event_names)
         self._event_names = None
 
-    def visit_event(self, name, info, arg_type, boxed):
+    def visit_event(self, name, info, arg_type, boxed, ifcond):
         self.decl += gen_event_send_decl(name, arg_type, boxed)
         self.defn += gen_event_send(name, arg_type, boxed)
         self._event_names.append(name)
diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index 1b96926fa7..4c437d60ec 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -142,34 +142,34 @@ 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, values, prefix, ifcond):
         self._gen_qlit(name, 'enum', {'values': values})
 
-    def visit_array_type(self, name, info, element_type):
+    def visit_array_type(self, name, info, element_type, ifcond):
         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, members, variants, ifcond):
         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, variants, ifcond):
         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,
-                      gen, success_response, boxed):
+                      gen, success_response, boxed, ifcond):
         arg_type = arg_type or self._schema.the_empty_object_type
         ret_type = ret_type or self._schema.the_empty_object_type
         self._gen_qlit(name, 'command',
                        {'arg-type': self._use_type(arg_type),
                         'ret-type': self._use_type(ret_type)})
 
-    def visit_event(self, name, info, arg_type, boxed):
+    def visit_event(self, name, info, arg_type, boxed, ifcond):
         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 dc05268917..6f06720adc 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -201,7 +201,7 @@ typedef struct QEnumLookup {
         self.decl += gen_type_cleanup_decl(name)
         self.defn += gen_type_cleanup(name)
 
-    def visit_enum_type(self, name, info, values, prefix):
+    def visit_enum_type(self, name, info, values, prefix, ifcond):
         # Special case for our lone builtin enum type
         # TODO use something cleaner than existence of info
         if not info:
@@ -212,7 +212,7 @@ typedef struct QEnumLookup {
             self._fwdecl += gen_enum(name, values, prefix)
             self.defn += gen_enum_lookup(name, values, prefix)
 
-    def visit_array_type(self, name, info, element_type):
+    def visit_array_type(self, name, info, element_type, ifcond):
         if isinstance(element_type, QAPISchemaBuiltinType):
             self._btin += gen_fwd_object_or_array(name)
             self._btin += gen_array(name, element_type)
@@ -224,7 +224,7 @@ typedef struct QEnumLookup {
             self.decl += 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, base, members, variants, ifcond):
         # Nothing to do for the special empty builtin
         if name == 'q_empty':
             return
@@ -238,7 +238,7 @@ typedef struct QEnumLookup {
             # 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, variants, ifcond):
         self._fwdecl += gen_fwd_object_or_array(name)
         self.decl += gen_object(name, None, [variants.tag_member], variants)
         self._gen_type_cleanup(name)
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 7e1cfc13f0..c29c2d869e 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -282,7 +282,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
         self.decl = self._btin + self.decl
         self._btin = None
 
-    def visit_enum_type(self, name, info, values, prefix):
+    def visit_enum_type(self, name, info, values, prefix, ifcond):
         # Special case for our lone builtin enum type
         # TODO use something cleaner than existence of info
         if not info:
@@ -293,7 +293,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
             self.decl += gen_visit_decl(name, scalar=True)
             self.defn += gen_visit_enum(name)
 
-    def visit_array_type(self, name, info, element_type):
+    def visit_array_type(self, name, info, element_type, ifcond):
         decl = gen_visit_decl(name)
         defn = gen_visit_list(name, element_type)
         if isinstance(element_type, QAPISchemaBuiltinType):
@@ -304,7 +304,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
             self.decl += decl
             self.defn += defn
 
-    def visit_object_type(self, name, info, base, members, variants):
+    def visit_object_type(self, name, info, base, members, variants, ifcond):
         # Nothing to do for the special empty builtin
         if name == 'q_empty':
             return
@@ -317,7 +317,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
             self.decl += gen_visit_decl(name)
             self.defn += gen_visit_object(name, base, members, variants)
 
-    def visit_alternate_type(self, name, info, variants):
+    def visit_alternate_type(self, name, info, variants, ifcond):
         self.decl += gen_visit_decl(name)
         self.defn += gen_visit_alternate(name, variants)
 
diff --git a/scripts/qapi2texi.py b/scripts/qapi2texi.py
index 8b542f9fff..ae7920aa87 100755
--- a/scripts/qapi2texi.py
+++ b/scripts/qapi2texi.py
@@ -207,7 +207,7 @@ class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor):
     def visit_begin(self, schema):
         self.out = ''
 
-    def visit_enum_type(self, name, info, values, prefix):
+    def visit_enum_type(self, name, info, values, prefix, ifcond):
         doc = self.cur_doc
         if self.out:
             self.out += '\n'
@@ -216,7 +216,7 @@ class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor):
                              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, base, members, variants, ifcond):
         doc = self.cur_doc
         if base and base.is_implicit():
             base = None
@@ -226,7 +226,7 @@ class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor):
                              name=doc.symbol,
                              body=texi_entity(doc, 'Members', base, variants))
 
-    def visit_alternate_type(self, name, info, variants):
+    def visit_alternate_type(self, name, info, variants, ifcond):
         doc = self.cur_doc
         if self.out:
             self.out += '\n'
@@ -235,7 +235,7 @@ class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor):
                              body=texi_entity(doc, 'Members'))
 
     def visit_command(self, name, info, arg_type, ret_type,
-                      gen, success_response, boxed):
+                      gen, success_response, boxed, ifcond):
         doc = self.cur_doc
         if self.out:
             self.out += '\n'
@@ -249,7 +249,7 @@ class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor):
                             name=doc.symbol,
                             body=body)
 
-    def visit_event(self, name, info, arg_type, boxed):
+    def visit_event(self, name, info, arg_type, boxed, ifcond):
         doc = self.cur_doc
         if self.out:
             self.out += '\n'
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 7fbaea19bc..fc5fd25f1b 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -56,18 +56,25 @@ alternate TestIfAlternate
     tag type
     case foo: int
     case bar: TestStruct
+    if defined(TEST_IF_ALT) && 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)
 enum TestIfEnum ['foo', 'bar']
+    if defined(TEST_IF_ENUM)
 event TestIfEvent q_obj_TestIfEvent-arg
    boxed=False
+    if defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)
 object TestIfStruct
     member foo: int optional=False
+    if 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)
 enum TestIfUnionKind ['foo']
+    if defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)
 object TestStruct
     member integer: int optional=False
     member boolean: bool optional=False
@@ -190,8 +197,10 @@ object q_obj_EVENT_D-arg
     member enum3: EnumOne optional=True
 object q_obj_TestIfCmd-arg
     member foo: TestIfStruct optional=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)
 object q_obj_TestStruct-wrapper
     member data: TestStruct optional=False
 object q_obj_UserDefFlatUnion2-base
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index c7724d3437..17fd975812 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -17,12 +17,13 @@ import sys
 
 
 class QAPISchemaTestVisitor(QAPISchemaVisitor):
-    def visit_enum_type(self, name, info, values, prefix):
+    def visit_enum_type(self, name, info, values, prefix, ifcond):
         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, base, members, variants, ifcond):
         print 'object %s' % name
         if base:
             print '    base %s' % base.name
@@ -30,21 +31,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, variants, ifcond):
         print 'alternate %s' % name
         self._print_variants(variants)
+        self._print_if(ifcond)
 
     def visit_command(self, name, info, arg_type, ret_type,
-                      gen, success_response, boxed):
+                      gen, success_response, boxed, ifcond):
         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, arg_type, boxed, ifcond):
         print 'event %s %s' % (name, arg_type and arg_type.name)
         print '   boxed=%s' % boxed
+        self._print_if(ifcond)
 
     @staticmethod
     def _print_variants(variants):
@@ -53,6 +58,12 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
             for v in variants.variants:
                 print '    case %s: %s' % (v.name, v.type.name)
 
+    @staticmethod
+    def _print_if(ifcond):
+        if ifcond:
+            print '    if %s' % ifcond
+
+
 schema = QAPISchema(sys.argv[1])
 schema.visit(QAPISchemaTestVisitor())
 
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 19/54] qapi: add #if/#endif helpers
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (17 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 18/54] qapi: add 'ifcond' to visitor methods Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-09-05  9:32   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 20/54] qapi-introspect: modify to_qlit() to take an optional suffix Marc-André Lureau
                   ` (36 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

Add helpers to generate #if/#endif and wrap visitor methods generating
code. Used in the following patches.

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

diff --git a/scripts/qapi.py b/scripts/qapi.py
index 86845a28f9..52099332f1 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -1892,6 +1892,57 @@ def guardend(name):
                  name=guardname(name))
 
 
+def gen_if(ifcond):
+    if not ifcond:
+        return ''
+    if isinstance(ifcond, str):
+        ifcond = [ifcond]
+    # Not using mcgen() because we don't want indent or \n stipped
+    ret = '\n'
+    for ifc in ifcond:
+        ret += '#if %s\n' % ifc
+    ret += '\n'
+    return ret
+
+
+def gen_endif(ifcond):
+    if not ifcond:
+        return ''
+    if isinstance(ifcond, str):
+        ifcond = [ifcond]
+    # Not using mcgen() because we don't want indent or \n stipped
+    ret = '\n'
+    for ifc in reversed(ifcond):
+        ret += '#endif /* %s */\n' % ifc
+    ret += '\n'
+    return ret
+
+
+# Wrap a method to add #if / #endif to generated code, only if some
+# code was generated.
+# self must have 'if_members' listing the attributes to wrap.
+# The last argument of the wrapped function must be the 'ifcond'.
+def ifcond_decorator(func):
+
+    def func_wrapper(self, *args, **kwargs):
+        ifcond = args[-1]
+        save = {}
+        for mem in self.if_members:
+            save[mem] = getattr(self, mem)
+        func(self, *args, **kwargs)
+        for mem, val in save.items():
+            newval = getattr(self, mem)
+            if newval != val:
+                assert newval.startswith(val)
+                newval = newval[len(val):]
+                val += gen_if(ifcond)
+                val += newval
+                val += gen_endif(ifcond)
+            setattr(self, mem, val)
+
+    return func_wrapper
+
+
 def gen_enum_lookup(name, values, prefix=None):
     ret = mcgen('''
 
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 20/54] qapi-introspect: modify to_qlit() to take an optional suffix
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (18 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 19/54] qapi: add #if/#endif helpers Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-09-05  9:42   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 21/54] qapi-introspect: modify to_qlit() to generate #if code Marc-André Lureau
                   ` (35 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

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>
---
 scripts/qapi-introspect.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index 4c437d60ec..dfb6d2ded4 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -16,7 +16,7 @@ def to_c_string(s):
     return '"' + s.replace('\\', r'\\').replace('"', r'\"') + '"'
 
 
-def to_qlit(obj, level=0, first_indent=True):
+def to_qlit(obj, level=0, first_indent=True, suffix=''):
 
     def indent(level):
         return level * 4 * ' '
@@ -29,11 +29,11 @@ def to_qlit(obj, level=0, first_indent=True):
     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, suffix=',')
                 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 = []
@@ -46,7 +46,7 @@ def to_qlit(obj, level=0, first_indent=True):
         ret += indent(level) + '}))'
     else:
         assert False                # not implemented
-    return ret
+    return ret + suffix
 
 
 class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor):
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 21/54] qapi-introspect: modify to_qlit() to generate #if code
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (19 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 20/54] qapi-introspect: modify to_qlit() to take an optional suffix Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 22/54] qapi-introspect: add preprocessor conditions to generated QLit Marc-André Lureau
                   ` (34 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

The generator now accepts (obj, condition) tuples to wrap generated
QLit objects with #if/#endif conditions.

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

diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index dfb6d2ded4..9ef6f271d4 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -26,6 +26,12 @@ def to_qlit(obj, level=0, first_indent=True, suffix=''):
         ret += indent(level)
     if obj is None:
         ret += 'QLIT_QNULL'
+    elif isinstance(obj, tuple):
+        obj, ifcond = obj
+        ret += gen_if(ifcond)
+        ret += to_qlit(obj, level, first_indent=False) + suffix
+        ret += gen_endif(ifcond)
+        suffix = ''
     elif isinstance(obj, str):
         ret += 'QLIT_QSTR(' + to_c_string(obj) + ')'
     elif isinstance(obj, list):
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 22/54] qapi-introspect: add preprocessor conditions to generated QLit
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (20 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 21/54] qapi-introspect: modify to_qlit() to generate #if code Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-09-05 14:24   ` Markus Armbruster
  2017-09-06 11:38   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 23/54] qapi-commands: add #if conditions to commands Marc-André Lureau
                   ` (33 subsequent siblings)
  55 siblings, 2 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

Add 'ifcond' condition to QLit objects.

to_qlit() handles the (obj, ifcond) tuples.

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

diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index 9ef6f271d4..5e736a06df 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -125,12 +125,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)}
@@ -146,26 +146,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}, None)
 
     def visit_enum_type(self, name, info, values, prefix, ifcond):
-        self._gen_qlit(name, 'enum', {'values': values})
+        self._gen_qlit(name, 'enum', {'values': values}, ifcond)
 
     def visit_array_type(self, name, info, element_type, ifcond):
         element = self._use_type(element_type)
-        self._gen_qlit('[' + element + ']', 'array', {'element-type': element})
+        self._gen_qlit('[' + element + ']', 'array', {'element-type': element},
+                       ifcond)
 
     def visit_object_type_flat(self, name, info, members, variants, ifcond):
         obj = {'members': [self._gen_member(m) for m in members]}
         if variants:
             obj.update(self._gen_variants(variants.tag_member.name,
                                           variants.variants))
-        self._gen_qlit(name, 'object', obj)
+        self._gen_qlit(name, 'object', obj, ifcond)
 
     def visit_alternate_type(self, name, info, variants, ifcond):
         self._gen_qlit(name, 'alternate',
                        {'members': [{'type': self._use_type(m.type)}
-                                    for m in variants.variants]})
+                                    for m in variants.variants]}, ifcond)
 
     def visit_command(self, name, info, arg_type, ret_type,
                       gen, success_response, boxed, ifcond):
@@ -173,11 +174,12 @@ const QLitObject %(c_name)s = %(c_string)s;
         ret_type = ret_type or self._schema.the_empty_object_type
         self._gen_qlit(name, 'command',
                        {'arg-type': self._use_type(arg_type),
-                        'ret-type': self._use_type(ret_type)})
+                        'ret-type': self._use_type(ret_type)}, ifcond)
 
     def visit_event(self, name, info, arg_type, boxed, ifcond):
         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)
 
 # Debugging aid: unmask QAPI schema's type names
 # We normally mask them, because they're not QMP wire ABI
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 23/54] qapi-commands: add #if conditions to commands
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (21 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 22/54] qapi-introspect: add preprocessor conditions to generated QLit Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-09-05 14:53   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 24/54] qapi-event: add #if conditions to events Marc-André Lureau
                   ` (32 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

Wrap generated code with #if/#endif using the ifcond_decorator.

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

diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index 5eb96b2d95..db45415c41 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -228,6 +228,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
         self.defn = None
         self._regy = None
         self._visited_ret_types = None
+        self.if_members = ['decl', 'defn', '_regy']
 
     def visit_begin(self, schema):
         self.decl = ''
@@ -240,6 +241,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
         self._regy = None
         self._visited_ret_types = None
 
+    @ifcond_decorator
     def visit_command(self, name, info, arg_type, ret_type,
                       gen, success_response, boxed, ifcond):
         if not gen:
diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
index 9b9a7ffee7..ad7b6e4e1d 100644
--- a/tests/test-qmp-commands.c
+++ b/tests/test-qmp-commands.c
@@ -10,11 +10,11 @@
 
 static QmpCommandList qmp_commands;
 
-/* #if defined(TEST_IF_CMD) */
+#if defined(TEST_IF_CMD)
 void qmp_TestIfCmd(TestIfStruct *foo, Error **errp)
 {
 }
-/* #endif */
+#endif
 
 void qmp_user_def_cmd(Error **errp)
 {
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 24/54] qapi-event: add #if conditions to events
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (22 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 23/54] qapi-commands: add #if conditions to commands Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 25/54] qapi-visit: add #if conditions to visitors Marc-André Lureau
                   ` (31 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

Wrap generated code with #if/#endif using the ifcond_decorator.

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

diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
index fec27fe2e1..f21ecd39f3 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi-event.py
@@ -152,6 +152,7 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
         self.decl = None
         self.defn = None
         self._event_names = None
+        self.if_members = ['decl', 'defn']
 
     def visit_begin(self, schema):
         self.decl = ''
@@ -163,6 +164,7 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
         self.defn += gen_enum_lookup(event_enum_name, self._event_names)
         self._event_names = None
 
+    @ifcond_decorator
     def visit_event(self, name, info, arg_type, boxed, ifcond):
         self.decl += gen_event_send_decl(name, arg_type, boxed)
         self.defn += gen_event_send(name, arg_type, boxed)
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 25/54] qapi-visit: add #if conditions to visitors
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (23 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 24/54] qapi-event: add #if conditions to events Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-09-06 10:54   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 26/54] qapi-types: refactor variants handling Marc-André Lureau
                   ` (30 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

Wrap generated code with #if/#endif using the ifcond_decorator.

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

diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index c29c2d869e..bb18c9edee 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -267,6 +267,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
         self.decl = None
         self.defn = None
         self._btin = None
+        self.if_members = ['decl', 'defn', '_btin']
 
     def visit_begin(self, schema):
         self.decl = ''
@@ -282,6 +283,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
         self.decl = self._btin + self.decl
         self._btin = None
 
+    @ifcond_decorator
     def visit_enum_type(self, name, info, values, prefix, ifcond):
         # Special case for our lone builtin enum type
         # TODO use something cleaner than existence of info
@@ -293,6 +295,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
             self.decl += gen_visit_decl(name, scalar=True)
             self.defn += gen_visit_enum(name)
 
+    @ifcond_decorator
     def visit_array_type(self, name, info, element_type, ifcond):
         decl = gen_visit_decl(name)
         defn = gen_visit_list(name, element_type)
@@ -304,6 +307,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
             self.decl += decl
             self.defn += defn
 
+    @ifcond_decorator
     def visit_object_type(self, name, info, base, members, variants, ifcond):
         # Nothing to do for the special empty builtin
         if name == 'q_empty':
@@ -317,6 +321,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
             self.decl += gen_visit_decl(name)
             self.defn += gen_visit_object(name, base, members, variants)
 
+    @ifcond_decorator
     def visit_alternate_type(self, name, info, variants, ifcond):
         self.decl += gen_visit_decl(name)
         self.defn += gen_visit_alternate(name, variants)
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 26/54] qapi-types: refactor variants handling
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (24 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 25/54] qapi-visit: add #if conditions to visitors Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 27/54] qapi-types: add #if conditions to types Marc-André Lureau
                   ` (29 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

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

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

diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 6f06720adc..05b0eee482 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -53,19 +53,23 @@ 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 {
 ''',
@@ -224,11 +228,7 @@ typedef struct QEnumLookup {
             self.decl += gen_array(name, element_type)
             self._gen_type_cleanup(name)
 
-    def visit_object_type(self, name, info, base, members, variants, ifcond):
-        # Nothing to do for the special empty builtin
-        if name == 'q_empty':
-            return
-        self._fwdecl += gen_fwd_object_or_array(name)
+    def _gen_object(self, name, info, base, members, variants):
         self.decl += gen_object(name, base, members, variants)
         if base and not base.is_implicit():
             self.decl += gen_upcast(name, base)
@@ -238,10 +238,18 @@ typedef struct QEnumLookup {
             # implicit types won't be directly allocated/freed
             self._gen_type_cleanup(name)
 
+    def visit_object_type(self, name, info, base, members, variants, ifcond):
+        # Nothing to do for the special empty builtin
+        if name == 'q_empty':
+            return
+        self._fwdecl += gen_fwd_object_or_array(name)
+        self.decl += gen_variants_objects(variants)
+        self._gen_object(name, info, base, members, variants)
+
     def visit_alternate_type(self, name, info, variants, ifcond):
         self._fwdecl += gen_fwd_object_or_array(name)
-        self.decl += gen_object(name, None, [variants.tag_member], variants)
-        self._gen_type_cleanup(name)
+        self.decl += gen_variants_objects(variants)
+        self._gen_object(name, info, None, [variants.tag_member], variants)
 
 # If you link code generated from multiple schemata, you want only one
 # instance of the code for built-in types.  Generate it only when
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 27/54] qapi-types: add #if conditions to types
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (25 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 26/54] qapi-types: refactor variants handling Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-09-06 11:43   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 28/54] qapi: do not define enumeration value explicitely Marc-André Lureau
                   ` (28 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

Wrap generated code with #if/#endif using the ifcond_decorator.

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

diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 05b0eee482..c1316312ac 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -175,6 +175,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
         self.defn = None
         self._fwdecl = None
         self._btin = None
+        self.if_members = ['decl', 'defn', '_fwdecl', '_btin']
 
     def visit_begin(self, schema):
         # gen_object() is recursive, ensure it doesn't visit the empty type
@@ -201,10 +202,12 @@ typedef struct QEnumLookup {
         self.decl = self._btin + self.decl
         self._btin = None
 
-    def _gen_type_cleanup(self, name):
+    @ifcond_decorator
+    def _gen_type_cleanup(self, name, ifcond):
         self.decl += gen_type_cleanup_decl(name)
         self.defn += gen_type_cleanup(name)
 
+    @ifcond_decorator
     def visit_enum_type(self, name, info, values, prefix, ifcond):
         # Special case for our lone builtin enum type
         # TODO use something cleaner than existence of info
@@ -216,6 +219,7 @@ typedef struct QEnumLookup {
             self._fwdecl += gen_enum(name, values, prefix)
             self.defn += gen_enum_lookup(name, values, prefix)
 
+    @ifcond_decorator
     def visit_array_type(self, name, info, element_type, ifcond):
         if isinstance(element_type, QAPISchemaBuiltinType):
             self._btin += gen_fwd_object_or_array(name)
@@ -226,9 +230,10 @@ typedef struct QEnumLookup {
         else:
             self._fwdecl += gen_fwd_object_or_array(name)
             self.decl += gen_array(name, element_type)
-            self._gen_type_cleanup(name)
+            self._gen_type_cleanup(name, ifcond)
 
-    def _gen_object(self, name, info, base, members, variants):
+    @ifcond_decorator
+    def _gen_object(self, name, info, base, members, variants, ifcond):
         self.decl += gen_object(name, base, members, variants)
         if base and not base.is_implicit():
             self.decl += gen_upcast(name, base)
@@ -236,7 +241,7 @@ typedef struct QEnumLookup {
         # 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 visit_object_type(self, name, info, base, members, variants, ifcond):
         # Nothing to do for the special empty builtin
@@ -244,12 +249,13 @@ typedef struct QEnumLookup {
             return
         self._fwdecl += gen_fwd_object_or_array(name)
         self.decl += gen_variants_objects(variants)
-        self._gen_object(name, info, base, members, variants)
+        self._gen_object(name, info, base, members, variants, ifcond)
 
     def visit_alternate_type(self, name, info, variants, ifcond):
         self._fwdecl += gen_fwd_object_or_array(name)
         self.decl += gen_variants_objects(variants)
-        self._gen_object(name, info, None, [variants.tag_member], variants)
+        self._gen_object(name, info, None, [variants.tag_member],
+                         variants, ifcond)
 
 # If you link code generated from multiple schemata, you want only one
 # instance of the code for built-in types.  Generate it only when
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 28/54] qapi: do not define enumeration value explicitely
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (26 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 27/54] qapi-types: add #if conditions to types Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 14:00   ` Philippe Mathieu-Daudé
  2017-09-05 17:45   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 29/54] qapi: add 'if' to enum members Marc-André Lureau
                   ` (27 subsequent siblings)
  55 siblings, 2 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

The C standard has the initial value at 0 and the subsequent values
incremented by 1. No need to set this explicitely.

This will prevent from artificial "gaps" when compiling out some enum
values and having unnecessarily large MAX values & enums arrays.

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

diff --git a/scripts/qapi.py b/scripts/qapi.py
index 52099332f1..9d075440d3 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -1979,14 +1979,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.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 29/54] qapi: add 'if' to enum members
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (27 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 28/54] qapi: do not define enumeration value explicitely Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-09-06 13:01   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 30/54] qapi: add #if conditions on generated enum values Marc-André Lureau
                   ` (26 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi.py                         | 33 +++++++++++++++++++++++++++------
 tests/qapi-schema/enum-dict-member.err  |  1 -
 tests/qapi-schema/enum-dict-member.exit |  2 +-
 tests/qapi-schema/enum-dict-member.json |  3 +--
 tests/qapi-schema/enum-dict-member.out  |  4 ++++
 tests/qapi-schema/qapi-schema-test.json |  5 +++--
 tests/qapi-schema/qapi-schema-test.out  |  3 ++-
 tests/qapi-schema/test-qapi.py          |  4 +++-
 8 files changed, 41 insertions(+), 14 deletions(-)

diff --git a/scripts/qapi.py b/scripts/qapi.py
index 9d075440d3..9c7c01c11d 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -729,6 +729,10 @@ def check_event(expr, info):
                allow_metas=meta)
 
 
+def enum_get_values(expr):
+    return [e if isinstance(e, str) else e['name'] for e in expr['data']]
+
+
 def check_union(expr, info):
     name = expr['union']
     base = expr.get('base')
@@ -788,7 +792,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_values(enum_define):
                 raise QAPISemError(info,
                                    "Discriminator value '%s' is not found in "
                                    "enum '%s'"
@@ -796,7 +800,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_values(enum_define):
             if value not in members.keys():
                 raise QAPISemError(info, "Union '%s' data missing '%s' branch"
                                    % (name, value))
@@ -827,7 +831,7 @@ def check_alternate(expr, info):
         if qtype == 'QTYPE_QSTRING':
             enum_expr = enum_types.get(value)
             if enum_expr:
-                for v in enum_expr['data']:
+                for v in enum_get_values(enum_expr):
                     if v in ['on', 'off']:
                         conflicting.add('QTYPE_QBOOL')
                     if re.match(r'[-+0-9.]', v): # lazy, could be tightened
@@ -857,6 +861,12 @@ def check_enum(expr, info):
         raise QAPISemError(info,
                            "Enum '%s' requires a string for 'prefix'" % name)
     for member in members:
+        if isinstance(member, dict):
+            if not 'name' in member:
+                raise QAPISemError(info, "Dictionary member of enum '%s' must "
+                                   "have a 'name' key" % name)
+            check_if(member, info)
+            member = member['name']
         check_name(info, "Member of enum '%s'" % name, member,
                    enum_member=True)
 
@@ -1145,12 +1155,15 @@ class QAPISchemaEnumType(QAPISchemaType):
     def member_names(self):
         return [v.name for v in self.values]
 
+    def members(self):
+        return [(v.name, v.ifcond) for v in self.values]
+
     def json_type(self):
         return 'string'
 
     def visit(self, visitor):
         visitor.visit_enum_type(self.name, self.info,
-                                self.member_names(), self.prefix, self.ifcond)
+                                self.members(), self.prefix, self.ifcond)
 
 
 class QAPISchemaArrayType(QAPISchemaType):
@@ -1274,9 +1287,11 @@ class QAPISchemaObjectType(QAPISchemaType):
 class QAPISchemaMember(object):
     role = 'member'
 
-    def __init__(self, name):
+    def __init__(self, name, ifcond=None):
         assert isinstance(name, str)
+        assert ifcond is None or isinstance(ifcond, str)
         self.name = name
+        self.ifcond = ifcond
         self.owner = None
 
     def set_owner(self, name):
@@ -1554,7 +1569,9 @@ class QAPISchema(object):
                                             qtype_values, 'QTYPE'))
 
     def _make_enum_members(self, values):
-        return [QAPISchemaMember(v) for v in values]
+        return [QAPISchemaMember(v['name'], v.get('if')) if isinstance(v, dict)
+                else QAPISchemaMember(v)
+                for v in values]
 
     def _make_implicit_enum_type(self, name, info, values, ifcond):
         # See also QAPISchemaObjectTypeMember._pretty_owner()
@@ -1950,6 +1967,8 @@ static const char *const %(c_name)s_array[] = {
 ''',
                 c_name=c_name(name))
     for value in values:
+        if isinstance(value, tuple):
+            value, ifcond = value
         index = c_enum_const(name, value, prefix)
         ret += mcgen('''
     [%(index)s] = "%(value)s",
@@ -1980,6 +1999,8 @@ typedef enum %(c_name)s {
                 c_name=c_name(name))
 
     for value in enum_values:
+        if isinstance(value, tuple):
+            value, ifcond = value
         ret += mcgen('''
     %(c_enum)s,
 ''',
diff --git a/tests/qapi-schema/enum-dict-member.err b/tests/qapi-schema/enum-dict-member.err
index 8ca146ea59..e69de29bb2 100644
--- a/tests/qapi-schema/enum-dict-member.err
+++ b/tests/qapi-schema/enum-dict-member.err
@@ -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.exit b/tests/qapi-schema/enum-dict-member.exit
index d00491fd7e..573541ac97 100644
--- a/tests/qapi-schema/enum-dict-member.exit
+++ b/tests/qapi-schema/enum-dict-member.exit
@@ -1 +1 @@
-1
+0
diff --git a/tests/qapi-schema/enum-dict-member.json b/tests/qapi-schema/enum-dict-member.json
index 79672e0f09..b09a83061c 100644
--- a/tests/qapi-schema/enum-dict-member.json
+++ b/tests/qapi-schema/enum-dict-member.json
@@ -1,2 +1 @@
-# we reject any enum member that is not a string
-{ 'enum': 'MyEnum', 'data': [ { 'value': 'str' } ] }
+{ 'enum': 'TestEnum', 'data': [ { 'name': 'foo' }, { 'name': 'bar' } ]}
diff --git a/tests/qapi-schema/enum-dict-member.out b/tests/qapi-schema/enum-dict-member.out
index e69de29bb2..cf8e3cce2b 100644
--- a/tests/qapi-schema/enum-dict-member.out
+++ b/tests/qapi-schema/enum-dict-member.out
@@ -0,0 +1,4 @@
+enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+    prefix QTYPE
+enum TestEnum ['foo', 'bar']
+object q_empty
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index dc2c444fc1..ad2b405d83 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 fc5fd25f1b..211c367632 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -60,7 +60,7 @@ alternate TestIfAlternate
 command TestIfCmd q_obj_TestIfCmd-arg -> None
    gen=True success_response=True boxed=False
     if defined(TEST_IF_CMD) && defined(TEST_IF_STRUCT)
-enum TestIfEnum ['foo', 'bar']
+enum TestIfEnum ['foo', ('bar', 'defined(TEST_IF_ENUM_BAR)')]
     if defined(TEST_IF_ENUM)
 event TestIfEvent q_obj_TestIfEvent-arg
    boxed=False
@@ -197,6 +197,7 @@ object q_obj_EVENT_D-arg
     member enum3: EnumOne optional=True
 object q_obj_TestIfCmd-arg
     member foo: TestIfStruct optional=False
+    member bar: TestIfEnum optional=False
     if defined(TEST_IF_CMD) && defined(TEST_IF_STRUCT)
 object q_obj_TestIfEvent-arg
     member foo: TestIfStruct optional=False
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index 17fd975812..70054848f0 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -18,7 +18,9 @@ import sys
 
 class QAPISchemaTestVisitor(QAPISchemaVisitor):
     def visit_enum_type(self, name, info, values, prefix, ifcond):
-        print 'enum %s %s' % (name, values)
+        values = ', '.join(["'%s'" % v[0] if not v[1] else str(v)
+                            for v in values])
+        print 'enum %s [%s]' % (name, values)
         if prefix:
             print '    prefix %s' % prefix
         self._print_if(ifcond)
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 30/54] qapi: add #if conditions on generated enum values
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (28 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 29/54] qapi: add 'if' to enum members Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-09-06 15:38   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 31/54] tests: add some enum members tests Marc-André Lureau
                   ` (25 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

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

diff --git a/scripts/qapi.py b/scripts/qapi.py
index 9c7c01c11d..201e425842 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -1967,13 +1967,16 @@ static const char *const %(c_name)s_array[] = {
 ''',
                 c_name=c_name(name))
     for value in values:
+        ifcond = None
         if isinstance(value, tuple):
             value, ifcond = value
+        ret += gen_if(ifcond)
         index = c_enum_const(name, value, prefix)
         ret += mcgen('''
     [%(index)s] = "%(value)s",
 ''',
                      index=index, value=value)
+        ret += gen_endif(ifcond)
 
     max_index = c_enum_const(name, '_MAX', prefix)
     ret += mcgen('''
@@ -1999,12 +2002,15 @@ typedef enum %(c_name)s {
                 c_name=c_name(name))
 
     for value in enum_values:
+        ifcond = None
         if isinstance(value, tuple):
             value, ifcond = value
+        ret += gen_if(ifcond)
         ret += mcgen('''
     %(c_enum)s,
 ''',
                      c_enum=c_enum_const(name, value, prefix))
+        ret += gen_endif(ifcond)
 
     ret += mcgen('''
 } %(c_name)s;
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 31/54] tests: add some enum members tests
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (29 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 30/54] qapi: add #if conditions on generated enum values Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-09-06 15:41   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 32/54] qapi: add 'if' to struct members Marc-André Lureau
                   ` (24 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 tests/Makefile.include                          | 2 ++
 tests/qapi-schema/enum-dict-member-invalid.err  | 1 +
 tests/qapi-schema/enum-dict-member-invalid.exit | 1 +
 tests/qapi-schema/enum-dict-member-invalid.json | 2 ++
 tests/qapi-schema/enum-dict-member-invalid.out  | 0
 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
 9 files changed, 11 insertions(+)
 create mode 100644 tests/qapi-schema/enum-dict-member-invalid.err
 create mode 100644 tests/qapi-schema/enum-dict-member-invalid.exit
 create mode 100644 tests/qapi-schema/enum-dict-member-invalid.json
 create mode 100644 tests/qapi-schema/enum-dict-member-invalid.out
 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/tests/Makefile.include b/tests/Makefile.include
index 1f1d8f075b..1c5ce6519e 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -436,6 +436,8 @@ 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-invalid.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-invalid.err b/tests/qapi-schema/enum-dict-member-invalid.err
new file mode 100644
index 0000000000..d12cca0df3
--- /dev/null
+++ b/tests/qapi-schema/enum-dict-member-invalid.err
@@ -0,0 +1 @@
+tests/qapi-schema/enum-dict-member-invalid.json:2: Dictionary member of enum 'MyEnum' must have a 'name' key
diff --git a/tests/qapi-schema/enum-dict-member-invalid.exit b/tests/qapi-schema/enum-dict-member-invalid.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/enum-dict-member-invalid.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/enum-dict-member-invalid.json b/tests/qapi-schema/enum-dict-member-invalid.json
new file mode 100644
index 0000000000..9cf8406867
--- /dev/null
+++ b/tests/qapi-schema/enum-dict-member-invalid.json
@@ -0,0 +1,2 @@
+# we reject any enum member that is not a string or a dict with 'name'
+{ 'enum': 'MyEnum', 'data': [ { 'value': 'str' } ] }
diff --git a/tests/qapi-schema/enum-dict-member-invalid.out b/tests/qapi-schema/enum-dict-member-invalid.out
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/qapi-schema/enum-if-invalid.err b/tests/qapi-schema/enum-if-invalid.err
new file mode 100644
index 0000000000..236b703e88
--- /dev/null
+++ b/tests/qapi-schema/enum-if-invalid.err
@@ -0,0 +1 @@
+tests/qapi-schema/enum-if-invalid.json:2: 'if' condition requires a string or a list of string
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
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 32/54] qapi: add 'if' to struct members
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (30 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 31/54] tests: add some enum members tests Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-09-07 14:26   ` Markus Armbruster
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 33/54] qapi: add some struct member tests Marc-André Lureau
                   ` (23 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi.py                         | 18 ++++++++++++++----
 tests/qapi-schema/qapi-schema-test.json |  9 ++++++---
 tests/qapi-schema/qapi-schema-test.out  |  4 +++-
 tests/qapi-schema/test-qapi.py          |  3 ++-
 4 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/scripts/qapi.py b/scripts/qapi.py
index 201e425842..946df83854 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -678,7 +678,13 @@ def check_type(info, source, value, allow_array=False,
         return
 
     if not allow_dict:
-        raise QAPISemError(info, "%s should be a type name" % source)
+        if isinstance(value, dict) and 'type' in value:
+            check_type(info, source, value['type'], allow_array,
+                       allow_dict, allow_optional, allow_metas)
+            check_if(value, info)
+            return
+        else:
+            raise QAPISemError(info, "%s should be a type name" % source)
 
     if not isinstance(value, OrderedDict):
         raise QAPISemError(info,
@@ -1332,8 +1338,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
@@ -1612,13 +1618,17 @@ class QAPISchema(object):
 
     def _make_member(self, name, typ, info):
         optional = False
+        ifcond = None
         if name.startswith('*'):
             name = name[1:]
             optional = True
+        if isinstance(typ, dict):
+            ifcond = typ.get('if')
+            typ = typ['type']
         if isinstance(typ, list):
             assert len(typ) == 1
             typ = self._make_array_type(typ[0], info)
-        return QAPISchemaObjectTypeMember(name, typ, optional)
+        return QAPISchemaObjectTypeMember(name, typ, optional, ifcond)
 
     def _make_members(self, data, info):
         return [self._make_member(key, value, info)
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index ad2b405d83..b136e4855f 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -191,7 +191,8 @@
 
 # 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 +205,10 @@
 { '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 211c367632..5d2f18e4aa 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -67,6 +67,7 @@ event TestIfEvent q_obj_TestIfEvent-arg
     if defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)
 object TestIfStruct
     member foo: int optional=False
+    member bar: int optional=False if=defined(TEST_IF_STRUCT_BAR)
     if defined(TEST_IF_STRUCT)
 object TestIfUnion
     member type: TestIfUnionKind optional=False
@@ -197,10 +198,11 @@ object q_obj_EVENT_D-arg
     member enum3: EnumOne optional=True
 object q_obj_TestIfCmd-arg
     member foo: TestIfStruct optional=False
-    member bar: TestIfEnum optional=False
+    member bar: TestIfEnum optional=False if=defined(TEST_IF_CMD_BAR)
     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)
 object q_obj_TestStruct-wrapper
     member data: TestStruct optional=False
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index 70054848f0..5d2f67a1d3 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -31,7 +31,8 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
             print '    base %s' % base.name
         for m in members:
             print '    member %s: %s optional=%s' % \
-                (m.name, m.type.name, m.optional)
+                (m.name, m.type.name, m.optional) + \
+                (' if=%s' % m.ifcond if m.ifcond else '')
         self._print_variants(variants)
         self._print_if(ifcond)
 
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 33/54] qapi: add some struct member tests
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (31 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 32/54] qapi: add 'if' to struct members Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 34/54] qapi: add #if conditions to generated struct members Marc-André Lureau
                   ` (22 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 tests/Makefile.include                    | 2 ++
 tests/qapi-schema/struct-if-invalid.err   | 1 +
 tests/qapi-schema/struct-if-invalid.exit  | 1 +
 tests/qapi-schema/struct-if-invalid.json  | 3 +++
 tests/qapi-schema/struct-if-invalid.out   | 0
 tests/qapi-schema/struct-member-type.err  | 0
 tests/qapi-schema/struct-member-type.exit | 1 +
 tests/qapi-schema/struct-member-type.json | 1 +
 tests/qapi-schema/struct-member-type.out  | 5 +++++
 9 files changed, 14 insertions(+)
 create mode 100644 tests/qapi-schema/struct-if-invalid.err
 create mode 100644 tests/qapi-schema/struct-if-invalid.exit
 create mode 100644 tests/qapi-schema/struct-if-invalid.json
 create mode 100644 tests/qapi-schema/struct-if-invalid.out
 create mode 100644 tests/qapi-schema/struct-member-type.err
 create mode 100644 tests/qapi-schema/struct-member-type.exit
 create mode 100644 tests/qapi-schema/struct-member-type.json
 create mode 100644 tests/qapi-schema/struct-member-type.out

diff --git a/tests/Makefile.include b/tests/Makefile.include
index 1c5ce6519e..e00cb9833b 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -512,7 +512,9 @@ 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-if-invalid.json
 qapi-schema += struct-member-invalid.json
+qapi-schema += struct-member-type.json
 qapi-schema += trailing-comma-list.json
 qapi-schema += trailing-comma-object.json
 qapi-schema += type-bypass-bad-gen.json
diff --git a/tests/qapi-schema/struct-if-invalid.err b/tests/qapi-schema/struct-if-invalid.err
new file mode 100644
index 0000000000..42245262a9
--- /dev/null
+++ b/tests/qapi-schema/struct-if-invalid.err
@@ -0,0 +1 @@
+tests/qapi-schema/struct-if-invalid.json:2: Member 'bar' of 'data' for struct 'TestIfStruct' should be a type name
diff --git a/tests/qapi-schema/struct-if-invalid.exit b/tests/qapi-schema/struct-if-invalid.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/struct-if-invalid.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/struct-if-invalid.json b/tests/qapi-schema/struct-if-invalid.json
new file mode 100644
index 0000000000..466cdb61e1
--- /dev/null
+++ b/tests/qapi-schema/struct-if-invalid.json
@@ -0,0 +1,3 @@
+# check missing 'type'
+{ 'struct': 'TestIfStruct', 'data':
+  { 'foo': 'int', 'bar': { 'if': 'defined(TEST_IF_STRUCT_BAR)' } } }
diff --git a/tests/qapi-schema/struct-if-invalid.out b/tests/qapi-schema/struct-if-invalid.out
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/qapi-schema/struct-member-type.err b/tests/qapi-schema/struct-member-type.err
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/qapi-schema/struct-member-type.exit b/tests/qapi-schema/struct-member-type.exit
new file mode 100644
index 0000000000..573541ac97
--- /dev/null
+++ b/tests/qapi-schema/struct-member-type.exit
@@ -0,0 +1 @@
+0
diff --git a/tests/qapi-schema/struct-member-type.json b/tests/qapi-schema/struct-member-type.json
new file mode 100644
index 0000000000..07de38fa4a
--- /dev/null
+++ b/tests/qapi-schema/struct-member-type.json
@@ -0,0 +1 @@
+{ 'struct': 'foo', 'data': { 'a': { 'type': 'str' } } }
diff --git a/tests/qapi-schema/struct-member-type.out b/tests/qapi-schema/struct-member-type.out
new file mode 100644
index 0000000000..2ea68909a9
--- /dev/null
+++ b/tests/qapi-schema/struct-member-type.out
@@ -0,0 +1,5 @@
+enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+    prefix QTYPE
+object foo
+    member a: str optional=False
+object q_empty
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 34/54] qapi: add #if conditions to generated struct members
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (32 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 33/54] qapi: add some struct member tests Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 35/54] qapi: add 'if' on union variants Marc-André Lureau
                   ` (21 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

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

diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index 5e736a06df..b379c7c170 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -136,6 +136,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):
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index c1316312ac..b7f4773fe1 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -41,6 +41,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;
@@ -50,6 +51,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
 
 
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index bb18c9edee..25914f71b0 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -53,6 +53,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)) {
@@ -72,6 +73,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('''
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 35/54] qapi: add 'if' on union variants
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (33 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 34/54] qapi: add #if conditions to generated struct members Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 36/54] qapi: add #if conditions to generated variants Marc-André Lureau
                   ` (20 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi.py                         | 14 +++++++++-----
 tests/qapi-schema/qapi-schema-test.json |  6 +++++-
 tests/qapi-schema/qapi-schema-test.out  |  9 ++++++++-
 tests/qapi-schema/test-qapi.py          |  3 ++-
 4 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/scripts/qapi.py b/scripts/qapi.py
index 946df83854..cd5d151809 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -1397,8 +1397,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):
@@ -1647,6 +1647,10 @@ class QAPISchema(object):
         return QAPISchemaObjectTypeVariant(case, typ)
 
     def _make_simple_variant(self, case, typ, info):
+        ifcond = None
+        if isinstance(typ, dict):
+            ifcond = typ.get('if')
+            typ = typ['type']
         if isinstance(typ, list):
             assert len(typ) == 1
             typ = self._make_array_type(typ[0], info)
@@ -1654,7 +1658,7 @@ class QAPISchema(object):
         typ = self._make_implicit_object_type(
             typ, info, None, 'wrapper',
             [self._make_member('data', typ, info)], type_entity.ifcond)
-        return QAPISchemaObjectTypeVariant(case, typ)
+        return QAPISchemaObjectTypeVariant(case, typ, ifcond)
 
     def _def_union_type(self, expr, info, doc):
         name = expr['union']
@@ -1674,8 +1678,8 @@ class QAPISchema(object):
         else:
             variants = [self._make_simple_variant(key, value, info)
                         for (key, value) in data.iteritems()]
-            typ = self._make_implicit_enum_type(name, info,
-                                                [v.name for v in variants],
+            values = [{'name': v.name, 'if': v.ifcond} for v in variants]
+            typ = self._make_implicit_enum_type(name, info, values,
                                                 ifcond)
             tag_member = QAPISchemaObjectTypeMember('type', typ, False)
             members = [tag_member]
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index b136e4855f..23dae79f92 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -199,9 +199,13 @@
   [ '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 5d2f18e4aa..12fc5a4425 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -73,8 +73,12 @@ 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)
-enum TestIfUnionKind ['foo']
+command TestIfUnionCmd q_obj_TestIfUnionCmd-arg -> None
+   gen=True success_response=True boxed=False
+    if defined(TEST_IF_UNION)
+enum TestIfUnionKind ['foo', ('union_bar', 'defined(TEST_IF_UNION_BAR)')]
     if defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)
 object TestStruct
     member integer: int optional=False
@@ -204,6 +208,9 @@ 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)
+object q_obj_TestIfUnionCmd-arg
+    member union_cmd_arg: TestIfUnion optional=False
+    if defined(TEST_IF_UNION)
 object q_obj_TestStruct-wrapper
     member data: TestStruct optional=False
 object q_obj_UserDefFlatUnion2-base
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index 5d2f67a1d3..b360d44df1 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -59,7 +59,8 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
         if variants:
             print '    tag %s' % variants.tag_member.name
             for v in variants.variants:
-                print '    case %s: %s' % (v.name, v.type.name)
+                print '    case %s: %s' % (v.name, v.type.name) + \
+                    (' if=%s' % v.ifcond if v.ifcond else '')
 
     @staticmethod
     def _print_if(ifcond):
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 36/54] qapi: add #if conditions to generated variants
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (34 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 35/54] qapi: add 'if' on union variants Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 37/54] qapi: 'if' to alternate variant Marc-André Lureau
                   ` (19 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi-introspect.py | 3 ++-
 scripts/qapi-types.py      | 2 ++
 scripts/qapi-visit.py      | 4 ++++
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index b379c7c170..5cd2a3fe3f 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -145,7 +145,8 @@ 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}, None)
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index b7f4773fe1..5924276990 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -129,11 +129,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 25914f71b0..a1ff509e53 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -82,6 +82,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);
@@ -92,6 +93,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();
@@ -182,6 +184,7 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
                  c_name=c_name(name))
 
     for var in variants.variants:
+        ret += gen_if(var.ifcond)
         ret += mcgen('''
     case %(case)s:
 ''',
@@ -209,6 +212,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.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 37/54] qapi: 'if' to alternate variant
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (35 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 36/54] qapi: add #if conditions to generated variants Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 38/54] qapi: add tests for invalid alternate Marc-André Lureau
                   ` (18 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

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

diff --git a/scripts/qapi.py b/scripts/qapi.py
index cd5d151809..bcd8d37c12 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -829,6 +829,8 @@ def check_alternate(expr, info):
         check_type(info, "Member '%s' of alternate '%s'" % (key, name),
                    value,
                    allow_metas=['built-in', 'union', 'struct', 'enum'])
+        if isinstance(value, dict):
+            value = value['type']
         qtype = find_alternate_member_qtype(value)
         if not qtype:
             raise QAPISemError(info, "Alternate '%s' member '%s' cannot use "
@@ -1644,7 +1646,11 @@ class QAPISchema(object):
                                               None, ifcond))
 
     def _make_variant(self, case, typ):
-        return QAPISchemaObjectTypeVariant(case, typ)
+        ifcond = None
+        if isinstance(typ, dict):
+            ifcond = typ.get('if')
+            typ = typ['type']
+        return QAPISchemaObjectTypeVariant(case, typ, ifcond)
 
     def _make_simple_variant(self, case, typ, info):
         ifcond = None
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index 23dae79f92..0032e4f026 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -206,9 +206,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)' } },
   'if': 'defined(TEST_IF_CMD) && defined(TEST_IF_STRUCT)' }
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 12fc5a4425..8b8144574b 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -55,8 +55,11 @@ enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
 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)
+command TestIfAlternateCmd q_obj_TestIfAlternateCmd-arg -> None
+   gen=True success_response=True boxed=False
+    if defined(TEST_IF_ALT)
 command TestIfCmd q_obj_TestIfCmd-arg -> None
    gen=True success_response=True boxed=False
     if defined(TEST_IF_CMD) && defined(TEST_IF_STRUCT)
@@ -200,6 +203,9 @@ object q_obj_EVENT_D-arg
     member b: str optional=False
     member c: str optional=True
     member enum3: EnumOne optional=True
+object q_obj_TestIfAlternateCmd-arg
+    member alt_cmd_arg: TestIfAlternate optional=False
+    if defined(TEST_IF_ALT)
 object q_obj_TestIfCmd-arg
     member foo: TestIfStruct optional=False
     member bar: TestIfEnum optional=False if=defined(TEST_IF_CMD_BAR)
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 38/54] qapi: add tests for invalid alternate
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (36 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 37/54] qapi: 'if' to alternate variant Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 39/54] qapi: add #if conditions to generated alternate variants Marc-André Lureau
                   ` (17 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 tests/Makefile.include                        | 1 +
 tests/qapi-schema/alternate-dict-invalid.err  | 1 +
 tests/qapi-schema/alternate-dict-invalid.exit | 1 +
 tests/qapi-schema/alternate-dict-invalid.json | 4 ++++
 tests/qapi-schema/alternate-dict-invalid.out  | 0
 5 files changed, 7 insertions(+)
 create mode 100644 tests/qapi-schema/alternate-dict-invalid.err
 create mode 100644 tests/qapi-schema/alternate-dict-invalid.exit
 create mode 100644 tests/qapi-schema/alternate-dict-invalid.json
 create mode 100644 tests/qapi-schema/alternate-dict-invalid.out

diff --git a/tests/Makefile.include b/tests/Makefile.include
index e00cb9833b..316d81fa95 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -374,6 +374,7 @@ qapi-schema += alternate-conflict-dict.json
 qapi-schema += alternate-conflict-enum-bool.json
 qapi-schema += alternate-conflict-enum-int.json
 qapi-schema += alternate-conflict-string.json
+qapi-schema += alternate-dict-invalid.json
 qapi-schema += alternate-empty.json
 qapi-schema += alternate-nested.json
 qapi-schema += alternate-unknown.json
diff --git a/tests/qapi-schema/alternate-dict-invalid.err b/tests/qapi-schema/alternate-dict-invalid.err
new file mode 100644
index 0000000000..707c40f0f6
--- /dev/null
+++ b/tests/qapi-schema/alternate-dict-invalid.err
@@ -0,0 +1 @@
+tests/qapi-schema/alternate-dict-invalid.json:2: Member 'two' of alternate 'Alt' should be a type name
diff --git a/tests/qapi-schema/alternate-dict-invalid.exit b/tests/qapi-schema/alternate-dict-invalid.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/alternate-dict-invalid.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/alternate-dict-invalid.json b/tests/qapi-schema/alternate-dict-invalid.json
new file mode 100644
index 0000000000..45f2c8ebef
--- /dev/null
+++ b/tests/qapi-schema/alternate-dict-invalid.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-dict-invalid.out b/tests/qapi-schema/alternate-dict-invalid.out
new file mode 100644
index 0000000000..e69de29bb2
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 39/54] qapi: add #if conditions to generated alternate variants
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (37 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 38/54] qapi: add tests for invalid alternate Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 40/54] docs: document schema configuration Marc-André Lureau
                   ` (16 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

Mostly covered by previous patches already.

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

diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index 5cd2a3fe3f..ed00005894 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -168,7 +168,7 @@ const QLitObject %(c_name)s = %(c_string)s;
 
     def visit_alternate_type(self, name, info, variants, ifcond):
         self._gen_qlit(name, 'alternate',
-                       {'members': [{'type': self._use_type(m.type)}
+                       {'members': [({'type': self._use_type(m.type)}, m.ifcond)
                                     for m in variants.variants]}, ifcond)
 
     def visit_command(self, name, info, arg_type, ret_type,
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 40/54] docs: document schema configuration
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (38 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 39/54] qapi: add #if conditions to generated alternate variants Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 41/54] qapi2texi: add 'If:' section to generated documentation Marc-André Lureau
                   ` (15 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau

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

diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
index b653e86bff..94555c01eb 100644
--- a/docs/devel/qapi-code-gen.txt
+++ b/docs/devel/qapi-code-gen.txt
@@ -682,6 +682,53 @@ Example: Red Hat, Inc. controls redhat.com, and may therefore add a
 downstream command __com.redhat_drive-mirror.
 
 
+=== Configuring the schema ===
+
+'struct', 'enum', 'union', 'alternate', 'command' and 'event'
+top-level QAPI expressions can take a 'if' keyword like:
+
+{ 'struct': 'IfStruct', 'data': { 'foo': 'int' },
+  'if': 'defined(IF_STRUCT) && defined(FOO)' }
+
+Members can be exploded as dictionnary with 'type' & 'if' keys:
+
+{ 'struct': 'IfStruct', 'data':
+  { 'foo': 'int',
+    'bar': { 'type': 'int', 'if': 'defined(IF_STRUCT_BAR)'} } }
+
+Enum values can be exploded as dictionnary with 'name' & 'if' keys:
+
+{ 'enum': 'IfEnum', 'data':
+  [ 'foo',
+    { 'name' : 'bar', 'if': 'defined(IF_ENUM_BAR)' } ] }
+
+The C code generators will wrap the corresponding lines with #if / #endif
+pre-processor conditions for a given 'if' value.
+
+Example for enum values:
+
+enum IfEnum {
+     IF_ENUM_FOO,
+#if defined(IF_ENUM_BAR)
+     IF_ENUM_BAR,
+#endif /* defined(IF_ENUM_BAR) */
+     IF_ENUM__MAX
+}
+
+Please note that you are responsbile 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.
+
+Poisoined symbols like TARGET_I386 can be wrapped around a preliminary
+NEED_CPU_H condition, using a list value, like so:
+
+{ ..., 'if': ['defined(NEED_CPU_H)', 'defined(TARGET_I386)'] }
+
+This will generate two consecutive #if lines to silence the C error
+when compiling common code. FIXME: split the schema in various units
+instead.
+
+
 == Client JSON Protocol introspection ==
 
 Clients of a Client JSON Protocol commonly need to figure out what
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 41/54] qapi2texi: add 'If:' section to generated documentation
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (39 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 40/54] docs: document schema configuration Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 42/54] qapi2texi: add 'If:' condition to enum values Marc-André Lureau
                   ` (14 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

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/qapi2texi.py | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/scripts/qapi2texi.py b/scripts/qapi2texi.py
index ae7920aa87..3a923ce438 100755
--- a/scripts/qapi2texi.py
+++ b/scripts/qapi2texi.py
@@ -132,7 +132,6 @@ def texi_enum_value(value):
     """Format a table of members item for an enumeration value"""
     return '@item @code{%s}\n' % value.name
 
-
 def texi_member(member, suffix=''):
     """Format a table of members item for an object type member"""
     typ = member.type.doc_type()
@@ -175,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:
@@ -189,14 +188,16 @@ def texi_sections(doc):
             body += '\n\n@b{%s:}\n' % name
 
         body += func(doc)
+    if ifcond:
+        body += '\n\n@b{If:} @code{%s}' % 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.QAPISchemaVisitor):
@@ -213,7 +214,7 @@ class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor):
             self.out += '\n'
         self.out += TYPE_FMT(type='Enum',
                              name=doc.symbol,
-                             body=texi_entity(doc, 'Values',
+                             body=texi_entity(doc, 'Values', ifcond,
                                               member_func=texi_enum_value))
 
     def visit_object_type(self, name, info, base, members, variants, ifcond):
@@ -224,7 +225,8 @@ class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor):
             self.out += '\n'
         self.out += TYPE_FMT(type='Object',
                              name=doc.symbol,
-                             body=texi_entity(doc, 'Members', base, variants))
+                             body=texi_entity(doc, 'Members', ifcond,
+                                              base, variants))
 
     def visit_alternate_type(self, name, info, variants, ifcond):
         doc = self.cur_doc
@@ -232,7 +234,7 @@ class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor):
             self.out += '\n'
         self.out += TYPE_FMT(type='Alternate',
                              name=doc.symbol,
-                             body=texi_entity(doc, 'Members'))
+                             body=texi_entity(doc, 'Members', ifcond))
 
     def visit_command(self, name, info, arg_type, ret_type,
                       gen, success_response, boxed, ifcond):
@@ -242,9 +244,9 @@ class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor):
         if boxed:
             body = texi_body(doc)
             body += '\n@b{Arguments:} the members of @code{%s}' % 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.out += MSG_FMT(type='Command',
                             name=doc.symbol,
                             body=body)
@@ -255,7 +257,7 @@ class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor):
             self.out += '\n'
         self.out += MSG_FMT(type='Event',
                             name=doc.symbol,
-                            body=texi_entity(doc, 'Arguments'))
+                            body=texi_entity(doc, 'Arguments', ifcond))
 
     def symbol(self, doc, entity):
         self.cur_doc = doc
@@ -266,7 +268,7 @@ class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor):
         assert not doc.args
         if self.out:
             self.out += '\n'
-        self.out += texi_body(doc) + texi_sections(doc)
+        self.out += texi_body(doc) + texi_sections(doc, None)
 
 
 def texi_schema(schema):
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 42/54] qapi2texi: add 'If:' condition to enum values
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (40 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 41/54] qapi2texi: add 'If:' section to generated documentation Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 43/54] qapi2texi: add 'If:' condition to struct members Marc-André Lureau
                   ` (13 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

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

diff --git a/scripts/qapi2texi.py b/scripts/qapi2texi.py
index 3a923ce438..8959cb0cdf 100755
--- a/scripts/qapi2texi.py
+++ b/scripts/qapi2texi.py
@@ -130,7 +130,9 @@ 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' % value.ifcond if value.ifcond else '')
 
 def texi_member(member, suffix=''):
     """Format a table of members item for an object type member"""
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 43/54] qapi2texi: add 'If:' condition to struct members
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (41 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 42/54] qapi2texi: add 'If:' condition to enum values Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 44/54] qapi2texi: add condition to variants Marc-André Lureau
                   ` (12 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

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

diff --git a/scripts/qapi2texi.py b/scripts/qapi2texi.py
index 8959cb0cdf..2c3e1d1a1c 100755
--- a/scripts/qapi2texi.py
+++ b/scripts/qapi2texi.py
@@ -138,9 +138,10 @@ def texi_member(member, suffix=''):
     """Format a table of members item for an object type member"""
     typ = member.type.doc_type()
     membertype = ': %s' % 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' % member.ifcond if member.ifcond else '',
         suffix)
 
 
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 44/54] qapi2texi: add condition to variants
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (42 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 43/54] qapi2texi: add 'If:' condition to struct members Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 45/54] qapi: add conditions to VNC type/commands/events on the schema Marc-André Lureau
                   ` (11 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster, Michael Roth

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

diff --git a/scripts/qapi2texi.py b/scripts/qapi2texi.py
index 2c3e1d1a1c..49a54d41db 100755
--- a/scripts/qapi2texi.py
+++ b/scripts/qapi2texi.py
@@ -163,8 +163,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,
+                ' (and @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:
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 45/54] qapi: add conditions to VNC type/commands/events on the schema
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (43 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 44/54] qapi2texi: add condition to variants Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 46/54] qapi: add conditions to SPICE " Marc-André Lureau
                   ` (10 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Daniel P. Berrange,
	Dr. David Alan Gilbert, Eric Blake, Markus Armbruster

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

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

Enum made conditional:

* QCryptoCipherAlgorithm

    # @des-rfb: RFB specific variant of single DES. Do not use except in VNC.

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>
---
 qapi-schema.json        | 34 ++++++++++++++++++++++------------
 qapi/crypto.json        |  3 ++-
 qapi/event.json         |  9 ++++++---
 crypto/cipher-builtin.c |  9 +++++++++
 crypto/cipher-gcrypt.c  | 10 ++++++++--
 crypto/cipher-nettle.c  | 14 +++++++++++---
 crypto/cipher.c         | 13 +++++++++++--
 hmp.c                   |  9 ++++++++-
 qmp.c                   | 30 ++++--------------------------
 hmp-commands-info.hx    |  2 ++
 10 files changed, 83 insertions(+), 50 deletions(-)

diff --git a/qapi-schema.json b/qapi-schema.json
index 802ea53d00..4ffbe1d9ff 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1660,7 +1660,8 @@
   'data': { 'host': 'str',
             'service': 'str',
             'family': 'NetworkAddressFamily',
-            'websocket': 'bool' } }
+            'websocket': 'bool' },
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @VncServerInfo:
@@ -1674,7 +1675,8 @@
 ##
 { 'struct': 'VncServerInfo',
   'base': 'VncBasicInfo',
-  'data': { '*auth': 'str' } }
+  'data': { '*auth': 'str' },
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @VncClientInfo:
@@ -1691,7 +1693,8 @@
 ##
 { 'struct': 'VncClientInfo',
   'base': 'VncBasicInfo',
-  'data': { '*x509_dname': 'str', '*sasl_username': 'str' } }
+  'data': { '*x509_dname': 'str', '*sasl_username': 'str' },
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @VncInfo:
@@ -1732,7 +1735,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:
@@ -1743,7 +1747,8 @@
 ##
 { 'enum': 'VncPrimaryAuth',
   'data': [ 'none', 'vnc', 'ra2', 'ra2ne', 'tight', 'ultra',
-            'tls', 'vencrypt', 'sasl' ] }
+            'tls', 'vencrypt', 'sasl' ],
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @VncVencryptSubAuth:
@@ -1757,7 +1762,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)' }
 
 
 ##
@@ -1775,7 +1781,8 @@
 { 'struct': 'VncServerInfo2',
   'base': 'VncBasicInfo',
   'data': { 'auth'      : 'VncPrimaryAuth',
-            '*vencrypt' : 'VncVencryptSubAuth' } }
+            '*vencrypt' : 'VncVencryptSubAuth' },
+  'if': 'defined(CONFIG_VNC)' }
 
 
 ##
@@ -1808,7 +1815,8 @@
             'clients'   : ['VncClientInfo'],
             'auth'      : 'VncPrimaryAuth',
             '*vencrypt' : 'VncVencryptSubAuth',
-            '*display'  : 'str' } }
+            '*display'  : 'str' },
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @query-vnc:
@@ -1839,7 +1847,8 @@
 #    }
 #
 ##
-{ 'command': 'query-vnc', 'returns': 'VncInfo' }
+{ 'command': 'query-vnc', 'returns': 'VncInfo',
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @query-vnc-servers:
@@ -1850,7 +1859,8 @@
 #
 # Since: 2.3
 ##
-{ 'command': 'query-vnc-servers', 'returns': ['VncInfo2'] }
+{ 'command': 'query-vnc-servers', 'returns': ['VncInfo2'],
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @SpiceBasicInfo:
@@ -3077,8 +3087,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)' }
 ##
 # @change:
 #
diff --git a/qapi/crypto.json b/qapi/crypto.json
index 6b6fde367a..b9bfff202c 100644
--- a/qapi/crypto.json
+++ b/qapi/crypto.json
@@ -79,7 +79,8 @@
 { 'enum': 'QCryptoCipherAlgorithm',
   'prefix': 'QCRYPTO_CIPHER_ALG',
   'data': ['aes-128', 'aes-192', 'aes-256',
-           'des-rfb', '3des',
+           { 'name': 'des-rfb', 'if': 'defined(CONFIG_VNC)' },
+           '3des',
            'cast5-128',
            'serpent-128', 'serpent-192', 'serpent-256',
            'twofish-128', 'twofish-192', 'twofish-256']}
diff --git a/qapi/event.json b/qapi/event.json
index 6d22b025cc..c8b8e9f384 100644
--- a/qapi/event.json
+++ b/qapi/event.json
@@ -263,7 +263,8 @@
 ##
 { 'event': 'VNC_CONNECTED',
   'data': { 'server': 'VncServerInfo',
-            'client': 'VncBasicInfo' } }
+            'client': 'VncBasicInfo' },
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @VNC_INITIALIZED:
@@ -290,7 +291,8 @@
 ##
 { 'event': 'VNC_INITIALIZED',
   'data': { 'server': 'VncServerInfo',
-            'client': 'VncClientInfo' } }
+            'client': 'VncClientInfo' },
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @VNC_DISCONNECTED:
@@ -316,7 +318,8 @@
 ##
 { 'event': 'VNC_DISCONNECTED',
   'data': { 'server': 'VncServerInfo',
-            'client': 'VncClientInfo' } }
+            'client': 'VncClientInfo' },
+  'if': 'defined(CONFIG_VNC)' }
 
 ##
 # @SPICE_CONNECTED:
diff --git a/crypto/cipher-builtin.c b/crypto/cipher-builtin.c
index e956cc5a53..647bcf3247 100644
--- a/crypto/cipher-builtin.c
+++ b/crypto/cipher-builtin.c
@@ -35,17 +35,22 @@ struct QCryptoCipherBuiltinAES {
     QCryptoCipherBuiltinAESContext key_tweak;
     uint8_t iv[AES_BLOCK_SIZE];
 };
+
+#ifdef CONFIG_VNC
 typedef struct QCryptoCipherBuiltinDESRFB QCryptoCipherBuiltinDESRFB;
 struct QCryptoCipherBuiltinDESRFB {
     uint8_t *key;
     size_t nkey;
 };
+#endif
 
 typedef struct QCryptoCipherBuiltin QCryptoCipherBuiltin;
 struct QCryptoCipherBuiltin {
     union {
         QCryptoCipherBuiltinAES aes;
+#ifdef CONFIG_VNC
         QCryptoCipherBuiltinDESRFB desrfb;
+#endif
     } state;
     size_t blocksize;
     void (*free)(QCryptoCipher *cipher);
@@ -403,7 +408,9 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
                              QCryptoCipherMode mode)
 {
     switch (alg) {
+#ifdef CONFIG_VNC
     case QCRYPTO_CIPHER_ALG_DES_RFB:
+#endif
     case QCRYPTO_CIPHER_ALG_AES_128:
     case QCRYPTO_CIPHER_ALG_AES_192:
     case QCRYPTO_CIPHER_ALG_AES_256:
@@ -449,9 +456,11 @@ static QCryptoCipherBuiltin *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
     }
 
     switch (alg) {
+#ifdef CONFIG_VNC
     case QCRYPTO_CIPHER_ALG_DES_RFB:
         ctxt = qcrypto_cipher_init_des_rfb(mode, key, nkey, errp);
         break;
+#endif
     case QCRYPTO_CIPHER_ALG_AES_128:
     case QCRYPTO_CIPHER_ALG_AES_192:
     case QCRYPTO_CIPHER_ALG_AES_256:
diff --git a/crypto/cipher-gcrypt.c b/crypto/cipher-gcrypt.c
index 3e46ee7502..18c01ca424 100644
--- a/crypto/cipher-gcrypt.c
+++ b/crypto/cipher-gcrypt.c
@@ -29,7 +29,9 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
                              QCryptoCipherMode mode)
 {
     switch (alg) {
+#ifdef CONFIG_VNC
     case QCRYPTO_CIPHER_ALG_DES_RFB:
+#endif
     case QCRYPTO_CIPHER_ALG_3DES:
     case QCRYPTO_CIPHER_ALG_AES_128:
     case QCRYPTO_CIPHER_ALG_AES_192:
@@ -114,10 +116,11 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
     }
 
     switch (alg) {
+#ifdef CONFIG_VNC
     case QCRYPTO_CIPHER_ALG_DES_RFB:
         gcryalg = GCRY_CIPHER_DES;
         break;
-
+#endif
     case QCRYPTO_CIPHER_ALG_3DES:
         gcryalg = GCRY_CIPHER_3DES;
         break;
@@ -181,6 +184,7 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
         }
     }
 
+#ifdef CONFIG_VNC
     if (alg == QCRYPTO_CIPHER_ALG_DES_RFB) {
         /* We're using standard DES cipher from gcrypt, so we need
          * to munge the key so that the results are the same as the
@@ -190,7 +194,9 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
         err = gcry_cipher_setkey(ctx->handle, rfbkey, nkey);
         g_free(rfbkey);
         ctx->blocksize = 8;
-    } else {
+    } else
+#endif /* CONFIG_VNC */
+    {
         if (mode == QCRYPTO_CIPHER_MODE_XTS) {
             nkey /= 2;
             err = gcry_cipher_setkey(ctx->handle, key, nkey);
diff --git a/crypto/cipher-nettle.c b/crypto/cipher-nettle.c
index 5e70c7984a..7b14f23f7e 100644
--- a/crypto/cipher-nettle.c
+++ b/crypto/cipher-nettle.c
@@ -67,6 +67,7 @@ static void aes_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
     aes_decrypt(&aesctx->dec, length, dst, src);
 }
 
+#ifdef CONFIG_VNC
 static void des_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
                                uint8_t *dst, const uint8_t *src)
 {
@@ -78,6 +79,7 @@ static void des_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
 {
     des_decrypt(ctx, length, dst, src);
 }
+#endif
 
 static void des3_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
                                 uint8_t *dst, const uint8_t *src)
@@ -141,6 +143,7 @@ static void aes_decrypt_wrapper(const void *ctx, size_t length,
     aes_decrypt(&aesctx->dec, length, dst, src);
 }
 
+#ifdef CONFIG_VNC
 static void des_encrypt_wrapper(const void *ctx, size_t length,
                                 uint8_t *dst, const uint8_t *src)
 {
@@ -152,6 +155,7 @@ static void des_decrypt_wrapper(const void *ctx, size_t length,
 {
     des_decrypt(ctx, length, dst, src);
 }
+#endif
 
 static void des3_encrypt_wrapper(const void *ctx, size_t length,
                                 uint8_t *dst, const uint8_t *src)
@@ -221,7 +225,9 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
                              QCryptoCipherMode mode)
 {
     switch (alg) {
+#ifdef CONFIG_VNC
     case QCRYPTO_CIPHER_ALG_DES_RFB:
+#endif
     case QCRYPTO_CIPHER_ALG_3DES:
     case QCRYPTO_CIPHER_ALG_AES_128:
     case QCRYPTO_CIPHER_ALG_AES_192:
@@ -271,7 +277,6 @@ static QCryptoCipherNettle *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
                                                    Error **errp)
 {
     QCryptoCipherNettle *ctx;
-    uint8_t *rfbkey;
 
     switch (mode) {
     case QCRYPTO_CIPHER_MODE_ECB:
@@ -292,7 +297,9 @@ static QCryptoCipherNettle *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
     ctx = g_new0(QCryptoCipherNettle, 1);
 
     switch (alg) {
-    case QCRYPTO_CIPHER_ALG_DES_RFB:
+#ifdef CONFIG_VNC
+    case QCRYPTO_CIPHER_ALG_DES_RFB: {
+        uint8_t *rfbkey;
         ctx->ctx = g_new0(struct des_ctx, 1);
         rfbkey = qcrypto_cipher_munge_des_rfb_key(key, nkey);
         des_set_key(ctx->ctx, rfbkey);
@@ -305,7 +312,8 @@ static QCryptoCipherNettle *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
 
         ctx->blocksize = DES_BLOCK_SIZE;
         break;
-
+    }
+#endif
     case QCRYPTO_CIPHER_ALG_3DES:
         ctx->ctx = g_new0(struct des3_ctx, 1);
         des3_set_key(ctx->ctx, key);
diff --git a/crypto/cipher.c b/crypto/cipher.c
index 43291cba7e..3e39882b7c 100644
--- a/crypto/cipher.c
+++ b/crypto/cipher.c
@@ -29,7 +29,9 @@ static size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = {
     [QCRYPTO_CIPHER_ALG_AES_128] = 16,
     [QCRYPTO_CIPHER_ALG_AES_192] = 24,
     [QCRYPTO_CIPHER_ALG_AES_256] = 32,
+#ifdef CONFIG_VNC
     [QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
+#endif
     [QCRYPTO_CIPHER_ALG_3DES] = 24,
     [QCRYPTO_CIPHER_ALG_CAST5_128] = 16,
     [QCRYPTO_CIPHER_ALG_SERPENT_128] = 16,
@@ -44,7 +46,9 @@ static size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = {
     [QCRYPTO_CIPHER_ALG_AES_128] = 16,
     [QCRYPTO_CIPHER_ALG_AES_192] = 16,
     [QCRYPTO_CIPHER_ALG_AES_256] = 16,
+#ifdef CONFIG_VNC
     [QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
+#endif
     [QCRYPTO_CIPHER_ALG_3DES] = 8,
     [QCRYPTO_CIPHER_ALG_CAST5_128] = 8,
     [QCRYPTO_CIPHER_ALG_SERPENT_128] = 16,
@@ -107,8 +111,11 @@ qcrypto_cipher_validate_key_length(QCryptoCipherAlgorithm alg,
     }
 
     if (mode == QCRYPTO_CIPHER_MODE_XTS) {
-        if (alg == QCRYPTO_CIPHER_ALG_DES_RFB
-                || alg == QCRYPTO_CIPHER_ALG_3DES) {
+        if (
+#ifdef CONFIG_VNC
+            alg == QCRYPTO_CIPHER_ALG_DES_RFB ||
+#endif
+            alg == QCRYPTO_CIPHER_ALG_3DES) {
             error_setg(errp, "XTS mode not compatible with DES-RFB/3DES");
             return false;
         }
@@ -132,6 +139,7 @@ qcrypto_cipher_validate_key_length(QCryptoCipherAlgorithm alg,
     return true;
 }
 
+#if defined(CONFIG_VNC)
 #if defined(CONFIG_GCRYPT) || defined(CONFIG_NETTLE)
 static uint8_t *
 qcrypto_cipher_munge_des_rfb_key(const uint8_t *key,
@@ -149,6 +157,7 @@ qcrypto_cipher_munge_des_rfb_key(const uint8_t *key,
     return ret;
 }
 #endif /* CONFIG_GCRYPT || CONFIG_NETTLE */
+#endif /* CONFIG_VNC */
 
 #ifdef CONFIG_GCRYPT
 #include "crypto/cipher-gcrypt.c"
diff --git a/hmp.c b/hmp.c
index 0eb318f938..bb0a695f2d 100644
--- a/hmp.c
+++ b/hmp.c
@@ -620,6 +620,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)
@@ -708,6 +709,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)
@@ -1718,12 +1720,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)
 {
@@ -1734,6 +1738,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,
@@ -1748,7 +1753,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,
                 read_only, BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN, &err);
diff --git a/qmp.c b/qmp.c
index b86201e349..2c90dacb56 100644
--- a/qmp.c
+++ b/qmp.c
@@ -130,22 +130,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-commands.hx ensures that QMP command query-spice exists only
@@ -403,23 +387,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 d9df238a5f..2fb7a556a3 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -419,6 +419,7 @@ STEXI
 Show which guest mouse is receiving events.
 ETEXI
 
+#if defined(CONFIG_VNC)
     {
         .name       = "vnc",
         .args_type  = "",
@@ -426,6 +427,7 @@ ETEXI
         .help       = "show the vnc server status",
         .cmd        = hmp_info_vnc,
     },
+#endif
 
 STEXI
 @item info vnc
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 46/54] qapi: add conditions to SPICE type/commands/events on the schema
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (44 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 45/54] qapi: add conditions to VNC type/commands/events on the schema Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 47/54] qapi: add conditions to REPLICATION type/commands " Marc-André Lureau
                   ` (9 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Markus Armbruster,
	Dr. David Alan Gilbert, Eric Blake

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

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 qapi-schema.json | 28 ++++++++++++++++++----------
 qapi/event.json  | 12 ++++++++----
 monitor.c        |  3 ---
 qmp.c            | 16 ----------------
 4 files changed, 26 insertions(+), 33 deletions(-)

diff --git a/qapi-schema.json b/qapi-schema.json
index 4ffbe1d9ff..08e96bd93f 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1878,7 +1878,8 @@
 { 'struct': 'SpiceBasicInfo',
   'data': { 'host': 'str',
             'port': 'str',
-            'family': 'NetworkAddressFamily' } }
+            'family': 'NetworkAddressFamily' },
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @SpiceServerInfo:
@@ -1891,7 +1892,8 @@
 ##
 { 'struct': 'SpiceServerInfo',
   'base': 'SpiceBasicInfo',
-  'data': { '*auth': 'str' } }
+  'data': { '*auth': 'str' },
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @SpiceChannel:
@@ -1916,7 +1918,8 @@
 { 'struct': 'SpiceChannel',
   'base': 'SpiceBasicInfo',
   'data': {'connection-id': 'int', 'channel-type': 'int', 'channel-id': 'int',
-           'tls': 'bool'} }
+           'tls': 'bool'},
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @SpiceQueryMouseMode:
@@ -1935,7 +1938,8 @@
 # Since: 1.1
 ##
 { 'enum': 'SpiceQueryMouseMode',
-  'data': [ 'client', 'server', 'unknown' ] }
+  'data': [ 'client', 'server', 'unknown' ],
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @SpiceInfo:
@@ -1972,7 +1976,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:
@@ -2017,7 +2022,8 @@
 #    }
 #
 ##
-{ 'command': 'query-spice', 'returns': 'SpiceInfo' }
+{ 'command': 'query-spice', 'returns': 'SpiceInfo',
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @BalloonInfo:
@@ -5091,7 +5097,8 @@
 # Since: 1.5
 ##
 { 'struct': 'ChardevSpiceChannel', 'data': { 'type'  : 'str' },
-  'base': 'ChardevCommon' }
+  'base': 'ChardevCommon',
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @ChardevSpicePort:
@@ -5103,7 +5110,8 @@
 # Since: 1.5
 ##
 { 'struct': 'ChardevSpicePort', 'data': { 'fqdn'  : 'str' },
-  'base': 'ChardevCommon' }
+  'base': 'ChardevCommon',
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @ChardevVC:
@@ -5157,8 +5165,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/event.json b/qapi/event.json
index c8b8e9f384..ff59551914 100644
--- a/qapi/event.json
+++ b/qapi/event.json
@@ -344,7 +344,8 @@
 ##
 { 'event': 'SPICE_CONNECTED',
   'data': { 'server': 'SpiceBasicInfo',
-            'client': 'SpiceBasicInfo' } }
+            'client': 'SpiceBasicInfo' },
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @SPICE_INITIALIZED:
@@ -372,7 +373,8 @@
 ##
 { 'event': 'SPICE_INITIALIZED',
   'data': { 'server': 'SpiceServerInfo',
-            'client': 'SpiceChannel' } }
+            'client': 'SpiceChannel' },
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @SPICE_DISCONNECTED:
@@ -397,7 +399,8 @@
 ##
 { 'event': 'SPICE_DISCONNECTED',
   'data': { 'server': 'SpiceBasicInfo',
-            'client': 'SpiceBasicInfo' } }
+            'client': 'SpiceBasicInfo' },
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @SPICE_MIGRATE_COMPLETED:
@@ -412,7 +415,8 @@
 #      "event": "SPICE_MIGRATE_COMPLETED" }
 #
 ##
-{ 'event': 'SPICE_MIGRATE_COMPLETED' }
+{ 'event': 'SPICE_MIGRATE_COMPLETED',
+  'if': 'defined(CONFIG_SPICE)' }
 
 ##
 # @MIGRATION:
diff --git a/monitor.c b/monitor.c
index 228f246fcc..e5a179d32e 100644
--- a/monitor.c
+++ b/monitor.c
@@ -971,9 +971,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 2c90dacb56..90816ba283 100644
--- a/qmp.c
+++ b/qmp.c
@@ -130,22 +130,6 @@ void qmp_cpu_add(int64_t id, Error **errp)
     }
 }
 
-#ifndef CONFIG_SPICE
-/*
- * qmp-commands.hx 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.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 47/54] qapi: add conditions to REPLICATION type/commands on the schema
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (45 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 46/54] qapi: add conditions to SPICE " Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 48/54] tests/qmp-test: add query-qmp-schema test Marc-André Lureau
                   ` (8 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, zhanghailiang, Juan Quintela,
	Dr. David Alan Gilbert, Markus Armbruster, Eric Blake

Add #if defined(CONFIG_REPLICATION) in generated code, and adjust the
code accordingly.

Made conditional:

* xen-set-replication, query-xen-replication-status,
  xen-colo-do-checkpoint

  Before the patch, we first register the commands unconditionally in
  generated code (requires a stub), then conditionally unregister in
  qmp_unregister_commands_hack().

  Afterwards, we register only when CONFIG_REPLICATION.  The command
  fails exactly the same, with CommandNotFound.

  Improvement, because now query-qmp-schema is accurate, and we're one
  step close to killing qmp_unregister_commands_hack().

* enum BlockdevDriver value "replication" in command blockdev-add

As well as enum BlockdevDriver value @replication BlockdevOptions
variant @replication, BlockdevOptionsReplication,
BlockdevOptionsReplicationMode.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 qapi-schema.json     | 12 ++++++++----
 qapi/block-core.json | 13 +++++++++----
 migration/colo.c     | 14 ++------------
 monitor.c            |  5 -----
 4 files changed, 19 insertions(+), 25 deletions(-)

diff --git a/qapi-schema.json b/qapi-schema.json
index 08e96bd93f..1091a80fd3 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -6361,7 +6361,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:
@@ -6376,7 +6377,8 @@
 # Since: 2.9
 ##
 { 'struct': 'ReplicationStatus',
-  'data': { 'error': 'bool', '*desc': 'str' } }
+  'data': { 'error': 'bool', '*desc': 'str' },
+  'if': 'defined(CONFIG_REPLICATION)' }
 
 ##
 # @query-xen-replication-status:
@@ -6393,7 +6395,8 @@
 # Since: 2.9
 ##
 { 'command': 'query-xen-replication-status',
-  'returns': 'ReplicationStatus' }
+  'returns': 'ReplicationStatus',
+  'if': 'defined(CONFIG_REPLICATION)' }
 
 ##
 # @xen-colo-do-checkpoint:
@@ -6409,7 +6412,8 @@
 #
 # Since: 2.9
 ##
-{ 'command': 'xen-colo-do-checkpoint' }
+{ 'command': 'xen-colo-do-checkpoint',
+  'if': 'defined(CONFIG_REPLICATION)' }
 
 ##
 # @GICCapability:
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 833c602150..f9a0834190 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -2182,7 +2182,9 @@
             'dmg', 'file', 'ftp', 'ftps', 'gluster', 'host_cdrom',
             'host_device', 'http', 'https', 'iscsi', 'luks', 'nbd', 'nfs',
             'null-aio', 'null-co', 'parallels', 'qcow', 'qcow2', 'qed',
-            'quorum', 'raw', 'rbd', 'replication', 'sheepdog', 'ssh',
+            'quorum', 'raw', 'rbd',
+            { 'name': 'replication', 'if': 'defined(CONFIG_REPLICATION)' },
+            'sheepdog', 'ssh',
             'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
 
 ##
@@ -2805,7 +2807,8 @@
 #
 # Since: 2.9
 ##
-{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }
+{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ],
+  'if': 'defined(CONFIG_REPLICATION)' }
 
 ##
 # @BlockdevOptionsReplication:
@@ -2823,7 +2826,8 @@
 { 'struct': 'BlockdevOptionsReplication',
   'base': 'BlockdevOptionsGenericFormat',
   'data': { 'mode': 'ReplicationMode',
-            '*top-id': 'str' } }
+            '*top-id': 'str' },
+  'if': 'defined(CONFIG_REPLICATION)' }
 
 ##
 # @NFSTransport:
@@ -3104,7 +3108,8 @@
       'quorum':     'BlockdevOptionsQuorum',
       'raw':        'BlockdevOptionsRaw',
       'rbd':        'BlockdevOptionsRbd',
-      'replication':'BlockdevOptionsReplication',
+      'replication': { 'type': 'BlockdevOptionsReplication',
+                       'if': 'defined(CONFIG_REPLICATION)' },
       'sheepdog':   'BlockdevOptionsSheepdog',
       'ssh':        'BlockdevOptionsSsh',
       'vdi':        'BlockdevOptionsGenericFormat',
diff --git a/migration/colo.c b/migration/colo.c
index 8bd7ef0531..1f352a6d86 100644
--- a/migration/colo.c
+++ b/migration/colo.c
@@ -150,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;
@@ -173,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);
 
@@ -195,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 e5a179d32e..008d7c2b06 100644
--- a/monitor.c
+++ b/monitor.c
@@ -971,11 +971,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");
 #endif
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 48/54] tests/qmp-test: add query-qmp-schema test
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (46 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 47/54] qapi: add conditions to REPLICATION type/commands " Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 49/54] build-sys: make qemu qapi objects per-target Marc-André Lureau
                   ` (7 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Markus Armbruster

The following patch is going to make qmp introspection per-target, and
test-qobject-input-visitor.c can no longer link with
qmp_schema_qlit. Use a run-time QMP test instead to validate the
query-qmp-schema schema.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 tests/qmp-test.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/tests/qmp-test.c b/tests/qmp-test.c
index 5d0260b2be..1fd37092b5 100644
--- a/tests/qmp-test.c
+++ b/tests/qmp-test.c
@@ -129,11 +129,32 @@ static void test_qmp_protocol(void)
     qtest_end();
 }
 
+static void test_qmp_query_schema(void)
+{
+    SchemaInfoList *schema;
+    QDict *resp;
+    Visitor *v;
+
+    qtest_start(common_args);
+
+    resp = qmp("{'execute': 'query-qmp-schema'}");
+    v = qobject_input_visitor_new(qdict_get(resp, "return"));
+    visit_type_SchemaInfoList(v, NULL, &schema, &error_abort);
+    g_assert(schema);
+
+    qapi_free_SchemaInfoList(schema);
+    visit_free(v);
+    QDECREF(resp);
+
+    qtest_end();
+}
+
 int main(int argc, char *argv[])
 {
     g_test_init(&argc, &argv, NULL);
 
     qtest_add_func("qmp/protocol", test_qmp_protocol);
+    qtest_add_func("qmp/query-schema", test_qmp_query_schema);
 
     return g_test_run();
 }
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 49/54] build-sys: make qemu qapi objects per-target
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (47 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 48/54] tests/qmp-test: add query-qmp-schema test Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 50/54] qapi: make rtc-reset-reinjection depend on TARGET_I386 Marc-André Lureau
                   ` (6 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Paolo Bonzini, Markus Armbruster,
	Michael Roth, Stefan Hajnoczi

QAPI can't do target-specific conditionals (the symbols are poisoned),
and the work-around is to pretend the target-specific stuff is
target-independent, with stubs for the other targets.  Makes the
target-specifity invisible in introspection.

To unpoison the symbols, we need to move the generated QAPI code to
the per-target build.

Keep qapi-types.o qapi-visit.o in util-obj as they are necessary for
common code, but they will be overwritten during the target link. Add
some stubs for block events, in code shared by tools & qemu.

The following patches will configure the schema to conditionally
remove per-target disabled features.

Drop "do_test_visitor_in_qmp_introspect(&&qmp_schema_qlit)" since it
is no longer in a common object, and covered by "query-qmp-schema
test" instead.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 stubs/qapi-event.c                 | 74 ++++++++++++++++++++++++++++++++++++++
 tests/test-qobject-input-visitor.c |  1 -
 Makefile.objs                      |  9 +----
 Makefile.target                    |  4 +++
 stubs/Makefile.objs                |  1 +
 trace/Makefile.objs                |  2 +-
 6 files changed, 81 insertions(+), 10 deletions(-)
 create mode 100644 stubs/qapi-event.c

diff --git a/stubs/qapi-event.c b/stubs/qapi-event.c
new file mode 100644
index 0000000000..9415299f3a
--- /dev/null
+++ b/stubs/qapi-event.c
@@ -0,0 +1,74 @@
+#include "qemu/osdep.h"
+#include "qapi-event.h"
+
+void qapi_event_send_device_tray_moved(const char *device, const char *id,
+                                       bool tray_open, Error **errp)
+{
+}
+
+void qapi_event_send_quorum_report_bad(QuorumOpType type, bool has_error,
+                                       const char *error, const char *node_name,
+                                       int64_t sector_num,
+                                       int64_t sectors_count, Error **errp)
+{
+}
+
+void qapi_event_send_quorum_failure(const char *reference, int64_t sector_num,
+                                    int64_t sectors_count, Error **errp)
+{
+}
+
+void qapi_event_send_block_job_cancelled(BlockJobType type, const char *device,
+                                         int64_t len, int64_t offset,
+                                         int64_t speed, Error **errp)
+{
+}
+
+void qapi_event_send_block_job_completed(BlockJobType type, const char *device,
+                                         int64_t len, int64_t offset,
+                                         int64_t speed, bool has_error,
+                                         const char *error, Error **errp)
+{
+}
+
+void qapi_event_send_block_job_error(const char *device,
+                                     IoOperationType operation,
+                                     BlockErrorAction action, Error **errp)
+{
+}
+
+void qapi_event_send_block_job_ready(BlockJobType type, const char *device,
+                                     int64_t len, int64_t offset, int64_t speed,
+                                     Error **errp)
+{
+}
+
+void qapi_event_send_block_io_error(const char *device, const char *node_name,
+                                    IoOperationType operation,
+                                    BlockErrorAction action, bool has_nospace,
+                                    bool nospace, const char *reason,
+                                    Error **errp)
+{
+}
+
+void qapi_event_send_block_image_corrupted(const char *device,
+                                           bool has_node_name,
+                                           const char *node_name,
+                                           const char *msg, bool has_offset,
+                                           int64_t offset, bool has_size,
+                                           int64_t size, bool fatal,
+                                           Error **errp)
+{
+}
+
+void qapi_event_send_block_write_threshold(const char *node_name,
+                                           uint64_t amount_exceeded,
+                                           uint64_t write_threshold,
+                                           Error **errp)
+{
+}
+
+void qapi_event_send_device_deleted(bool has_device, const char *device,
+                                    const char *path, Error **errp)
+{
+}
diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
index be7d7ea654..bb35a4d15f 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -1267,7 +1267,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 24a4ea08b8..2664720f9b 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -2,7 +2,7 @@
 # Common libraries for tools and emulators
 stub-obj-y = stubs/ crypto/
 util-obj-y = util/ qobject/ qapi/
-util-obj-y += qmp-introspect.o qapi-types.o qapi-visit.o qapi-event.o
+util-obj-y += qapi-types.o qapi-visit.o
 
 chardev-obj-y = chardev/
 
@@ -72,13 +72,6 @@ common-obj-y += chardev/
 common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o
 
 common-obj-$(CONFIG_FDT) += device_tree.o
-
-######################################################################
-# qapi
-
-common-obj-y += qmp-marshal.o
-common-obj-y += qmp-introspect.o
-common-obj-y += qmp.o hmp.o
 endif
 
 #######################################################################
diff --git a/Makefile.target b/Makefile.target
index 7f42c45db8..c5f8ded4fa 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -157,6 +157,10 @@ endif
 
 GENERATED_FILES += hmp-commands.h hmp-commands-info.h
 
+obj-y += qmp-introspect.o qapi-types.o qapi-visit.o qapi-event.o
+obj-y += qmp-marshal.o qmp-introspect.o
+obj-y += qmp.o hmp.o
+
 endif # CONFIG_SOFTMMU
 
 # Workaround for http://gcc.gnu.org/PR55489, see configure.
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index e69c217aff..717b342c80 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -22,6 +22,7 @@ stub-obj-y += migr-blocker.o
 stub-obj-y += change-state-handler.o
 stub-obj-y += monitor.o
 stub-obj-y += notify-event.o
+stub-obj-y += qapi-event.o
 stub-obj-y += qtest.o
 stub-obj-y += replay.o
 stub-obj-y += runstate-check.o
diff --git a/trace/Makefile.objs b/trace/Makefile.objs
index afd571c3ec..6447729d60 100644
--- a/trace/Makefile.objs
+++ b/trace/Makefile.objs
@@ -56,4 +56,4 @@ util-obj-$(CONFIG_TRACE_SIMPLE) += simple.o
 util-obj-$(CONFIG_TRACE_FTRACE) += ftrace.o
 util-obj-y += control.o
 target-obj-y += control-target.o
-util-obj-y += qmp.o
+target-obj-y += qmp.o
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 50/54] qapi: make rtc-reset-reinjection depend on TARGET_I386
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (48 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 49/54] build-sys: make qemu qapi objects per-target Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 51/54] qapi: make s390 commands depend on TARGET_S390X Marc-André Lureau
                   ` (5 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Dr. David Alan Gilbert,
	Markus Armbruster, Eric Blake

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 qapi-schema.json |  3 ++-
 monitor.c        | 10 ----------
 2 files changed, 2 insertions(+), 11 deletions(-)

diff --git a/qapi-schema.json b/qapi-schema.json
index 1091a80fd3..58574b3044 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -6294,7 +6294,8 @@
 # <- { "return": {} }
 #
 ##
-{ 'command': 'rtc-reset-reinjection' }
+{ 'command': 'rtc-reset-reinjection',
+  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_I386)'] }
 
 # Rocker ethernet network switch
 { 'include': 'qapi/rocker.json' }
diff --git a/monitor.c b/monitor.c
index 008d7c2b06..fcacf10f59 100644
--- a/monitor.c
+++ b/monitor.c
@@ -971,9 +971,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");
-#endif
 #ifndef TARGET_S390X
     qmp_unregister_command(&qmp_commands, "dump-skeys");
 #endif
@@ -4156,13 +4153,6 @@ QemuOptsList qemu_mon_opts = {
     },
 };
 
-#ifndef TARGET_I386
-void qmp_rtc_reset_reinjection(Error **errp)
-{
-    error_setg(errp, QERR_FEATURE_DISABLED, "rtc-reset-reinjection");
-}
-#endif
-
 #ifndef TARGET_S390X
 void qmp_dump_skeys(const char *filename, Error **errp)
 {
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 51/54] qapi: make s390 commands depend on TARGET_S390X
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (49 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 50/54] qapi: make rtc-reset-reinjection depend on TARGET_I386 Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 14:24   ` Cornelia Huck
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 52/54] qapi: make query-gic-capabilities depend on TARGET_ARM Marc-André Lureau
                   ` (4 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Markus Armbruster,
	Dr. David Alan Gilbert, Eric Blake, Paolo Bonzini,
	Richard Henderson, Alexander Graf

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 qapi-schema.json                        | 10 +++++++---
 include/sysemu/arch_init.h              |  6 ------
 monitor.c                               | 14 --------------
 qmp.c                                   | 14 --------------
 stubs/arch-query-cpu-model-baseline.c   | 12 ------------
 stubs/arch-query-cpu-model-comparison.c | 12 ------------
 target/s390x/cpu_models.c               |  4 ++--
 stubs/Makefile.objs                     |  2 --
 8 files changed, 9 insertions(+), 65 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-schema.json b/qapi-schema.json
index 58574b3044..d4e1552ddc 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3577,7 +3577,8 @@
 #
 ##
 { 'command': 'dump-skeys',
-  'data': { 'filename': 'str' } }
+  'data': { 'filename': 'str' },
+  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
 
 ##
 # @netdev_add:
@@ -4621,7 +4622,9 @@
 ##
 { 'command': 'query-cpu-model-comparison',
   'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
-  'returns': 'CpuModelCompareInfo' }
+  'returns': 'CpuModelCompareInfo',
+  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
+
 
 ##
 # @CpuModelBaselineInfo:
@@ -4673,7 +4676,8 @@
 { 'command': 'query-cpu-model-baseline',
   'data': { 'modela': 'CpuModelInfo',
             'modelb': 'CpuModelInfo' },
-  'returns': 'CpuModelBaselineInfo' }
+  'returns': 'CpuModelBaselineInfo',
+  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
 
 ##
 # @AddfdInfo:
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index 8751c468ed..e9f1ea0cca 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -35,11 +35,5 @@ 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/monitor.c b/monitor.c
index fcacf10f59..c9f04652b4 100644
--- a/monitor.c
+++ b/monitor.c
@@ -971,19 +971,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");
@@ -4153,13 +4146,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 90816ba283..7b6861846f 100644
--- a/qmp.c
+++ b/qmp.c
@@ -553,20 +553,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 094ec13c2c..0000000000
--- a/stubs/arch-query-cpu-model-baseline.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "sysemu/arch_init.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 d5486ae980..0000000000
--- a/stubs/arch-query-cpu-model-comparison.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "sysemu/arch_init.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 fa1338fc72..cdff9cdd3b 100644
--- a/target/s390x/cpu_models.c
+++ b/target/s390x/cpu_models.c
@@ -559,7 +559,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)
 {
@@ -632,7 +632,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 717b342c80..1421824eb3 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.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 52/54] qapi: make query-gic-capabilities depend on TARGET_ARM
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (50 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 51/54] qapi: make s390 commands depend on TARGET_S390X Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 53/54] qapi: make query-cpu-model-expansion depend on s390 or x86 Marc-André Lureau
                   ` (3 subsequent siblings)
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Markus Armbruster,
	Dr. David Alan Gilbert, Eric Blake

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 qapi-schema.json |  3 ++-
 monitor.c        | 11 -----------
 2 files changed, 2 insertions(+), 12 deletions(-)

diff --git a/qapi-schema.json b/qapi-schema.json
index d4e1552ddc..6c1adb35b5 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -6461,7 +6461,8 @@
 #                 { "version": 3, "emulated": false, "kernel": true } ] }
 #
 ##
-{ 'command': 'query-gic-capabilities', 'returns': ['GICCapability'] }
+{ 'command': 'query-gic-capabilities', 'returns': ['GICCapability'],
+  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_ARM)']}
 
 ##
 # @CpuInstanceProperties:
diff --git a/monitor.c b/monitor.c
index c9f04652b4..6ddc3c7ff7 100644
--- a/monitor.c
+++ b/monitor.c
@@ -971,9 +971,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
@@ -4146,14 +4143,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());
-- 
2.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 53/54] qapi: make query-cpu-model-expansion depend on s390 or x86
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (51 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 52/54] qapi: make query-gic-capabilities depend on TARGET_ARM Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 18:42   ` Eduardo Habkost
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 54/54] qapi: make query-cpu-definitions depend on specific targets Marc-André Lureau
                   ` (2 subsequent siblings)
  55 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Dr. David Alan Gilbert,
	Markus Armbruster, Eric Blake, Paolo Bonzini, Richard Henderson,
	Eduardo Habkost, Alexander Graf

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 qapi-schema.json                       |  4 +++-
 include/sysemu/arch_init.h             |  3 ---
 monitor.c                              |  3 ---
 qmp.c                                  |  7 -------
 stubs/arch-query-cpu-model-expansion.c | 12 ------------
 target/i386/cpu.c                      |  2 +-
 target/s390x/cpu_models.c              |  3 ++-
 stubs/Makefile.objs                    |  1 -
 8 files changed, 6 insertions(+), 29 deletions(-)
 delete mode 100644 stubs/arch-query-cpu-model-expansion.c

diff --git a/qapi-schema.json b/qapi-schema.json
index 6c1adb35b5..127a2c71c6 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -4535,7 +4535,9 @@
 { 'command': 'query-cpu-model-expansion',
   'data': { 'type': 'CpuModelExpansionType',
             'model': 'CpuModelInfo' },
-  'returns': 'CpuModelExpansionInfo' }
+  'returns': 'CpuModelExpansionInfo',
+  'if': ['defined(NEED_CPU_H)',
+         'defined(TARGET_S390X) || defined(TARGET_I386)']}
 
 ##
 # @CpuModelCompareResult:
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index e9f1ea0cca..fb3d20a1b8 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -32,8 +32,5 @@ 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 6ddc3c7ff7..ca67a584d2 100644
--- a/monitor.c
+++ b/monitor.c
@@ -971,9 +971,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 7b6861846f..afa266ec1e 100644
--- a/qmp.c
+++ b/qmp.c
@@ -546,13 +546,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 ae7cf554d1..0000000000
--- a/stubs/arch-query-cpu-model-expansion.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "sysemu/arch_init.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 ddc45abd70..d683e70a13 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -2574,7 +2574,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 cdff9cdd3b..863dce064f 100644
--- a/target/s390x/cpu_models.c
+++ b/target/s390x/cpu_models.c
@@ -22,6 +22,7 @@
 #ifndef CONFIG_USER_ONLY
 #include "sysemu/arch_init.h"
 #endif
+#include "qmp-commands.h"
 
 #define CPUDEF_INIT(_type, _gen, _ec_ga, _mha_pow, _hmfai, _name, _desc) \
     {                                                                    \
@@ -520,7 +521,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 1421824eb3..eb17628ede 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.14.1.146.gd35faa819

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

* [Qemu-devel] [PATCH v2 54/54] qapi: make query-cpu-definitions depend on specific targets
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (52 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 53/54] qapi: make query-cpu-model-expansion depend on s390 or x86 Marc-André Lureau
@ 2017-08-22 13:22 ` Marc-André Lureau
  2017-08-22 14:47 ` [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code no-reply
  2017-08-23 12:46 ` Markus Armbruster
  55 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 13:22 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Dr. David Alan Gilbert,
	Markus Armbruster, Eric Blake, Paolo Bonzini, Peter Maydell,
	Richard Henderson, Eduardo Habkost, David Gibson, Alexander Graf,
	open list:ARM, open list:PowerPC

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

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 qapi-schema.json            |  4 +++-
 include/sysemu/arch_init.h  |  2 --
 monitor.c                   | 22 ----------------------
 qmp.c                       |  5 -----
 stubs/arch-query-cpu-def.c  | 10 ----------
 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 -
 10 files changed, 10 insertions(+), 45 deletions(-)
 delete mode 100644 stubs/arch-query-cpu-def.c

diff --git a/qapi-schema.json b/qapi-schema.json
index 127a2c71c6..194859f683 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -4433,7 +4433,9 @@
 #
 # Since: 1.2.0
 ##
-{ 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'] }
+{ 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'],
+  'if': ['defined(NEED_CPU_H)',
+         'defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_I386) || defined(TARGET_S390X)'] }
 
 ##
 # @CpuModelInfo:
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index fb3d20a1b8..e9721b9ce8 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -31,6 +31,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 ca67a584d2..ac400e65ee 100644
--- a/monitor.c
+++ b/monitor.c
@@ -957,26 +957,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
-}
-
 void monitor_init_qmp_commands(void)
 {
     /*
@@ -996,8 +976,6 @@ 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 afa266ec1e..d57ccf1251 100644
--- a/qmp.c
+++ b/qmp.c
@@ -541,11 +541,6 @@ DevicePropertyInfoList *qmp_device_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 cefe4beb82..0000000000
--- a/stubs/arch-query-cpu-def.c
+++ /dev/null
@@ -1,10 +0,0 @@
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "sysemu/arch_init.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 fa60040361..54543a0b01 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -15,6 +15,7 @@
 #include <zlib.h> /* For crc32 */
 #include "exec/semihost.h"
 #include "sysemu/kvm.h"
+#include "qmp-commands.h"
 
 #define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */
 
@@ -5332,7 +5333,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 d683e70a13..e5f61f6bff 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -36,6 +36,7 @@
 #include "qapi/visitor.h"
 #include "qom/qom-qobject.h"
 #include "sysemu/arch_init.h"
+#include "qmp-commands.h"
 
 #if defined(CONFIG_KVM)
 #include <linux/kvm_para.h>
@@ -2318,7 +2319,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 8fb407ed73..5845a15296 100644
--- a/target/ppc/translate_init.c
+++ b/target/ppc/translate_init.c
@@ -34,6 +34,7 @@
 #include "hw/ppc/ppc.h"
 #include "mmu-book3s-v3.h"
 #include "sysemu/qtest.h"
+#include "qmp-commands.h"
 
 //#define PPC_DUMP_CPU
 //#define PPC_DEBUG_SPR
@@ -10401,7 +10402,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 863dce064f..8021dda341 100644
--- a/target/s390x/cpu_models.c
+++ b/target/s390x/cpu_models.c
@@ -387,7 +387,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 eb17628ede..67bf15261d 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.14.1.146.gd35faa819

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

* Re: [Qemu-devel] [PATCH v2 11/54] quorum: use qapi_enum_parse() in quorum_open
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 11/54] quorum: use qapi_enum_parse() in quorum_open Marc-André Lureau
@ 2017-08-22 13:40   ` Alberto Garcia
  2017-08-23 11:15     ` Markus Armbruster
  2017-08-23 11:24   ` Markus Armbruster
  1 sibling, 1 reply; 140+ messages in thread
From: Alberto Garcia @ 2017-08-22 13:40 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel
  Cc: Kevin Wolf, Max Reitz, open list:Quorum

On Tue 22 Aug 2017 03:22:12 PM CEST, Marc-André Lureau wrote:

> @@ -925,7 +908,13 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
>          goto exit;
>      }
>  
> -    ret = parse_read_pattern(qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN));
> +    if (!qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN)) {
> +        ret = QUORUM_READ_PATTERN_QUORUM;
> +    } else {
> +        ret = qapi_enum_parse(QuorumReadPattern_lookup,
> +                              qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN),
> +                              QUORUM_READ_PATTERN__MAX, -EINVAL, NULL);
> +    }

I don't like so much that you call qemu_opt_get() twice with the same
parameters, but else the change makes sense.

Berto

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

* Re: [Qemu-devel] [PATCH v2 14/54] qapi2texi: minor python code simplification
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 14/54] qapi2texi: minor python code simplification Marc-André Lureau
@ 2017-08-22 13:56   ` Philippe Mathieu-Daudé
  2017-09-01 15:49   ` Markus Armbruster
  1 sibling, 0 replies; 140+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-08-22 13:56 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel; +Cc: Markus Armbruster, Michael Roth

On 08/22/2017 10:22 AM, Marc-André Lureau wrote:
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> ---
>   scripts/qapi2texi.py | 7 +++----
>   1 file changed, 3 insertions(+), 4 deletions(-)
> 
> diff --git a/scripts/qapi2texi.py b/scripts/qapi2texi.py
> index a317526e51..8b542f9fff 100755
> --- a/scripts/qapi2texi.py
> +++ b/scripts/qapi2texi.py
> @@ -136,10 +136,9 @@ def texi_enum_value(value):
>   def texi_member(member, suffix=''):
>       """Format a table of members item for an object type member"""
>       typ = member.type.doc_type()
> -    return '@item @code{%s%s%s}%s%s\n' % (
> -        member.name,
> -        ': ' if typ else '',
> -        typ if typ else '',
> +    membertype = ': %s' % typ if typ else ''
> +    return '@item @code{%s%s}%s%s\n' % (
> +        member.name, membertype,
>           ' (optional)' if member.optional else '',
>           suffix)
>   
> 

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

* Re: [Qemu-devel] [PATCH v2 28/54] qapi: do not define enumeration value explicitely
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 28/54] qapi: do not define enumeration value explicitely Marc-André Lureau
@ 2017-08-22 14:00   ` Philippe Mathieu-Daudé
  2017-09-05 17:45   ` Markus Armbruster
  1 sibling, 0 replies; 140+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-08-22 14:00 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel; +Cc: Markus Armbruster, Michael Roth

On 08/22/2017 10:22 AM, Marc-André Lureau wrote:
> 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>

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> ---
>   scripts/qapi.py | 7 ++-----
>   1 file changed, 2 insertions(+), 5 deletions(-)
> 
> diff --git a/scripts/qapi.py b/scripts/qapi.py
> index 52099332f1..9d075440d3 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi.py
> @@ -1979,14 +1979,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;
> 

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

* Re: [Qemu-devel] [PATCH v2 51/54] qapi: make s390 commands depend on TARGET_S390X
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 51/54] qapi: make s390 commands depend on TARGET_S390X Marc-André Lureau
@ 2017-08-22 14:24   ` Cornelia Huck
  2017-08-22 14:25     ` David Hildenbrand
  0 siblings, 1 reply; 140+ messages in thread
From: Cornelia Huck @ 2017-08-22 14:24 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: qemu-devel, Alexander Graf, Markus Armbruster,
	Dr. David Alan Gilbert, Paolo Bonzini, Richard Henderson,
	David Hildenbrand

On Tue, 22 Aug 2017 15:22:52 +0200
Marc-André Lureau <marcandre.lureau@redhat.com> wrote:

> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  qapi-schema.json                        | 10 +++++++---
>  include/sysemu/arch_init.h              |  6 ------
>  monitor.c                               | 14 --------------
>  qmp.c                                   | 14 --------------
>  stubs/arch-query-cpu-model-baseline.c   | 12 ------------
>  stubs/arch-query-cpu-model-comparison.c | 12 ------------
>  target/s390x/cpu_models.c               |  4 ++--
>  stubs/Makefile.objs                     |  2 --
>  8 files changed, 9 insertions(+), 65 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-schema.json b/qapi-schema.json
> index 58574b3044..d4e1552ddc 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -3577,7 +3577,8 @@
>  #
>  ##
>  { 'command': 'dump-skeys',
> -  'data': { 'filename': 'str' } }
> +  'data': { 'filename': 'str' },
> +  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}

I agree with making this s390x specific...
>  
>  ##
>  # @netdev_add:
> @@ -4621,7 +4622,9 @@
>  ##
>  { 'command': 'query-cpu-model-comparison',
>    'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
> -  'returns': 'CpuModelCompareInfo' }
> +  'returns': 'CpuModelCompareInfo',
> +  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
> +
>  
>  ##
>  # @CpuModelBaselineInfo:
> @@ -4673,7 +4676,8 @@
>  { 'command': 'query-cpu-model-baseline',
>    'data': { 'modela': 'CpuModelInfo',
>              'modelb': 'CpuModelInfo' },
> -  'returns': 'CpuModelBaselineInfo' }
> +  'returns': 'CpuModelBaselineInfo',
> +  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}

...but I'm not sure about the cpu model stuff. Wasn't the idea to move
to this model for all architectures later? (Given that we have stubs
for architectures not implementing this, instead of ifdeffing it in
monitor.c)

>  
>  ##
>  # @AddfdInfo:
> diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
> index 8751c468ed..e9f1ea0cca 100644
> --- a/include/sysemu/arch_init.h
> +++ b/include/sysemu/arch_init.h
> @@ -35,11 +35,5 @@ 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/monitor.c b/monitor.c
> index fcacf10f59..c9f04652b4 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -971,19 +971,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");
> @@ -4153,13 +4146,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 90816ba283..7b6861846f 100644
> --- a/qmp.c
> +++ b/qmp.c
> @@ -553,20 +553,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 094ec13c2c..0000000000
> --- a/stubs/arch-query-cpu-model-baseline.c
> +++ /dev/null
> @@ -1,12 +0,0 @@
> -#include "qemu/osdep.h"
> -#include "qemu-common.h"
> -#include "sysemu/arch_init.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 d5486ae980..0000000000
> --- a/stubs/arch-query-cpu-model-comparison.c
> +++ /dev/null
> @@ -1,12 +0,0 @@
> -#include "qemu/osdep.h"
> -#include "qemu-common.h"
> -#include "sysemu/arch_init.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 fa1338fc72..cdff9cdd3b 100644
> --- a/target/s390x/cpu_models.c
> +++ b/target/s390x/cpu_models.c
> @@ -559,7 +559,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)
>  {
> @@ -632,7 +632,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 717b342c80..1421824eb3 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

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

* Re: [Qemu-devel] [PATCH v2 51/54] qapi: make s390 commands depend on TARGET_S390X
  2017-08-22 14:24   ` Cornelia Huck
@ 2017-08-22 14:25     ` David Hildenbrand
  2017-08-22 14:41       ` Marc-André Lureau
  2017-08-22 15:58       ` Markus Armbruster
  0 siblings, 2 replies; 140+ messages in thread
From: David Hildenbrand @ 2017-08-22 14:25 UTC (permalink / raw)
  To: Cornelia Huck, Marc-André Lureau
  Cc: qemu-devel, Alexander Graf, Markus Armbruster,
	Dr. David Alan Gilbert, Paolo Bonzini, Richard Henderson

On 22.08.2017 16:24, Cornelia Huck wrote:
> On Tue, 22 Aug 2017 15:22:52 +0200
> Marc-André Lureau <marcandre.lureau@redhat.com> wrote:
> 
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> ---
>>  qapi-schema.json                        | 10 +++++++---
>>  include/sysemu/arch_init.h              |  6 ------
>>  monitor.c                               | 14 --------------
>>  qmp.c                                   | 14 --------------
>>  stubs/arch-query-cpu-model-baseline.c   | 12 ------------
>>  stubs/arch-query-cpu-model-comparison.c | 12 ------------
>>  target/s390x/cpu_models.c               |  4 ++--
>>  stubs/Makefile.objs                     |  2 --
>>  8 files changed, 9 insertions(+), 65 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-schema.json b/qapi-schema.json
>> index 58574b3044..d4e1552ddc 100644
>> --- a/qapi-schema.json
>> +++ b/qapi-schema.json
>> @@ -3577,7 +3577,8 @@
>>  #
>>  ##
>>  { 'command': 'dump-skeys',
>> -  'data': { 'filename': 'str' } }
>> +  'data': { 'filename': 'str' },
>> +  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
> 
> I agree with making this s390x specific...
>>  
>>  ##
>>  # @netdev_add:
>> @@ -4621,7 +4622,9 @@
>>  ##
>>  { 'command': 'query-cpu-model-comparison',
>>    'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
>> -  'returns': 'CpuModelCompareInfo' }
>> +  'returns': 'CpuModelCompareInfo',
>> +  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
>> +
>>  
>>  ##
>>  # @CpuModelBaselineInfo:
>> @@ -4673,7 +4676,8 @@
>>  { 'command': 'query-cpu-model-baseline',
>>    'data': { 'modela': 'CpuModelInfo',
>>              'modelb': 'CpuModelInfo' },
>> -  'returns': 'CpuModelBaselineInfo' }
>> +  'returns': 'CpuModelBaselineInfo',
>> +  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
> 
> ...but I'm not sure about the cpu model stuff. Wasn't the idea to move
> to this model for all architectures later? (Given that we have stubs
> for architectures not implementing this, instead of ifdeffing it in
> monitor.c)
> 

+1, not architecture specific (in contrast to skey), simply not
supported _yet_ on other architectures.


-- 

Thanks,

David

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

* Re: [Qemu-devel] [PATCH v2 51/54] qapi: make s390 commands depend on TARGET_S390X
  2017-08-22 14:25     ` David Hildenbrand
@ 2017-08-22 14:41       ` Marc-André Lureau
  2017-08-22 15:14         ` Cornelia Huck
  2017-08-22 15:58       ` Markus Armbruster
  1 sibling, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 14:41 UTC (permalink / raw)
  To: David Hildenbrand
  Cc: Cornelia Huck, qemu-devel, Alexander Graf, Markus Armbruster,
	Dr. David Alan Gilbert, Paolo Bonzini, Richard Henderson

Hi

----- Original Message -----
> On 22.08.2017 16:24, Cornelia Huck wrote:
> > On Tue, 22 Aug 2017 15:22:52 +0200
> > Marc-André Lureau <marcandre.lureau@redhat.com> wrote:
> > 
> >> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> >> ---
> >>  qapi-schema.json                        | 10 +++++++---
> >>  include/sysemu/arch_init.h              |  6 ------
> >>  monitor.c                               | 14 --------------
> >>  qmp.c                                   | 14 --------------
> >>  stubs/arch-query-cpu-model-baseline.c   | 12 ------------
> >>  stubs/arch-query-cpu-model-comparison.c | 12 ------------
> >>  target/s390x/cpu_models.c               |  4 ++--
> >>  stubs/Makefile.objs                     |  2 --
> >>  8 files changed, 9 insertions(+), 65 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-schema.json b/qapi-schema.json
> >> index 58574b3044..d4e1552ddc 100644
> >> --- a/qapi-schema.json
> >> +++ b/qapi-schema.json
> >> @@ -3577,7 +3577,8 @@
> >>  #
> >>  ##
> >>  { 'command': 'dump-skeys',
> >> -  'data': { 'filename': 'str' } }
> >> +  'data': { 'filename': 'str' },
> >> +  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
> > 
> > I agree with making this s390x specific...
> >>  
> >>  ##
> >>  # @netdev_add:
> >> @@ -4621,7 +4622,9 @@
> >>  ##
> >>  { 'command': 'query-cpu-model-comparison',
> >>    'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
> >> -  'returns': 'CpuModelCompareInfo' }
> >> +  'returns': 'CpuModelCompareInfo',
> >> +  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
> >> +
> >>  
> >>  ##
> >>  # @CpuModelBaselineInfo:
> >> @@ -4673,7 +4676,8 @@
> >>  { 'command': 'query-cpu-model-baseline',
> >>    'data': { 'modela': 'CpuModelInfo',
> >>              'modelb': 'CpuModelInfo' },
> >> -  'returns': 'CpuModelBaselineInfo' }
> >> +  'returns': 'CpuModelBaselineInfo',
> >> +  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
> > 
> > ...but I'm not sure about the cpu model stuff. Wasn't the idea to move
> > to this model for all architectures later? (Given that we have stubs
> > for architectures not implementing this, instead of ifdeffing it in
> > monitor.c)
> > 
> 
> +1, not architecture specific (in contrast to skey), simply not
> supported _yet_ on other architectures.

We can add other archs once they implement it. See for example:
"qapi: make query-cpu-model-expansion depend on s390 or x86"

Thanks

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

* Re: [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (53 preceding siblings ...)
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 54/54] qapi: make query-cpu-definitions depend on specific targets Marc-André Lureau
@ 2017-08-22 14:47 ` no-reply
  2017-08-23 12:46 ` Markus Armbruster
  55 siblings, 0 replies; 140+ messages in thread
From: no-reply @ 2017-08-22 14:47 UTC (permalink / raw)
  To: marcandre.lureau; +Cc: famz, qemu-devel

Hi,

This series failed automatic 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: 20170822132255.23945-1-marcandre.lureau@redhat.com
Subject: [Qemu-devel] [PATCH v2 00/54] 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
time make docker-test-build@min-glib
time make docker-test-mingw@fedora
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 t [tag update]            patchew/20170822044155.2451-1-famz@redhat.com -> patchew/20170822044155.2451-1-famz@redhat.com
 t [tag update]            patchew/20170822131832.20191-1-pbonzini@redhat.com -> patchew/20170822131832.20191-1-pbonzini@redhat.com
 * [new tag]               patchew/20170822132255.23945-1-marcandre.lureau@redhat.com -> patchew/20170822132255.23945-1-marcandre.lureau@redhat.com
Switched to a new branch 'test'
627ef8fb30 qapi: make query-cpu-definitions depend on specific targets
9705bcfe69 qapi: make query-cpu-model-expansion depend on s390 or x86
0a775880dc qapi: make query-gic-capabilities depend on TARGET_ARM
09f8e14b9c qapi: make s390 commands depend on TARGET_S390X
173457a4cd qapi: make rtc-reset-reinjection depend on TARGET_I386
03259ff7c4 build-sys: make qemu qapi objects per-target
7f6bd1987b tests/qmp-test: add query-qmp-schema test
6fa41c7019 qapi: add conditions to REPLICATION type/commands on the schema
d020289f5a qapi: add conditions to SPICE type/commands/events on the schema
118f523d11 qapi: add conditions to VNC type/commands/events on the schema
85020b1c8a qapi2texi: add condition to variants
f57b57862e qapi2texi: add 'If:' condition to struct members
ba7362ca41 qapi2texi: add 'If:' condition to enum values
7d8a910601 qapi2texi: add 'If:' section to generated documentation
5199112182 docs: document schema configuration
c9aade4b64 qapi: add #if conditions to generated alternate variants
0140d5d1d9 qapi: add tests for invalid alternate
2dcf4937be qapi: 'if' to alternate variant
659a9c6203 qapi: add #if conditions to generated variants
92904b193b qapi: add 'if' on union variants
9f637cc68e qapi: add #if conditions to generated struct members
2b4dc7d3ba qapi: add some struct member tests
e891dc5b79 qapi: add 'if' to struct members
1a7945c720 tests: add some enum members tests
7650def8bf qapi: add #if conditions on generated enum values
9212dbe09b qapi: add 'if' to enum members
de96d784c4 qapi: do not define enumeration value explicitely
3cfb1eeed5 qapi-types: add #if conditions to types
32ca81ef7b qapi-types: refactor variants handling
485c15eb75 qapi-visit: add #if conditions to visitors
b7235d5a5c qapi-event: add #if conditions to events
ab7bf3056f qapi-commands: add #if conditions to commands
b737b01150 qapi-introspect: add preprocessor conditions to generated QLit
1eb1801bc3 qapi-introspect: modify to_qlit() to generate #if code
899e418ec8 qapi-introspect: modify to_qlit() to take an optional suffix
8a2f4230f6 qapi: add #if/#endif helpers
014659c86d qapi: add 'ifcond' to visitor methods
8b0df12378 qapi: add 'if' condition on entity objects
5b08af5119 qapi: add a test for invalid 'if'
a4edc81322 qapi: add 'if' to top-level expressions
73c1054006 qapi2texi: minor python code simplification
6c2e553fbf qapi: drop the sentinel in enum array
8a7c11363e qapi: change enum lookup structure
fcd64e4a60 quorum: use qapi_enum_parse() in quorum_open
46a06700c9 block: use qemu_enum_parse() in blkdebug_debug_breakpoint
948de5e4a3 hmp: use qapi_enum_parse() in hmp_migrate_set_parameter
d99d4020ff hmp: use qapi_enum_parse() in hmp_migrate_set_capability
00fc59f527 tpm: simplify driver registration & lookup
62a6dbbbf0 qapi: introduce qapi_enum_lookup()
c466dcdfe1 qapi: generate a literal qobject for introspection
c84ab4f77a qlit: add qobject_form_qlit()
f910ebcff2 qobject: add literal qobject type
30ba273ecb qdict: add qdict_put_null() helper
ce5e899d47 qapi: fix type_seen key error

=== OUTPUT BEGIN ===
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into '/var/tmp/patchew-tester-tmp-h8optu9x/src/dtc'...
Submodule path 'dtc': checked out '558cd81bdd432769b59bff01240c44f82cfb1a9d'
  BUILD   centos6
make[1]: Entering directory '/var/tmp/patchew-tester-tmp-h8optu9x/src'
  ARCHIVE qemu.tgz
  ARCHIVE dtc.tgz
  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
git-1.7.1-8.el6.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.3-15.el6.x86_64
zlib-devel-1.2.3-29.el6.x86_64

Environment variables:
PACKAGES=bison     bzip2-devel     ccache     csnappy-devel     flex     g++     gcc     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=c9e34928e9a8
TERM=xterm
MAKEFLAGS= -j8
HISTSIZE=1000
J=8
USER=root
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.tbz=01;31:*.tbz2=01;31:*.bz=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
CCACHE_DIR=/var/tmp/ccache
EXTRA_CONFIGURE_OPTS=
V=
SHOW_ENV=1
MAIL=/var/spool/mail/root
PATH=/usr/lib/ccache:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
LANG=en_US.UTF-8
TARGET_LIST=
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
TEST_DIR=/tmp/qemu-test
LOGNAME=root
LESSOPEN=||/usr/bin/lesspipe.sh %s
FEATURES= dtc
DEBUG=
G_BROKEN_FILENAMES=1
CCACHE_HASHDIR=
_=/usr/bin/env

Configure options:
--enable-werror --target-list=x86_64-softmmu,aarch64-softmmu --prefix=/var/tmp/qemu-build/install
No C++ compiler available; disabling C++ specific optional code
Install prefix    /var/tmp/qemu-build/install
BIOS directory    /var/tmp/qemu-build/install/share/qemu
binary directory  /var/tmp/qemu-build/install/bin
library directory /var/tmp/qemu-build/install/lib
module directory  /var/tmp/qemu-build/install/lib/qemu
libexec directory /var/tmp/qemu-build/install/libexec
include directory /var/tmp/qemu-build/install/include
config directory  /var/tmp/qemu-build/install/etc
local state directory   /var/tmp/qemu-build/install/var
Manual directory  /var/tmp/qemu-build/install/share/man
ELF interp prefix /usr/gnemul/qemu-%M
Source path       /tmp/qemu-test/src
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   -DNCURSES_WIDECHAR   -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  -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   -I/usr/include/cacard -I/usr/include/nss3 -I/usr/include/nspr4  
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
pixman            system
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
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
TCG support       yes
TCG debug enabled no
TCG interpreter   no
RDMA support      yes
fdt support       yes
preadv support    yes
fdatasync         yes
madvise           yes
posix_madvise     yes
libcap-ng support no
vhost-net 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
QOM debugging     yes
Live block migration yes
lzo support       yes
snappy support    no
bzip2 support     yes
NUMA host support no
tcmalloc support  no
jemalloc support  no
avx2 optimization no
replication support yes
VxHS block device no
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     qapi-types.h
  GEN     qmp-commands.h
  GEN     qemu-options.def
  GEN     qapi-visit.h
  GEN     qapi-event.h
  GEN     x86_64-softmmu/config-devices.mak
  GEN     aarch64-softmmu/config-devices.mak
  GEN     qmp-marshal.c
  GEN     qapi-types.c
  GEN     qapi-visit.c
  GEN     qapi-event.c
  GEN     qmp-introspect.h
  GEN     qmp-introspect.c
  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     tests/test-qapi-types.h
  GEN     tests/test-qapi-visit.h
  GEN     tests/test-qmp-commands.h
  GEN     tests/test-qapi-event.h
  GEN     tests/test-qmp-introspect.h
  GEN     trace-root.h
  GEN     util/trace.h
  GEN     crypto/trace.h
  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/virtio/trace.h
  GEN     hw/audio/trace.h
  GEN     hw/misc/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/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/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/xen/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     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/virtio/trace.c
  GEN     hw/audio/trace.c
  GEN     hw/misc/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/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/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/xen/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     config-all-devices.mak
	 DEP /tmp/qemu-test/src/dtc/tests/trees.S
	 DEP /tmp/qemu-test/src/dtc/tests/dumptrees.c
	 DEP /tmp/qemu-test/src/dtc/tests/testutils.c
	 DEP /tmp/qemu-test/src/dtc/tests/value-labels.c
	 DEP /tmp/qemu-test/src/dtc/tests/asm_tree_dump.c
	 DEP /tmp/qemu-test/src/dtc/tests/truncated_property.c
	 DEP /tmp/qemu-test/src/dtc/tests/check_path.c
	 DEP /tmp/qemu-test/src/dtc/tests/overlay_bad_fixup.c
	 DEP /tmp/qemu-test/src/dtc/tests/overlay.c
	 DEP /tmp/qemu-test/src/dtc/tests/subnode_iterate.c
	 DEP /tmp/qemu-test/src/dtc/tests/property_iterate.c
	 DEP /tmp/qemu-test/src/dtc/tests/integer-expressions.c
	 DEP /tmp/qemu-test/src/dtc/tests/utilfdt_test.c
	 DEP /tmp/qemu-test/src/dtc/tests/path_offset_aliases.c
	 DEP /tmp/qemu-test/src/dtc/tests/add_subnode_with_nops.c
	 DEP /tmp/qemu-test/src/dtc/tests/dtbs_equal_unordered.c
	 DEP /tmp/qemu-test/src/dtc/tests/dtb_reverse.c
	 DEP /tmp/qemu-test/src/dtc/tests/dtbs_equal_ordered.c
	 DEP /tmp/qemu-test/src/dtc/tests/extra-terminating-null.c
	 DEP /tmp/qemu-test/src/dtc/tests/incbin.c
	 DEP /tmp/qemu-test/src/dtc/tests/boot-cpuid.c
	 DEP /tmp/qemu-test/src/dtc/tests/phandle_format.c
	 DEP /tmp/qemu-test/src/dtc/tests/path-references.c
	 DEP /tmp/qemu-test/src/dtc/tests/references.c
	 DEP /tmp/qemu-test/src/dtc/tests/string_escapes.c
	 DEP /tmp/qemu-test/src/dtc/tests/propname_escapes.c
	 DEP /tmp/qemu-test/src/dtc/tests/appendprop2.c
	 DEP /tmp/qemu-test/src/dtc/tests/appendprop1.c
	 DEP /tmp/qemu-test/src/dtc/tests/del_node.c
	 DEP /tmp/qemu-test/src/dtc/tests/del_property.c
	 DEP /tmp/qemu-test/src/dtc/tests/setprop.c
	 DEP /tmp/qemu-test/src/dtc/tests/set_name.c
	 DEP /tmp/qemu-test/src/dtc/tests/rw_tree1.c
	 DEP /tmp/qemu-test/src/dtc/tests/open_pack.c
	 DEP /tmp/qemu-test/src/dtc/tests/mangle-layout.c
	 DEP /tmp/qemu-test/src/dtc/tests/nopulate.c
	 DEP /tmp/qemu-test/src/dtc/tests/move_and_save.c
	 DEP /tmp/qemu-test/src/dtc/tests/sw_tree1.c
	 DEP /tmp/qemu-test/src/dtc/tests/nop_node.c
	 DEP /tmp/qemu-test/src/dtc/tests/nop_property.c
	 DEP /tmp/qemu-test/src/dtc/tests/setprop_inplace.c
	 DEP /tmp/qemu-test/src/dtc/tests/stringlist.c
	 DEP /tmp/qemu-test/src/dtc/tests/addr_size_cells.c
	 DEP /tmp/qemu-test/src/dtc/tests/notfound.c
	 DEP /tmp/qemu-test/src/dtc/tests/sized_cells.c
	 DEP /tmp/qemu-test/src/dtc/tests/char_literal.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_alias.c
	 DEP /tmp/qemu-test/src/dtc/tests/node_offset_by_compatible.c
	 DEP /tmp/qemu-test/src/dtc/tests/node_check_compatible.c
	 DEP /tmp/qemu-test/src/dtc/tests/node_offset_by_phandle.c
	 DEP /tmp/qemu-test/src/dtc/tests/node_offset_by_prop_value.c
	 DEP /tmp/qemu-test/src/dtc/tests/parent_offset.c
	 DEP /tmp/qemu-test/src/dtc/tests/supernode_atdepth_offset.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_path.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_phandle.c
	 DEP /tmp/qemu-test/src/dtc/tests/getprop.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_name.c
	 DEP /tmp/qemu-test/src/dtc/tests/subnode_offset.c
	 DEP /tmp/qemu-test/src/dtc/tests/path_offset.c
	 DEP /tmp/qemu-test/src/dtc/tests/find_property.c
	 DEP /tmp/qemu-test/src/dtc/tests/root_node.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_mem_rsv.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_overlay.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_addresses.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_empty_tree.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_rw.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_strerror.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_sw.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_wip.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_ro.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt.c
	 DEP /tmp/qemu-test/src/dtc/util.c
	 DEP /tmp/qemu-test/src/dtc/fdtput.c
	 DEP /tmp/qemu-test/src/dtc/fdtget.c
	 DEP /tmp/qemu-test/src/dtc/fdtdump.c
	 LEX convert-dtsv0-lexer.lex.c
	 DEP /tmp/qemu-test/src/dtc/srcpos.c
	 BISON dtc-parser.tab.c
	 LEX dtc-lexer.lex.c
	 DEP /tmp/qemu-test/src/dtc/treesource.c
	 DEP /tmp/qemu-test/src/dtc/livetree.c
	 DEP /tmp/qemu-test/src/dtc/fstree.c
	 DEP /tmp/qemu-test/src/dtc/flattree.c
	 DEP /tmp/qemu-test/src/dtc/dtc.c
	 DEP /tmp/qemu-test/src/dtc/data.c
	 DEP /tmp/qemu-test/src/dtc/checks.c
	 DEP convert-dtsv0-lexer.lex.c
	 DEP dtc-parser.tab.c
	 DEP dtc-lexer.lex.c
	CHK version_gen.h
	UPD version_gen.h
	 DEP /tmp/qemu-test/src/dtc/util.c
	 CC libfdt/fdt.o
	 CC libfdt/fdt_ro.o
	 CC libfdt/fdt_wip.o
	 CC libfdt/fdt_sw.o
	 CC libfdt/fdt_rw.o
	 CC libfdt/fdt_strerror.o
	 CC libfdt/fdt_empty_tree.o
	 CC libfdt/fdt_addresses.o
	 CC libfdt/fdt_overlay.o
	 AR libfdt/libfdt.a
ar: creating libfdt/libfdt.a
a - libfdt/fdt.o
a - libfdt/fdt_ro.o
a - libfdt/fdt_wip.o
a - libfdt/fdt_sw.o
a - libfdt/fdt_rw.o
a - libfdt/fdt_strerror.o
a - libfdt/fdt_empty_tree.o
a - libfdt/fdt_addresses.o
a - libfdt/fdt_overlay.o
  GEN     qga/qapi-generated/qga-qapi-types.h
  CC      tests/qemu-iotests/socket_scm_helper.o
  GEN     qga/qapi-generated/qga-qapi-visit.h
  GEN     qga/qapi-generated/qga-qmp-commands.h
  GEN     qga/qapi-generated/qga-qapi-types.c
  GEN     qga/qapi-generated/qga-qapi-visit.c
  GEN     qga/qapi-generated/qga-qmp-marshal.c
  CC      qapi-types.o
  CC      qapi-visit.o
  CC      qapi/qapi-visit-core.o
  CC      qapi/qapi-dealloc-visitor.o
  CC      qapi/qobject-input-visitor.o
  CC      qapi/qobject-output-visitor.o
  CC      qapi/qmp-registry.o
  CC      qapi/qmp-dispatch.o
  CC      qapi/string-input-visitor.o
  CC      qapi/string-output-visitor.o
  CC      qapi/opts-visitor.o
  CC      qapi/qapi-clone-visitor.o
  CC      qapi/qmp-event.o
  CC      qapi/qapi-util.o
  CC      qobject/qnull.o
  CC      qobject/qnum.o
  CC      qobject/qstring.o
  CC      qobject/qdict.o
  CC      qobject/qlist.o
  CC      qobject/qbool.o
  CC      qobject/qlit.o
  CC      qobject/qjson.o
  CC      qobject/qobject.o
  CC      qobject/json-lexer.o
  CC      qobject/json-streamer.o
  CC      qobject/json-parser.o
  CC      trace/control.o
  CC      util/osdep.o
  CC      util/cutils.o
  CC      util/unicode.o
  CC      util/qemu-timer-common.o
  CC      util/bufferiszero.o
  CC      util/lockcnt.o
  CC      util/aiocb.o
  CC      util/async.o
  CC      util/thread-pool.o
  CC      util/qemu-timer.o
  CC      util/main-loop.o
  CC      util/iohandler.o
  CC      util/aio-posix.o
  CC      util/compatfd.o
  CC      util/event_notifier-posix.o
  CC      util/mmap-alloc.o
  CC      util/oslib-posix.o
  CC      util/qemu-openpty.o
  CC      util/qemu-thread-posix.o
  CC      util/memfd.o
  CC      util/envlist.o
  CC      util/path.o
  CC      util/module.o
  CC      util/host-utils.o
  CC      util/bitmap.o
  CC      util/bitops.o
  CC      util/hbitmap.o
  CC      util/fifo8.o
  CC      util/acl.o
  CC      util/cacheinfo.o
  CC      util/error.o
  CC      util/qemu-error.o
  CC      util/id.o
  CC      util/iov.o
  CC      util/qemu-config.o
  CC      util/qemu-sockets.o
  CC      util/uri.o
  CC      util/notify.o
  CC      util/qemu-option.o
  CC      util/qemu-progress.o
  CC      util/keyval.o
  CC      util/hexdump.o
  CC      util/crc32c.o
  CC      util/uuid.o
  CC      util/throttle.o
  CC      util/getauxval.o
  CC      util/readline.o
  CC      util/rcu.o
  CC      util/qemu-coroutine.o
  CC      util/qemu-coroutine-lock.o
  CC      util/qemu-coroutine-io.o
  CC      util/qemu-coroutine-sleep.o
  CC      util/coroutine-ucontext.o
  CC      util/timed-average.o
  CC      util/buffer.o
  CC      util/base64.o
  CC      util/log.o
  CC      util/qdist.o
  CC      util/qht.o
  CC      util/range.o
  CC      util/stats64.o
  CC      trace-root.o
  CC      util/systemd.o
  CC      util/trace.o
  CC      crypto/trace.o
  CC      io/trace.o
  CC      migration/trace.o
  CC      block/trace.o
  CC      chardev/trace.o
  CC      hw/block/trace.o
  CC      hw/block/dataplane/trace.o
  CC      hw/char/trace.o
  CC      hw/intc/trace.o
  CC      hw/net/trace.o
  CC      hw/virtio/trace.o
  CC      hw/audio/trace.o
  CC      hw/misc/trace.o
  CC      hw/usb/trace.o
  CC      hw/scsi/trace.o
  CC      hw/nvram/trace.o
  CC      hw/display/trace.o
  CC      hw/input/trace.o
  CC      hw/timer/trace.o
  CC      hw/dma/trace.o
  CC      hw/sparc/trace.o
  CC      hw/sd/trace.o
  CC      hw/isa/trace.o
  CC      hw/mem/trace.o
  CC      hw/i386/trace.o
  CC      hw/i386/xen/trace.o
  CC      hw/9pfs/trace.o
  CC      hw/ppc/trace.o
  CC      hw/pci/trace.o
  CC      hw/s390x/trace.o
  CC      hw/vfio/trace.o
  CC      hw/acpi/trace.o
  CC      hw/arm/trace.o
  CC      hw/alpha/trace.o
  CC      hw/xen/trace.o
  CC      ui/trace.o
  CC      audio/trace.o
  CC      net/trace.o
  CC      target/arm/trace.o
  CC      target/i386/trace.o
  CC      target/mips/trace.o
  CC      target/sparc/trace.o
  CC      target/s390x/trace.o
  CC      target/ppc/trace.o
  CC      qom/trace.o
  CC      linux-user/trace.o
  CC      qapi/trace.o
  CC      accel/tcg/trace.o
  CC      accel/kvm/trace.o
  CC      nbd/trace.o
  CC      crypto/pbkdf-stub.o
  CC      stubs/bdrv-next-monitor-owned.o
  CC      stubs/blk-commit-all.o
  CC      stubs/blockdev-close-all-bdrv-states.o
  CC      stubs/clock-warp.o
  CC      stubs/cpu-get-clock.o
  CC      stubs/cpu-get-icount.o
  CC      stubs/dump.o
  CC      stubs/error-printf.o
  CC      stubs/fdset.o
  CC      stubs/gdbstub.o
  CC      stubs/get-vm-name.o
  CC      stubs/iothread.o
  CC      stubs/iothread-lock.o
  CC      stubs/is-daemonized.o
  CC      stubs/machine-init-done.o
  CC      stubs/migr-blocker.o
  CC      stubs/change-state-handler.o
  CC      stubs/monitor.o
  CC      stubs/notify-event.o
  CC      stubs/qapi-event.o
  CC      stubs/qtest.o
  CC      stubs/replay.o
  CC      stubs/runstate-check.o
  CC      stubs/set-fd-handler.o
  CC      stubs/slirp.o
  CC      stubs/sysbus.o
  CC      stubs/trace-control.o
  CC      stubs/uuid.o
  CC      stubs/vm-stop.o
  CC      stubs/vmstate.o
  CC      stubs/qmp_pc_dimm_device_list.o
  CC      stubs/target-monitor-defs.o
  CC      stubs/target-get-monitor-def.o
  CC      stubs/pc_madt_cpu_entry.o
  CC      stubs/vmgenid.o
  CC      stubs/xen-common.o
  CC      stubs/xen-hvm.o
  CC      contrib/ivshmem-client/ivshmem-client.o
  CC      contrib/ivshmem-client/main.o
  CC      contrib/ivshmem-server/ivshmem-server.o
  CC      contrib/ivshmem-server/main.o
  CC      qemu-nbd.o
  CC      block.o
  CC      blockjob.o
  CC      qemu-io-cmds.o
  CC      replication.o
  CC      block/raw-format.o
  CC      block/qcow.o
  CC      block/vdi.o
  CC      block/vmdk.o
  CC      block/cloop.o
  CC      block/bochs.o
  CC      block/vpc.o
  CC      block/vvfat.o
  CC      block/dmg.o
  CC      block/qcow2.o
  CC      block/qcow2-refcount.o
  CC      block/qcow2-cluster.o
  CC      block/qcow2-snapshot.o
  CC      block/qcow2-cache.o
  CC      block/qcow2-bitmap.o
  CC      block/qed.o
  CC      block/qed-l2-cache.o
  CC      block/qed-table.o
  CC      block/qed-cluster.o
  CC      block/qed-check.o
  CC      block/vhdx.o
  CC      block/vhdx-endian.o
  CC      block/vhdx-log.o
  CC      block/quorum.o
  CC      block/parallels.o
  CC      block/blkdebug.o
  CC      block/blkverify.o
  CC      block/blkreplay.o
  CC      block/block-backend.o
  CC      block/snapshot.o
  CC      block/qapi.o
  CC      block/file-posix.o
  CC      block/null.o
  CC      block/mirror.o
  CC      block/commit.o
  CC      block/io.o
  CC      block/throttle-groups.o
  CC      block/nbd.o
  CC      block/nbd-client.o
  CC      block/sheepdog.o
  CC      block/accounting.o
  CC      block/dirty-bitmap.o
  CC      block/write-threshold.o
  CC      block/backup.o
/tmp/qemu-test/src/block/nbd-client.c: In function ‘nbd_read_reply_entry’:
/tmp/qemu-test/src/block/nbd-client.c:110: warning: ‘ret’ may be used uninitialized in this function
/tmp/qemu-test/src/block/nbd-client.c:73: note: ‘ret’ was declared here
  CC      block/replication.o
  CC      block/crypto.o
  CC      nbd/server.o
  CC      nbd/client.o
  CC      nbd/common.o
  CC      block/dmg-bz2.o
  CC      crypto/init.o
  CC      crypto/hash.o
  CC      crypto/hash-glib.o
  CC      crypto/hmac.o
  CC      crypto/hmac-glib.o
  CC      crypto/aes.o
  CC      crypto/desrfb.o
  CC      crypto/cipher.o
  CC      crypto/tlscreds.o
  CC      crypto/tlscredsanon.o
  CC      crypto/tlscredsx509.o
  CC      crypto/tlssession.o
  CC      crypto/secret.o
  CC      crypto/random-platform.o
  CC      crypto/pbkdf.o
  CC      crypto/ivgen.o
  CC      crypto/ivgen-essiv.o
  CC      crypto/ivgen-plain.o
  CC      crypto/ivgen-plain64.o
  CC      crypto/afsplit.o
  CC      crypto/xts.o
  CC      crypto/block.o
  CC      crypto/block-qcow.o
  CC      crypto/block-luks.o
  CC      io/channel.o
  CC      io/channel-buffer.o
  CC      io/channel-command.o
  CC      io/channel-file.o
  CC      io/channel-socket.o
  CC      io/channel-tls.o
  CC      io/channel-watch.o
  CC      io/channel-websock.o
  CC      io/channel-util.o
  CC      io/dns-resolver.o
  CC      io/task.o
  CC      qom/object.o
  CC      qom/container.o
  CC      qom/qom-qobject.o
  CC      qom/object_interfaces.o
  GEN     qemu-img-cmds.h
  CC      qemu-io.o
  CC      qemu-bridge-helper.o
  CC      blockdev.o
  CC      blockdev-nbd.o
  CC      bootdevice.o
  CC      iothread.o
  CC      qdev-monitor.o
  CC      device-hotplug.o
  CC      os-posix.o
  CC      bt-host.o
  CC      bt-vhci.o
  CC      dma-helpers.o
  CC      vl.o
  CC      tpm.o
  CC      device_tree.o
  CC      cpus-common.o
  CC      audio/audio.o
  CC      audio/noaudio.o
  CC      audio/wavaudio.o
  CC      audio/mixeng.o
  CC      audio/sdlaudio.o
  CC      audio/ossaudio.o
  CC      audio/spiceaudio.o
  CC      audio/wavcapture.o
  CC      backends/rng.o
  CC      backends/rng-egd.o
  CC      backends/rng-random.o
  CC      backends/tpm.o
  CC      backends/hostmem.o
  CC      backends/hostmem-ram.o
  CC      backends/hostmem-file.o
  CC      backends/cryptodev.o
  CC      backends/cryptodev-builtin.o
  CC      block/stream.o
  CC      chardev/msmouse.o
  CC      chardev/wctablet.o
  CC      chardev/testdev.o
  CC      chardev/spice.o
  CC      disas/arm.o
  CC      disas/i386.o
  CC      fsdev/qemu-fsdev-dummy.o
  CC      fsdev/qemu-fsdev-opts.o
  CC      fsdev/qemu-fsdev-throttle.o
  CC      hw/acpi/core.o
  CC      hw/acpi/piix4.o
  CC      hw/acpi/pcihp.o
  CC      hw/acpi/ich9.o
  CC      hw/acpi/tco.o
  CC      hw/acpi/cpu_hotplug.o
  CC      hw/acpi/memory_hotplug.o
  CC      hw/acpi/cpu.o
  CC      hw/acpi/nvdimm.o
  CC      hw/acpi/vmgenid.o
  CC      hw/acpi/acpi_interface.o
  CC      hw/acpi/bios-linker-loader.o
  CC      hw/acpi/aml-build.o
  CC      hw/acpi/ipmi.o
  CC      hw/acpi/acpi-stub.o
  CC      hw/acpi/ipmi-stub.o
  CC      hw/audio/sb16.o
  CC      hw/audio/es1370.o
  CC      hw/audio/ac97.o
  CC      hw/audio/fmopl.o
  CC      hw/audio/adlib.o
  CC      hw/audio/gus.o
  CC      hw/audio/gusemu_hal.o
  CC      hw/audio/gusemu_mixer.o
  CC      hw/audio/cs4231a.o
  CC      hw/audio/intel-hda.o
  CC      hw/audio/hda-codec.o
  CC      hw/audio/pcspk.o
  CC      hw/audio/wm8750.o
  CC      hw/audio/pl041.o
  CC      hw/audio/lm4549.o
  CC      hw/audio/marvell_88w8618.o
  CC      hw/audio/soundhw.o
  CC      hw/block/block.o
  CC      hw/block/cdrom.o
  CC      hw/block/hd-geometry.o
  CC      hw/block/fdc.o
  CC      hw/block/m25p80.o
  CC      hw/block/nand.o
  CC      hw/block/pflash_cfi01.o
  CC      hw/block/pflash_cfi02.o
  CC      hw/block/xen_disk.o
  CC      hw/block/ecc.o
  CC      hw/block/onenand.o
  CC      hw/block/nvme.o
  CC      hw/bt/core.o
  CC      hw/bt/l2cap.o
  CC      hw/bt/sdp.o
  CC      hw/bt/hci.o
  CC      hw/bt/hid.o
  CC      hw/bt/hci-csr.o
  CC      hw/char/ipoctal232.o
  CC      hw/char/parallel.o
  CC      hw/char/pl011.o
  CC      hw/char/serial.o
  CC      hw/char/serial-isa.o
  CC      hw/char/serial-pci.o
  CC      hw/char/virtio-console.o
  CC      hw/char/xen_console.o
  CC      hw/char/cadence_uart.o
  CC      hw/char/cmsdk-apb-uart.o
  CC      hw/char/debugcon.o
  CC      hw/char/imx_serial.o
  CC      hw/core/qdev.o
  CC      hw/core/qdev-properties.o
  CC      hw/core/bus.o
  CC      hw/core/reset.o
  CC      hw/core/fw-path-provider.o
  CC      hw/core/irq.o
  CC      hw/core/hotplug.o
  CC      hw/core/nmi.o
  CC      hw/core/ptimer.o
  CC      hw/core/sysbus.o
  CC      hw/core/machine.o
  CC      hw/core/loader.o
  CC      hw/core/qdev-properties-system.o
  CC      hw/core/register.o
  CC      hw/core/or-irq.o
  CC      hw/core/platform-bus.o
  CC      hw/cpu/core.o
  CC      hw/display/ads7846.o
  CC      hw/display/cirrus_vga.o
  CC      hw/display/pl110.o
  CC      hw/display/ssd0303.o
  CC      hw/display/ssd0323.o
  CC      hw/display/xenfb.o
  CC      hw/display/vga-pci.o
  CC      hw/display/vga-isa.o
  CC      hw/display/vmware_vga.o
  CC      hw/display/exynos4210_fimd.o
  CC      hw/display/framebuffer.o
  CC      hw/display/blizzard.o
  CC      hw/display/tc6393xb.o
  CC      hw/display/qxl.o
  CC      hw/display/qxl-logger.o
  CC      hw/display/qxl-render.o
  CC      hw/dma/pl080.o
  CC      hw/dma/pl330.o
  CC      hw/dma/i8257.o
  CC      hw/dma/xlnx-zynq-devcfg.o
  CC      hw/gpio/max7310.o
  CC      hw/gpio/pl061.o
  CC      hw/gpio/zaurus.o
  CC      hw/gpio/gpio_key.o
  CC      hw/i2c/core.o
  CC      hw/i2c/smbus.o
  CC      hw/i2c/smbus_eeprom.o
  CC      hw/i2c/i2c-ddc.o
  CC      hw/i2c/versatile_i2c.o
  CC      hw/i2c/smbus_ich9.o
  CC      hw/i2c/pm_smbus.o
  CC      hw/i2c/bitbang_i2c.o
  CC      hw/i2c/exynos4210_i2c.o
  CC      hw/i2c/imx_i2c.o
  CC      hw/i2c/aspeed_i2c.o
  CC      hw/ide/core.o
  CC      hw/ide/atapi.o
  CC      hw/ide/qdev.o
  CC      hw/ide/pci.o
  CC      hw/ide/isa.o
  CC      hw/ide/piix.o
  CC      hw/ide/microdrive.o
  CC      hw/ide/ahci.o
  CC      hw/ide/ich.o
  CC      hw/input/hid.o
  CC      hw/input/lm832x.o
  CC      hw/input/pckbd.o
  CC      hw/input/pl050.o
  CC      hw/input/ps2.o
  CC      hw/input/stellaris_input.o
  CC      hw/input/tsc2005.o
  CC      hw/input/vmmouse.o
  CC      hw/input/virtio-input.o
  CC      hw/input/virtio-input-hid.o
  CC      hw/input/virtio-input-host.o
  CC      hw/intc/i8259_common.o
  CC      hw/intc/i8259.o
  CC      hw/intc/pl190.o
  CC      hw/intc/imx_avic.o
  CC      hw/intc/realview_gic.o
  CC      hw/intc/ioapic_common.o
  CC      hw/intc/arm_gic_common.o
  CC      hw/intc/arm_gic.o
  CC      hw/intc/arm_gicv2m.o
  CC      hw/intc/arm_gicv3_common.o
  CC      hw/intc/arm_gicv3.o
  CC      hw/intc/arm_gicv3_dist.o
  CC      hw/intc/arm_gicv3_redist.o
  CC      hw/intc/arm_gicv3_its_common.o
  CC      hw/intc/intc.o
  CC      hw/ipack/ipack.o
  CC      hw/ipack/tpci200.o
  CC      hw/ipmi/ipmi.o
  CC      hw/ipmi/ipmi_bmc_sim.o
  CC      hw/ipmi/ipmi_bmc_extern.o
  CC      hw/ipmi/isa_ipmi_kcs.o
  CC      hw/ipmi/isa_ipmi_bt.o
  CC      hw/isa/isa-bus.o
  CC      hw/isa/apm.o
  CC      hw/mem/pc-dimm.o
  CC      hw/mem/nvdimm.o
  CC      hw/misc/applesmc.o
  CC      hw/misc/max111x.o
  CC      hw/misc/tmp105.o
  CC      hw/misc/tmp421.o
  CC      hw/misc/debugexit.o
  CC      hw/misc/sga.o
  CC      hw/misc/pc-testdev.o
  CC      hw/misc/pci-testdev.o
  CC      hw/misc/edu.o
  CC      hw/misc/unimp.o
  CC      hw/misc/arm_l2x0.o
  CC      hw/misc/arm_integrator_debug.o
  CC      hw/misc/a9scu.o
  CC      hw/misc/arm11scu.o
  CC      hw/net/xen_nic.o
  CC      hw/net/ne2000.o
  CC      hw/net/eepro100.o
  CC      hw/net/pcnet-pci.o
  CC      hw/net/pcnet.o
  CC      hw/net/e1000.o
  CC      hw/net/e1000x_common.o
  CC      hw/net/net_tx_pkt.o
  CC      hw/net/net_rx_pkt.o
  CC      hw/net/e1000e.o
  CC      hw/net/e1000e_core.o
  CC      hw/net/rtl8139.o
  CC      hw/net/vmxnet3.o
  CC      hw/net/smc91c111.o
  CC      hw/net/lan9118.o
  CC      hw/net/ne2000-isa.o
  CC      hw/net/xgmac.o
  CC      hw/net/allwinner_emac.o
  CC      hw/net/imx_fec.o
  CC      hw/net/stellaris_enet.o
  CC      hw/net/cadence_gem.o
  CC      hw/net/ftgmac100.o
  CC      hw/net/rocker/rocker.o
  CC      hw/net/rocker/rocker_fp.o
  CC      hw/net/rocker/rocker_desc.o
  CC      hw/net/rocker/rocker_world.o
  CC      hw/net/rocker/rocker_of_dpa.o
  CC      hw/nvram/eeprom93xx.o
  CC      hw/nvram/fw_cfg.o
  CC      hw/nvram/chrp_nvram.o
  CC      hw/pci-bridge/pci_bridge_dev.o
  CC      hw/pci-bridge/pcie_root_port.o
  CC      hw/pci-bridge/gen_pcie_root_port.o
  CC      hw/pci-bridge/pci_expander_bridge.o
  CC      hw/pci-bridge/xio3130_upstream.o
  CC      hw/pci-bridge/xio3130_downstream.o
  CC      hw/pci-bridge/ioh3420.o
  CC      hw/pci-bridge/i82801b11.o
  CC      hw/pci-host/pam.o
  CC      hw/pci-host/versatile.o
  CC      hw/pci-host/piix.o
  CC      hw/pci-host/q35.o
  CC      hw/pci-host/gpex.o
  CC      hw/pci/pci.o
  CC      hw/pci/pci_bridge.o
  CC      hw/pci/msix.o
  CC      hw/pci/msi.o
  CC      hw/pci/shpc.o
  CC      hw/pci/slotid_cap.o
  CC      hw/pci/pci_host.o
  CC      hw/pci/pcie_host.o
  CC      hw/pci/pcie.o
  CC      hw/pci/pcie_aer.o
  CC      hw/pci/pci-stub.o
  CC      hw/pci/pcie_port.o
  CC      hw/pcmcia/pcmcia.o
  CC      hw/scsi/scsi-disk.o
  CC      hw/scsi/scsi-generic.o
  CC      hw/scsi/scsi-bus.o
  CC      hw/scsi/lsi53c895a.o
  CC      hw/scsi/mptsas.o
  CC      hw/scsi/mptconfig.o
  CC      hw/scsi/mptendian.o
  CC      hw/scsi/megasas.o
  CC      hw/scsi/vmw_pvscsi.o
  CC      hw/scsi/esp.o
  CC      hw/scsi/esp-pci.o
  CC      hw/sd/pl181.o
  CC      hw/sd/ssi-sd.o
  CC      hw/sd/sd.o
  CC      hw/sd/core.o
  CC      hw/sd/sdhci.o
  CC      hw/smbios/smbios.o
  CC      hw/smbios/smbios_type_38.o
  CC      hw/smbios/smbios-stub.o
  CC      hw/smbios/smbios_type_38-stub.o
  CC      hw/ssi/pl022.o
  CC      hw/ssi/ssi.o
  CC      hw/ssi/xilinx_spips.o
  CC      hw/ssi/aspeed_smc.o
  CC      hw/ssi/stm32f2xx_spi.o
  CC      hw/timer/arm_timer.o
  CC      hw/timer/arm_mptimer.o
  CC      hw/timer/armv7m_systick.o
  CC      hw/timer/a9gtimer.o
  CC      hw/timer/cadence_ttc.o
  CC      hw/timer/ds1338.o
  CC      hw/timer/hpet.o
  CC      hw/timer/i8254.o
  CC      hw/timer/i8254_common.o
  CC      hw/timer/pl031.o
  CC      hw/timer/twl92230.o
  CC      hw/timer/imx_epit.o
  CC      hw/timer/imx_gpt.o
  CC      hw/timer/stm32f2xx_timer.o
  CC      hw/timer/aspeed_timer.o
  CC      hw/timer/cmsdk-apb-timer.o
  CC      hw/tpm/tpm_tis.o
  CC      hw/tpm/tpm_passthrough.o
  CC      hw/tpm/tpm_util.o
  CC      hw/usb/core.o
  CC      hw/usb/combined-packet.o
  CC      hw/usb/bus.o
  CC      hw/usb/libhw.o
  CC      hw/usb/desc.o
  CC      hw/usb/desc-msos.o
  CC      hw/usb/hcd-uhci.o
  CC      hw/usb/hcd-ohci.o
  CC      hw/usb/hcd-ehci.o
  CC      hw/usb/hcd-ehci-pci.o
  CC      hw/usb/hcd-ehci-sysbus.o
  CC      hw/usb/hcd-xhci.o
  CC      hw/usb/hcd-xhci-nec.o
  CC      hw/usb/hcd-musb.o
  CC      hw/usb/dev-hub.o
  CC      hw/usb/dev-hid.o
  CC      hw/usb/dev-wacom.o
  CC      hw/usb/dev-storage.o
  CC      hw/usb/dev-uas.o
  CC      hw/usb/dev-audio.o
  CC      hw/usb/dev-serial.o
  CC      hw/usb/dev-network.o
  CC      hw/usb/dev-bluetooth.o
  CC      hw/usb/dev-smartcard-reader.o
  CC      hw/usb/ccid-card-passthru.o
  CC      hw/usb/ccid-card-emulated.o
  CC      hw/usb/dev-mtp.o
  CC      hw/usb/host-stub.o
  CC      hw/virtio/virtio-rng.o
  CC      hw/virtio/virtio-pci.o
  CC      hw/virtio/virtio-bus.o
  CC      hw/virtio/virtio-mmio.o
  CC      hw/virtio/vhost-stub.o
  CC      hw/watchdog/watchdog.o
  CC      hw/watchdog/wdt_i6300esb.o
  CC      hw/watchdog/wdt_ib700.o
  CC      hw/watchdog/wdt_aspeed.o
  CC      hw/xen/xen_backend.o
  CC      hw/xen/xen_devconfig.o
  CC      hw/xen/xen_pvdev.o
  CC      hw/xen/xen-common.o
  CC      migration/migration.o
  CC      migration/socket.o
  CC      migration/fd.o
  CC      migration/exec.o
  CC      migration/tls.o
  CC      migration/channel.o
  CC      migration/savevm.o
  CC      migration/colo-comm.o
  CC      migration/colo.o
  CC      migration/colo-failover.o
  CC      migration/vmstate.o
  CC      migration/vmstate-types.o
  CC      migration/page_cache.o
  CC      migration/qemu-file.o
  CC      migration/global_state.o
  CC      migration/qemu-file-channel.o
  CC      migration/xbzrle.o
  CC      migration/postcopy-ram.o
  CC      migration/qjson.o
  CC      migration/rdma.o
  CC      migration/block.o
  CC      net/net.o
  CC      net/queue.o
  CC      net/checksum.o
  CC      net/util.o
  CC      net/hub.o
  CC      net/socket.o
  CC      net/dump.o
  CC      net/eth.o
  CC      net/l2tpv3.o
  CC      net/vhost-user.o
  CC      net/slirp.o
  CC      net/filter.o
  CC      net/filter-buffer.o
  CC      net/filter-mirror.o
  CC      net/colo-compare.o
  CC      net/colo.o
  CC      net/filter-rewriter.o
  CC      net/filter-replay.o
  CC      net/tap.o
  CC      net/tap-linux.o
  CC      qom/cpu.o
  CC      replay/replay.o
  CC      replay/replay-internal.o
  CC      replay/replay-events.o
  CC      replay/replay-time.o
  CC      replay/replay-input.o
  CC      replay/replay-char.o
  CC      replay/replay-snapshot.o
  CC      replay/replay-net.o
/tmp/qemu-test/src/replay/replay-internal.c: In function ‘replay_put_array’:
/tmp/qemu-test/src/replay/replay-internal.c:65: warning: ignoring return value of ‘fwrite’, declared with attribute warn_unused_result
  CC      replay/replay-audio.o
  CC      slirp/cksum.o
  CC      slirp/if.o
  CC      slirp/ip_icmp.o
  CC      slirp/ip6_icmp.o
  CC      slirp/ip6_input.o
  CC      slirp/ip6_output.o
  CC      slirp/ip_input.o
  CC      slirp/ip_output.o
  CC      slirp/dnssearch.o
  CC      slirp/dhcpv6.o
  CC      slirp/slirp.o
  CC      slirp/mbuf.o
  CC      slirp/misc.o
  CC      slirp/sbuf.o
  CC      slirp/socket.o
  CC      slirp/tcp_input.o
  CC      slirp/tcp_output.o
  CC      slirp/tcp_subr.o
  CC      slirp/tcp_timer.o
  CC      slirp/udp.o
  CC      slirp/udp6.o
  CC      slirp/bootp.o
  CC      slirp/tftp.o
  CC      slirp/arp_table.o
  CC      slirp/ndp_table.o
  CC      slirp/ncsi.o
  CC      ui/keymaps.o
  CC      ui/console.o
/tmp/qemu-test/src/slirp/tcp_input.c: In function ‘tcp_input’:
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_p’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_len’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_tos’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_id’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_off’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_ttl’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_sum’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_src.s_addr’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_dst.s_addr’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:220: warning: ‘save_ip6.ip_nh’ may be used uninitialized in this function
  CC      ui/cursor.o
  CC      ui/qemu-pixman.o
  CC      ui/input.o
  CC      ui/input-keymap.o
  CC      ui/input-legacy.o
  CC      ui/input-linux.o
  CC      ui/spice-core.o
  CC      ui/spice-input.o
  CC      ui/spice-display.o
  CC      ui/sdl.o
  CC      ui/sdl_zoom.o
  CC      ui/x_keymap.o
  CC      ui/curses.o
  CC      ui/vnc.o
  CC      ui/vnc-enc-zlib.o
  CC      ui/vnc-enc-hextile.o
  CC      ui/vnc-enc-tight.o
  CC      ui/vnc-palette.o
  CC      ui/vnc-enc-zrle.o
  CC      ui/vnc-auth-vencrypt.o
  CC      ui/vnc-ws.o
  CC      ui/vnc-jobs.o
  CC      ui/gtk.o
  CC      ui/shader.o
  VERT    ui/shader/texture-blit-vert.h
  FRAG    ui/shader/texture-blit-frag.h
  CC      ui/egl-helpers.o
  CC      ui/egl-context.o
  CC      ui/gtk-egl.o
  CC      chardev/char.o
  CC      chardev/char-fd.o
  CC      chardev/char-fe.o
  CC      chardev/char-file.o
  CC      chardev/char-io.o
  CC      chardev/char-mux.o
  CC      chardev/char-null.o
  CC      chardev/char-parallel.o
  CC      chardev/char-pipe.o
  CC      chardev/char-pty.o
  CC      chardev/char-ringbuf.o
In file included from /usr/include/gtk-2.0/gtk/gtk.h:235,
                 from /tmp/qemu-test/src/include/ui/gtk.h:10,
                 from /tmp/qemu-test/src/ui/gtk-egl.c:21:
/usr/include/gtk-2.0/gtk/gtkitemfactory.h:47: warning: function declaration isn’t a prototype
  CC      chardev/char-serial.o
  CC      chardev/char-socket.o
  CC      chardev/char-stdio.o
  CC      chardev/char-udp.o
  AS      optionrom/multiboot.o
  AS      optionrom/linuxboot.o
In file included from /usr/include/gtk-2.0/gtk/gtk.h:235,
                 from /tmp/qemu-test/src/include/ui/gtk.h:10,
                 from /tmp/qemu-test/src/ui/gtk.c:43:
/usr/include/gtk-2.0/gtk/gtkitemfactory.h:47: warning: function declaration isn’t a prototype
  CC      optionrom/linuxboot_dma.o
cc: unrecognized option '-no-integrated-as'
cc: unrecognized option '-no-integrated-as'
  AS      optionrom/kvmvapic.o
  LINK    tests/qemu-iotests/socket_scm_helper
  BUILD   optionrom/multiboot.img
  BUILD   optionrom/linuxboot.img
  BUILD   optionrom/linuxboot_dma.img
  CC      qga/commands.o
  BUILD   optionrom/kvmvapic.img
  BUILD   optionrom/multiboot.raw
  BUILD   optionrom/linuxboot.raw
  BUILD   optionrom/linuxboot_dma.raw
  BUILD   optionrom/kvmvapic.raw
  CC      qga/guest-agent-command-state.o
  SIGN    optionrom/multiboot.bin
  SIGN    optionrom/linuxboot.bin
  SIGN    optionrom/linuxboot_dma.bin
  SIGN    optionrom/kvmvapic.bin
  CC      qga/main.o
  CC      qga/commands-posix.o
  CC      qga/channel-posix.o
  CC      qga/qapi-generated/qga-qapi-types.o
  CC      qga/qapi-generated/qga-qapi-visit.o
  CC      qga/qapi-generated/qga-qmp-marshal.o
  AR      libqemuutil.a
  AR      libqemustub.a
  CC      qemu-img.o
  CC      ui/console-gl.o
  LINK    ivshmem-client
  LINK    ivshmem-server
  LINK    qemu-nbd
  LINK    qemu-io
  LINK    qemu-bridge-helper
  LINK    qemu-ga
  GEN     x86_64-softmmu/hmp-commands.h
  GEN     x86_64-softmmu/hmp-commands-info.h
  GEN     x86_64-softmmu/config-target.h
  GEN     aarch64-softmmu/hmp-commands-info.h
  GEN     aarch64-softmmu/config-target.h
  GEN     aarch64-softmmu/hmp-commands.h
  CC      x86_64-softmmu/exec.o
  CC      x86_64-softmmu/tcg/tcg.o
  CC      x86_64-softmmu/tcg/optimize.o
  CC      x86_64-softmmu/tcg/tcg-op.o
  CC      x86_64-softmmu/tcg/tcg-common.o
  CC      x86_64-softmmu/tcg/tcg-runtime.o
  CC      aarch64-softmmu/exec.o
  CC      x86_64-softmmu/fpu/softfloat.o
  CC      aarch64-softmmu/tcg/tcg.o
  CC      x86_64-softmmu/disas.o
  GEN     x86_64-softmmu/gdbstub-xml.c
  CC      x86_64-softmmu/hax-stub.o
  CC      x86_64-softmmu/arch_init.o
  CC      x86_64-softmmu/cpus.o
  CC      x86_64-softmmu/monitor.o
  CC      aarch64-softmmu/tcg/tcg-op.o
  CC      x86_64-softmmu/gdbstub.o
  CC      x86_64-softmmu/balloon.o
  LINK    qemu-img
  CC      aarch64-softmmu/tcg/optimize.o
  CC      aarch64-softmmu/tcg/tcg-common.o
  CC      x86_64-softmmu/ioport.o
  CC      x86_64-softmmu/numa.o
  CC      aarch64-softmmu/tcg/tcg-runtime.o
  CC      x86_64-softmmu/qtest.o
  CC      x86_64-softmmu/memory.o
  CC      aarch64-softmmu/fpu/softfloat.o
  CC      x86_64-softmmu/memory_mapping.o
  CC      aarch64-softmmu/disas.o
  CC      x86_64-softmmu/dump.o
  GEN     aarch64-softmmu/gdbstub-xml.c
  CC      aarch64-softmmu/hax-stub.o
  CC      aarch64-softmmu/arch_init.o
  CC      aarch64-softmmu/cpus.o
  CC      aarch64-softmmu/monitor.o
  CC      aarch64-softmmu/gdbstub.o
  CC      x86_64-softmmu/migration/ram.o
  CC      aarch64-softmmu/balloon.o
  CC      aarch64-softmmu/ioport.o
  CC      aarch64-softmmu/numa.o
  CC      x86_64-softmmu/qmp-introspect.o
  CC      x86_64-softmmu/qapi-types.o
  CC      aarch64-softmmu/qtest.o
  CC      aarch64-softmmu/memory.o
  CC      x86_64-softmmu/qapi-visit.o
  CC      aarch64-softmmu/memory_mapping.o
  CC      aarch64-softmmu/dump.o
  CC      aarch64-softmmu/migration/ram.o
  CC      aarch64-softmmu/qmp-introspect.o
  CC      x86_64-softmmu/qapi-event.o
  CC      aarch64-softmmu/qapi-types.o
  CC      x86_64-softmmu/qmp-marshal.o
  CC      x86_64-softmmu/qmp.o
  CC      aarch64-softmmu/qapi-visit.o
  CC      aarch64-softmmu/qapi-event.o
  CC      aarch64-softmmu/qmp-marshal.o
  CC      aarch64-softmmu/qmp.o
  CC      x86_64-softmmu/hmp.o
  CC      aarch64-softmmu/hmp.o
  CC      aarch64-softmmu/accel/accel.o
  CC      aarch64-softmmu/accel/stubs/kvm-stub.o
  CC      aarch64-softmmu/accel/tcg/tcg-all.o
  CC      aarch64-softmmu/accel/tcg/cputlb.o
  CC      aarch64-softmmu/accel/tcg/cpu-exec.o
  CC      x86_64-softmmu/accel/accel.o
  CC      x86_64-softmmu/accel/kvm/kvm-all.o
  CC      x86_64-softmmu/accel/tcg/tcg-all.o
  CC      aarch64-softmmu/accel/tcg/cpu-exec-common.o
  CC      x86_64-softmmu/accel/tcg/cputlb.o
  CC      aarch64-softmmu/accel/tcg/translate-all.o
  CC      aarch64-softmmu/hw/adc/stm32f2xx_adc.o
  CC      aarch64-softmmu/hw/block/virtio-blk.o
  CC      aarch64-softmmu/hw/block/dataplane/virtio-blk.o
  CC      x86_64-softmmu/accel/tcg/cpu-exec.o
  CC      x86_64-softmmu/accel/tcg/cpu-exec-common.o
  CC      aarch64-softmmu/hw/char/exynos4210_uart.o
  CC      aarch64-softmmu/hw/char/omap_uart.o
  CC      x86_64-softmmu/accel/tcg/translate-all.o
  CC      aarch64-softmmu/hw/char/digic-uart.o
  CC      aarch64-softmmu/hw/char/stm32f2xx_usart.o
  CC      aarch64-softmmu/hw/char/bcm2835_aux.o
  CC      x86_64-softmmu/hw/block/virtio-blk.o
  CC      aarch64-softmmu/hw/char/virtio-serial-bus.o
  CC      aarch64-softmmu/hw/core/generic-loader.o
  CC      aarch64-softmmu/hw/core/null-machine.o
  CC      x86_64-softmmu/hw/block/dataplane/virtio-blk.o
  CC      x86_64-softmmu/hw/char/virtio-serial-bus.o
  CC      aarch64-softmmu/hw/cpu/arm11mpcore.o
  CC      aarch64-softmmu/hw/cpu/realview_mpcore.o
  CC      x86_64-softmmu/hw/core/generic-loader.o
  CC      x86_64-softmmu/hw/core/null-machine.o
  CC      x86_64-softmmu/hw/display/vga.o
  CC      aarch64-softmmu/hw/cpu/a9mpcore.o
  CC      aarch64-softmmu/hw/cpu/a15mpcore.o
  CC      aarch64-softmmu/hw/display/omap_dss.o
  CC      aarch64-softmmu/hw/display/omap_lcdc.o
  CC      x86_64-softmmu/hw/display/virtio-gpu.o
  CC      aarch64-softmmu/hw/display/pxa2xx_lcd.o
  CC      aarch64-softmmu/hw/display/bcm2835_fb.o
  CC      aarch64-softmmu/hw/display/vga.o
  CC      aarch64-softmmu/hw/display/virtio-gpu.o
  CC      aarch64-softmmu/hw/display/virtio-gpu-3d.o
  CC      aarch64-softmmu/hw/display/virtio-gpu-pci.o
  CC      aarch64-softmmu/hw/display/dpcd.o
  CC      aarch64-softmmu/hw/display/xlnx_dp.o
  CC      x86_64-softmmu/hw/display/virtio-gpu-3d.o
  CC      x86_64-softmmu/hw/display/virtio-gpu-pci.o
  CC      aarch64-softmmu/hw/dma/xlnx_dpdma.o
  CC      aarch64-softmmu/hw/dma/omap_dma.o
  CC      aarch64-softmmu/hw/dma/soc_dma.o
  CC      x86_64-softmmu/hw/display/virtio-vga.o
  CC      aarch64-softmmu/hw/dma/pxa2xx_dma.o
  CC      x86_64-softmmu/hw/intc/apic.o
  CC      aarch64-softmmu/hw/dma/bcm2835_dma.o
  CC      x86_64-softmmu/hw/intc/apic_common.o
  CC      aarch64-softmmu/hw/gpio/omap_gpio.o
  CC      aarch64-softmmu/hw/gpio/imx_gpio.o
  CC      aarch64-softmmu/hw/gpio/bcm2835_gpio.o
  CC      aarch64-softmmu/hw/i2c/omap_i2c.o
  CC      aarch64-softmmu/hw/input/pxa2xx_keypad.o
  CC      x86_64-softmmu/hw/intc/ioapic.o
  CC      x86_64-softmmu/hw/isa/lpc_ich9.o
  CC      x86_64-softmmu/hw/misc/vmport.o
  CC      aarch64-softmmu/hw/input/tsc210x.o
  CC      aarch64-softmmu/hw/intc/armv7m_nvic.o
  CC      x86_64-softmmu/hw/misc/ivshmem.o
  CC      x86_64-softmmu/hw/misc/pvpanic.o
  CC      aarch64-softmmu/hw/intc/exynos4210_gic.o
  CC      aarch64-softmmu/hw/intc/exynos4210_combiner.o
  CC      aarch64-softmmu/hw/intc/omap_intc.o
  CC      aarch64-softmmu/hw/intc/bcm2835_ic.o
  CC      aarch64-softmmu/hw/intc/bcm2836_control.o
  CC      aarch64-softmmu/hw/intc/allwinner-a10-pic.o
  CC      x86_64-softmmu/hw/misc/hyperv_testdev.o
  CC      x86_64-softmmu/hw/misc/mmio_interface.o
  CC      aarch64-softmmu/hw/intc/aspeed_vic.o
  CC      aarch64-softmmu/hw/intc/arm_gicv3_cpuif.o
  CC      aarch64-softmmu/hw/misc/ivshmem.o
  CC      x86_64-softmmu/hw/net/virtio-net.o
  CC      aarch64-softmmu/hw/misc/arm_sysctl.o
  CC      x86_64-softmmu/hw/net/vhost_net.o
  CC      aarch64-softmmu/hw/misc/cbus.o
  CC      aarch64-softmmu/hw/misc/exynos4210_pmu.o
  CC      x86_64-softmmu/hw/scsi/virtio-scsi.o
  CC      x86_64-softmmu/hw/scsi/virtio-scsi-dataplane.o
  CC      x86_64-softmmu/hw/scsi/vhost-scsi-common.o
  CC      aarch64-softmmu/hw/misc/exynos4210_clk.o
  CC      x86_64-softmmu/hw/scsi/vhost-scsi.o
  CC      x86_64-softmmu/hw/scsi/vhost-user-scsi.o
  CC      x86_64-softmmu/hw/timer/mc146818rtc.o
  CC      aarch64-softmmu/hw/misc/exynos4210_rng.o
  CC      aarch64-softmmu/hw/misc/imx_ccm.o
  CC      aarch64-softmmu/hw/misc/imx31_ccm.o
  CC      x86_64-softmmu/hw/vfio/common.o
  CC      aarch64-softmmu/hw/misc/imx25_ccm.o
  CC      x86_64-softmmu/hw/vfio/pci.o
  CC      aarch64-softmmu/hw/misc/imx6_ccm.o
  CC      aarch64-softmmu/hw/misc/imx6_src.o
  CC      aarch64-softmmu/hw/misc/mst_fpga.o
  CC      x86_64-softmmu/hw/vfio/pci-quirks.o
  CC      x86_64-softmmu/hw/vfio/platform.o
  CC      x86_64-softmmu/hw/vfio/spapr.o
  CC      x86_64-softmmu/hw/virtio/virtio.o
  CC      aarch64-softmmu/hw/misc/omap_clk.o
  CC      aarch64-softmmu/hw/misc/omap_gpmc.o
  CC      x86_64-softmmu/hw/virtio/virtio-balloon.o
  CC      x86_64-softmmu/hw/virtio/vhost.o
  CC      aarch64-softmmu/hw/misc/omap_l4.o
  CC      x86_64-softmmu/hw/virtio/vhost-backend.o
  CC      x86_64-softmmu/hw/virtio/vhost-user.o
  CC      x86_64-softmmu/hw/virtio/vhost-vsock.o
  CC      aarch64-softmmu/hw/misc/omap_sdrc.o
  CC      aarch64-softmmu/hw/misc/omap_tap.o
  CC      x86_64-softmmu/hw/virtio/virtio-crypto.o
  CC      aarch64-softmmu/hw/misc/bcm2835_mbox.o
  CC      aarch64-softmmu/hw/misc/bcm2835_property.o
  CC      x86_64-softmmu/hw/virtio/virtio-crypto-pci.o
  CC      x86_64-softmmu/hw/xen/xen-host-pci-device.o
  CC      aarch64-softmmu/hw/misc/bcm2835_rng.o
  CC      aarch64-softmmu/hw/misc/zynq_slcr.o
  CC      x86_64-softmmu/hw/xen/xen_pt.o
  CC      aarch64-softmmu/hw/misc/zynq-xadc.o
  CC      x86_64-softmmu/hw/xen/xen_pt_config_init.o
  CC      aarch64-softmmu/hw/misc/stm32f2xx_syscfg.o
  CC      x86_64-softmmu/hw/xen/xen_pt_graphics.o
  CC      aarch64-softmmu/hw/misc/mps2-scc.o
  CC      aarch64-softmmu/hw/misc/auxbus.o
  CC      x86_64-softmmu/hw/xen/xen_pt_msi.o
  CC      aarch64-softmmu/hw/misc/aspeed_scu.o
  CC      aarch64-softmmu/hw/misc/aspeed_sdmc.o
  CC      x86_64-softmmu/hw/i386/multiboot.o
  CC      aarch64-softmmu/hw/misc/mmio_interface.o
  CC      x86_64-softmmu/hw/i386/pc.o
  CC      x86_64-softmmu/hw/i386/pc_piix.o
  CC      x86_64-softmmu/hw/i386/pc_q35.o
  CC      aarch64-softmmu/hw/net/virtio-net.o
  CC      aarch64-softmmu/hw/net/vhost_net.o
  CC      x86_64-softmmu/hw/i386/pc_sysfw.o
  CC      x86_64-softmmu/hw/i386/x86-iommu.o
  CC      aarch64-softmmu/hw/pcmcia/pxa2xx.o
  CC      x86_64-softmmu/hw/i386/intel_iommu.o
  CC      x86_64-softmmu/hw/i386/amd_iommu.o
  CC      aarch64-softmmu/hw/scsi/virtio-scsi.o
  CC      aarch64-softmmu/hw/scsi/virtio-scsi-dataplane.o
  CC      x86_64-softmmu/hw/i386/kvmvapic.o
/tmp/qemu-test/src/hw/i386/pc_piix.c: In function ‘igd_passthrough_isa_bridge_create’:
/tmp/qemu-test/src/hw/i386/pc_piix.c:1065: warning: ‘pch_rev_id’ may be used uninitialized in this function
  CC      aarch64-softmmu/hw/scsi/vhost-scsi-common.o
  CC      x86_64-softmmu/hw/i386/acpi-build.o
  CC      x86_64-softmmu/hw/i386/pci-assign-load-rom.o
  CC      x86_64-softmmu/hw/i386/../xenpv/xen_machine_pv.o
  CC      aarch64-softmmu/hw/scsi/vhost-scsi.o
  CC      x86_64-softmmu/hw/i386/kvm/clock.o
  CC      aarch64-softmmu/hw/scsi/vhost-user-scsi.o
  CC      x86_64-softmmu/hw/i386/kvm/apic.o
  CC      x86_64-softmmu/hw/i386/kvm/i8259.o
  CC      x86_64-softmmu/hw/i386/kvm/ioapic.o
  CC      x86_64-softmmu/hw/i386/kvm/i8254.o
  CC      aarch64-softmmu/hw/sd/omap_mmc.o
  CC      x86_64-softmmu/hw/i386/kvm/pci-assign.o
  CC      x86_64-softmmu/hw/i386/xen/xen_platform.o
  CC      x86_64-softmmu/hw/i386/xen/xen_apic.o
  CC      x86_64-softmmu/hw/i386/xen/xen_pvdevice.o
  CC      x86_64-softmmu/hw/i386/xen/xen-hvm.o
  CC      x86_64-softmmu/hw/i386/xen/xen-mapcache.o
  CC      aarch64-softmmu/hw/sd/pxa2xx_mmci.o
  CC      x86_64-softmmu/target/i386/helper.o
  CC      x86_64-softmmu/target/i386/cpu.o
  CC      x86_64-softmmu/target/i386/gdbstub.o
/tmp/qemu-test/src/hw/i386/acpi-build.c: In function ‘build_append_pci_bus_devices’:
/tmp/qemu-test/src/hw/i386/acpi-build.c:539: warning: ‘notify_method’ may be used uninitialized in this function
  CC      x86_64-softmmu/target/i386/xsave_helper.o
  CC      aarch64-softmmu/hw/sd/bcm2835_sdhost.o
  CC      x86_64-softmmu/target/i386/translate.o
  CC      x86_64-softmmu/target/i386/bpt_helper.o
  CC      x86_64-softmmu/target/i386/cc_helper.o
  CC      x86_64-softmmu/target/i386/excp_helper.o
  CC      aarch64-softmmu/hw/ssi/omap_spi.o
  CC      aarch64-softmmu/hw/ssi/imx_spi.o
  CC      aarch64-softmmu/hw/timer/exynos4210_mct.o
  CC      x86_64-softmmu/target/i386/fpu_helper.o
  CC      x86_64-softmmu/target/i386/int_helper.o
  CC      aarch64-softmmu/hw/timer/exynos4210_pwm.o
  CC      aarch64-softmmu/hw/timer/exynos4210_rtc.o
  CC      x86_64-softmmu/target/i386/mem_helper.o
  CC      x86_64-softmmu/target/i386/misc_helper.o
  CC      x86_64-softmmu/target/i386/mpx_helper.o
  CC      x86_64-softmmu/target/i386/seg_helper.o
  CC      x86_64-softmmu/target/i386/smm_helper.o
  CC      aarch64-softmmu/hw/timer/omap_gptimer.o
  CC      aarch64-softmmu/hw/timer/omap_synctimer.o
  CC      x86_64-softmmu/target/i386/svm_helper.o
  CC      aarch64-softmmu/hw/timer/pxa2xx_timer.o
  CC      x86_64-softmmu/target/i386/machine.o
  CC      aarch64-softmmu/hw/timer/digic-timer.o
  CC      aarch64-softmmu/hw/timer/allwinner-a10-pit.o
  CC      aarch64-softmmu/hw/usb/tusb6010.o
  CC      aarch64-softmmu/hw/vfio/common.o
  CC      aarch64-softmmu/hw/vfio/pci.o
  CC      aarch64-softmmu/hw/vfio/pci-quirks.o
  CC      x86_64-softmmu/target/i386/arch_memory_mapping.o
  CC      aarch64-softmmu/hw/vfio/platform.o
  CC      aarch64-softmmu/hw/vfio/calxeda-xgmac.o
  CC      aarch64-softmmu/hw/vfio/amd-xgbe.o
  CC      aarch64-softmmu/hw/vfio/spapr.o
  CC      aarch64-softmmu/hw/virtio/virtio.o
  CC      x86_64-softmmu/target/i386/arch_dump.o
  CC      aarch64-softmmu/hw/virtio/virtio-balloon.o
  CC      aarch64-softmmu/hw/virtio/vhost.o
  CC      aarch64-softmmu/hw/virtio/vhost-backend.o
  CC      aarch64-softmmu/hw/virtio/vhost-user.o
  CC      x86_64-softmmu/target/i386/monitor.o
  CC      aarch64-softmmu/hw/virtio/vhost-vsock.o
  CC      aarch64-softmmu/hw/virtio/virtio-crypto.o
  CC      aarch64-softmmu/hw/virtio/virtio-crypto-pci.o
  CC      aarch64-softmmu/hw/arm/boot.o
  CC      x86_64-softmmu/target/i386/kvm.o
  CC      x86_64-softmmu/target/i386/hyperv.o
  GEN     trace/generated-helpers.c
  CC      aarch64-softmmu/hw/arm/collie.o
  CC      aarch64-softmmu/hw/arm/exynos4_boards.o
  CC      x86_64-softmmu/trace/control-target.o
  CC      aarch64-softmmu/hw/arm/gumstix.o
  CC      x86_64-softmmu/trace/qmp.o
  CC      aarch64-softmmu/hw/arm/highbank.o
  CC      aarch64-softmmu/hw/arm/digic_boards.o
  CC      aarch64-softmmu/hw/arm/integratorcp.o
  CC      aarch64-softmmu/hw/arm/mainstone.o
  CC      aarch64-softmmu/hw/arm/musicpal.o
  CC      x86_64-softmmu/gdbstub-xml.o
  CC      x86_64-softmmu/trace/generated-helpers.o
  CC      aarch64-softmmu/hw/arm/nseries.o
  CC      aarch64-softmmu/hw/arm/omap_sx1.o
  CC      aarch64-softmmu/hw/arm/palm.o
  CC      aarch64-softmmu/hw/arm/realview.o
  CC      aarch64-softmmu/hw/arm/spitz.o
  CC      aarch64-softmmu/hw/arm/stellaris.o
  LINK    x86_64-softmmu/qemu-system-x86_64
  CC      aarch64-softmmu/hw/arm/tosa.o
  CC      aarch64-softmmu/hw/arm/versatilepb.o
  CC      aarch64-softmmu/hw/arm/vexpress.o
  CC      aarch64-softmmu/hw/arm/virt.o
  CC      aarch64-softmmu/hw/arm/xilinx_zynq.o
  CC      aarch64-softmmu/hw/arm/z2.o
  CC      aarch64-softmmu/hw/arm/virt-acpi-build.o
  CC      aarch64-softmmu/hw/arm/netduino2.o
  CC      aarch64-softmmu/hw/arm/sysbus-fdt.o
  CC      aarch64-softmmu/hw/arm/armv7m.o
  CC      aarch64-softmmu/hw/arm/exynos4210.o
  CC      aarch64-softmmu/hw/arm/pxa2xx.o
  CC      aarch64-softmmu/hw/arm/pxa2xx_gpio.o
  CC      aarch64-softmmu/hw/arm/pxa2xx_pic.o
  CC      aarch64-softmmu/hw/arm/digic.o
  CC      aarch64-softmmu/hw/arm/omap1.o
  CC      aarch64-softmmu/hw/arm/omap2.o
  CC      aarch64-softmmu/hw/arm/strongarm.o
  CC      aarch64-softmmu/hw/arm/allwinner-a10.o
  CC      aarch64-softmmu/hw/arm/cubieboard.o
  CC      aarch64-softmmu/hw/arm/bcm2835_peripherals.o
  CC      aarch64-softmmu/hw/arm/bcm2836.o
  CC      aarch64-softmmu/hw/arm/raspi.o
  CC      aarch64-softmmu/hw/arm/stm32f205_soc.o
  CC      aarch64-softmmu/hw/arm/xlnx-zynqmp.o
  CC      aarch64-softmmu/hw/arm/xlnx-ep108.o
  CC      aarch64-softmmu/hw/arm/fsl-imx25.o
  CC      aarch64-softmmu/hw/arm/imx25_pdk.o
  CC      aarch64-softmmu/hw/arm/fsl-imx31.o
  CC      aarch64-softmmu/hw/arm/kzm.o
  CC      aarch64-softmmu/hw/arm/fsl-imx6.o
  CC      aarch64-softmmu/hw/arm/sabrelite.o
  CC      aarch64-softmmu/hw/arm/aspeed_soc.o
  CC      aarch64-softmmu/hw/arm/aspeed.o
  CC      aarch64-softmmu/hw/arm/mps2.o
  CC      aarch64-softmmu/target/arm/arm-semi.o
  CC      aarch64-softmmu/target/arm/machine.o
  CC      aarch64-softmmu/target/arm/psci.o
  CC      aarch64-softmmu/target/arm/arch_dump.o
  CC      aarch64-softmmu/target/arm/monitor.o
  CC      aarch64-softmmu/target/arm/kvm-stub.o
  CC      aarch64-softmmu/target/arm/translate.o
  CC      aarch64-softmmu/target/arm/op_helper.o
  CC      aarch64-softmmu/target/arm/helper.o
  CC      aarch64-softmmu/target/arm/cpu.o
  CC      aarch64-softmmu/target/arm/neon_helper.o
  CC      aarch64-softmmu/target/arm/iwmmxt_helper.o
  CC      aarch64-softmmu/target/arm/gdbstub.o
  CC      aarch64-softmmu/target/arm/cpu64.o
  CC      aarch64-softmmu/target/arm/translate-a64.o
  CC      aarch64-softmmu/target/arm/helper-a64.o
  CC      aarch64-softmmu/target/arm/gdbstub64.o
  CC      aarch64-softmmu/target/arm/crypto_helper.o
  CC      aarch64-softmmu/target/arm/arm-powerctl.o
  GEN     trace/generated-helpers.c
  CC      aarch64-softmmu/trace/control-target.o
  CC      aarch64-softmmu/trace/qmp.o
  CC      aarch64-softmmu/gdbstub-xml.o
  CC      aarch64-softmmu/trace/generated-helpers.o
/tmp/qemu-test/src/target/arm/translate-a64.c: In function ‘handle_shri_with_rndacc’:
/tmp/qemu-test/src/target/arm/translate-a64.c:6372: warning: ‘tcg_src_hi’ may be used uninitialized in this function
/tmp/qemu-test/src/target/arm/translate-a64.c: In function ‘disas_simd_scalar_two_reg_misc’:
/tmp/qemu-test/src/target/arm/translate-a64.c:8099: warning: ‘rmode’ may be used uninitialized in this function
  LINK    aarch64-softmmu/qemu-system-aarch64
  TEST    tests/qapi-schema/alternate-any.out
  TEST    tests/qapi-schema/alternate-array.out
  TEST    tests/qapi-schema/alternate-base.out
  TEST    tests/qapi-schema/alternate-clash.out
  TEST    tests/qapi-schema/alternate-conflict-enum-int.out
  TEST    tests/qapi-schema/alternate-conflict-enum-bool.out
  TEST    tests/qapi-schema/alternate-conflict-dict.out
  TEST    tests/qapi-schema/alternate-conflict-string.out
  TEST    tests/qapi-schema/alternate-dict-invalid.out
  TEST    tests/qapi-schema/alternate-empty.out
  TEST    tests/qapi-schema/alternate-nested.out
  TEST    tests/qapi-schema/alternate-unknown.out
  TEST    tests/qapi-schema/args-alternate.out
  TEST    tests/qapi-schema/args-any.out
  TEST    tests/qapi-schema/args-array-empty.out
  TEST    tests/qapi-schema/args-array-unknown.out
  TEST    tests/qapi-schema/args-bad-boxed.out
  TEST    tests/qapi-schema/args-boxed-anon.out
  TEST    tests/qapi-schema/args-boxed-empty.out
  TEST    tests/qapi-schema/args-boxed-string.out
  TEST    tests/qapi-schema/args-int.out
  TEST    tests/qapi-schema/args-invalid.out
  TEST    tests/qapi-schema/args-member-array-bad.out
  TEST    tests/qapi-schema/args-member-case.out
  TEST    tests/qapi-schema/args-member-unknown.out
  TEST    tests/qapi-schema/args-name-clash.out
  TEST    tests/qapi-schema/args-union.out
  TEST    tests/qapi-schema/args-unknown.out
  TEST    tests/qapi-schema/bad-base.out
  TEST    tests/qapi-schema/bad-data.out
  TEST    tests/qapi-schema/bad-ident.out
  TEST    tests/qapi-schema/bad-if.out
  TEST    tests/qapi-schema/bad-type-bool.out
  TEST    tests/qapi-schema/bad-type-dict.out
  TEST    tests/qapi-schema/bad-type-int.out
  TEST    tests/qapi-schema/base-cycle-direct.out
  TEST    tests/qapi-schema/base-cycle-indirect.out
  TEST    tests/qapi-schema/command-int.out
  TEST    tests/qapi-schema/comments.out
  TEST    tests/qapi-schema/doc-bad-alternate-member.out
  TEST    tests/qapi-schema/doc-bad-command-arg.out
  TEST    tests/qapi-schema/doc-bad-symbol.out
  TEST    tests/qapi-schema/doc-bad-union-member.out
  TEST    tests/qapi-schema/doc-before-include.out
  TEST    tests/qapi-schema/doc-before-pragma.out
  TEST    tests/qapi-schema/doc-duplicated-arg.out
  TEST    tests/qapi-schema/doc-duplicated-return.out
  TEST    tests/qapi-schema/doc-duplicated-since.out
  TEST    tests/qapi-schema/doc-empty-arg.out
  TEST    tests/qapi-schema/doc-empty-section.out
  TEST    tests/qapi-schema/doc-interleaved-section.out
  TEST    tests/qapi-schema/doc-empty-symbol.out
  TEST    tests/qapi-schema/doc-good.out
  TEST    tests/qapi-schema/doc-invalid-end.out
  TEST    tests/qapi-schema/doc-invalid-end2.out
  TEST    tests/qapi-schema/doc-invalid-return.out
  TEST    tests/qapi-schema/doc-invalid-section.out
  TEST    tests/qapi-schema/doc-invalid-start.out
  TEST    tests/qapi-schema/doc-missing.out
  TEST    tests/qapi-schema/doc-missing-colon.out
  TEST    tests/qapi-schema/doc-missing-expr.out
  TEST    tests/qapi-schema/doc-missing-space.out
  TEST    tests/qapi-schema/doc-no-symbol.out
  TEST    tests/qapi-schema/double-type.out
  TEST    tests/qapi-schema/double-data.out
  TEST    tests/qapi-schema/duplicate-key.out
  TEST    tests/qapi-schema/empty.out
  TEST    tests/qapi-schema/enum-bad-name.out
  TEST    tests/qapi-schema/enum-bad-prefix.out
  TEST    tests/qapi-schema/enum-clash-member.out
  TEST    tests/qapi-schema/enum-dict-member.out
  TEST    tests/qapi-schema/enum-dict-member-invalid.out
  TEST    tests/qapi-schema/enum-if-invalid.out
  TEST    tests/qapi-schema/enum-int-member.out
  TEST    tests/qapi-schema/enum-member-case.out
  TEST    tests/qapi-schema/enum-missing-data.out
  TEST    tests/qapi-schema/enum-wrong-data.out
  TEST    tests/qapi-schema/escape-outside-string.out
  TEST    tests/qapi-schema/escape-too-big.out
  TEST    tests/qapi-schema/escape-too-short.out
  TEST    tests/qapi-schema/event-boxed-empty.out
  TEST    tests/qapi-schema/event-case.out
  TEST    tests/qapi-schema/event-nest-struct.out
  TEST    tests/qapi-schema/flat-union-array-branch.out
  TEST    tests/qapi-schema/flat-union-bad-base.out
  TEST    tests/qapi-schema/flat-union-bad-discriminator.out
  TEST    tests/qapi-schema/flat-union-base-any.out
  TEST    tests/qapi-schema/flat-union-base-union.out
  TEST    tests/qapi-schema/flat-union-clash-member.out
  TEST    tests/qapi-schema/flat-union-empty.out
  TEST    tests/qapi-schema/flat-union-incomplete-branch.out
  TEST    tests/qapi-schema/flat-union-inline.out
  TEST    tests/qapi-schema/flat-union-int-branch.out
  TEST    tests/qapi-schema/flat-union-invalid-branch-key.out
  TEST    tests/qapi-schema/flat-union-invalid-discriminator.out
  TEST    tests/qapi-schema/flat-union-no-base.out
  TEST    tests/qapi-schema/flat-union-optional-discriminator.out
  TEST    tests/qapi-schema/flat-union-string-discriminator.out
  TEST    tests/qapi-schema/funny-char.out
  TEST    tests/qapi-schema/ident-with-escape.out
  TEST    tests/qapi-schema/include-before-err.out
  TEST    tests/qapi-schema/include-cycle.out
  TEST    tests/qapi-schema/include-extra-junk.out
  TEST    tests/qapi-schema/include-format-err.out
  TEST    tests/qapi-schema/include-nested-err.out
  TEST    tests/qapi-schema/include-no-file.out
  TEST    tests/qapi-schema/include-non-file.out
  TEST    tests/qapi-schema/include-relpath.out
  TEST    tests/qapi-schema/include-repetition.out
  TEST    tests/qapi-schema/include-self-cycle.out
  TEST    tests/qapi-schema/include-simple.out
  TEST    tests/qapi-schema/indented-expr.out
  TEST    tests/qapi-schema/leading-comma-list.out
  TEST    tests/qapi-schema/leading-comma-object.out
  TEST    tests/qapi-schema/missing-colon.out
  TEST    tests/qapi-schema/missing-comma-list.out
  TEST    tests/qapi-schema/missing-comma-object.out
  TEST    tests/qapi-schema/missing-type.out
  TEST    tests/qapi-schema/nested-struct-data.out
  TEST    tests/qapi-schema/non-objects.out
  TEST    tests/qapi-schema/pragma-doc-required-crap.out
  TEST    tests/qapi-schema/pragma-extra-junk.out
  TEST    tests/qapi-schema/pragma-name-case-whitelist-crap.out
  TEST    tests/qapi-schema/pragma-non-dict.out
  TEST    tests/qapi-schema/pragma-returns-whitelist-crap.out
  TEST    tests/qapi-schema/qapi-schema-test.out
  TEST    tests/qapi-schema/quoted-structural-chars.out
  TEST    tests/qapi-schema/redefined-builtin.out
  TEST    tests/qapi-schema/redefined-command.out
  TEST    tests/qapi-schema/redefined-event.out
  TEST    tests/qapi-schema/redefined-type.out
  TEST    tests/qapi-schema/reserved-command-q.out
  TEST    tests/qapi-schema/reserved-enum-q.out
  TEST    tests/qapi-schema/reserved-member-has.out
  TEST    tests/qapi-schema/reserved-member-q.out
  TEST    tests/qapi-schema/reserved-member-u.out
  TEST    tests/qapi-schema/reserved-member-underscore.out
  TEST    tests/qapi-schema/reserved-type-kind.out
  TEST    tests/qapi-schema/reserved-type-list.out
  TEST    tests/qapi-schema/returns-alternate.out
  TEST    tests/qapi-schema/returns-array-bad.out
  TEST    tests/qapi-schema/returns-dict.out
  TEST    tests/qapi-schema/returns-unknown.out
  TEST    tests/qapi-schema/returns-whitelist.out
  TEST    tests/qapi-schema/struct-base-clash-deep.out
  TEST    tests/qapi-schema/struct-base-clash.out
  TEST    tests/qapi-schema/struct-data-invalid.out
  TEST    tests/qapi-schema/struct-if-invalid.out
  TEST    tests/qapi-schema/struct-member-invalid.out
  TEST    tests/qapi-schema/struct-member-type.out
  TEST    tests/qapi-schema/trailing-comma-list.out
  TEST    tests/qapi-schema/trailing-comma-object.out
  TEST    tests/qapi-schema/type-bypass-bad-gen.out
  TEST    tests/qapi-schema/unclosed-list.out
  TEST    tests/qapi-schema/unclosed-object.out
  TEST    tests/qapi-schema/unclosed-string.out
  TEST    tests/qapi-schema/unicode-str.out
  TEST    tests/qapi-schema/union-base-empty.out
  TEST    tests/qapi-schema/union-base-no-discriminator.out
  TEST    tests/qapi-schema/union-branch-case.out
  TEST    tests/qapi-schema/union-clash-branches.out
  TEST    tests/qapi-schema/union-empty.out
  TEST    tests/qapi-schema/union-invalid-base.out
  TEST    tests/qapi-schema/union-optional-branch.out
  TEST    tests/qapi-schema/union-unknown.out
  TEST    tests/qapi-schema/unknown-escape.out
  TEST    tests/qapi-schema/unknown-expr-key.out
  GEN     tests/qapi-schema/doc-good.test.texi
  CC      tests/check-qdict.o
  CC      tests/test-char.o
  CC      tests/check-qnum.o
  CC      tests/check-qstring.o
  CC      tests/check-qnull.o
  CC      tests/check-qlist.o
  CC      tests/check-qjson.o
  CC      tests/check-qlit.o
  CC      tests/test-qobject-output-visitor.o
  GEN     tests/test-qapi-visit.c
  GEN     tests/test-qapi-types.c
  GEN     tests/test-qapi-event.c
  GEN     tests/test-qmp-introspect.c
  CC      tests/test-clone-visitor.o
  CC      tests/test-qobject-input-visitor.o
  CC      tests/test-qmp-commands.o
  GEN     tests/test-qmp-marshal.c
  CC      tests/test-string-input-visitor.o
  CC      tests/test-string-output-visitor.o
  CC      tests/test-qmp-event.o
  CC      tests/test-opts-visitor.o
  CC      tests/test-coroutine.o
  CC      tests/iothread.o
  CC      tests/test-visitor-serialization.o
  CC      tests/test-iov.o
  CC      tests/test-aio.o
  CC      tests/test-aio-multithread.o
  CC      tests/test-throttle.o
  CC      tests/test-thread-pool.o
  CC      tests/test-hbitmap.o
  CC      tests/test-blockjob.o
  CC      tests/test-blockjob-txn.o
  CC      tests/test-x86-cpuid.o
  CC      tests/test-xbzrle.o
  CC      tests/test-vmstate.o
  CC      tests/test-cutils.o
  CC      tests/test-shift128.o
  CC      tests/test-mul64.o
  CC      tests/test-int128.o
/tmp/qemu-test/src/tests/test-int128.c:180: warning: ‘__noclone__’ attribute directive ignored
  CC      tests/rcutorture.o
  CC      tests/test-rcu-list.o
  CC      tests/test-qdist.o
  CC      tests/test-qht.o
  CC      tests/test-qht-par.o
  CC      tests/qht-bench.o
  CC      tests/test-bitops.o
  CC      tests/test-bitcnt.o
  CC      tests/check-qom-interface.o
  CC      tests/check-qom-proplist.o
  CC      tests/test-qemu-opts.o
  CC      tests/test-keyval.o
  CC      tests/test-write-threshold.o
  CC      tests/test-crypto-hash.o
  CC      tests/test-crypto-hmac.o
  CC      tests/test-crypto-cipher.o
  CC      tests/test-crypto-secret.o
  CC      tests/test-qga.o
  CC      tests/libqtest.o
  CC      tests/test-timed-average.o
  CC      tests/test-io-task.o
  CC      tests/test-io-channel-socket.o
  CC      tests/io-channel-helpers.o
  CC      tests/test-io-channel-file.o
  CC      tests/test-io-channel-command.o
  CC      tests/test-io-channel-buffer.o
  CC      tests/test-base64.o
  CC      tests/test-crypto-ivgen.o
  CC      tests/test-crypto-afsplit.o
  CC      tests/test-crypto-xts.o
  CC      tests/test-crypto-block.o
  CC      tests/test-logging.o
  CC      tests/test-replication.o
  CC      tests/test-bufferiszero.o
  CC      tests/test-uuid.o
  CC      tests/ptimer-test.o
  CC      tests/ptimer-test-stubs.o
  CC      tests/test-qapi-util.o
  CC      tests/vhost-user-test.o
  CC      tests/libqos/pci.o
  CC      tests/libqos/fw_cfg.o
  CC      tests/libqos/malloc.o
  CC      tests/libqos/i2c.o
  CC      tests/libqos/libqos.o
  CC      tests/libqos/malloc-spapr.o
  CC      tests/libqos/libqos-spapr.o
  CC      tests/libqos/rtas.o
  CC      tests/libqos/pci-spapr.o
  CC      tests/libqos/pci-pc.o
  CC      tests/libqos/malloc-pc.o
  CC      tests/libqos/libqos-pc.o
  CC      tests/libqos/ahci.o
  CC      tests/libqos/virtio.o
  CC      tests/libqos/virtio-pci.o
  CC      tests/libqos/virtio-mmio.o
  CC      tests/libqos/malloc-generic.o
  CC      tests/endianness-test.o
  CC      tests/fdc-test.o
  CC      tests/ide-test.o
  CC      tests/ahci-test.o
  CC      tests/hd-geo-test.o
  CC      tests/boot-order-test.o
  CC      tests/bios-tables-test.o
  CC      tests/boot-sector.o
  CC      tests/acpi-utils.o
  CC      tests/boot-serial-test.o
  CC      tests/pxe-test.o
  CC      tests/rtc-test.o
  CC      tests/ipmi-kcs-test.o
  CC      tests/ipmi-bt-test.o
  CC      tests/i440fx-test.o
  CC      tests/fw_cfg-test.o
  CC      tests/drive_del-test.o
  CC      tests/wdt_ib700-test.o
  CC      tests/tco-test.o
  CC      tests/e1000-test.o
  CC      tests/e1000e-test.o
  CC      tests/rtl8139-test.o
  CC      tests/pcnet-test.o
  CC      tests/eepro100-test.o
  CC      tests/ne2000-test.o
  CC      tests/nvme-test.o
  CC      tests/ac97-test.o
  CC      tests/es1370-test.o
  CC      tests/virtio-net-test.o
  CC      tests/virtio-balloon-test.o
  CC      tests/virtio-blk-test.o
  CC      tests/virtio-rng-test.o
  CC      tests/virtio-scsi-test.o
  CC      tests/virtio-serial-test.o
  CC      tests/virtio-console-test.o
  CC      tests/tpci200-test.o
  CC      tests/ipoctal232-test.o
  CC      tests/display-vga-test.o
  CC      tests/intel-hda-test.o
  CC      tests/ivshmem-test.o
  CC      tests/megasas-test.o
  CC      tests/pvpanic-test.o
  CC      tests/vmxnet3-test.o
  CC      tests/i82801b11-test.o
  CC      tests/ioh3420-test.o
  CC      tests/usb-hcd-ohci-test.o
  CC      tests/libqos/usb.o
  CC      tests/usb-hcd-uhci-test.o
  CC      tests/usb-hcd-ehci-test.o
  CC      tests/usb-hcd-xhci-test.o
  CC      tests/pc-cpu-test.o
  CC      tests/q35-test.o
  CC      tests/vmgenid-test.o
  CC      tests/test-netfilter.o
  CC      tests/test-filter-mirror.o
  CC      tests/test-filter-redirector.o
  CC      tests/postcopy-test.o
  CC      tests/test-x86-cpuid-compat.o
  CC      tests/numa-test.o
  CC      tests/qmp-test.o
  CC      tests/device-introspect-test.o
  CC      tests/qom-test.o
  CC      tests/test-hmp.o
  LINK    tests/check-qdict
  LINK    tests/test-char
  LINK    tests/check-qnum
  LINK    tests/check-qstring
  LINK    tests/check-qlist
  LINK    tests/check-qnull
  LINK    tests/check-qjson
  LINK    tests/check-qlit
  CC      tests/test-qapi-visit.o
  CC      tests/test-qapi-types.o
  CC      tests/test-qapi-event.o
  CC      tests/test-qmp-introspect.o
  CC      tests/test-qmp-marshal.o
  LINK    tests/test-coroutine
  LINK    tests/test-iov
  LINK    tests/test-aio
  LINK    tests/test-aio-multithread
  LINK    tests/test-throttle
  LINK    tests/test-thread-pool
  LINK    tests/test-hbitmap
  LINK    tests/test-blockjob
  LINK    tests/test-blockjob-txn
  LINK    tests/test-x86-cpuid
  LINK    tests/test-xbzrle
  LINK    tests/test-vmstate
  LINK    tests/test-cutils
  LINK    tests/test-shift128
  LINK    tests/test-mul64
  LINK    tests/test-int128
  LINK    tests/rcutorture
  LINK    tests/test-rcu-list
  LINK    tests/test-qdist
  LINK    tests/test-qht
  LINK    tests/qht-bench
  LINK    tests/test-bitops
  LINK    tests/test-bitcnt
  LINK    tests/check-qom-interface
  LINK    tests/check-qom-proplist
  LINK    tests/test-qemu-opts
  LINK    tests/test-keyval
  LINK    tests/test-write-threshold
  LINK    tests/test-crypto-hash
  LINK    tests/test-crypto-hmac
  LINK    tests/test-crypto-cipher
  LINK    tests/test-crypto-secret
  LINK    tests/test-qga
  LINK    tests/test-timed-average
  LINK    tests/test-io-task
  LINK    tests/test-io-channel-socket
  LINK    tests/test-io-channel-file
  LINK    tests/test-io-channel-command
  LINK    tests/test-io-channel-buffer
  LINK    tests/test-base64
  LINK    tests/test-crypto-ivgen
  LINK    tests/test-crypto-afsplit
  LINK    tests/test-crypto-xts
  LINK    tests/test-crypto-block
  LINK    tests/test-logging
  LINK    tests/test-replication
  LINK    tests/test-bufferiszero
  LINK    tests/test-uuid
  LINK    tests/ptimer-test
  LINK    tests/test-qapi-util
  LINK    tests/vhost-user-test
  LINK    tests/endianness-test
  LINK    tests/fdc-test
  LINK    tests/ide-test
  LINK    tests/ahci-test
  LINK    tests/hd-geo-test
  LINK    tests/boot-order-test
  LINK    tests/bios-tables-test
  LINK    tests/boot-serial-test
  LINK    tests/pxe-test
  LINK    tests/rtc-test
  LINK    tests/ipmi-kcs-test
  LINK    tests/ipmi-bt-test
  LINK    tests/i440fx-test
  LINK    tests/fw_cfg-test
  LINK    tests/drive_del-test
  LINK    tests/wdt_ib700-test
  LINK    tests/tco-test
  LINK    tests/e1000-test
  LINK    tests/e1000e-test
  LINK    tests/rtl8139-test
  LINK    tests/pcnet-test
  LINK    tests/eepro100-test
  LINK    tests/ne2000-test
  LINK    tests/nvme-test
  LINK    tests/ac97-test
  LINK    tests/es1370-test
  LINK    tests/virtio-net-test
  LINK    tests/virtio-balloon-test
  LINK    tests/virtio-blk-test
  LINK    tests/virtio-rng-test
  LINK    tests/virtio-scsi-test
  LINK    tests/virtio-serial-test
  LINK    tests/virtio-console-test
  LINK    tests/tpci200-test
  LINK    tests/ipoctal232-test
  LINK    tests/display-vga-test
  LINK    tests/intel-hda-test
  LINK    tests/ivshmem-test
  LINK    tests/megasas-test
  LINK    tests/vmxnet3-test
  LINK    tests/pvpanic-test
  LINK    tests/i82801b11-test
  LINK    tests/ioh3420-test
  LINK    tests/usb-hcd-ohci-test
  LINK    tests/usb-hcd-uhci-test
  LINK    tests/usb-hcd-ehci-test
  LINK    tests/usb-hcd-xhci-test
  LINK    tests/pc-cpu-test
  LINK    tests/q35-test
  LINK    tests/vmgenid-test
  LINK    tests/test-netfilter
  LINK    tests/test-filter-mirror
  LINK    tests/test-filter-redirector
  LINK    tests/postcopy-test
  LINK    tests/test-x86-cpuid-compat
  LINK    tests/numa-test
  LINK    tests/qmp-test
  LINK    tests/device-introspect-test
  LINK    tests/qom-test
  LINK    tests/test-hmp
  GTESTER tests/check-qnum
  GTESTER tests/check-qdict
  GTESTER tests/test-char
  GTESTER tests/check-qstring
  GTESTER tests/check-qlist
  GTESTER tests/check-qnull
  GTESTER tests/check-qjson
  GTESTER tests/check-qlit
  LINK    tests/test-qobject-output-visitor
  LINK    tests/test-clone-visitor
  LINK    tests/test-qobject-input-visitor
  LINK    tests/test-qmp-commands
  LINK    tests/test-string-input-visitor
  LINK    tests/test-string-output-visitor
  LINK    tests/test-qmp-event
  GTESTER tests/test-coroutine
  LINK    tests/test-opts-visitor
  LINK    tests/test-visitor-serialization
  GTESTER tests/test-iov
  GTESTER tests/test-aio-multithread
  GTESTER tests/test-aio
  GTESTER tests/test-throttle
  GTESTER tests/test-hbitmap
  GTESTER tests/test-thread-pool
  GTESTER tests/test-blockjob
  GTESTER tests/test-blockjob-txn
  GTESTER tests/test-x86-cpuid
  GTESTER tests/test-xbzrle
  GTESTER tests/test-vmstate
Failed to load simple/primitive:b_1
Failed to load simple/primitive:i64_2
Failed to load simple/primitive:i32_1
Failed to load simple/primitive:i32_1
Failed to load test/with_tmp:a
Failed to load test/tmp_child_parent:f
Failed to load test/tmp_child:parent
Failed to load test/with_tmp:tmp
Failed to load test/tmp_child:diff
Failed to load test/with_tmp:tmp
Failed to load test/tmp_child:diff
Failed to load test/with_tmp:tmp
  GTESTER tests/test-cutils
  GTESTER tests/test-shift128
  GTESTER tests/test-mul64
  GTESTER tests/test-int128
  GTESTER tests/rcutorture
  GTESTER tests/test-qdist
  GTESTER tests/test-rcu-list
  GTESTER tests/test-qht
  LINK    tests/test-qht-par
  GTESTER tests/test-bitops
  GTESTER tests/test-bitcnt
  GTESTER tests/check-qom-interface
  GTESTER tests/check-qom-proplist
  GTESTER tests/test-qemu-opts
  GTESTER tests/test-keyval
  GTESTER tests/test-write-threshold
  GTESTER tests/test-crypto-hash
  GTESTER tests/test-crypto-hmac
  GTESTER tests/test-crypto-cipher
  GTESTER tests/test-crypto-secret
  GTESTER tests/test-qga
  GTESTER tests/test-timed-average
  GTESTER tests/test-io-task
  GTESTER tests/test-io-channel-socket
  GTESTER tests/test-io-channel-file
  GTESTER tests/test-io-channel-command
  GTESTER tests/test-io-channel-buffer
  GTESTER tests/test-base64
  GTESTER tests/test-crypto-ivgen
  GTESTER tests/test-crypto-afsplit
  GTESTER tests/test-crypto-xts
  GTESTER tests/test-crypto-block
  GTESTER tests/test-logging
  GTESTER tests/test-replication
  GTESTER tests/test-bufferiszero
  GTESTER tests/test-uuid
  GTESTER tests/ptimer-test
  GTESTER tests/test-qapi-util
  GTESTER check-qtest-x86_64
  GTESTER check-qtest-aarch64
  GTESTER tests/test-qobject-output-visitor
  GTESTER tests/test-clone-visitor
  GTESTER tests/test-qobject-input-visitor
  GTESTER tests/test-qmp-commands
  GTESTER tests/test-string-input-visitor
  GTESTER tests/test-string-output-visitor
  GTESTER tests/test-qmp-event
  GTESTER tests/test-visitor-serialization
  GTESTER tests/test-opts-visitor
  GTESTER tests/test-qht-par
Could not access KVM kernel module: No such file or directory
qemu-system-x86_64: failed to initialize KVM: No such file or directory
qemu-system-x86_64: Back to tcg accelerator
Could not access KVM kernel module: No such file or directory
qemu-system-x86_64: failed to initialize KVM: No such file or directory
qemu-system-x86_64: Back to tcg accelerator
Could not access KVM kernel module: No such file or directory
qemu-system-x86_64: failed to initialize KVM: No such file or directory
qemu-system-x86_64: Back to tcg accelerator
Could not access KVM kernel module: No such file or directory
qemu-system-x86_64: failed to initialize KVM: No such file or directory
qemu-system-x86_64: Back to tcg accelerator
Could not access KVM kernel module: No such file or directory
qemu-system-x86_64: failed to initialize KVM: No such file or directory
qemu-system-x86_64: Back to tcg accelerator
Could not access KVM kernel module: No such file or directory
qemu-system-x86_64: failed to initialize KVM: No such file or directory
qemu-system-x86_64: Back to tcg accelerator
Could not access KVM kernel module: No such file or directory
qemu-system-x86_64: failed to initialize KVM: No such file or directory
qemu-system-x86_64: Back to tcg accelerator
Could not access KVM kernel module: No such file or directory
qemu-system-x86_64: failed to initialize KVM: No such file or directory
qemu-system-x86_64: Back to tcg accelerator
Could not access KVM kernel module: No such file or directory
qemu-system-x86_64: failed to initialize KVM: No such file or directory
qemu-system-x86_64: Back to tcg accelerator
Could not access KVM kernel module: No such file or directory
qemu-system-x86_64: failed to initialize KVM: No such file or directory
qemu-system-x86_64: Back to tcg accelerator
Could not access KVM kernel module: No such file or directory
qemu-system-x86_64: failed to initialize KVM: No such file or directory
qemu-system-x86_64: Back to tcg accelerator
Could not access KVM kernel module: No such file or directory
qemu-system-x86_64: failed to initialize KVM: No such file or directory
qemu-system-x86_64: Back to tcg accelerator
Could not access KVM kernel module: No such file or directory
qemu-system-x86_64: failed to initialize KVM: No such file or directory
qemu-system-x86_64: Back to tcg accelerator
Could not access KVM kernel module: No such file or directory
qemu-system-x86_64: failed to initialize KVM: No such file or directory
qemu-system-x86_64: Back to tcg accelerator
Could not access KVM kernel module: No such file or directory
qemu-system-x86_64: failed to initialize KVM: No such file or directory
qemu-system-x86_64: Back to tcg accelerator
Could not access KVM kernel module: No such file or directory
qemu-system-x86_64: failed to initialize KVM: No such file or directory
qemu-system-x86_64: Back to tcg accelerator
Could not access KVM kernel module: No such file or directory
qemu-system-x86_64: failed to initialize KVM: No such file or directory
qemu-system-x86_64: Back to tcg accelerator
make[1]: Leaving directory '/var/tmp/patchew-tester-tmp-h8optu9x/src'

real	9m42.146s
user	0m5.398s
sys	0m2.034s
  BUILD   min-glib
make[1]: Entering directory '/var/tmp/patchew-tester-tmp-h8optu9x/src'
  ARCHIVE qemu.tgz
  ARCHIVE dtc.tgz
  COPY    RUNNER
    RUN test-build in qemu:min-glib 
Environment variables:
HOSTNAME=38d54a5ca9c2
TERM=xterm
MAKEFLAGS= -j8
HISTSIZE=1000
J=8
USER=root
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.tbz=01;31:*.tbz2=01;31:*.bz=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
CCACHE_DIR=/var/tmp/ccache
EXTRA_CONFIGURE_OPTS=
V=
SHOW_ENV=1
MAIL=/var/spool/mail/root
PATH=/usr/lib/ccache:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
LANG=en_US.UTF-8
TARGET_LIST=
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
TEST_DIR=/tmp/qemu-test
LOGNAME=root
LESSOPEN=||/usr/bin/lesspipe.sh %s
FEATURES= dtc
DEBUG=
G_BROKEN_FILENAMES=1
CCACHE_HASHDIR=
_=/usr/bin/env

Configure options:
--enable-werror --target-list=x86_64-softmmu,aarch64-softmmu --prefix=/var/tmp/qemu-build/install
No C++ compiler available; disabling C++ specific optional code
Install prefix    /var/tmp/qemu-build/install
BIOS directory    /var/tmp/qemu-build/install/share/qemu
binary directory  /var/tmp/qemu-build/install/bin
library directory /var/tmp/qemu-build/install/lib
module directory  /var/tmp/qemu-build/install/lib/qemu
libexec directory /var/tmp/qemu-build/install/libexec
include directory /var/tmp/qemu-build/install/include
config directory  /var/tmp/qemu-build/install/etc
local state directory   /var/tmp/qemu-build/install/var
Manual directory  /var/tmp/qemu-build/install/share/man
ELF interp prefix /usr/gnemul/qemu-%M
Source path       /tmp/qemu-test/src
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
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
pixman            system
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
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
TCG support       yes
TCG debug enabled no
TCG interpreter   no
RDMA support      no
fdt support       yes
preadv support    yes
fdatasync         yes
madvise           yes
posix_madvise     yes
libcap-ng support no
vhost-net 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
QOM debugging     yes
Live block migration yes
lzo support       no
snappy support    no
bzip2 support     no
NUMA host support no
tcmalloc support  no
jemalloc support  no
avx2 optimization no
replication support yes
VxHS block device no
  GEN     x86_64-softmmu/config-devices.mak.tmp
mkdir -p dtc/libfdt
  GEN     aarch64-softmmu/config-devices.mak.tmp
mkdir -p dtc/tests
  GEN     config-host.h
  GEN     qemu-options.def
  GEN     qmp-commands.h
  GEN     qapi-types.h
  GEN     qapi-visit.h
  GEN     qapi-event.h
  GEN     x86_64-softmmu/config-devices.mak
  GEN     aarch64-softmmu/config-devices.mak
  GEN     qmp-marshal.c
  GEN     qapi-types.c
  GEN     qapi-visit.c
  GEN     qapi-event.c
  GEN     qmp-introspect.h
  GEN     qmp-introspect.c
  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     tests/test-qapi-types.h
  GEN     tests/test-qmp-commands.h
  GEN     tests/test-qapi-event.h
  GEN     tests/test-qapi-visit.h
  GEN     tests/test-qmp-introspect.h
  GEN     trace-root.h
  GEN     util/trace.h
  GEN     crypto/trace.h
  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/virtio/trace.h
  GEN     hw/audio/trace.h
  GEN     hw/misc/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/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/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/xen/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     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/virtio/trace.c
  GEN     hw/audio/trace.c
  GEN     hw/misc/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/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/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/xen/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     config-all-devices.mak
	 DEP /tmp/qemu-test/src/dtc/tests/dumptrees.c
	 DEP /tmp/qemu-test/src/dtc/tests/trees.S
	 DEP /tmp/qemu-test/src/dtc/tests/testutils.c
	 DEP /tmp/qemu-test/src/dtc/tests/value-labels.c
	 DEP /tmp/qemu-test/src/dtc/tests/asm_tree_dump.c
	 DEP /tmp/qemu-test/src/dtc/tests/truncated_property.c
	 DEP /tmp/qemu-test/src/dtc/tests/check_path.c
	 DEP /tmp/qemu-test/src/dtc/tests/overlay_bad_fixup.c
	 DEP /tmp/qemu-test/src/dtc/tests/overlay.c
	 DEP /tmp/qemu-test/src/dtc/tests/subnode_iterate.c
	 DEP /tmp/qemu-test/src/dtc/tests/integer-expressions.c
	 DEP /tmp/qemu-test/src/dtc/tests/property_iterate.c
	 DEP /tmp/qemu-test/src/dtc/tests/utilfdt_test.c
	 DEP /tmp/qemu-test/src/dtc/tests/path_offset_aliases.c
	 DEP /tmp/qemu-test/src/dtc/tests/add_subnode_with_nops.c
	 DEP /tmp/qemu-test/src/dtc/tests/dtbs_equal_unordered.c
	 DEP /tmp/qemu-test/src/dtc/tests/dtb_reverse.c
	 DEP /tmp/qemu-test/src/dtc/tests/dtbs_equal_ordered.c
	 DEP /tmp/qemu-test/src/dtc/tests/extra-terminating-null.c
	 DEP /tmp/qemu-test/src/dtc/tests/incbin.c
	 DEP /tmp/qemu-test/src/dtc/tests/boot-cpuid.c
	 DEP /tmp/qemu-test/src/dtc/tests/phandle_format.c
	 DEP /tmp/qemu-test/src/dtc/tests/path-references.c
	 DEP /tmp/qemu-test/src/dtc/tests/references.c
	 DEP /tmp/qemu-test/src/dtc/tests/string_escapes.c
	 DEP /tmp/qemu-test/src/dtc/tests/propname_escapes.c
	 DEP /tmp/qemu-test/src/dtc/tests/appendprop2.c
	 DEP /tmp/qemu-test/src/dtc/tests/appendprop1.c
	 DEP /tmp/qemu-test/src/dtc/tests/del_node.c
	 DEP /tmp/qemu-test/src/dtc/tests/del_property.c
	 DEP /tmp/qemu-test/src/dtc/tests/setprop.c
	 DEP /tmp/qemu-test/src/dtc/tests/set_name.c
	 DEP /tmp/qemu-test/src/dtc/tests/rw_tree1.c
	 DEP /tmp/qemu-test/src/dtc/tests/open_pack.c
	 DEP /tmp/qemu-test/src/dtc/tests/nopulate.c
	 DEP /tmp/qemu-test/src/dtc/tests/mangle-layout.c
	 DEP /tmp/qemu-test/src/dtc/tests/sw_tree1.c
	 DEP /tmp/qemu-test/src/dtc/tests/move_and_save.c
	 DEP /tmp/qemu-test/src/dtc/tests/nop_node.c
	 DEP /tmp/qemu-test/src/dtc/tests/nop_property.c
	 DEP /tmp/qemu-test/src/dtc/tests/setprop_inplace.c
	 DEP /tmp/qemu-test/src/dtc/tests/stringlist.c
	 DEP /tmp/qemu-test/src/dtc/tests/addr_size_cells.c
	 DEP /tmp/qemu-test/src/dtc/tests/notfound.c
	 DEP /tmp/qemu-test/src/dtc/tests/sized_cells.c
	 DEP /tmp/qemu-test/src/dtc/tests/char_literal.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_alias.c
	 DEP /tmp/qemu-test/src/dtc/tests/node_offset_by_compatible.c
	 DEP /tmp/qemu-test/src/dtc/tests/node_check_compatible.c
	 DEP /tmp/qemu-test/src/dtc/tests/node_offset_by_phandle.c
	 DEP /tmp/qemu-test/src/dtc/tests/node_offset_by_prop_value.c
	 DEP /tmp/qemu-test/src/dtc/tests/parent_offset.c
	 DEP /tmp/qemu-test/src/dtc/tests/supernode_atdepth_offset.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_path.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_phandle.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_name.c
	 DEP /tmp/qemu-test/src/dtc/tests/getprop.c
	 DEP /tmp/qemu-test/src/dtc/tests/path_offset.c
	 DEP /tmp/qemu-test/src/dtc/tests/subnode_offset.c
	 DEP /tmp/qemu-test/src/dtc/tests/find_property.c
	 DEP /tmp/qemu-test/src/dtc/tests/root_node.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_mem_rsv.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_overlay.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_addresses.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_empty_tree.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_rw.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_sw.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_strerror.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_wip.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_ro.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt.c
	 DEP /tmp/qemu-test/src/dtc/fdtput.c
	 DEP /tmp/qemu-test/src/dtc/util.c
	 DEP /tmp/qemu-test/src/dtc/fdtget.c
	 DEP /tmp/qemu-test/src/dtc/fdtdump.c
	 LEX convert-dtsv0-lexer.lex.c
make[1]: flex: Command not found
	 DEP /tmp/qemu-test/src/dtc/srcpos.c
	 BISON dtc-parser.tab.c
	 LEX dtc-lexer.lex.c
make[1]: bison: Command not found
make[1]: flex: Command not found
	 DEP /tmp/qemu-test/src/dtc/treesource.c
	 DEP /tmp/qemu-test/src/dtc/fstree.c
	 DEP /tmp/qemu-test/src/dtc/flattree.c
	 DEP /tmp/qemu-test/src/dtc/dtc.c
	 DEP /tmp/qemu-test/src/dtc/livetree.c
	 DEP /tmp/qemu-test/src/dtc/data.c
	 DEP /tmp/qemu-test/src/dtc/checks.c
	CHK version_gen.h
	 LEX convert-dtsv0-lexer.lex.c
	 LEX dtc-lexer.lex.c
make[1]: 	 BISON dtc-parser.tab.c
flex: Command not found
make[1]: flex: Command not found
make[1]: bison: Command not found
	UPD version_gen.h
	 DEP /tmp/qemu-test/src/dtc/util.c
	 LEX convert-dtsv0-lexer.lex.c
make[1]: flex: Command not found
	 BISON dtc-parser.tab.c
	 LEX dtc-lexer.lex.c
make[1]: bison: Command not found
make[1]: flex: Command not found
	 CC libfdt/fdt_ro.o
	 CC libfdt/fdt.o
	 CC libfdt/fdt_sw.o
	 CC libfdt/fdt_rw.o
	 CC libfdt/fdt_wip.o
	 CC libfdt/fdt_strerror.o
	 CC libfdt/fdt_empty_tree.o
	 CC libfdt/fdt_overlay.o
	 CC libfdt/fdt_addresses.o
	 AR libfdt/libfdt.a
ar: creating libfdt/libfdt.a
a - libfdt/fdt.o
a - libfdt/fdt_ro.o
a - libfdt/fdt_wip.o
a - libfdt/fdt_sw.o
a - libfdt/fdt_rw.o
a - libfdt/fdt_strerror.o
a - libfdt/fdt_empty_tree.o
a - libfdt/fdt_addresses.o
a - libfdt/fdt_overlay.o
	 LEX convert-dtsv0-lexer.lex.c
make[1]: flex: Command not found
	 LEX dtc-lexer.lex.c
	 BISON dtc-parser.tab.c
make[1]: flex: Command not found
make[1]: bison: Command not found
  CC      tests/qemu-iotests/socket_scm_helper.o
  GEN     qga/qapi-generated/qga-qapi-visit.h
  GEN     qga/qapi-generated/qga-qapi-visit.c
  GEN     qga/qapi-generated/qga-qmp-commands.h
  GEN     qga/qapi-generated/qga-qapi-types.h
  GEN     qga/qapi-generated/qga-qapi-types.c
  GEN     qga/qapi-generated/qga-qmp-marshal.c
  CC      qapi-types.o
  CC      qapi-visit.o
  CC      qapi/qapi-visit-core.o
  CC      qapi/qapi-dealloc-visitor.o
  CC      qapi/qobject-input-visitor.o
  CC      qapi/qobject-output-visitor.o
  CC      qapi/qmp-registry.o
  CC      qapi/qmp-dispatch.o
  CC      qapi/string-input-visitor.o
  CC      qapi/string-output-visitor.o
  CC      qapi/opts-visitor.o
  CC      qapi/qapi-clone-visitor.o
  CC      qapi/qmp-event.o
  CC      qapi/qapi-util.o
  CC      qobject/qnull.o
  CC      qobject/qnum.o
  CC      qobject/qstring.o
  CC      qobject/qdict.o
  CC      qobject/qlist.o
  CC      qobject/qbool.o
  CC      qobject/qlit.o
  CC      qobject/qjson.o
  CC      qobject/qobject.o
  CC      qobject/json-lexer.o
  CC      qobject/json-streamer.o
  CC      qobject/json-parser.o
  CC      trace/control.o
  CC      util/osdep.o
  CC      util/cutils.o
  CC      util/unicode.o
  CC      util/qemu-timer-common.o
  CC      util/lockcnt.o
  CC      util/bufferiszero.o
  CC      util/aiocb.o
  CC      util/async.o
  CC      util/thread-pool.o
  CC      util/qemu-timer.o
  CC      util/main-loop.o
  CC      util/iohandler.o
  CC      util/aio-posix.o
  CC      util/compatfd.o
  CC      util/event_notifier-posix.o
  CC      util/mmap-alloc.o
  CC      util/oslib-posix.o
  CC      util/qemu-openpty.o
  CC      util/qemu-thread-posix.o
  CC      util/memfd.o
  CC      util/envlist.o
  CC      util/path.o
  CC      util/host-utils.o
  CC      util/bitmap.o
  CC      util/module.o
  CC      util/bitops.o
  CC      util/hbitmap.o
  CC      util/fifo8.o
  CC      util/acl.o
  CC      util/cacheinfo.o
  CC      util/error.o
  CC      util/qemu-error.o
  CC      util/id.o
  CC      util/iov.o
  CC      util/qemu-config.o
  CC      util/qemu-sockets.o
  CC      util/uri.o
  CC      util/notify.o
  CC      util/qemu-option.o
  CC      util/qemu-progress.o
  CC      util/keyval.o
  CC      util/hexdump.o
  CC      util/crc32c.o
  CC      util/uuid.o
  CC      util/throttle.o
  CC      util/getauxval.o
  CC      util/readline.o
  CC      util/rcu.o
  CC      util/qemu-coroutine.o
  CC      util/qemu-coroutine-lock.o
  CC      util/qemu-coroutine-io.o
  CC      util/qemu-coroutine-sleep.o
  CC      util/coroutine-ucontext.o
  CC      util/buffer.o
  CC      util/timed-average.o
  CC      util/base64.o
  CC      util/log.o
  CC      util/qdist.o
  CC      util/qht.o
  CC      util/range.o
  CC      util/stats64.o
  CC      util/systemd.o
  CC      trace-root.o
  CC      util/trace.o
  CC      crypto/trace.o
  CC      io/trace.o
  CC      migration/trace.o
  CC      block/trace.o
  CC      chardev/trace.o
  CC      hw/block/dataplane/trace.o
  CC      hw/block/trace.o
  CC      hw/char/trace.o
  CC      hw/intc/trace.o
  CC      hw/net/trace.o
  CC      hw/virtio/trace.o
  CC      hw/audio/trace.o
  CC      hw/misc/trace.o
  CC      hw/usb/trace.o
  CC      hw/scsi/trace.o
  CC      hw/nvram/trace.o
  CC      hw/display/trace.o
  CC      hw/input/trace.o
  CC      hw/timer/trace.o
  CC      hw/dma/trace.o
  CC      hw/sparc/trace.o
  CC      hw/sd/trace.o
  CC      hw/isa/trace.o
  CC      hw/mem/trace.o
  CC      hw/i386/trace.o
  CC      hw/i386/xen/trace.o
  CC      hw/9pfs/trace.o
  CC      hw/ppc/trace.o
  CC      hw/pci/trace.o
  CC      hw/s390x/trace.o
  CC      hw/vfio/trace.o
  CC      hw/acpi/trace.o
  CC      hw/arm/trace.o
  CC      hw/alpha/trace.o
  CC      hw/xen/trace.o
  CC      ui/trace.o
  CC      audio/trace.o
  CC      net/trace.o
  CC      target/arm/trace.o
  CC      target/i386/trace.o
  CC      target/mips/trace.o
  CC      target/sparc/trace.o
  CC      target/s390x/trace.o
  CC      target/ppc/trace.o
  CC      qom/trace.o
  CC      linux-user/trace.o
  CC      qapi/trace.o
  CC      accel/tcg/trace.o
  CC      accel/kvm/trace.o
  CC      nbd/trace.o
  CC      crypto/pbkdf-stub.o
  CC      stubs/bdrv-next-monitor-owned.o
  CC      stubs/blk-commit-all.o
  CC      stubs/blockdev-close-all-bdrv-states.o
  CC      stubs/clock-warp.o
  CC      stubs/cpu-get-clock.o
  CC      stubs/cpu-get-icount.o
  CC      stubs/dump.o
  CC      stubs/error-printf.o
  CC      stubs/fdset.o
  CC      stubs/gdbstub.o
  CC      stubs/get-vm-name.o
  CC      stubs/iothread.o
  CC      stubs/iothread-lock.o
  CC      stubs/is-daemonized.o
  CC      stubs/machine-init-done.o
  CC      stubs/migr-blocker.o
  CC      stubs/change-state-handler.o
  CC      stubs/monitor.o
  CC      stubs/notify-event.o
  CC      stubs/qapi-event.o
  CC      stubs/qtest.o
  CC      stubs/replay.o
  CC      stubs/runstate-check.o
  CC      stubs/set-fd-handler.o
  CC      stubs/slirp.o
  CC      stubs/sysbus.o
  CC      stubs/uuid.o
  CC      stubs/trace-control.o
  CC      stubs/vm-stop.o
  CC      stubs/vmstate.o
  CC      stubs/qmp_pc_dimm_device_list.o
  CC      stubs/target-monitor-defs.o
  CC      stubs/target-get-monitor-def.o
  CC      stubs/pc_madt_cpu_entry.o
  CC      stubs/vmgenid.o
  CC      stubs/xen-common.o
  CC      stubs/xen-hvm.o
  CC      contrib/ivshmem-client/ivshmem-client.o
  CC      contrib/ivshmem-client/main.o
  CC      contrib/ivshmem-server/ivshmem-server.o
  CC      contrib/ivshmem-server/main.o
  CC      qemu-nbd.o
  CC      block.o
  CC      blockjob.o
  CC      qemu-io-cmds.o
  CC      replication.o
  CC      block/raw-format.o
  CC      block/qcow.o
  CC      block/vdi.o
  CC      block/vmdk.o
  CC      block/cloop.o
  CC      block/bochs.o
  CC      block/vpc.o
  CC      block/vvfat.o
  CC      block/dmg.o
  CC      block/qcow2.o
  CC      block/qcow2-refcount.o
  CC      block/qcow2-cluster.o
  CC      block/qcow2-snapshot.o
  CC      block/qcow2-cache.o
  CC      block/qcow2-bitmap.o
  CC      block/qed.o
  CC      block/qed-l2-cache.o
  CC      block/qed-table.o
  CC      block/qed-cluster.o
  CC      block/qed-check.o
  CC      block/vhdx.o
  CC      block/vhdx-endian.o
  CC      block/vhdx-log.o
  CC      block/quorum.o
  CC      block/parallels.o
  CC      block/blkdebug.o
  CC      block/blkverify.o
  CC      block/blkreplay.o
  CC      block/block-backend.o
  CC      block/snapshot.o
  CC      block/qapi.o
  CC      block/file-posix.o
  CC      block/null.o
  CC      block/mirror.o
  CC      block/commit.o
  CC      block/io.o
  CC      block/throttle-groups.o
  CC      block/nbd.o
  CC      block/nbd-client.o
  CC      block/sheepdog.o
  CC      block/accounting.o
  CC      block/dirty-bitmap.o
  CC      block/write-threshold.o
  CC      block/backup.o
  CC      block/replication.o
/tmp/qemu-test/src/block/nbd-client.c: In function ‘nbd_read_reply_entry’:
/tmp/qemu-test/src/block/nbd-client.c:110: warning: ‘ret’ may be used uninitialized in this function
/tmp/qemu-test/src/block/nbd-client.c:73: note: ‘ret’ was declared here
  CC      block/crypto.o
  CC      nbd/server.o
  CC      nbd/client.o
  CC      nbd/common.o
  CC      crypto/init.o
  CC      crypto/hash.o
  CC      crypto/hash-glib.o
  CC      crypto/hmac.o
  CC      crypto/hmac-glib.o
  CC      crypto/aes.o
  CC      crypto/desrfb.o
  CC      crypto/cipher.o
  CC      crypto/tlscreds.o
  CC      crypto/tlscredsanon.o
  CC      crypto/tlscredsx509.o
  CC      crypto/tlssession.o
  CC      crypto/secret.o
  CC      crypto/random-platform.o
  CC      crypto/pbkdf.o
  CC      crypto/ivgen.o
  CC      crypto/ivgen-essiv.o
  CC      crypto/ivgen-plain.o
  CC      crypto/ivgen-plain64.o
  CC      crypto/afsplit.o
  CC      crypto/xts.o
  CC      crypto/block.o
  CC      crypto/block-qcow.o
  CC      crypto/block-luks.o
  CC      io/channel.o
  CC      io/channel-buffer.o
  CC      io/channel-command.o
  CC      io/channel-file.o
  CC      io/channel-socket.o
  CC      io/channel-tls.o
  CC      io/channel-watch.o
  CC      io/channel-websock.o
  CC      io/channel-util.o
  CC      io/dns-resolver.o
  CC      io/task.o
  CC      qom/object.o
  CC      qom/container.o
  CC      qom/qom-qobject.o
  CC      qom/object_interfaces.o
  GEN     qemu-img-cmds.h
  CC      qemu-io.o
  CC      qemu-bridge-helper.o
  CC      blockdev.o
  CC      blockdev-nbd.o
  CC      bootdevice.o
  CC      iothread.o
  CC      qdev-monitor.o
  CC      device-hotplug.o
  CC      os-posix.o
  CC      bt-host.o
  CC      bt-vhci.o
  CC      dma-helpers.o
  CC      vl.o
  CC      tpm.o
  CC      device_tree.o
  CC      cpus-common.o
  CC      audio/audio.o
  CC      audio/noaudio.o
  CC      audio/wavaudio.o
  CC      audio/mixeng.o
  CC      audio/sdlaudio.o
  CC      audio/ossaudio.o
  CC      audio/wavcapture.o
  CC      backends/rng.o
  CC      backends/rng-egd.o
  CC      backends/rng-random.o
  CC      backends/tpm.o
  CC      backends/hostmem.o
  CC      backends/hostmem-ram.o
  CC      backends/hostmem-file.o
  CC      backends/cryptodev.o
  CC      backends/cryptodev-builtin.o
  CC      block/stream.o
  CC      chardev/msmouse.o
  CC      chardev/wctablet.o
  CC      chardev/testdev.o
  CC      disas/arm.o
  CC      disas/i386.o
  CC      fsdev/qemu-fsdev-dummy.o
  CC      fsdev/qemu-fsdev-opts.o
  CC      fsdev/qemu-fsdev-throttle.o
  CC      hw/acpi/core.o
  CC      hw/acpi/piix4.o
  CC      hw/acpi/pcihp.o
  CC      hw/acpi/ich9.o
  CC      hw/acpi/tco.o
  CC      hw/acpi/cpu_hotplug.o
  CC      hw/acpi/memory_hotplug.o
  CC      hw/acpi/cpu.o
  CC      hw/acpi/nvdimm.o
  CC      hw/acpi/vmgenid.o
  CC      hw/acpi/acpi_interface.o
  CC      hw/acpi/bios-linker-loader.o
  CC      hw/acpi/aml-build.o
  CC      hw/acpi/acpi-stub.o
  CC      hw/acpi/ipmi.o
  CC      hw/acpi/ipmi-stub.o
  CC      hw/audio/sb16.o
  CC      hw/audio/es1370.o
  CC      hw/audio/ac97.o
  CC      hw/audio/fmopl.o
  CC      hw/audio/adlib.o
  CC      hw/audio/gus.o
  CC      hw/audio/gusemu_hal.o
  CC      hw/audio/gusemu_mixer.o
  CC      hw/audio/cs4231a.o
  CC      hw/audio/intel-hda.o
  CC      hw/audio/pcspk.o
  CC      hw/audio/hda-codec.o
  CC      hw/audio/wm8750.o
  CC      hw/audio/pl041.o
  CC      hw/audio/lm4549.o
  CC      hw/audio/marvell_88w8618.o
  CC      hw/audio/soundhw.o
  CC      hw/block/block.o
  CC      hw/block/cdrom.o
  CC      hw/block/hd-geometry.o
  CC      hw/block/fdc.o
  CC      hw/block/m25p80.o
  CC      hw/block/nand.o
  CC      hw/block/pflash_cfi01.o
  CC      hw/block/pflash_cfi02.o
  CC      hw/block/ecc.o
  CC      hw/block/onenand.o
  CC      hw/block/nvme.o
  CC      hw/bt/core.o
  CC      hw/bt/l2cap.o
  CC      hw/bt/sdp.o
  CC      hw/bt/hci.o
  CC      hw/bt/hid.o
  CC      hw/bt/hci-csr.o
  CC      hw/char/ipoctal232.o
  CC      hw/char/parallel.o
  CC      hw/char/pl011.o
  CC      hw/char/serial.o
  CC      hw/char/serial-isa.o
  CC      hw/char/serial-pci.o
  CC      hw/char/virtio-console.o
  CC      hw/char/cadence_uart.o
  CC      hw/char/cmsdk-apb-uart.o
  CC      hw/char/debugcon.o
  CC      hw/char/imx_serial.o
  CC      hw/core/qdev.o
  CC      hw/core/qdev-properties.o
  CC      hw/core/bus.o
  CC      hw/core/reset.o
  CC      hw/core/fw-path-provider.o
  CC      hw/core/irq.o
  CC      hw/core/hotplug.o
  CC      hw/core/nmi.o
  CC      hw/core/ptimer.o
  CC      hw/core/sysbus.o
  CC      hw/core/machine.o
  CC      hw/core/loader.o
  CC      hw/core/qdev-properties-system.o
  CC      hw/core/register.o
  CC      hw/core/or-irq.o
  CC      hw/core/platform-bus.o
  CC      hw/cpu/core.o
  CC      hw/display/ads7846.o
  CC      hw/display/cirrus_vga.o
  CC      hw/display/pl110.o
  CC      hw/display/ssd0303.o
  CC      hw/display/ssd0323.o
  CC      hw/display/vga-pci.o
  CC      hw/display/vga-isa.o
  CC      hw/display/vmware_vga.o
  CC      hw/display/blizzard.o
  CC      hw/display/exynos4210_fimd.o
  CC      hw/display/framebuffer.o
  CC      hw/display/tc6393xb.o
  CC      hw/dma/pl080.o
  CC      hw/dma/pl330.o
  CC      hw/dma/i8257.o
  CC      hw/dma/xlnx-zynq-devcfg.o
  CC      hw/gpio/max7310.o
  CC      hw/gpio/pl061.o
  CC      hw/gpio/zaurus.o
  CC      hw/gpio/gpio_key.o
  CC      hw/i2c/core.o
  CC      hw/i2c/smbus.o
  CC      hw/i2c/smbus_eeprom.o
  CC      hw/i2c/i2c-ddc.o
  CC      hw/i2c/versatile_i2c.o
  CC      hw/i2c/smbus_ich9.o
  CC      hw/i2c/pm_smbus.o
  CC      hw/i2c/bitbang_i2c.o
  CC      hw/i2c/exynos4210_i2c.o
  CC      hw/i2c/imx_i2c.o
  CC      hw/i2c/aspeed_i2c.o
  CC      hw/ide/core.o
  CC      hw/ide/atapi.o
  CC      hw/ide/qdev.o
  CC      hw/ide/pci.o
  CC      hw/ide/isa.o
  CC      hw/ide/piix.o
  CC      hw/ide/microdrive.o
  CC      hw/ide/ahci.o
  CC      hw/ide/ich.o
  CC      hw/input/hid.o
  CC      hw/input/lm832x.o
  CC      hw/input/pckbd.o
  CC      hw/input/pl050.o
  CC      hw/input/ps2.o
  CC      hw/input/stellaris_input.o
  CC      hw/input/tsc2005.o
  CC      hw/input/vmmouse.o
  CC      hw/input/virtio-input.o
  CC      hw/input/virtio-input-hid.o
  CC      hw/input/virtio-input-host.o
  CC      hw/intc/i8259_common.o
  CC      hw/intc/i8259.o
  CC      hw/intc/pl190.o
  CC      hw/intc/imx_avic.o
  CC      hw/intc/realview_gic.o
  CC      hw/intc/ioapic_common.o
  CC      hw/intc/arm_gic_common.o
  CC      hw/intc/arm_gic.o
  CC      hw/intc/arm_gicv2m.o
  CC      hw/intc/arm_gicv3_common.o
  CC      hw/intc/arm_gicv3.o
  CC      hw/intc/arm_gicv3_dist.o
  CC      hw/intc/arm_gicv3_redist.o
  CC      hw/intc/arm_gicv3_its_common.o
  CC      hw/intc/intc.o
  CC      hw/ipack/ipack.o
  CC      hw/ipack/tpci200.o
  CC      hw/ipmi/ipmi.o
  CC      hw/ipmi/ipmi_bmc_sim.o
  CC      hw/ipmi/ipmi_bmc_extern.o
  CC      hw/ipmi/isa_ipmi_kcs.o
  CC      hw/ipmi/isa_ipmi_bt.o
  CC      hw/isa/isa-bus.o
  CC      hw/isa/apm.o
  CC      hw/mem/pc-dimm.o
  CC      hw/mem/nvdimm.o
  CC      hw/misc/applesmc.o
  CC      hw/misc/max111x.o
  CC      hw/misc/tmp105.o
  CC      hw/misc/tmp421.o
  CC      hw/misc/debugexit.o
  CC      hw/misc/sga.o
  CC      hw/misc/pc-testdev.o
  CC      hw/misc/pci-testdev.o
  CC      hw/misc/edu.o
  CC      hw/misc/unimp.o
  CC      hw/misc/arm_l2x0.o
  CC      hw/misc/arm_integrator_debug.o
  CC      hw/misc/a9scu.o
  CC      hw/misc/arm11scu.o
  CC      hw/net/ne2000.o
  CC      hw/net/eepro100.o
  CC      hw/net/pcnet-pci.o
  CC      hw/net/pcnet.o
  CC      hw/net/e1000.o
  CC      hw/net/e1000x_common.o
  CC      hw/net/net_tx_pkt.o
  CC      hw/net/net_rx_pkt.o
  CC      hw/net/e1000e.o
  CC      hw/net/e1000e_core.o
  CC      hw/net/rtl8139.o
  CC      hw/net/vmxnet3.o
  CC      hw/net/smc91c111.o
  CC      hw/net/lan9118.o
  CC      hw/net/ne2000-isa.o
  CC      hw/net/xgmac.o
  CC      hw/net/allwinner_emac.o
  CC      hw/net/imx_fec.o
  CC      hw/net/cadence_gem.o
  CC      hw/net/stellaris_enet.o
  CC      hw/net/ftgmac100.o
  CC      hw/net/rocker/rocker.o
  CC      hw/net/rocker/rocker_fp.o
  CC      hw/net/rocker/rocker_desc.o
  CC      hw/net/rocker/rocker_world.o
  CC      hw/net/rocker/rocker_of_dpa.o
  CC      hw/nvram/eeprom93xx.o
  CC      hw/nvram/fw_cfg.o
  CC      hw/nvram/chrp_nvram.o
  CC      hw/pci-bridge/pci_bridge_dev.o
  CC      hw/pci-bridge/pcie_root_port.o
  CC      hw/pci-bridge/gen_pcie_root_port.o
  CC      hw/pci-bridge/pci_expander_bridge.o
  CC      hw/pci-bridge/xio3130_upstream.o
  CC      hw/pci-bridge/xio3130_downstream.o
  CC      hw/pci-bridge/ioh3420.o
  CC      hw/pci-bridge/i82801b11.o
  CC      hw/pci-host/pam.o
  CC      hw/pci-host/versatile.o
  CC      hw/pci-host/piix.o
  CC      hw/pci-host/q35.o
  CC      hw/pci-host/gpex.o
  CC      hw/pci/pci.o
  CC      hw/pci/pci_bridge.o
  CC      hw/pci/msix.o
  CC      hw/pci/msi.o
  CC      hw/pci/shpc.o
  CC      hw/pci/slotid_cap.o
  CC      hw/pci/pci_host.o
  CC      hw/pci/pcie_host.o
  CC      hw/pci/pcie.o
  CC      hw/pci/pcie_aer.o
  CC      hw/pci/pcie_port.o
  CC      hw/pci/pci-stub.o
  CC      hw/pcmcia/pcmcia.o
  CC      hw/scsi/scsi-disk.o
  CC      hw/scsi/scsi-generic.o
  CC      hw/scsi/scsi-bus.o
  CC      hw/scsi/lsi53c895a.o
  CC      hw/scsi/mptsas.o
  CC      hw/scsi/mptconfig.o
  CC      hw/scsi/mptendian.o
  CC      hw/scsi/megasas.o
  CC      hw/scsi/vmw_pvscsi.o
  CC      hw/scsi/esp.o
  CC      hw/scsi/esp-pci.o
  CC      hw/sd/pl181.o
  CC      hw/sd/ssi-sd.o
  CC      hw/sd/sd.o
  CC      hw/sd/core.o
  CC      hw/sd/sdhci.o
  CC      hw/smbios/smbios.o
  CC      hw/smbios/smbios_type_38.o
  CC      hw/smbios/smbios-stub.o
  CC      hw/smbios/smbios_type_38-stub.o
  CC      hw/ssi/pl022.o
  CC      hw/ssi/ssi.o
  CC      hw/ssi/xilinx_spips.o
  CC      hw/ssi/aspeed_smc.o
  CC      hw/ssi/stm32f2xx_spi.o
  CC      hw/timer/arm_timer.o
  CC      hw/timer/arm_mptimer.o
  CC      hw/timer/armv7m_systick.o
  CC      hw/timer/a9gtimer.o
  CC      hw/timer/cadence_ttc.o
  CC      hw/timer/ds1338.o
  CC      hw/timer/hpet.o
  CC      hw/timer/i8254_common.o
  CC      hw/timer/i8254.o
  CC      hw/timer/pl031.o
  CC      hw/timer/twl92230.o
  CC      hw/timer/imx_epit.o
  CC      hw/timer/imx_gpt.o
  CC      hw/timer/stm32f2xx_timer.o
  CC      hw/timer/aspeed_timer.o
  CC      hw/timer/cmsdk-apb-timer.o
  CC      hw/tpm/tpm_tis.o
  CC      hw/tpm/tpm_passthrough.o
  CC      hw/tpm/tpm_util.o
  CC      hw/usb/core.o
  CC      hw/usb/combined-packet.o
  CC      hw/usb/bus.o
  CC      hw/usb/libhw.o
  CC      hw/usb/desc.o
  CC      hw/usb/desc-msos.o
  CC      hw/usb/hcd-uhci.o
  CC      hw/usb/hcd-ohci.o
  CC      hw/usb/hcd-ehci.o
  CC      hw/usb/hcd-ehci-pci.o
  CC      hw/usb/hcd-ehci-sysbus.o
  CC      hw/usb/hcd-xhci.o
  CC      hw/usb/hcd-xhci-nec.o
  CC      hw/usb/hcd-musb.o
  CC      hw/usb/dev-hub.o
  CC      hw/usb/dev-hid.o
  CC      hw/usb/dev-wacom.o
  CC      hw/usb/dev-storage.o
  CC      hw/usb/dev-uas.o
  CC      hw/usb/dev-audio.o
  CC      hw/usb/dev-serial.o
  CC      hw/usb/dev-network.o
  CC      hw/usb/dev-bluetooth.o
  CC      hw/usb/dev-smartcard-reader.o
  CC      hw/usb/dev-mtp.o
  CC      hw/usb/host-stub.o
  CC      hw/virtio/virtio-rng.o
  CC      hw/virtio/virtio-pci.o
  CC      hw/virtio/virtio-bus.o
  CC      hw/virtio/virtio-mmio.o
  CC      hw/virtio/vhost-stub.o
  CC      hw/watchdog/watchdog.o
  CC      hw/watchdog/wdt_i6300esb.o
  CC      hw/watchdog/wdt_ib700.o
  CC      hw/watchdog/wdt_aspeed.o
  CC      migration/migration.o
  CC      migration/socket.o
  CC      migration/fd.o
  CC      migration/exec.o
  CC      migration/tls.o
  CC      migration/channel.o
  CC      migration/savevm.o
  CC      migration/colo-comm.o
  CC      migration/colo.o
  CC      migration/colo-failover.o
  CC      migration/vmstate.o
  CC      migration/vmstate-types.o
  CC      migration/page_cache.o
  CC      migration/qemu-file.o
  CC      migration/global_state.o
  CC      migration/qemu-file-channel.o
  CC      migration/xbzrle.o
  CC      migration/postcopy-ram.o
  CC      migration/qjson.o
  CC      migration/block.o
  CC      net/net.o
  CC      net/queue.o
  CC      net/checksum.o
  CC      net/util.o
  CC      net/hub.o
  CC      net/socket.o
  CC      net/dump.o
  CC      net/eth.o
  CC      net/l2tpv3.o
  CC      net/vhost-user.o
  CC      net/slirp.o
  CC      net/filter.o
  CC      net/filter-buffer.o
  CC      net/filter-mirror.o
  CC      net/colo-compare.o
  CC      net/colo.o
  CC      net/filter-rewriter.o
  CC      net/filter-replay.o
  CC      net/tap.o
  CC      net/tap-linux.o
  CC      qom/cpu.o
  CC      replay/replay.o
  CC      replay/replay-internal.o
  CC      replay/replay-events.o
  CC      replay/replay-time.o
  CC      replay/replay-input.o
  CC      replay/replay-char.o
  CC      replay/replay-snapshot.o
  CC      replay/replay-net.o
  CC      replay/replay-audio.o
/tmp/qemu-test/src/replay/replay-internal.c: In function ‘replay_put_array’:
/tmp/qemu-test/src/replay/replay-internal.c:65: warning: ignoring return value of ‘fwrite’, declared with attribute warn_unused_result
  CC      slirp/cksum.o
  CC      slirp/if.o
  CC      slirp/ip6_icmp.o
  CC      slirp/ip_icmp.o
  CC      slirp/ip6_input.o
  CC      slirp/ip6_output.o
  CC      slirp/ip_input.o
  CC      slirp/ip_output.o
  CC      slirp/dnssearch.o
  CC      slirp/dhcpv6.o
  CC      slirp/slirp.o
  CC      slirp/mbuf.o
  CC      slirp/misc.o
  CC      slirp/sbuf.o
  CC      slirp/socket.o
  CC      slirp/tcp_input.o
  CC      slirp/tcp_output.o
  CC      slirp/tcp_subr.o
  CC      slirp/tcp_timer.o
  CC      slirp/udp.o
  CC      slirp/udp6.o
  CC      slirp/bootp.o
  CC      slirp/tftp.o
  CC      slirp/arp_table.o
  CC      slirp/ndp_table.o
  CC      slirp/ncsi.o
/tmp/qemu-test/src/slirp/tcp_input.c: In function ‘tcp_input’:
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_p’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_len’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_tos’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_id’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_off’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_ttl’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_sum’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_src.s_addr’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_dst.s_addr’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:220: warning: ‘save_ip6.ip_nh’ may be used uninitialized in this function
  CC      ui/keymaps.o
  CC      ui/console.o
  CC      ui/cursor.o
  CC      ui/qemu-pixman.o
  CC      ui/input.o
  CC      ui/input-keymap.o
  CC      ui/input-legacy.o
  CC      ui/input-linux.o
  CC      ui/sdl.o
  CC      ui/sdl_zoom.o
  CC      ui/x_keymap.o
  CC      ui/vnc.o
  CC      ui/vnc-enc-zlib.o
  CC      ui/vnc-enc-hextile.o
  CC      ui/vnc-enc-tight.o
  CC      ui/vnc-palette.o
  CC      ui/vnc-enc-zrle.o
  CC      ui/vnc-auth-vencrypt.o
  CC      ui/vnc-ws.o
  CC      ui/vnc-jobs.o
  CC      chardev/char.o
  CC      chardev/char-fd.o
  CC      chardev/char-fe.o
  CC      chardev/char-file.o
  CC      chardev/char-io.o
  CC      chardev/char-mux.o
  CC      chardev/char-null.o
  CC      chardev/char-parallel.o
  CC      chardev/char-pipe.o
  CC      chardev/char-pty.o
  CC      chardev/char-ringbuf.o
  CC      chardev/char-serial.o
  CC      chardev/char-socket.o
  CC      chardev/char-stdio.o
  CC      chardev/char-udp.o
  LINK    tests/qemu-iotests/socket_scm_helper
  CC      qga/commands.o
  CC      qga/guest-agent-command-state.o
  AS      optionrom/multiboot.o
  AS      optionrom/linuxboot.o
  CC      optionrom/linuxboot_dma.o
  AS      optionrom/kvmvapic.o
cc: unrecognized option '-no-integrated-as'
cc: unrecognized option '-no-integrated-as'
  CC      qga/main.o
  BUILD   optionrom/multiboot.img
  BUILD   optionrom/linuxboot.img
  BUILD   optionrom/linuxboot_dma.img
  BUILD   optionrom/kvmvapic.img
  BUILD   optionrom/multiboot.raw
  BUILD   optionrom/linuxboot.raw
  BUILD   optionrom/linuxboot_dma.raw
  BUILD   optionrom/kvmvapic.raw
  SIGN    optionrom/multiboot.bin
  SIGN    optionrom/linuxboot.bin
  SIGN    optionrom/linuxboot_dma.bin
  CC      qga/commands-posix.o
  SIGN    optionrom/kvmvapic.bin
  CC      qga/channel-posix.o
  CC      qga/qapi-generated/qga-qapi-types.o
  CC      qga/qapi-generated/qga-qapi-visit.o
  CC      qga/qapi-generated/qga-qmp-marshal.o
  AR      libqemuutil.a
  AR      libqemustub.a
  CC      qemu-img.o
  LINK    qemu-io
  LINK    qemu-bridge-helper
  LINK    ivshmem-client
  LINK    ivshmem-server
  LINK    qemu-nbd
  GEN     x86_64-softmmu/hmp-commands.h
  GEN     x86_64-softmmu/hmp-commands-info.h
  GEN     x86_64-softmmu/config-target.h
  GEN     aarch64-softmmu/hmp-commands.h
  GEN     aarch64-softmmu/config-target.h
  GEN     aarch64-softmmu/hmp-commands-info.h
  CC      x86_64-softmmu/exec.o
  CC      x86_64-softmmu/tcg/tcg.o
  CC      x86_64-softmmu/tcg/tcg-op.o
  CC      x86_64-softmmu/tcg/optimize.o
  CC      x86_64-softmmu/tcg/tcg-common.o
  CC      x86_64-softmmu/tcg/tcg-runtime.o
  CC      aarch64-softmmu/exec.o
  LINK    qemu-ga
  CC      aarch64-softmmu/tcg/tcg.o
  CC      aarch64-softmmu/tcg/tcg-op.o
  CC      aarch64-softmmu/tcg/optimize.o
  LINK    qemu-img
  CC      aarch64-softmmu/tcg/tcg-common.o
  CC      aarch64-softmmu/tcg/tcg-runtime.o
  CC      aarch64-softmmu/fpu/softfloat.o
  CC      aarch64-softmmu/disas.o
  GEN     aarch64-softmmu/gdbstub-xml.c
  CC      aarch64-softmmu/hax-stub.o
  CC      aarch64-softmmu/arch_init.o
  CC      aarch64-softmmu/cpus.o
  CC      aarch64-softmmu/monitor.o
  CC      aarch64-softmmu/gdbstub.o
  CC      aarch64-softmmu/balloon.o
  CC      aarch64-softmmu/ioport.o
  CC      aarch64-softmmu/numa.o
  CC      aarch64-softmmu/qtest.o
  CC      x86_64-softmmu/fpu/softfloat.o
  CC      x86_64-softmmu/disas.o
  CC      aarch64-softmmu/memory.o
  CC      aarch64-softmmu/memory_mapping.o
  CC      aarch64-softmmu/dump.o
  CC      aarch64-softmmu/migration/ram.o
  CC      aarch64-softmmu/qmp-introspect.o
  GEN     x86_64-softmmu/gdbstub-xml.c
  CC      aarch64-softmmu/qapi-types.o
  CC      x86_64-softmmu/hax-stub.o
  CC      x86_64-softmmu/arch_init.o
  CC      x86_64-softmmu/cpus.o
  CC      x86_64-softmmu/monitor.o
  CC      x86_64-softmmu/gdbstub.o
  CC      x86_64-softmmu/balloon.o
  CC      aarch64-softmmu/qapi-visit.o
  CC      x86_64-softmmu/ioport.o
  CC      aarch64-softmmu/qapi-event.o
  CC      x86_64-softmmu/numa.o
  CC      x86_64-softmmu/qtest.o
  CC      x86_64-softmmu/memory.o
  CC      x86_64-softmmu/memory_mapping.o
  CC      x86_64-softmmu/dump.o
  CC      x86_64-softmmu/migration/ram.o
  CC      aarch64-softmmu/qmp-marshal.o
  CC      x86_64-softmmu/qmp-introspect.o
  CC      x86_64-softmmu/qapi-types.o
  CC      x86_64-softmmu/qapi-visit.o
  CC      x86_64-softmmu/qapi-event.o
  CC      aarch64-softmmu/qmp.o
  CC      x86_64-softmmu/qmp-marshal.o
  CC      aarch64-softmmu/hmp.o
  CC      x86_64-softmmu/qmp.o
  CC      x86_64-softmmu/hmp.o
  CC      x86_64-softmmu/accel/accel.o
  CC      x86_64-softmmu/accel/kvm/kvm-all.o
  CC      aarch64-softmmu/accel/accel.o
  CC      x86_64-softmmu/accel/tcg/tcg-all.o
  CC      aarch64-softmmu/accel/stubs/kvm-stub.o
  CC      x86_64-softmmu/accel/tcg/cputlb.o
  CC      aarch64-softmmu/accel/tcg/tcg-all.o
  CC      aarch64-softmmu/accel/tcg/cputlb.o
  CC      aarch64-softmmu/accel/tcg/cpu-exec.o
  CC      aarch64-softmmu/accel/tcg/cpu-exec-common.o
  CC      x86_64-softmmu/accel/tcg/cpu-exec.o
  CC      x86_64-softmmu/accel/tcg/cpu-exec-common.o
  CC      aarch64-softmmu/accel/tcg/translate-all.o
  CC      x86_64-softmmu/accel/tcg/translate-all.o
  CC      aarch64-softmmu/hw/adc/stm32f2xx_adc.o
  CC      x86_64-softmmu/hw/block/virtio-blk.o
  CC      x86_64-softmmu/hw/block/dataplane/virtio-blk.o
  CC      aarch64-softmmu/hw/block/virtio-blk.o
  CC      aarch64-softmmu/hw/block/dataplane/virtio-blk.o
  CC      aarch64-softmmu/hw/char/exynos4210_uart.o
  CC      aarch64-softmmu/hw/char/omap_uart.o
  CC      aarch64-softmmu/hw/char/digic-uart.o
  CC      x86_64-softmmu/hw/char/virtio-serial-bus.o
  CC      aarch64-softmmu/hw/char/stm32f2xx_usart.o
  CC      aarch64-softmmu/hw/char/bcm2835_aux.o
  CC      aarch64-softmmu/hw/char/virtio-serial-bus.o
  CC      x86_64-softmmu/hw/core/generic-loader.o
  CC      aarch64-softmmu/hw/core/generic-loader.o
  CC      aarch64-softmmu/hw/core/null-machine.o
  CC      x86_64-softmmu/hw/core/null-machine.o
  CC      x86_64-softmmu/hw/display/vga.o
  CC      x86_64-softmmu/hw/display/virtio-gpu.o
  CC      aarch64-softmmu/hw/cpu/arm11mpcore.o
  CC      aarch64-softmmu/hw/cpu/realview_mpcore.o
  CC      aarch64-softmmu/hw/cpu/a9mpcore.o
  CC      x86_64-softmmu/hw/display/virtio-gpu-3d.o
  CC      aarch64-softmmu/hw/cpu/a15mpcore.o
  CC      x86_64-softmmu/hw/display/virtio-gpu-pci.o
  CC      aarch64-softmmu/hw/display/omap_dss.o
  CC      x86_64-softmmu/hw/display/virtio-vga.o
  CC      aarch64-softmmu/hw/display/omap_lcdc.o
  CC      x86_64-softmmu/hw/intc/apic.o
  CC      x86_64-softmmu/hw/intc/apic_common.o
  CC      aarch64-softmmu/hw/display/pxa2xx_lcd.o
  CC      aarch64-softmmu/hw/display/bcm2835_fb.o
  CC      x86_64-softmmu/hw/intc/ioapic.o
  CC      x86_64-softmmu/hw/isa/lpc_ich9.o
  CC      x86_64-softmmu/hw/misc/vmport.o
  CC      aarch64-softmmu/hw/display/vga.o
  CC      x86_64-softmmu/hw/misc/ivshmem.o
  CC      x86_64-softmmu/hw/misc/pvpanic.o
  CC      x86_64-softmmu/hw/misc/hyperv_testdev.o
  CC      aarch64-softmmu/hw/display/virtio-gpu.o
  CC      aarch64-softmmu/hw/display/virtio-gpu-3d.o
  CC      aarch64-softmmu/hw/display/virtio-gpu-pci.o
  CC      x86_64-softmmu/hw/misc/mmio_interface.o
  CC      aarch64-softmmu/hw/display/dpcd.o
  CC      x86_64-softmmu/hw/net/virtio-net.o
  CC      x86_64-softmmu/hw/net/vhost_net.o
  CC      x86_64-softmmu/hw/scsi/virtio-scsi.o
  CC      aarch64-softmmu/hw/display/xlnx_dp.o
  CC      x86_64-softmmu/hw/scsi/virtio-scsi-dataplane.o
  CC      x86_64-softmmu/hw/scsi/vhost-scsi-common.o
  CC      x86_64-softmmu/hw/scsi/vhost-scsi.o
  CC      x86_64-softmmu/hw/scsi/vhost-user-scsi.o
  CC      aarch64-softmmu/hw/dma/xlnx_dpdma.o
  CC      aarch64-softmmu/hw/dma/omap_dma.o
  CC      x86_64-softmmu/hw/timer/mc146818rtc.o
  CC      x86_64-softmmu/hw/vfio/common.o
  CC      x86_64-softmmu/hw/vfio/pci.o
  CC      aarch64-softmmu/hw/dma/soc_dma.o
  CC      aarch64-softmmu/hw/dma/pxa2xx_dma.o
  CC      x86_64-softmmu/hw/vfio/pci-quirks.o
  CC      aarch64-softmmu/hw/dma/bcm2835_dma.o
  CC      aarch64-softmmu/hw/gpio/omap_gpio.o
  CC      aarch64-softmmu/hw/gpio/imx_gpio.o
  CC      aarch64-softmmu/hw/gpio/bcm2835_gpio.o
  CC      x86_64-softmmu/hw/vfio/platform.o
  CC      x86_64-softmmu/hw/vfio/spapr.o
  CC      aarch64-softmmu/hw/i2c/omap_i2c.o
  CC      aarch64-softmmu/hw/input/pxa2xx_keypad.o
  CC      x86_64-softmmu/hw/virtio/virtio.o
  CC      x86_64-softmmu/hw/virtio/virtio-balloon.o
  CC      aarch64-softmmu/hw/input/tsc210x.o
  CC      x86_64-softmmu/hw/virtio/vhost.o
  CC      aarch64-softmmu/hw/intc/armv7m_nvic.o
  CC      x86_64-softmmu/hw/virtio/vhost-backend.o
  CC      aarch64-softmmu/hw/intc/exynos4210_gic.o
  CC      x86_64-softmmu/hw/virtio/vhost-user.o
  CC      x86_64-softmmu/hw/virtio/vhost-vsock.o
  CC      x86_64-softmmu/hw/virtio/virtio-crypto.o
  CC      aarch64-softmmu/hw/intc/exynos4210_combiner.o
  CC      x86_64-softmmu/hw/virtio/virtio-crypto-pci.o
  CC      x86_64-softmmu/hw/i386/multiboot.o
  CC      aarch64-softmmu/hw/intc/omap_intc.o
  CC      aarch64-softmmu/hw/intc/bcm2835_ic.o
  CC      x86_64-softmmu/hw/i386/pc.o
  CC      x86_64-softmmu/hw/i386/pc_piix.o
  CC      x86_64-softmmu/hw/i386/pc_q35.o
  CC      x86_64-softmmu/hw/i386/pc_sysfw.o
  CC      x86_64-softmmu/hw/i386/x86-iommu.o
  CC      x86_64-softmmu/hw/i386/intel_iommu.o
  CC      aarch64-softmmu/hw/intc/bcm2836_control.o
  CC      x86_64-softmmu/hw/i386/amd_iommu.o
  CC      x86_64-softmmu/hw/i386/kvmvapic.o
  CC      x86_64-softmmu/hw/i386/acpi-build.o
  CC      x86_64-softmmu/hw/i386/pci-assign-load-rom.o
  CC      aarch64-softmmu/hw/intc/allwinner-a10-pic.o
/tmp/qemu-test/src/hw/i386/pc_piix.c: In function ‘igd_passthrough_isa_bridge_create’:
/tmp/qemu-test/src/hw/i386/pc_piix.c:1065: warning: ‘pch_rev_id’ may be used uninitialized in this function
  CC      x86_64-softmmu/hw/i386/kvm/clock.o
  CC      x86_64-softmmu/hw/i386/kvm/apic.o
  CC      x86_64-softmmu/hw/i386/kvm/i8259.o
  CC      aarch64-softmmu/hw/intc/aspeed_vic.o
  CC      aarch64-softmmu/hw/intc/arm_gicv3_cpuif.o
  CC      x86_64-softmmu/hw/i386/kvm/ioapic.o
  CC      aarch64-softmmu/hw/misc/ivshmem.o
  CC      aarch64-softmmu/hw/misc/arm_sysctl.o
  CC      x86_64-softmmu/hw/i386/kvm/i8254.o
/tmp/qemu-test/src/hw/i386/acpi-build.c: In function ‘build_append_pci_bus_devices’:
/tmp/qemu-test/src/hw/i386/acpi-build.c:539: warning: ‘notify_method’ may be used uninitialized in this function
  CC      aarch64-softmmu/hw/misc/cbus.o
  CC      x86_64-softmmu/hw/i386/kvm/pci-assign.o
  CC      x86_64-softmmu/target/i386/helper.o
  CC      aarch64-softmmu/hw/misc/exynos4210_pmu.o
  CC      x86_64-softmmu/target/i386/cpu.o
  CC      aarch64-softmmu/hw/misc/exynos4210_clk.o
  CC      aarch64-softmmu/hw/misc/exynos4210_rng.o
  CC      aarch64-softmmu/hw/misc/imx_ccm.o
  CC      x86_64-softmmu/target/i386/gdbstub.o
  CC      x86_64-softmmu/target/i386/xsave_helper.o
  CC      x86_64-softmmu/target/i386/translate.o
  CC      aarch64-softmmu/hw/misc/imx31_ccm.o
  CC      x86_64-softmmu/target/i386/bpt_helper.o
  CC      x86_64-softmmu/target/i386/cc_helper.o
  CC      x86_64-softmmu/target/i386/excp_helper.o
  CC      aarch64-softmmu/hw/misc/imx25_ccm.o
  CC      x86_64-softmmu/target/i386/fpu_helper.o
  CC      aarch64-softmmu/hw/misc/imx6_ccm.o
  CC      aarch64-softmmu/hw/misc/imx6_src.o
  CC      aarch64-softmmu/hw/misc/mst_fpga.o
  CC      x86_64-softmmu/target/i386/int_helper.o
  CC      aarch64-softmmu/hw/misc/omap_clk.o
  CC      x86_64-softmmu/target/i386/mem_helper.o
  CC      x86_64-softmmu/target/i386/misc_helper.o
  CC      aarch64-softmmu/hw/misc/omap_gpmc.o
  CC      aarch64-softmmu/hw/misc/omap_l4.o
  CC      aarch64-softmmu/hw/misc/omap_sdrc.o
  CC      x86_64-softmmu/target/i386/mpx_helper.o
  CC      aarch64-softmmu/hw/misc/omap_tap.o
  CC      aarch64-softmmu/hw/misc/bcm2835_mbox.o
  CC      x86_64-softmmu/target/i386/seg_helper.o
  CC      x86_64-softmmu/target/i386/smm_helper.o
  CC      aarch64-softmmu/hw/misc/bcm2835_property.o
  CC      aarch64-softmmu/hw/misc/bcm2835_rng.o
  CC      x86_64-softmmu/target/i386/svm_helper.o
  CC      aarch64-softmmu/hw/misc/zynq_slcr.o
  CC      x86_64-softmmu/target/i386/machine.o
  CC      aarch64-softmmu/hw/misc/zynq-xadc.o
  CC      x86_64-softmmu/target/i386/arch_memory_mapping.o
  CC      aarch64-softmmu/hw/misc/stm32f2xx_syscfg.o
  CC      aarch64-softmmu/hw/misc/mps2-scc.o
  CC      x86_64-softmmu/target/i386/arch_dump.o
  CC      x86_64-softmmu/target/i386/monitor.o
  CC      x86_64-softmmu/target/i386/kvm.o
  CC      aarch64-softmmu/hw/misc/auxbus.o
  CC      aarch64-softmmu/hw/misc/aspeed_scu.o
  CC      x86_64-softmmu/target/i386/hyperv.o
  CC      aarch64-softmmu/hw/misc/aspeed_sdmc.o
  GEN     trace/generated-helpers.c
  CC      x86_64-softmmu/trace/control-target.o
  CC      aarch64-softmmu/hw/misc/mmio_interface.o
  CC      x86_64-softmmu/trace/qmp.o
  CC      aarch64-softmmu/hw/net/virtio-net.o
  CC      x86_64-softmmu/gdbstub-xml.o
  CC      aarch64-softmmu/hw/net/vhost_net.o
  CC      aarch64-softmmu/hw/pcmcia/pxa2xx.o
  CC      aarch64-softmmu/hw/scsi/virtio-scsi.o
  CC      aarch64-softmmu/hw/scsi/virtio-scsi-dataplane.o
  CC      aarch64-softmmu/hw/scsi/vhost-scsi-common.o
  CC      x86_64-softmmu/trace/generated-helpers.o
  CC      aarch64-softmmu/hw/scsi/vhost-scsi.o
  CC      aarch64-softmmu/hw/scsi/vhost-user-scsi.o
  CC      aarch64-softmmu/hw/sd/omap_mmc.o
  CC      aarch64-softmmu/hw/sd/pxa2xx_mmci.o
  CC      aarch64-softmmu/hw/sd/bcm2835_sdhost.o
  CC      aarch64-softmmu/hw/ssi/omap_spi.o
  CC      aarch64-softmmu/hw/ssi/imx_spi.o
  CC      aarch64-softmmu/hw/timer/exynos4210_mct.o
  CC      aarch64-softmmu/hw/timer/exynos4210_pwm.o
  CC      aarch64-softmmu/hw/timer/exynos4210_rtc.o
  CC      aarch64-softmmu/hw/timer/omap_gptimer.o
  CC      aarch64-softmmu/hw/timer/omap_synctimer.o
  CC      aarch64-softmmu/hw/timer/pxa2xx_timer.o
  CC      aarch64-softmmu/hw/timer/digic-timer.o
  CC      aarch64-softmmu/hw/timer/allwinner-a10-pit.o
  CC      aarch64-softmmu/hw/usb/tusb6010.o
  CC      aarch64-softmmu/hw/vfio/common.o
  CC      aarch64-softmmu/hw/vfio/pci.o
  CC      aarch64-softmmu/hw/vfio/pci-quirks.o
  CC      aarch64-softmmu/hw/vfio/platform.o
  CC      aarch64-softmmu/hw/vfio/calxeda-xgmac.o
  CC      aarch64-softmmu/hw/vfio/amd-xgbe.o
  CC      aarch64-softmmu/hw/vfio/spapr.o
  CC      aarch64-softmmu/hw/virtio/virtio.o
  CC      aarch64-softmmu/hw/virtio/virtio-balloon.o
  CC      aarch64-softmmu/hw/virtio/vhost.o
  CC      aarch64-softmmu/hw/virtio/vhost-backend.o
  CC      aarch64-softmmu/hw/virtio/vhost-user.o
  CC      aarch64-softmmu/hw/virtio/vhost-vsock.o
  CC      aarch64-softmmu/hw/virtio/virtio-crypto.o
  CC      aarch64-softmmu/hw/virtio/virtio-crypto-pci.o
  CC      aarch64-softmmu/hw/arm/boot.o
  CC      aarch64-softmmu/hw/arm/collie.o
  CC      aarch64-softmmu/hw/arm/exynos4_boards.o
  CC      aarch64-softmmu/hw/arm/gumstix.o
  LINK    x86_64-softmmu/qemu-system-x86_64
  CC      aarch64-softmmu/hw/arm/highbank.o
  CC      aarch64-softmmu/hw/arm/digic_boards.o
  CC      aarch64-softmmu/hw/arm/integratorcp.o
  CC      aarch64-softmmu/hw/arm/mainstone.o
  CC      aarch64-softmmu/hw/arm/musicpal.o
  CC      aarch64-softmmu/hw/arm/nseries.o
  CC      aarch64-softmmu/hw/arm/omap_sx1.o
  CC      aarch64-softmmu/hw/arm/palm.o
  CC      aarch64-softmmu/hw/arm/realview.o
  CC      aarch64-softmmu/hw/arm/spitz.o
  CC      aarch64-softmmu/hw/arm/stellaris.o
  CC      aarch64-softmmu/hw/arm/tosa.o
  CC      aarch64-softmmu/hw/arm/versatilepb.o
  CC      aarch64-softmmu/hw/arm/vexpress.o
  CC      aarch64-softmmu/hw/arm/virt.o
  CC      aarch64-softmmu/hw/arm/xilinx_zynq.o
  CC      aarch64-softmmu/hw/arm/z2.o
  CC      aarch64-softmmu/hw/arm/virt-acpi-build.o
  CC      aarch64-softmmu/hw/arm/netduino2.o
  CC      aarch64-softmmu/hw/arm/sysbus-fdt.o
  CC      aarch64-softmmu/hw/arm/armv7m.o
  CC      aarch64-softmmu/hw/arm/exynos4210.o
  CC      aarch64-softmmu/hw/arm/pxa2xx.o
  CC      aarch64-softmmu/hw/arm/pxa2xx_gpio.o
  CC      aarch64-softmmu/hw/arm/pxa2xx_pic.o
  CC      aarch64-softmmu/hw/arm/digic.o
  CC      aarch64-softmmu/hw/arm/omap1.o
  CC      aarch64-softmmu/hw/arm/omap2.o
  CC      aarch64-softmmu/hw/arm/strongarm.o
  CC      aarch64-softmmu/hw/arm/allwinner-a10.o
  CC      aarch64-softmmu/hw/arm/cubieboard.o
  CC      aarch64-softmmu/hw/arm/bcm2835_peripherals.o
  CC      aarch64-softmmu/hw/arm/bcm2836.o
  CC      aarch64-softmmu/hw/arm/raspi.o
  CC      aarch64-softmmu/hw/arm/stm32f205_soc.o
  CC      aarch64-softmmu/hw/arm/xlnx-zynqmp.o
  CC      aarch64-softmmu/hw/arm/xlnx-ep108.o
  CC      aarch64-softmmu/hw/arm/fsl-imx25.o
  CC      aarch64-softmmu/hw/arm/imx25_pdk.o
  CC      aarch64-softmmu/hw/arm/fsl-imx31.o
  CC      aarch64-softmmu/hw/arm/kzm.o
  CC      aarch64-softmmu/hw/arm/fsl-imx6.o
  CC      aarch64-softmmu/hw/arm/sabrelite.o
  CC      aarch64-softmmu/hw/arm/aspeed_soc.o
  CC      aarch64-softmmu/hw/arm/aspeed.o
  CC      aarch64-softmmu/hw/arm/mps2.o
  CC      aarch64-softmmu/target/arm/arm-semi.o
  CC      aarch64-softmmu/target/arm/machine.o
  CC      aarch64-softmmu/target/arm/psci.o
  CC      aarch64-softmmu/target/arm/arch_dump.o
  CC      aarch64-softmmu/target/arm/monitor.o
  CC      aarch64-softmmu/target/arm/kvm-stub.o
  CC      aarch64-softmmu/target/arm/translate.o
  CC      aarch64-softmmu/target/arm/op_helper.o
  CC      aarch64-softmmu/target/arm/helper.o
  CC      aarch64-softmmu/target/arm/cpu.o
  CC      aarch64-softmmu/target/arm/neon_helper.o
  CC      aarch64-softmmu/target/arm/iwmmxt_helper.o
  CC      aarch64-softmmu/target/arm/gdbstub.o
  CC      aarch64-softmmu/target/arm/cpu64.o
  CC      aarch64-softmmu/target/arm/translate-a64.o
  CC      aarch64-softmmu/target/arm/helper-a64.o
  CC      aarch64-softmmu/target/arm/gdbstub64.o
  CC      aarch64-softmmu/target/arm/crypto_helper.o
  CC      aarch64-softmmu/target/arm/arm-powerctl.o
  GEN     trace/generated-helpers.c
  CC      aarch64-softmmu/trace/control-target.o
  CC      aarch64-softmmu/trace/qmp.o
  CC      aarch64-softmmu/gdbstub-xml.o
  CC      aarch64-softmmu/trace/generated-helpers.o
/tmp/qemu-test/src/target/arm/translate-a64.c: In function ‘handle_shri_with_rndacc’:
/tmp/qemu-test/src/target/arm/translate-a64.c:6372: warning: ‘tcg_src_hi’ may be used uninitialized in this function
/tmp/qemu-test/src/target/arm/translate-a64.c: In function ‘disas_simd_scalar_two_reg_misc’:
/tmp/qemu-test/src/target/arm/translate-a64.c:8099: warning: ‘rmode’ may be used uninitialized in this function
  LINK    aarch64-softmmu/qemu-system-aarch64
make[1]: Leaving directory '/var/tmp/patchew-tester-tmp-h8optu9x/src'

real	3m22.368s
user	0m4.907s
sys	0m1.721s
  BUILD   fedora
make[1]: Entering directory '/var/tmp/patchew-tester-tmp-h8optu9x/src'
  ARCHIVE qemu.tgz
  ARCHIVE dtc.tgz
  COPY    RUNNER
    RUN test-mingw in qemu:fedora 
Packages installed:
PyYAML-3.11-13.fc25.x86_64
SDL-devel-1.2.15-21.fc24.x86_64
bc-1.06.95-16.fc24.x86_64
bison-3.0.4-4.fc24.x86_64
bzip2-1.0.6-21.fc25.x86_64
ccache-3.3.4-1.fc25.x86_64
clang-3.9.1-2.fc25.x86_64
findutils-4.6.0-8.fc25.x86_64
flex-2.6.0-3.fc25.x86_64
gcc-6.3.1-1.fc25.x86_64
gcc-c++-6.3.1-1.fc25.x86_64
git-2.9.4-1.fc25.x86_64
glib2-devel-2.50.3-1.fc25.x86_64
hostname-3.15-8.fc25.x86_64
libaio-devel-0.3.110-6.fc24.x86_64
libfdt-devel-1.4.2-1.fc25.x86_64
make-4.1-6.fc25.x86_64
mingw32-SDL-1.2.15-7.fc24.noarch
mingw32-bzip2-1.0.6-7.fc24.noarch
mingw32-curl-7.47.0-1.fc24.noarch
mingw32-glib2-2.50.3-1.fc25.noarch
mingw32-gmp-6.1.1-1.fc25.noarch
mingw32-gnutls-3.5.5-2.fc25.noarch
mingw32-gtk2-2.24.31-2.fc25.noarch
mingw32-gtk3-3.22.17-1.fc25.noarch
mingw32-libjpeg-turbo-1.5.1-1.fc25.noarch
mingw32-libpng-1.6.27-1.fc25.noarch
mingw32-libssh2-1.4.3-5.fc24.noarch
mingw32-libtasn1-4.9-1.fc25.noarch
mingw32-nettle-3.3-1.fc25.noarch
mingw32-pixman-0.34.0-1.fc25.noarch
mingw32-pkg-config-0.28-6.fc24.x86_64
mingw64-SDL-1.2.15-7.fc24.noarch
mingw64-bzip2-1.0.6-7.fc24.noarch
mingw64-curl-7.47.0-1.fc24.noarch
mingw64-glib2-2.50.3-1.fc25.noarch
mingw64-gmp-6.1.1-1.fc25.noarch
mingw64-gnutls-3.5.5-2.fc25.noarch
mingw64-gtk2-2.24.31-2.fc25.noarch
mingw64-gtk3-3.22.17-1.fc25.noarch
mingw64-libjpeg-turbo-1.5.1-1.fc25.noarch
mingw64-libpng-1.6.27-1.fc25.noarch
mingw64-libssh2-1.4.3-5.fc24.noarch
mingw64-libtasn1-4.9-1.fc25.noarch
mingw64-nettle-3.3-1.fc25.noarch
mingw64-pixman-0.34.0-1.fc25.noarch
mingw64-pkg-config-0.28-6.fc24.x86_64
package python2 is not installed
perl-5.24.2-387.fc25.x86_64
pixman-devel-0.34.0-2.fc24.x86_64
sparse-0.5.0-10.fc25.x86_64
tar-1.29-3.fc25.x86_64
which-2.21-1.fc25.x86_64
zlib-devel-1.2.8-10.fc24.x86_64

Environment variables:
PACKAGES=ccache git tar PyYAML sparse flex bison python2 bzip2 hostname     glib2-devel pixman-devel zlib-devel SDL-devel libfdt-devel     gcc gcc-c++ clang make perl which bc findutils libaio-devel     mingw32-pixman mingw32-glib2 mingw32-gmp mingw32-SDL mingw32-pkg-config     mingw32-gtk2 mingw32-gtk3 mingw32-gnutls mingw32-nettle mingw32-libtasn1     mingw32-libjpeg-turbo mingw32-libpng mingw32-curl mingw32-libssh2     mingw32-bzip2     mingw64-pixman mingw64-glib2 mingw64-gmp mingw64-SDL mingw64-pkg-config     mingw64-gtk2 mingw64-gtk3 mingw64-gnutls mingw64-nettle mingw64-libtasn1     mingw64-libjpeg-turbo mingw64-libpng mingw64-curl mingw64-libssh2     mingw64-bzip2
HOSTNAME=befaad95d8c9
TERM=xterm
MAKEFLAGS= -j8
HISTSIZE=1000
J=8
USER=root
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.m4a=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.oga=01;36:*.opus=01;36:*.spx=01;36:*.xspf=01;36:
CCACHE_DIR=/var/tmp/ccache
EXTRA_CONFIGURE_OPTS=
V=
SHOW_ENV=1
MAIL=/var/spool/mail/root
PATH=/usr/lib/ccache:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
TARGET_LIST=
HISTCONTROL=ignoredups
FGC=f25
SHLVL=1
HOME=/root
TEST_DIR=/tmp/qemu-test
DISTTAG=f25container
LOGNAME=root
LESSOPEN=||/usr/bin/lesspipe.sh %s
FEATURES=mingw clang pyyaml dtc
DEBUG=
_=/usr/bin/env

Configure options:
--enable-werror --target-list=x86_64-softmmu,aarch64-softmmu --prefix=/var/tmp/qemu-build/install --cross-prefix=x86_64-w64-mingw32- --enable-trace-backends=simple --enable-debug --enable-gnutls --enable-nettle --enable-curl --enable-vnc --enable-bzip2 --enable-guest-agent --with-sdlabi=1.2 --with-gtkabi=2.0
Install prefix    /var/tmp/qemu-build/install
BIOS directory    /var/tmp/qemu-build/install
binary directory  /var/tmp/qemu-build/install
library directory /var/tmp/qemu-build/install/lib
module directory  /var/tmp/qemu-build/install/lib
libexec directory /var/tmp/qemu-build/install/libexec
include directory /var/tmp/qemu-build/install/include
config directory  /var/tmp/qemu-build/install
local state directory   queried at runtime
Windows SDK       no
Source path       /tmp/qemu-test/src
C compiler        x86_64-w64-mingw32-gcc
Host C compiler   cc
C++ compiler      x86_64-w64-mingw32-g++
Objective-C compiler clang
ARFLAGS           rv
CFLAGS            -g 
QEMU_CFLAGS       -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/pixman-1  -I$(SRC_PATH)/dtc/libfdt -Werror -mms-bitfields -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/glib-2.0 -I/usr/x86_64-w64-mingw32/sys-root/mingw/lib/glib-2.0/include -I/usr/x86_64-w64-mingw32/sys-root/mingw/include  -m64 -mcx16 -mthreads -D__USE_MINGW_ANSI_STDIO=1 -DWIN32_LEAN_AND_MEAN -DWINVER=0x501 -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-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/x86_64-w64-mingw32/sys-root/mingw/include -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/p11-kit-1 -I/usr/x86_64-w64-mingw32/sys-root/mingw/include  -I/usr/x86_64-w64-mingw32/sys-root/mingw/include   -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/libpng16 
LDFLAGS           -Wl,--nxcompat -Wl,--no-seh -Wl,--dynamicbase -Wl,--warn-common -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    no
profiler          no
static build      no
pixman            system
SDL support       yes (1.2.15)
GTK support       yes (2.24.31)
GTK GL support    no
VTE support       no 
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    no
virgl support     no
curl support      yes
mingw32 support   yes
Audio drivers     dsound
Block whitelist (rw) 
Block whitelist (ro) 
VirtFS support    no
VNC support       yes
VNC SASL support  no
VNC JPEG support  yes
VNC PNG support   yes
xen support       no
brlapi support    no
bluez  support    no
Documentation     no
PIE               no
vde support       no
netmap support    no
Linux AIO support no
ATTR/XATTR support no
Install blobs     yes
KVM support       no
HAX support       yes
TCG support       yes
TCG debug enabled yes
TCG interpreter   no
RDMA support      no
fdt support       yes
preadv support    no
fdatasync         no
madvise           no
posix_madvise     no
libcap-ng support no
vhost-net support no
vhost-scsi support no
vhost-vsock support no
vhost-user support no
Trace backends    simple
Trace output file trace-<pid>
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 yes
QGA MSI support   no
seccomp support   no
coroutine backend win32
coroutine pool    yes
debug stack usage no
crypto afalg      no
GlusterFS support no
gcov              gcov
gcov enabled      no
TPM support       yes
libssh2 support   yes
TPM passthrough   no
QOM debugging     yes
Live block migration yes
lzo support       no
snappy support    no
bzip2 support     yes
NUMA host support no
tcmalloc support  no
jemalloc support  no
avx2 optimization yes
replication support yes
VxHS block device no
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     qmp-commands.h
  GEN     qapi-types.h
  GEN     qapi-visit.h
  GEN     qapi-event.h
  GEN     x86_64-softmmu/config-devices.mak
  GEN     qmp-marshal.c
  GEN     qapi-types.c
  GEN     aarch64-softmmu/config-devices.mak
  GEN     qapi-visit.c
  GEN     qapi-event.c
  GEN     qmp-introspect.h
  GEN     qmp-introspect.c
  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     tests/test-qapi-types.h
  GEN     tests/test-qapi-visit.h
  GEN     tests/test-qmp-commands.h
  GEN     tests/test-qapi-event.h
  GEN     tests/test-qmp-introspect.h
  GEN     trace-root.h
  GEN     util/trace.h
  GEN     crypto/trace.h
  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/virtio/trace.h
  GEN     hw/audio/trace.h
  GEN     hw/misc/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/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/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/xen/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     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/virtio/trace.c
  GEN     hw/audio/trace.c
  GEN     hw/misc/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/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/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/xen/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     config-all-devices.mak
	 DEP /tmp/qemu-test/src/dtc/tests/dumptrees.c
	 DEP /tmp/qemu-test/src/dtc/tests/trees.S
	 DEP /tmp/qemu-test/src/dtc/tests/testutils.c
	 DEP /tmp/qemu-test/src/dtc/tests/value-labels.c
	 DEP /tmp/qemu-test/src/dtc/tests/asm_tree_dump.c
	 DEP /tmp/qemu-test/src/dtc/tests/truncated_property.c
	 DEP /tmp/qemu-test/src/dtc/tests/check_path.c
	 DEP /tmp/qemu-test/src/dtc/tests/overlay_bad_fixup.c
	 DEP /tmp/qemu-test/src/dtc/tests/subnode_iterate.c
	 DEP /tmp/qemu-test/src/dtc/tests/overlay.c
	 DEP /tmp/qemu-test/src/dtc/tests/integer-expressions.c
	 DEP /tmp/qemu-test/src/dtc/tests/property_iterate.c
	 DEP /tmp/qemu-test/src/dtc/tests/utilfdt_test.c
	 DEP /tmp/qemu-test/src/dtc/tests/path_offset_aliases.c
	 DEP /tmp/qemu-test/src/dtc/tests/add_subnode_with_nops.c
	 DEP /tmp/qemu-test/src/dtc/tests/dtbs_equal_unordered.c
	 DEP /tmp/qemu-test/src/dtc/tests/dtb_reverse.c
	 DEP /tmp/qemu-test/src/dtc/tests/dtbs_equal_ordered.c
	 DEP /tmp/qemu-test/src/dtc/tests/extra-terminating-null.c
	 DEP /tmp/qemu-test/src/dtc/tests/incbin.c
	 DEP /tmp/qemu-test/src/dtc/tests/boot-cpuid.c
	 DEP /tmp/qemu-test/src/dtc/tests/phandle_format.c
	 DEP /tmp/qemu-test/src/dtc/tests/path-references.c
	 DEP /tmp/qemu-test/src/dtc/tests/string_escapes.c
	 DEP /tmp/qemu-test/src/dtc/tests/references.c
	 DEP /tmp/qemu-test/src/dtc/tests/propname_escapes.c
	 DEP /tmp/qemu-test/src/dtc/tests/appendprop2.c
	 DEP /tmp/qemu-test/src/dtc/tests/appendprop1.c
	 DEP /tmp/qemu-test/src/dtc/tests/del_node.c
	 DEP /tmp/qemu-test/src/dtc/tests/del_property.c
	 DEP /tmp/qemu-test/src/dtc/tests/setprop.c
	 DEP /tmp/qemu-test/src/dtc/tests/set_name.c
	 DEP /tmp/qemu-test/src/dtc/tests/rw_tree1.c
	 DEP /tmp/qemu-test/src/dtc/tests/open_pack.c
	 DEP /tmp/qemu-test/src/dtc/tests/nopulate.c
	 DEP /tmp/qemu-test/src/dtc/tests/mangle-layout.c
	 DEP /tmp/qemu-test/src/dtc/tests/move_and_save.c
	 DEP /tmp/qemu-test/src/dtc/tests/sw_tree1.c
	 DEP /tmp/qemu-test/src/dtc/tests/nop_node.c
	 DEP /tmp/qemu-test/src/dtc/tests/nop_property.c
	 DEP /tmp/qemu-test/src/dtc/tests/setprop_inplace.c
	 DEP /tmp/qemu-test/src/dtc/tests/stringlist.c
	 DEP /tmp/qemu-test/src/dtc/tests/addr_size_cells.c
	 DEP /tmp/qemu-test/src/dtc/tests/notfound.c
	 DEP /tmp/qemu-test/src/dtc/tests/sized_cells.c
	 DEP /tmp/qemu-test/src/dtc/tests/char_literal.c
	 DEP /tmp/qemu-test/src/dtc/tests/node_offset_by_compatible.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_alias.c
	 DEP /tmp/qemu-test/src/dtc/tests/node_check_compatible.c
	 DEP /tmp/qemu-test/src/dtc/tests/node_offset_by_phandle.c
	 DEP /tmp/qemu-test/src/dtc/tests/node_offset_by_prop_value.c
	 DEP /tmp/qemu-test/src/dtc/tests/parent_offset.c
	 DEP /tmp/qemu-test/src/dtc/tests/supernode_atdepth_offset.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_path.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_phandle.c
	 DEP /tmp/qemu-test/src/dtc/tests/getprop.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_name.c
	 DEP /tmp/qemu-test/src/dtc/tests/path_offset.c
	 DEP /tmp/qemu-test/src/dtc/tests/subnode_offset.c
	 DEP /tmp/qemu-test/src/dtc/tests/root_node.c
	 DEP /tmp/qemu-test/src/dtc/tests/find_property.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_mem_rsv.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_overlay.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_addresses.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_empty_tree.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_strerror.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_rw.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_wip.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_sw.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_ro.c
	 DEP /tmp/qemu-test/src/dtc/util.c
	 DEP /tmp/qemu-test/src/dtc/fdtput.c
	 DEP /tmp/qemu-test/src/dtc/fdtget.c
	 DEP /tmp/qemu-test/src/dtc/fdtdump.c
	 LEX convert-dtsv0-lexer.lex.c
	 DEP /tmp/qemu-test/src/dtc/srcpos.c
	 BISON dtc-parser.tab.c
	 LEX dtc-lexer.lex.c
	 DEP /tmp/qemu-test/src/dtc/treesource.c
	 DEP /tmp/qemu-test/src/dtc/livetree.c
	 DEP /tmp/qemu-test/src/dtc/fstree.c
	 DEP /tmp/qemu-test/src/dtc/flattree.c
	 DEP /tmp/qemu-test/src/dtc/dtc.c
	 DEP /tmp/qemu-test/src/dtc/data.c
	 DEP /tmp/qemu-test/src/dtc/checks.c
	 DEP convert-dtsv0-lexer.lex.c
	 DEP dtc-parser.tab.c
	 DEP dtc-lexer.lex.c
	CHK version_gen.h
	UPD version_gen.h
	 DEP /tmp/qemu-test/src/dtc/util.c
	 CC libfdt/fdt.o
	 CC libfdt/fdt_ro.o
	 CC libfdt/fdt_wip.o
	 CC libfdt/fdt_rw.o
	 CC libfdt/fdt_sw.o
	 CC libfdt/fdt_strerror.o
	 CC libfdt/fdt_empty_tree.o
	 CC libfdt/fdt_addresses.o
	 CC libfdt/fdt_overlay.o
	 AR libfdt/libfdt.a
x86_64-w64-mingw32-ar: creating libfdt/libfdt.a
a - libfdt/fdt.o
a - libfdt/fdt_ro.o
a - libfdt/fdt_wip.o
a - libfdt/fdt_sw.o
a - libfdt/fdt_rw.o
a - libfdt/fdt_strerror.o
a - libfdt/fdt_empty_tree.o
a - libfdt/fdt_addresses.o
a - libfdt/fdt_overlay.o
  RC      version.o
  GEN     qga/qapi-generated/qga-qapi-types.h
  GEN     qga/qapi-generated/qga-qapi-visit.h
  GEN     qga/qapi-generated/qga-qmp-commands.h
  GEN     qga/qapi-generated/qga-qapi-visit.c
  GEN     qga/qapi-generated/qga-qmp-marshal.c
  GEN     qga/qapi-generated/qga-qapi-types.c
  CC      qapi-types.o
  CC      qapi-visit.o
  CC      qapi/qapi-visit-core.o
  CC      qapi/qapi-dealloc-visitor.o
  CC      qapi/qobject-input-visitor.o
  CC      qapi/qmp-registry.o
  CC      qapi/qmp-dispatch.o
  CC      qapi/qobject-output-visitor.o
  CC      qapi/string-input-visitor.o
  CC      qapi/string-output-visitor.o
  CC      qapi/opts-visitor.o
  CC      qapi/qapi-clone-visitor.o
  CC      qapi/qmp-event.o
  CC      qapi/qapi-util.o
  CC      qobject/qnull.o
  CC      qobject/qnum.o
  CC      qobject/qstring.o
  CC      qobject/qdict.o
  CC      qobject/qlist.o
  CC      qobject/qbool.o
  CC      qobject/qlit.o
  CC      qobject/qjson.o
  CC      qobject/qobject.o
  CC      qobject/json-lexer.o
  CC      qobject/json-streamer.o
  CC      qobject/json-parser.o
  CC      trace/simple.o
  CC      trace/control.o
  CC      util/osdep.o
  CC      util/cutils.o
  CC      util/unicode.o
  CC      util/qemu-timer-common.o
  CC      util/bufferiszero.o
  CC      util/lockcnt.o
  CC      util/aiocb.o
  CC      util/async.o
  CC      util/thread-pool.o
  CC      util/qemu-timer.o
  CC      util/main-loop.o
  CC      util/iohandler.o
  CC      util/aio-win32.o
  CC      util/event_notifier-win32.o
  CC      util/oslib-win32.o
  CC      util/qemu-thread-win32.o
  CC      util/envlist.o
  CC      util/path.o
  CC      util/module.o
  CC      util/host-utils.o
  CC      util/bitmap.o
  CC      util/bitops.o
  CC      util/hbitmap.o
  CC      util/fifo8.o
  CC      util/acl.o
  CC      util/cacheinfo.o
  CC      util/error.o
  CC      util/qemu-error.o
  CC      util/id.o
  CC      util/iov.o
  CC      util/qemu-config.o
  CC      util/qemu-sockets.o
  CC      util/uri.o
  CC      util/notify.o
  CC      util/qemu-option.o
  CC      util/qemu-progress.o
  CC      util/keyval.o
  CC      util/hexdump.o
  CC      util/crc32c.o
  CC      util/uuid.o
  CC      util/throttle.o
  CC      util/getauxval.o
  CC      util/readline.o
  CC      util/rcu.o
  CC      util/qemu-coroutine.o
  CC      util/qemu-coroutine-lock.o
  CC      util/qemu-coroutine-io.o
  CC      util/qemu-coroutine-sleep.o
  CC      util/coroutine-win32.o
  CC      util/buffer.o
  CC      util/timed-average.o
  CC      util/base64.o
  CC      util/log.o
  CC      util/qdist.o
  CC      util/qht.o
  CC      util/range.o
  CC      util/stats64.o
  CC      util/systemd.o
  CC      trace-root.o
  CC      util/trace.o
  CC      crypto/trace.o
  CC      io/trace.o
  CC      migration/trace.o
  CC      block/trace.o
  CC      chardev/trace.o
  CC      hw/block/trace.o
  CC      hw/block/dataplane/trace.o
  CC      hw/char/trace.o
  CC      hw/intc/trace.o
  CC      hw/net/trace.o
  CC      hw/virtio/trace.o
  CC      hw/audio/trace.o
  CC      hw/misc/trace.o
  CC      hw/usb/trace.o
  CC      hw/scsi/trace.o
  CC      hw/nvram/trace.o
  CC      hw/display/trace.o
  CC      hw/input/trace.o
  CC      hw/timer/trace.o
  CC      hw/dma/trace.o
  CC      hw/sparc/trace.o
  CC      hw/sd/trace.o
  CC      hw/isa/trace.o
  CC      hw/mem/trace.o
  CC      hw/i386/trace.o
  CC      hw/i386/xen/trace.o
  CC      hw/9pfs/trace.o
  CC      hw/ppc/trace.o
  CC      hw/pci/trace.o
  CC      hw/s390x/trace.o
  CC      hw/vfio/trace.o
  CC      hw/acpi/trace.o
  CC      hw/arm/trace.o
  CC      hw/alpha/trace.o
  CC      hw/xen/trace.o
  CC      ui/trace.o
  CC      audio/trace.o
  CC      net/trace.o
  CC      target/arm/trace.o
  CC      target/i386/trace.o
  CC      target/mips/trace.o
  CC      target/sparc/trace.o
  CC      target/s390x/trace.o
  CC      target/ppc/trace.o
  CC      qom/trace.o
  CC      linux-user/trace.o
  CC      qapi/trace.o
  CC      accel/tcg/trace.o
  CC      accel/kvm/trace.o
  CC      nbd/trace.o
  CC      crypto/pbkdf-stub.o
  CC      stubs/bdrv-next-monitor-owned.o
  CC      stubs/blk-commit-all.o
  CC      stubs/blockdev-close-all-bdrv-states.o
  CC      stubs/clock-warp.o
  CC      stubs/cpu-get-clock.o
  CC      stubs/cpu-get-icount.o
  CC      stubs/dump.o
  CC      stubs/error-printf.o
  CC      stubs/fdset.o
  CC      stubs/gdbstub.o
  CC      stubs/get-vm-name.o
  CC      stubs/iothread.o
  CC      stubs/iothread-lock.o
  CC      stubs/is-daemonized.o
  CC      stubs/machine-init-done.o
  CC      stubs/migr-blocker.o
  CC      stubs/change-state-handler.o
  CC      stubs/monitor.o
  CC      stubs/notify-event.o
  CC      stubs/qapi-event.o
  CC      stubs/qtest.o
  CC      stubs/replay.o
  CC      stubs/runstate-check.o
  CC      stubs/set-fd-handler.o
  CC      stubs/slirp.o
  CC      stubs/sysbus.o
  CC      stubs/trace-control.o
  CC      stubs/uuid.o
  CC      stubs/vm-stop.o
  CC      stubs/vmstate.o
  CC      stubs/fd-register.o
  CC      stubs/qmp_pc_dimm_device_list.o
  CC      stubs/target-monitor-defs.o
  CC      stubs/target-get-monitor-def.o
  CC      stubs/pc_madt_cpu_entry.o
  CC      stubs/vmgenid.o
  CC      stubs/xen-common.o
  CC      stubs/xen-hvm.o
  GEN     qemu-img-cmds.h
  CC      block.o
  CC      blockjob.o
  CC      qemu-io-cmds.o
  CC      replication.o
  CC      block/raw-format.o
  CC      block/qcow.o
  CC      block/vdi.o
  CC      block/vmdk.o
  CC      block/cloop.o
  CC      block/bochs.o
  CC      block/vpc.o
  CC      block/vvfat.o
  CC      block/dmg.o
  CC      block/qcow2.o
  CC      block/qcow2-refcount.o
  CC      block/qcow2-cluster.o
  CC      block/qcow2-snapshot.o
  CC      block/qcow2-cache.o
  CC      block/qcow2-bitmap.o
  CC      block/qed.o
  CC      block/qed-l2-cache.o
  CC      block/qed-table.o
  CC      block/qed-cluster.o
  CC      block/qed-check.o
  CC      block/vhdx.o
  CC      block/vhdx-endian.o
  CC      block/vhdx-log.o
  CC      block/quorum.o
  CC      block/parallels.o
  CC      block/blkdebug.o
  CC      block/blkverify.o
  CC      block/blkreplay.o
  CC      block/block-backend.o
  CC      block/snapshot.o
  CC      block/qapi.o
  CC      block/file-win32.o
  CC      block/win32-aio.o
  CC      block/null.o
  CC      block/mirror.o
  CC      block/commit.o
  CC      block/io.o
  CC      block/throttle-groups.o
In file included from /tmp/qemu-test/src/block/file-win32.c:25:0:
/tmp/qemu-test/src/block/file-win32.c: In function 'raw_truncate':
/tmp/qemu-test/src/block/file-win32.c:473:38: error: 'reallocMode_lookup' undeclared (first use in this function)
                    qapi_enum_lookup(&reallocMode_lookup, prealloc));
                                      ^
/tmp/qemu-test/src/include/qapi/error.h:162:35: note: in definition of macro 'error_setg'
                         (fmt), ## __VA_ARGS__)
                                   ^~~~~~~~~~~
/tmp/qemu-test/src/block/file-win32.c:473:38: note: each undeclared identifier is reported only once for each function it appears in
                    qapi_enum_lookup(&reallocMode_lookup, prealloc));
                                      ^
/tmp/qemu-test/src/include/qapi/error.h:162:35: note: in definition of macro 'error_setg'
                         (fmt), ## __VA_ARGS__)
                                   ^~~~~~~~~~~
/tmp/qemu-test/src/rules.mak:66: recipe for target 'block/file-win32.o' failed
make: *** [block/file-win32.o] Error 1
make: *** Waiting for unfinished jobs....
Traceback (most recent call last):
  File "./tests/docker/docker.py", line 382, in <module>
    sys.exit(main())
  File "./tests/docker/docker.py", line 379, in main
    return args.cmdobj.run(args, argv)
  File "./tests/docker/docker.py", line 237, in run
    return Docker().run(argv, args.keep, quiet=args.quiet)
  File "./tests/docker/docker.py", line 205, in run
    quiet=quiet)
  File "./tests/docker/docker.py", line 123, 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=84cc5aaa874811e7aedf52540069c830', '-u', '0', '-t', '--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', '/var/tmp/patchew-tester-tmp-h8optu9x/src/docker-src.2017-08-22-10.45.15.8837:/var/tmp/qemu:z,ro', '-v', '/root/.cache/qemu-docker-ccache:/var/tmp/ccache:z', 'qemu:fedora', '/var/tmp/qemu/run', 'test-mingw']' returned non-zero exit status 2
make[1]: *** [tests/docker/Makefile.include:139: docker-run] Error 1
make[1]: Leaving directory '/var/tmp/patchew-tester-tmp-h8optu9x/src'
make: *** [tests/docker/Makefile.include:168: docker-run-test-mingw@fedora] Error 2

real	2m2.540s
user	0m5.081s
sys	0m1.568s
=== 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] 140+ messages in thread

* Re: [Qemu-devel] [PATCH v2 01/54] qapi: fix type_seen key error
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 01/54] qapi: fix type_seen key error Marc-André Lureau
@ 2017-08-22 15:00   ` Markus Armbruster
  2017-08-22 15:50     ` Marc-André Lureau
  2017-08-25  6:02   ` Markus Armbruster
  1 sibling, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-08-22 15:00 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> The type_seen member can be of a different type than the 'qtype' being
> checked, since a string create several conflicts. Lookup the real
> conflicting type in the conflict set, that one must be present in
> type_seen.
>
> This fixes the following error, reproducible with the modified test:
>
> Traceback (most recent call last):
>   File "/home/elmarco/src/qq/tests/qapi-schema/test-qapi.py", line 56, in <module>
>     schema = QAPISchema(sys.argv[1])
>   File "/home/elmarco/src/qq/scripts/qapi.py", line 1470, in __init__
>     self.exprs = check_exprs(parser.exprs)
>   File "/home/elmarco/src/qq/scripts/qapi.py", line 959, in check_exprs
>     check_alternate(expr, info)
>   File "/home/elmarco/src/qq/scripts/qapi.py", line 831, in check_alternate
>     % (name, key, types_seen[qtype]))
> KeyError: 'QTYPE_QSTRING'
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi.py                                  | 6 ++++--
>  tests/qapi-schema/alternate-conflict-string.json | 4 ++--
>  2 files changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/scripts/qapi.py b/scripts/qapi.py
> index 8aa2775f12..a3ac799535 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi.py
> @@ -825,10 +825,12 @@ def check_alternate(expr, info):
>              else:
>                  conflicting.add('QTYPE_QNUM')
>                  conflicting.add('QTYPE_QBOOL')
> -        if conflicting & set(types_seen):
> +        conflict = conflicting & set(types_seen)
> +        if conflict:
> +            conflict_qtype = list(conflict)[0]

Converting from set to list just to extract an element is clumsly.
Let's use conflict.pop(), and eliminate the variable.  Can do on commit.

>              raise QAPISemError(info, "Alternate '%s' member '%s' can't "
>                                 "be distinguished from member '%s'"
> -                               % (name, key, types_seen[qtype]))
> +                               % (name, key, types_seen[conflict_qtype]))
>          for qt in conflicting:
>              types_seen[qt] = key
>  
> diff --git a/tests/qapi-schema/alternate-conflict-string.json b/tests/qapi-schema/alternate-conflict-string.json
> index 85adbd4adc..bb2702978e 100644
> --- a/tests/qapi-schema/alternate-conflict-string.json
> +++ b/tests/qapi-schema/alternate-conflict-string.json
> @@ -1,4 +1,4 @@
>  # alternate branches of 'str' type conflict with all scalar types
>  { 'alternate': 'Alt',
> -  'data': { 'one': 'str',
> -            'two': 'int' } }
> +  'data': { 'one': 'int',
> +            'two': 'str' } }

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

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

* Re: [Qemu-devel] [PATCH v2 02/54] qdict: add qdict_put_null() helper
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 02/54] qdict: add qdict_put_null() helper Marc-André Lureau
@ 2017-08-22 15:09   ` Markus Armbruster
  2017-08-25 15:46     ` Eric Blake
  0 siblings, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-08-22 15:09 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>
> ---
>  include/qapi/qmp/qdict.h | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
> index 363e431106..a35bed9f16 100644
> --- a/include/qapi/qmp/qdict.h
> +++ b/include/qapi/qmp/qdict.h
> @@ -60,6 +60,8 @@ void qdict_destroy_obj(QObject *obj);
   /* Helpers for int, bool, and string */
   #define qdict_put_int(qdict, key, value) \
           qdict_put(qdict, key, qnum_from_int(value))
   #define qdict_put_bool(qdict, key, value) \
>          qdict_put(qdict, key, qbool_from_bool(value))
>  #define qdict_put_str(qdict, key, value) \
>          qdict_put(qdict, key, qstring_from_str(value))
> +#define qdict_put_null(qdict, key) \
> +        qdict_put(qdict, key, qnull())
>  
>  /* High level helpers */
>  double qdict_get_double(const QDict *qdict, const char *key);

Marginal.  I can accept it for completeness's sake, or rather a step
towards completeness.  But please update the "Helpers for ..." comment,
and convert existing qdict_put(QD, K, qnull()) to use qdict_put_null().
A quick grep finds some in target/i386/cpu.c.  There might be more.

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

* Re: [Qemu-devel] [PATCH v2 51/54] qapi: make s390 commands depend on TARGET_S390X
  2017-08-22 14:41       ` Marc-André Lureau
@ 2017-08-22 15:14         ` Cornelia Huck
  2017-08-22 15:46           ` Marc-André Lureau
  0 siblings, 1 reply; 140+ messages in thread
From: Cornelia Huck @ 2017-08-22 15:14 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: David Hildenbrand, qemu-devel, Alexander Graf, Markus Armbruster,
	Dr. David Alan Gilbert, Paolo Bonzini, Richard Henderson

On Tue, 22 Aug 2017 10:41:34 -0400 (EDT)
Marc-André Lureau <marcandre.lureau@redhat.com> wrote:

> Hi
> 
> ----- Original Message -----
> > On 22.08.2017 16:24, Cornelia Huck wrote:  
> > > On Tue, 22 Aug 2017 15:22:52 +0200
> > > Marc-André Lureau <marcandre.lureau@redhat.com> wrote:

> > >> @@ -4621,7 +4622,9 @@
> > >>  ##
> > >>  { 'command': 'query-cpu-model-comparison',
> > >>    'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
> > >> -  'returns': 'CpuModelCompareInfo' }
> > >> +  'returns': 'CpuModelCompareInfo',
> > >> +  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
> > >> +
> > >>  
> > >>  ##
> > >>  # @CpuModelBaselineInfo:
> > >> @@ -4673,7 +4676,8 @@
> > >>  { 'command': 'query-cpu-model-baseline',
> > >>    'data': { 'modela': 'CpuModelInfo',
> > >>              'modelb': 'CpuModelInfo' },
> > >> -  'returns': 'CpuModelBaselineInfo' }
> > >> +  'returns': 'CpuModelBaselineInfo',
> > >> +  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}  
> > > 
> > > ...but I'm not sure about the cpu model stuff. Wasn't the idea to move
> > > to this model for all architectures later? (Given that we have stubs
> > > for architectures not implementing this, instead of ifdeffing it in
> > > monitor.c)
> > >   
> > 
> > +1, not architecture specific (in contrast to skey), simply not
> > supported _yet_ on other architectures.  
> 
> We can add other archs once they implement it. See for example:
> "qapi: make query-cpu-model-expansion depend on s390 or x86"

That seems a bit like whack-a-mole, though. Depending on something like
"provides cpumodel feature xy" makes it clearer that this is supposed
to be non-architecture-specific.

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

* Re: [Qemu-devel] [PATCH v2 03/54] qobject: add literal qobject type
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 03/54] qobject: add literal qobject type Marc-André Lureau
@ 2017-08-22 15:31   ` Markus Armbruster
  2017-08-22 15:42     ` Marc-André Lureau
  0 siblings, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-08-22 15:31 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

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

> Promote LiteralQObject from tests/check-qjson.c to qobject/qlit.c,
> allowing to statically declare complex qobjects.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Your patch does more than that!  It also

* renames the now externally visible identifiers,

* adds support for qnull and qnum,

* cleans up types (int vs. bool) and style,

* makes compare_litqobj_to_qobj() case QTYPE_QNULL and QTYPE_QSTRING
  more robust, and

* fixes bugs in compare_litqobj_to_qobj() case QTYPE_QDICT, QTYPE_QLIST
  (I think).

Squashing the renames into the code motion is tolerable, but the rest
isn't, because it makes patch review harder for no benefit at all.
Moreover, the commit message fails to record the changes.  I noticed
them only because out of an abundance of caution I checked the patch is
just what it's advertised to be: code motion.  Well, it isn't.

Separate patches, please!

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

* Re: [Qemu-devel] [PATCH v2 04/54] qlit: add qobject_form_qlit()
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 04/54] qlit: add qobject_form_qlit() Marc-André Lureau
@ 2017-08-22 15:40   ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-08-22 15:40 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Typo in the subject: s/form/from/

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

> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  include/qapi/qmp/qlit.h |  2 ++
>  qobject/qlit.c          | 37 +++++++++++++++++++++++++++++++++++++
>  tests/check-qlit.c      | 26 ++++++++++++++++++++++++++
>  3 files changed, 65 insertions(+)
>
> diff --git a/include/qapi/qmp/qlit.h b/include/qapi/qmp/qlit.h
> index 2cdceb448d..dd562b7d69 100644
> --- a/include/qapi/qmp/qlit.h
> +++ b/include/qapi/qmp/qlit.h
> @@ -51,4 +51,6 @@ struct QLitDictEntry {
>  
>  bool qlit_equal_qobject(QLitObject *lhs, QObject *rhs);
>  
> +QObject *qobject_from_qlit(const QLitObject *qlit);
> +
>  #endif /* QLIT_H_ */
> diff --git a/qobject/qlit.c b/qobject/qlit.c
> index f4ebeb6259..5a2aa44355 100644
> --- a/qobject/qlit.c
> +++ b/qobject/qlit.c
> @@ -104,3 +104,40 @@ bool qlit_equal_qobject(QLitObject *lhs, QObject *rhs)
>  
>      return false;
>  }
> +
> +QObject *qobject_from_qlit(const QLitObject *qlit)
> +{
> +    int i;
> +
> +    switch (qlit->type) {
> +    case QTYPE_QNULL:
> +        return QOBJECT(qnull());
> +    case QTYPE_QNUM:
> +        return QOBJECT(qnum_from_int(qlit->value.qnum));
> +    case QTYPE_QSTRING:
> +        return QOBJECT(qstring_from_str(qlit->value.qstr));
> +    case QTYPE_QDICT: {
> +        QDict *qdict = qdict_new();
> +        for (i = 0; qlit->value.qdict[i].value.type != QTYPE_NONE; i++) {

Terser:

           for (i = 0; qlit->value.qdict[i].key; i++) {

> +            QLitDictEntry *e = &qlit->value.qdict[i];
> +
> +            qdict_put_obj(qdict, e->key, qobject_from_qlit(&e->value));
> +        }
> +        return QOBJECT(qdict);
> +    }
> +    case QTYPE_QLIST: {
> +        QList *qlist = qlist_new();
> +
> +        for (i = 0; qlit->value.qlist[i].type != QTYPE_NONE; i++) {

Could omit != QTYPE_NONE, because we're very much relying on QTYPE_NONE
being zero anyway.  Matter of taste.

> +            qlist_append_obj(qlist, qobject_from_qlit(&qlit->value.qlist[i]));
> +        }
> +        return QOBJECT(qlist);
> +    }
> +    case QTYPE_QBOOL:
> +        return QOBJECT(qbool_from_bool(qlit->value.qbool));
> +    case QTYPE_NONE:

Make that

       default:

to remove all doubt.

> +        assert(0);
> +    }
> +
> +    return NULL;
> +}
> diff --git a/tests/check-qlit.c b/tests/check-qlit.c
> index 5736b61ebf..f25f3d9633 100644
> --- a/tests/check-qlit.c
> +++ b/tests/check-qlit.c
> @@ -58,11 +58,37 @@ static void qlit_equal_qobject_test(void)
>      qobject_decref(qobj);
>  }
>  
> +static void qobject_from_qlit_test(void)
> +{
> +    QObject *obj, *qobj = qobject_from_qlit(&qlit);
> +    QDict *qdict;
> +    QList *bee;
> +
> +    qdict = qobject_to_qdict(qobj);
> +    g_assert_cmpint(qdict_get_int(qdict, "foo"), ==, 42);
> +    g_assert_cmpstr(qdict_get_str(qdict, "bar"), ==, "hello world");
> +    g_assert(qobject_type(qdict_get(qdict, "baz")) == QTYPE_QNULL);
> +
> +    bee = qdict_get_qlist(qdict, "bee");
> +    obj = qlist_pop(bee);
> +    g_assert_cmpint(qnum_get_int(qobject_to_qnum(obj)), ==, 43);
> +    qobject_decref(obj);
> +    obj = qlist_pop(bee);
> +    g_assert_cmpint(qnum_get_int(qobject_to_qnum(obj)), ==, 44);
> +    qobject_decref(obj);
> +    obj = qlist_pop(bee);
> +    g_assert(qbool_get_bool(qobject_to_qbool(obj)));
> +    qobject_decref(obj);
> +
> +    qobject_decref(qobj);
> +}
> +
>  int main(int argc, char **argv)
>  {
>      g_test_init(&argc, &argv, NULL);
>  
>      g_test_add_func("/qlit/equal_qobject", qlit_equal_qobject_test);
> +    g_test_add_func("/qlit/qobject_from_qlit", qobject_from_qlit_test);
>  
>      return g_test_run();
>  }

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

* Re: [Qemu-devel] [PATCH v2 03/54] qobject: add literal qobject type
  2017-08-22 15:31   ` Markus Armbruster
@ 2017-08-22 15:42     ` Marc-André Lureau
  2017-08-22 16:24       ` Markus Armbruster
  0 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 15:42 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel

Hi

----- Original Message -----
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> 
> > Promote LiteralQObject from tests/check-qjson.c to qobject/qlit.c,
> > allowing to statically declare complex qobjects.
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> 
> Your patch does more than that!  It also
> 
> * renames the now externally visible identifiers,
> 
> * adds support for qnull and qnum,
> 
> * cleans up types (int vs. bool) and style,
> 
> * makes compare_litqobj_to_qobj() case QTYPE_QNULL and QTYPE_QSTRING
>   more robust, and
> 
> * fixes bugs in compare_litqobj_to_qobj() case QTYPE_QDICT, QTYPE_QLIST
>   (I think).
> 
> Squashing the renames into the code motion is tolerable, but the rest
> isn't, because it makes patch review harder for no benefit at all.

The title said "add" and in the commit message "promote", it's not just a "move".

Imho, it's best to take a fresh look at the implementation since it is no longer in tests and can be used from qemu/programs.

As such you can review the code as "new" code, and check the corresponding tests. Finally, the existing test is simply adapted to that code.

> Moreover, the commit message fails to record the changes.  I noticed
> them only because out of an abundance of caution I checked the patch is
> just what it's advertised to be: code motion.  Well, it isn't.
> 
> Separate patches, please!

Sure, I can do that, I just thought it was extra overhead given my approach.

thanks

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

* Re: [Qemu-devel] [PATCH v2 51/54] qapi: make s390 commands depend on TARGET_S390X
  2017-08-22 15:14         ` Cornelia Huck
@ 2017-08-22 15:46           ` Marc-André Lureau
  0 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 15:46 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: David Hildenbrand, qemu-devel, Alexander Graf, Markus Armbruster,
	Dr. David Alan Gilbert, Paolo Bonzini, Richard Henderson

Hi

----- Original Message -----
> On Tue, 22 Aug 2017 10:41:34 -0400 (EDT)
> Marc-André Lureau <marcandre.lureau@redhat.com> wrote:
> 
> > Hi
> > 
> > ----- Original Message -----
> > > On 22.08.2017 16:24, Cornelia Huck wrote:
> > > > On Tue, 22 Aug 2017 15:22:52 +0200
> > > > Marc-André Lureau <marcandre.lureau@redhat.com> wrote:
> 
> > > >> @@ -4621,7 +4622,9 @@
> > > >>  ##
> > > >>  { 'command': 'query-cpu-model-comparison',
> > > >>    'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
> > > >> -  'returns': 'CpuModelCompareInfo' }
> > > >> +  'returns': 'CpuModelCompareInfo',
> > > >> +  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
> > > >> +
> > > >>  
> > > >>  ##
> > > >>  # @CpuModelBaselineInfo:
> > > >> @@ -4673,7 +4676,8 @@
> > > >>  { 'command': 'query-cpu-model-baseline',
> > > >>    'data': { 'modela': 'CpuModelInfo',
> > > >>              'modelb': 'CpuModelInfo' },
> > > >> -  'returns': 'CpuModelBaselineInfo' }
> > > >> +  'returns': 'CpuModelBaselineInfo',
> > > >> +  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
> > > > 
> > > > ...but I'm not sure about the cpu model stuff. Wasn't the idea to move
> > > > to this model for all architectures later? (Given that we have stubs
> > > > for architectures not implementing this, instead of ifdeffing it in
> > > > monitor.c)
> > > >   
> > > 
> > > +1, not architecture specific (in contrast to skey), simply not
> > > supported _yet_ on other architectures.
> > 
> > We can add other archs once they implement it. See for example:
> > "qapi: make query-cpu-model-expansion depend on s390 or x86"
> 
> That seems a bit like whack-a-mole, though. Depending on something like
> "provides cpumodel feature xy" makes it clearer that this is supposed
> to be non-architecture-specific.

I would say the function name and documentation should say if it's architecture specific. The #ifdef in qapi generation or in qemu code base is just an implementation detail. I suggest to add FIXME in the schema so people looking at this realize it's not yet there (instead of error stubs in qemu code / runtime).
> 

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

* Re: [Qemu-devel] [PATCH v2 01/54] qapi: fix type_seen key error
  2017-08-22 15:00   ` Markus Armbruster
@ 2017-08-22 15:50     ` Marc-André Lureau
  2017-08-22 16:40       ` Markus Armbruster
  0 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-22 15:50 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth

Hi

----- Original Message -----
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> 
> > The type_seen member can be of a different type than the 'qtype' being
> > checked, since a string create several conflicts. Lookup the real
> > conflicting type in the conflict set, that one must be present in
> > type_seen.
> >
> > This fixes the following error, reproducible with the modified test:
> >
> > Traceback (most recent call last):
> >   File "/home/elmarco/src/qq/tests/qapi-schema/test-qapi.py", line 56, in
> >   <module>
> >     schema = QAPISchema(sys.argv[1])
> >   File "/home/elmarco/src/qq/scripts/qapi.py", line 1470, in __init__
> >     self.exprs = check_exprs(parser.exprs)
> >   File "/home/elmarco/src/qq/scripts/qapi.py", line 959, in check_exprs
> >     check_alternate(expr, info)
> >   File "/home/elmarco/src/qq/scripts/qapi.py", line 831, in check_alternate
> >     % (name, key, types_seen[qtype]))
> > KeyError: 'QTYPE_QSTRING'
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >  scripts/qapi.py                                  | 6 ++++--
> >  tests/qapi-schema/alternate-conflict-string.json | 4 ++--
> >  2 files changed, 6 insertions(+), 4 deletions(-)
> >
> > diff --git a/scripts/qapi.py b/scripts/qapi.py
> > index 8aa2775f12..a3ac799535 100644
> > --- a/scripts/qapi.py
> > +++ b/scripts/qapi.py
> > @@ -825,10 +825,12 @@ def check_alternate(expr, info):
> >              else:
> >                  conflicting.add('QTYPE_QNUM')
> >                  conflicting.add('QTYPE_QBOOL')
> > -        if conflicting & set(types_seen):
> > +        conflict = conflicting & set(types_seen)
> > +        if conflict:
> > +            conflict_qtype = list(conflict)[0]
> 
> Converting from set to list just to extract an element is clumsly.
> Let's use conflict.pop(), and eliminate the variable.  Can do on commit.

I didn't realize that. thanks

> 
> >              raise QAPISemError(info, "Alternate '%s' member '%s' can't "
> >                                 "be distinguished from member '%s'"
> > -                               % (name, key, types_seen[qtype]))
> > +                               % (name, key, types_seen[conflict_qtype]))
> >          for qt in conflicting:
> >              types_seen[qt] = key
> >  
> > diff --git a/tests/qapi-schema/alternate-conflict-string.json
> > b/tests/qapi-schema/alternate-conflict-string.json
> > index 85adbd4adc..bb2702978e 100644
> > --- a/tests/qapi-schema/alternate-conflict-string.json
> > +++ b/tests/qapi-schema/alternate-conflict-string.json
> > @@ -1,4 +1,4 @@
> >  # alternate branches of 'str' type conflict with all scalar types
> >  { 'alternate': 'Alt',
> > -  'data': { 'one': 'str',
> > -            'two': 'int' } }
> > +  'data': { 'one': 'int',
> > +            'two': 'str' } }
> 
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
> 

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

* Re: [Qemu-devel] [PATCH v2 51/54] qapi: make s390 commands depend on TARGET_S390X
  2017-08-22 14:25     ` David Hildenbrand
  2017-08-22 14:41       ` Marc-André Lureau
@ 2017-08-22 15:58       ` Markus Armbruster
  2017-08-22 16:01         ` David Hildenbrand
  1 sibling, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-08-22 15:58 UTC (permalink / raw)
  To: David Hildenbrand
  Cc: Cornelia Huck, Marc-André Lureau, Alexander Graf,
	qemu-devel, Paolo Bonzini, Dr. David Alan Gilbert,
	Richard Henderson

David Hildenbrand <david@redhat.com> writes:

> On 22.08.2017 16:24, Cornelia Huck wrote:
>> On Tue, 22 Aug 2017 15:22:52 +0200
>> Marc-André Lureau <marcandre.lureau@redhat.com> wrote:
>> 
>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>>> ---
>>>  qapi-schema.json                        | 10 +++++++---
>>>  include/sysemu/arch_init.h              |  6 ------
>>>  monitor.c                               | 14 --------------
>>>  qmp.c                                   | 14 --------------
>>>  stubs/arch-query-cpu-model-baseline.c   | 12 ------------
>>>  stubs/arch-query-cpu-model-comparison.c | 12 ------------
>>>  target/s390x/cpu_models.c               |  4 ++--
>>>  stubs/Makefile.objs                     |  2 --
>>>  8 files changed, 9 insertions(+), 65 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-schema.json b/qapi-schema.json
>>> index 58574b3044..d4e1552ddc 100644
>>> --- a/qapi-schema.json
>>> +++ b/qapi-schema.json
>>> @@ -3577,7 +3577,8 @@
>>>  #
>>>  ##
>>>  { 'command': 'dump-skeys',
>>> -  'data': { 'filename': 'str' } }
>>> +  'data': { 'filename': 'str' },
>>> +  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
>> 
>> I agree with making this s390x specific...
>>>  
>>>  ##
>>>  # @netdev_add:
>>> @@ -4621,7 +4622,9 @@
>>>  ##
>>>  { 'command': 'query-cpu-model-comparison',
>>>    'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
>>> -  'returns': 'CpuModelCompareInfo' }
>>> +  'returns': 'CpuModelCompareInfo',
>>> +  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
>>> +
>>>  
>>>  ##
>>>  # @CpuModelBaselineInfo:
>>> @@ -4673,7 +4676,8 @@
>>>  { 'command': 'query-cpu-model-baseline',
>>>    'data': { 'modela': 'CpuModelInfo',
>>>              'modelb': 'CpuModelInfo' },
>>> -  'returns': 'CpuModelBaselineInfo' }
>>> +  'returns': 'CpuModelBaselineInfo',
>>> +  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
>> 
>> ...but I'm not sure about the cpu model stuff. Wasn't the idea to move
>> to this model for all architectures later? (Given that we have stubs
>> for architectures not implementing this, instead of ifdeffing it in
>> monitor.c)
>> 
>
> +1, not architecture specific (in contrast to skey), simply not
> supported _yet_ on other architectures.

Yes, but Marc-André's patch makes the "not supported yet" information
available in query-qmp-schema.  Carrying such information is pretty much
the point of schema introspection.

We could add a comment explaining this command isn't target-specific,
but just happens not to be implemented for some targets.  Would that
help?

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

* Re: [Qemu-devel] [PATCH v2 51/54] qapi: make s390 commands depend on TARGET_S390X
  2017-08-22 15:58       ` Markus Armbruster
@ 2017-08-22 16:01         ` David Hildenbrand
  2017-08-22 16:25           ` Markus Armbruster
  0 siblings, 1 reply; 140+ messages in thread
From: David Hildenbrand @ 2017-08-22 16:01 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: Cornelia Huck, Marc-André Lureau, Alexander Graf,
	qemu-devel, Paolo Bonzini, Dr. David Alan Gilbert,
	Richard Henderson


> Yes, but Marc-André's patch makes the "not supported yet" information
> available in query-qmp-schema.  Carrying such information is pretty much
> the point of schema introspection.
> 
> We could add a comment explaining this command isn't target-specific,
> but just happens not to be implemented for some targets.  Would that
> help?
> 

Certainly!

-- 

Thanks,

David

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

* Re: [Qemu-devel] [PATCH v2 03/54] qobject: add literal qobject type
  2017-08-22 15:42     ` Marc-André Lureau
@ 2017-08-22 16:24       ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-08-22 16:24 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

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

> Hi
>
> ----- Original Message -----
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>> 
>> > Promote LiteralQObject from tests/check-qjson.c to qobject/qlit.c,
>> > allowing to statically declare complex qobjects.
>> >
>> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> 
>> Your patch does more than that!  It also
>> 
>> * renames the now externally visible identifiers,
>> 
>> * adds support for qnull and qnum,
>> 
>> * cleans up types (int vs. bool) and style,
>> 
>> * makes compare_litqobj_to_qobj() case QTYPE_QNULL and QTYPE_QSTRING
>>   more robust, and
>> 
>> * fixes bugs in compare_litqobj_to_qobj() case QTYPE_QDICT, QTYPE_QLIST
>>   (I think).
>> 
>> Squashing the renames into the code motion is tolerable, but the rest
>> isn't, because it makes patch review harder for no benefit at all.
>
> The title said "add" and in the commit message "promote", it's not just a "move".

Yes, that's what it says, and it fooled me just fine %-}

> Imho, it's best to take a fresh look at the implementation since it is no longer in tests and can be used from qemu/programs.
>
> As such you can review the code as "new" code, and check the corresponding tests. Finally, the existing test is simply adapted to that code.
>
>> Moreover, the commit message fails to record the changes.  I noticed
>> them only because out of an abundance of caution I checked the patch is
>> just what it's advertised to be: code motion.  Well, it isn't.
>> 
>> Separate patches, please!
>
> Sure, I can do that, I just thought it was extra overhead given my approach.

Thanks.

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

* Re: [Qemu-devel] [PATCH v2 51/54] qapi: make s390 commands depend on TARGET_S390X
  2017-08-22 16:01         ` David Hildenbrand
@ 2017-08-22 16:25           ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-08-22 16:25 UTC (permalink / raw)
  To: David Hildenbrand
  Cc: qemu-devel, Cornelia Huck, Dr. David Alan Gilbert,
	Alexander Graf, Paolo Bonzini, Marc-André Lureau,
	Richard Henderson

David Hildenbrand <david@redhat.com> writes:

>> Yes, but Marc-André's patch makes the "not supported yet" information
>> available in query-qmp-schema.  Carrying such information is pretty much
>> the point of schema introspection.
>> 
>> We could add a comment explaining this command isn't target-specific,
>> but just happens not to be implemented for some targets.  Would that
>> help?
>> 
>
> Certainly!

Let's do it then.

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

* Re: [Qemu-devel] [PATCH v2 05/54] qapi: generate a literal qobject for introspection
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 05/54] qapi: generate a literal qobject for introspection Marc-André Lureau
@ 2017-08-22 16:33   ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-08-22 16:33 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth, Dr. David Alan Gilbert

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

> Replace the generated json string with a literal qobject. The later is
> easier to deal with, at run time as well as compile time: adding #if
> conditionals will be easier than in a json string.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi-introspect.py         | 91 ++++++++++++++++++++++----------------
>  monitor.c                          |  2 +-
>  tests/test-qobject-input-visitor.c | 11 +++--
>  docs/devel/qapi-code-gen.txt       | 29 +++++++-----
>  4 files changed, 80 insertions(+), 53 deletions(-)
>
> diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
> index 032bcea491..1b96926fa7 100644
> --- a/scripts/qapi-introspect.py
> +++ b/scripts/qapi-introspect.py
> @@ -12,72 +12,80 @@
>  from qapi import *
>  
>  
> -# Caveman's json.dumps() replacement (we're stuck at Python 2.4)
> -# TODO try to use json.dumps() once we get unstuck
> -def to_json(obj, level=0):
> +def to_c_string(s):
> +    return '"' + s.replace('\\', r'\\').replace('"', r'\"') + '"'
> +
> +
> +def to_qlit(obj, level=0, first_indent=True):

I still think suppress_first_indent=False would be nicer, but it's not
worth arguing now.

> +
> +    def indent(level):
> +        return level * 4 * ' '
> +
> +    ret = ''
> +    if first_indent:
> +        ret += indent(level)
>      if obj is None:
> -        ret = 'null'
> +        ret += 'QLIT_QNULL'
>      elif isinstance(obj, str):
> -        ret = '"' + obj.replace('"', r'\"') + '"'
> +        ret += 'QLIT_QSTR(' + to_c_string(obj) + ')'
>      elif isinstance(obj, list):
> -        elts = [to_json(elt, level + 1)
> +        elts = [to_qlit(elt, level + 1)
>                  for elt in obj]
> -        ret = '[' + ', '.join(elts) + ']'
> +        elts.append(indent(level + 1) + "{}")
> +        ret += 'QLIT_QLIST(((QLitObject[]) {\n'
> +        ret += ',\n'.join(elts) + '\n'
> +        ret += indent(level) + '}))'
>      elif isinstance(obj, dict):
> -        elts = ['"%s": %s' % (key.replace('"', r'\"'),
> -                              to_json(obj[key], level + 1))
> -                for key in sorted(obj.keys())]
> -        ret = '{' + ', '.join(elts) + '}'
> +        elts = []
> +        for key, value in sorted(obj.iteritems()):
> +            elts.append(indent(level + 1) + '{ %s, %s }' %
> +                        (to_c_string(key), to_qlit(value, level + 1, False)))
> +        elts.append(indent(level + 1) + '{}')
> +        ret += 'QLIT_QDICT(((QLitDictEntry[]) {\n'
> +        ret += ',\n'.join(elts) + '\n'
> +        ret += indent(level) + '}))'
>      else:
>          assert False                # not implemented
> -    if level == 1:
> -        ret = '\n' + ret
>      return ret

Note to self: is there simple a way to get rid of the extra pair of
parenthesis in QLIT_QLIST(( ... )) and QLIT_QDICT(( ... ))?

>  
>  
> -def to_c_string(string):
> -    return '"' + string.replace('\\', r'\\').replace('"', r'\"') + '"'
> -
> -

Let's not move to_c_string() without need.

>  class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor):
>      def __init__(self, unmask):
>          self._unmask = unmask
>          self.defn = None
>          self.decl = None
>          self._schema = None
> -        self._jsons = None
> +        self._qlits = None
>          self._used_types = None
>          self._name_map = None
>  
>      def visit_begin(self, schema):
>          self._schema = schema
> -        self._jsons = []
> +        self._qlits = []
>          self._used_types = []
>          self._name_map = {}
>  
>      def visit_end(self):
>          # visit the types that are actually used
> -        jsons = self._jsons
> -        self._jsons = []
> +        qlits = self._qlits
> +        self._qlits = []
>          for typ in self._used_types:
>              typ.visit(self)
>          # generate C
>          # TODO can generate awfully long lines
> -        jsons.extend(self._jsons)
> -        name = c_name(prefix, protect=False) + 'qmp_schema_json'
> +        qlits.extend(self._qlits)
> +        name = c_name(prefix, protect=False) + 'qmp_schema_qlit'
>          self.decl = mcgen('''
> -extern const char %(c_name)s[];
> +extern const QLitObject %(c_name)s;
>  ''',
>                            c_name=c_name(name))
> -        lines = to_json(jsons).split('\n')
> -        c_string = '\n    '.join([to_c_string(line) for line in lines])
>          self.defn = mcgen('''
> -const char %(c_name)s[] = %(c_string)s;
> +const QLitObject %(c_name)s = %(c_string)s;
>  ''',
>                            c_name=c_name(name),
> -                          c_string=c_string)
> +                          c_string=to_qlit(qlits))
>          self._schema = None
> -        self._jsons = None
> +        self._qlits = None
>          self._used_types = None
>          self._name_map = None
>  
> @@ -111,12 +119,12 @@ const char %(c_name)s[] = %(c_string)s;
>              return '[' + self._use_type(typ.element_type) + ']'
>          return self._name(typ.name)
>  
> -    def _gen_json(self, name, mtype, obj):
> +    def _gen_qlit(self, name, mtype, obj):
>          if mtype not in ('command', 'event', 'builtin', 'array'):
>              name = self._name(name)
>          obj['name'] = name
>          obj['meta-type'] = mtype
> -        self._jsons.append(obj)
> +        self._qlits.append(obj)
>  
>      def _gen_member(self, member):
>          ret = {'name': member.name, 'type': self._use_type(member.type)}
> @@ -132,24 +140,24 @@ const char %(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_json(name, 'builtin', {'json-type': json_type})
> +        self._gen_qlit(name, 'builtin', {'json-type': json_type})
>  
>      def visit_enum_type(self, name, info, values, prefix):
> -        self._gen_json(name, 'enum', {'values': values})
> +        self._gen_qlit(name, 'enum', {'values': values})
>  
>      def visit_array_type(self, name, info, element_type):
>          element = self._use_type(element_type)
> -        self._gen_json('[' + element + ']', 'array', {'element-type': element})
> +        self._gen_qlit('[' + element + ']', 'array', {'element-type': element})
>  
>      def visit_object_type_flat(self, name, info, 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_json(name, 'object', obj)
> +        self._gen_qlit(name, 'object', obj)
>  
>      def visit_alternate_type(self, name, info, variants):
> -        self._gen_json(name, 'alternate',
> +        self._gen_qlit(name, 'alternate',
>                         {'members': [{'type': self._use_type(m.type)}
>                                      for m in variants.variants]})
>  
> @@ -157,13 +165,13 @@ const char %(c_name)s[] = %(c_string)s;
>                        gen, success_response, boxed):
>          arg_type = arg_type or self._schema.the_empty_object_type
>          ret_type = ret_type or self._schema.the_empty_object_type
> -        self._gen_json(name, 'command',
> +        self._gen_qlit(name, 'command',
>                         {'arg-type': self._use_type(arg_type),
>                          'ret-type': self._use_type(ret_type)})
>  
>      def visit_event(self, name, info, arg_type, boxed):
>          arg_type = arg_type or self._schema.the_empty_object_type
> -        self._gen_json(name, 'event', {'arg-type': self._use_type(arg_type)})
> +        self._gen_qlit(name, 'event', {'arg-type': self._use_type(arg_type)})
>  
>  # Debugging aid: unmask QAPI schema's type names
>  # We normally mask them, because they're not QMP wire ABI
> @@ -205,11 +213,18 @@ h_comment = '''
>  
>  fdef.write(mcgen('''
>  #include "qemu/osdep.h"
> +#include "qapi/qmp/qlit.h"
>  #include "%(prefix)sqmp-introspect.h"
>  
>  ''',
>                   prefix=prefix))
>  
> +fdecl.write(mcgen('''
> +#include "qemu/osdep.h"
> +#include "qapi/qmp/qlit.h"
> +
> +'''))
> +
>  schema = QAPISchema(input_file)
>  gen = QAPISchemaGenIntrospectVisitor(opt_unmask)
>  schema.visit(gen)
> diff --git a/monitor.c b/monitor.c
> index e0f880107f..14c27d4b6f 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -953,7 +953,7 @@ EventInfoList *qmp_query_events(Error **errp)
>  static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
>                                   Error **errp)
>  {
> -    *ret_data = qobject_from_json(qmp_schema_json, &error_abort);
> +    *ret_data = qobject_from_qlit(&qmp_schema_qlit);
>  }
>  
>  /*
> diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
> index bcf02617dc..bdd00f6bd8 100644
> --- a/tests/test-qobject-input-visitor.c
> +++ b/tests/test-qobject-input-visitor.c
> @@ -1247,24 +1247,27 @@ static void test_visitor_in_fail_alternate(TestInputVisitorData *data,
>  }
>  
>  static void do_test_visitor_in_qmp_introspect(TestInputVisitorData *data,
> -                                              const char *schema_json)
> +                                              const QLitObject *qlit)
>  {
>      SchemaInfoList *schema = NULL;
> +    QObject *obj = qobject_from_qlit(qlit);
>      Visitor *v;
>  
> -    v = visitor_input_test_init_raw(data, schema_json);
> +    v = qobject_input_visitor_new(obj);
>  
>      visit_type_SchemaInfoList(v, NULL, &schema, &error_abort);
>      g_assert(schema);
>  
>      qapi_free_SchemaInfoList(schema);
> +    qobject_decref(obj);
> +    visit_free(v);
>  }
>  
>  static void test_visitor_in_qmp_introspect(TestInputVisitorData *data,
>                                             const void *unused)
>  {
> -    do_test_visitor_in_qmp_introspect(data, test_qmp_schema_json);
> -    do_test_visitor_in_qmp_introspect(data, qmp_schema_json);
> +    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/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
> index 9903ac4c19..b653e86bff 100644
> --- a/docs/devel/qapi-code-gen.txt
> +++ b/docs/devel/qapi-code-gen.txt
> @@ -1295,18 +1295,27 @@ Example:
>      #ifndef EXAMPLE_QMP_INTROSPECT_H
>      #define EXAMPLE_QMP_INTROSPECT_H
>  
> -    extern const char example_qmp_schema_json[];
> +    extern const QLitObject qmp_schema_qlit;
>  
>      #endif
>      $ cat qapi-generated/example-qmp-introspect.c
>  [Uninteresting stuff omitted...]
>  
> -    const char example_qmp_schema_json[] = "["
> -        "{\"arg-type\": \"0\", \"meta-type\": \"event\", \"name\": \"MY_EVENT\"}, "
> -        "{\"arg-type\": \"1\", \"meta-type\": \"command\", \"name\": \"my-command\", \"ret-type\": \"2\"}, "
> -        "{\"members\": [], \"meta-type\": \"object\", \"name\": \"0\"}, "
> -        "{\"members\": [{\"name\": \"arg1\", \"type\": \"[2]\"}], \"meta-type\": \"object\", \"name\": \"1\"}, "
> -        "{\"members\": [{\"name\": \"integer\", \"type\": \"int\"}, {\"default\": null, \"name\": \"string\", \"type\": \"str\"}], \"meta-type\": \"object\", \"name\": \"2\"}, "
> -        "{\"element-type\": \"2\", \"meta-type\": \"array\", \"name\": \"[2]\"}, "
> -        "{\"json-type\": \"int\", \"meta-type\": \"builtin\", \"name\": \"int\"}, "
> -        "{\"json-type\": \"string\", \"meta-type\": \"builtin\", \"name\": \"str\"}]";
> +    const QLitObject example_qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
> +        QLIT_QDICT(((QLitDictEntry[]) {
> +            { "arg-type", QLIT_QSTR("0") },
> +            { "meta-type", QLIT_QSTR("event") },
> +            { "name", QLIT_QSTR("Event") },
> +            { }
> +        })),
> +        QLIT_QDICT(((QLitDictEntry[]) {
> +            { "members", QLIT_QLIST(((QLitObject[]) {
> +                { }
> +            })) },
> +            { "meta-type", QLIT_QSTR("object") },
> +            { "name", QLIT_QSTR("0") },
> +            { }
> +        })),
> +        ...
> +        { }
> +    }));

Preferably without the to_c_string() move:
Reviewed-by: Markus Armbruster <armbru@redhat.com>

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

* Re: [Qemu-devel] [PATCH v2 01/54] qapi: fix type_seen key error
  2017-08-22 15:50     ` Marc-André Lureau
@ 2017-08-22 16:40       ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-08-22 16:40 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> Hi
>
> ----- Original Message -----
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>> 
>> > The type_seen member can be of a different type than the 'qtype' being
>> > checked, since a string create several conflicts. Lookup the real
>> > conflicting type in the conflict set, that one must be present in
>> > type_seen.
>> >
>> > This fixes the following error, reproducible with the modified test:
>> >
>> > Traceback (most recent call last):
>> >   File "/home/elmarco/src/qq/tests/qapi-schema/test-qapi.py", line 56, in
>> >   <module>
>> >     schema = QAPISchema(sys.argv[1])
>> >   File "/home/elmarco/src/qq/scripts/qapi.py", line 1470, in __init__
>> >     self.exprs = check_exprs(parser.exprs)
>> >   File "/home/elmarco/src/qq/scripts/qapi.py", line 959, in check_exprs
>> >     check_alternate(expr, info)
>> >   File "/home/elmarco/src/qq/scripts/qapi.py", line 831, in check_alternate
>> >     % (name, key, types_seen[qtype]))
>> > KeyError: 'QTYPE_QSTRING'
>> >
>> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> > ---
>> >  scripts/qapi.py                                  | 6 ++++--
>> >  tests/qapi-schema/alternate-conflict-string.json | 4 ++--
>> >  2 files changed, 6 insertions(+), 4 deletions(-)
>> >
>> > diff --git a/scripts/qapi.py b/scripts/qapi.py
>> > index 8aa2775f12..a3ac799535 100644
>> > --- a/scripts/qapi.py
>> > +++ b/scripts/qapi.py
>> > @@ -825,10 +825,12 @@ def check_alternate(expr, info):
>> >              else:
>> >                  conflicting.add('QTYPE_QNUM')
>> >                  conflicting.add('QTYPE_QBOOL')
>> > -        if conflicting & set(types_seen):
>> > +        conflict = conflicting & set(types_seen)
>> > +        if conflict:
>> > +            conflict_qtype = list(conflict)[0]
>> 
>> Converting from set to list just to extract an element is clumsly.
>> Let's use conflict.pop(), and eliminate the variable.  Can do on commit.
>
> I didn't realize that. thanks

I didn't know about .pop() either, but I went "there's *got* to be a
better way!" and searched the docs for it :)

[...]

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

* Re: [Qemu-devel] [PATCH v2 06/54] qapi: introduce qapi_enum_lookup()
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 06/54] qapi: introduce qapi_enum_lookup() Marc-André Lureau
@ 2017-08-22 18:10   ` John Snow
  2017-08-23  8:02   ` Markus Armbruster
  1 sibling, 0 replies; 140+ messages in thread
From: John Snow @ 2017-08-22 18:10 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel
  Cc: open list:Sheepdog, Stefan Hajnoczi, Michael S. Tsirkin,
	Jeff Cody, Michael Roth, Gerd Hoffmann, Josh Durgin,
	zhanghailiang, open list:Block Jobs, Juan Quintela,
	Markus Armbruster, Liu Yuan, Jason Wang, Eduardo Habkost,
	Stefan Weil, Peter Lieven, Dr. David Alan Gilbert,
	Ronnie Sahlberg, Igor Mammedov, Kevin Wolf, Hitoshi Mitake,
	Max Reitz, Paolo Bonzini



On 08/22/2017 09:22 AM, Marc-André Lureau wrote:
> This will help with the introduction of a new structure to handle
> enum lookup.
> 

Procedurally for the sake of review, it's a little odd to introduce the
function, deploy it, and then change it and update all callers.

content-wise, I'm really glad to have a function like this that we can
use universally.

ACK (6, 12)

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

* Re: [Qemu-devel] [PATCH v2 53/54] qapi: make query-cpu-model-expansion depend on s390 or x86
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 53/54] qapi: make query-cpu-model-expansion depend on s390 or x86 Marc-André Lureau
@ 2017-08-22 18:42   ` Eduardo Habkost
  2017-08-23 10:21     ` Marc-André Lureau
  0 siblings, 1 reply; 140+ messages in thread
From: Eduardo Habkost @ 2017-08-22 18:42 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: qemu-devel, Dr. David Alan Gilbert, Markus Armbruster,
	Eric Blake, Paolo Bonzini, Richard Henderson, Alexander Graf

On Tue, Aug 22, 2017 at 03:22:54PM +0200, Marc-André Lureau wrote:
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  qapi-schema.json                       |  4 +++-
>  include/sysemu/arch_init.h             |  3 ---
>  monitor.c                              |  3 ---
>  qmp.c                                  |  7 -------
>  stubs/arch-query-cpu-model-expansion.c | 12 ------------
>  target/i386/cpu.c                      |  2 +-
>  target/s390x/cpu_models.c              |  3 ++-
>  stubs/Makefile.objs                    |  1 -
>  8 files changed, 6 insertions(+), 29 deletions(-)
>  delete mode 100644 stubs/arch-query-cpu-model-expansion.c
> 
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 6c1adb35b5..127a2c71c6 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -4535,7 +4535,9 @@
>  { 'command': 'query-cpu-model-expansion',
>    'data': { 'type': 'CpuModelExpansionType',
>              'model': 'CpuModelInfo' },
> -  'returns': 'CpuModelExpansionInfo' }
> +  'returns': 'CpuModelExpansionInfo',
> +  'if': ['defined(NEED_CPU_H)',
> +         'defined(TARGET_S390X) || defined(TARGET_I386)']}

Maybe this is already documented somewhere in the series (I'm
still going through the other patches), but: why exactly is
'defined(NEED_CPU_H)' in the list, too?

I always assumed that all the QAPI and QMP dispatching code would
be compiled only once, and never be compiled with -DNEED_CPU_H
defined.

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v2 06/54] qapi: introduce qapi_enum_lookup()
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 06/54] qapi: introduce qapi_enum_lookup() Marc-André Lureau
  2017-08-22 18:10   ` John Snow
@ 2017-08-23  8:02   ` Markus Armbruster
  2017-08-23 10:10     ` Marc-André Lureau
  1 sibling, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-08-23  8:02 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: qemu-devel, open list:Sheepdog, Stefan Hajnoczi,
	Michael S. Tsirkin, Jeff Cody, Michael Roth, Gerd Hoffmann,
	Josh Durgin, zhanghailiang, open list:Block Jobs, Juan Quintela,
	Liu Yuan, Jason Wang, Eduardo Habkost, Stefan Weil, Peter Lieven,
	Dr. David Alan Gilbert, Ronnie Sahlberg, Igor Mammedov,
	John Snow, Kevin Wolf, Hitoshi Mitake, Max Reitz, Paolo Bonzini

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

> This will help with the introduction of a new structure to handle
> enum lookup.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
[...]
>  45 files changed, 206 insertions(+), 122 deletions(-)

Hmm.

> diff --git a/include/qapi/util.h b/include/qapi/util.h
> index 7436ed815c..60733b6a80 100644
> --- a/include/qapi/util.h
> +++ b/include/qapi/util.h
> @@ -11,6 +11,8 @@
>  #ifndef QAPI_UTIL_H
>  #define QAPI_UTIL_H
>  
> +const char *qapi_enum_lookup(const char * const lookup[], int val);
> +
>  int qapi_enum_parse(const char * const lookup[], const char *buf,
>                      int max, int def, Error **errp);
>  
> diff --git a/backends/hostmem.c b/backends/hostmem.c
> index 4606b73849..c4f795475c 100644
> --- a/backends/hostmem.c
> +++ b/backends/hostmem.c
> @@ -13,6 +13,7 @@
>  #include "sysemu/hostmem.h"
>  #include "hw/boards.h"
>  #include "qapi/error.h"
> +#include "qapi/util.h"
>  #include "qapi/visitor.h"
>  #include "qapi-types.h"
>  #include "qapi-visit.h"
> @@ -304,7 +305,7 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
>              return;
>          } else if (maxnode == 0 && backend->policy != MPOL_DEFAULT) {
>              error_setg(errp, "host-nodes must be set for policy %s",
> -                       HostMemPolicy_lookup[backend->policy]);
> +                qapi_enum_lookup(HostMemPolicy_lookup, backend->policy));
>              return;
>          }
>  

Lookup becomes even more verbose.

Could we claw back some readability with macros?  Say in addition to

    typedef enum FOO {
        ...
    } FOO;

    extern const char *const FOO_lookup[];

generate

    #define FOO_str(val) qapi_enum_lookup(FOO_lookup, (val))

Needs a matching qapi-code-gen.txt update.

With that, this patch hunk would become

               error_setg(errp, "host-nodes must be set for policy %s",
  -                       HostMemPolicy_lookup[backend->policy]);
  +                       HostMemPolicy_str(backend->policy);

Perhaps we could even throw in some type checking:

    #define FOO_str(val) (type_check(typeof((val)), FOO) \
                          + qapi_enum_lookup(FOO_lookup, (val)))

What do you think?  Want me to explore a fixup patch you could squash
in?

[Skipping lots of mechanical changes...]

I think you missed test-qobject-input-visitor.c and
string-input-visitor.c.

In test-qobject-input-visitor.c's test_visitor_in_enum():

        v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);

You update it in PATCH 12, but the code only works as long as EnumOne
has no holes.  Mapping the enum to string like we do everywhere else in
this patch would be cleaner.

The loop control also subscripts EnumOne_lookup[i].  You take care of
that one in PATCH 12.  That's okay.

Same for test-string-input-visitor.c's test_visitor_in_enum().

There's one more in test_native_list_integer_helper():

    g_string_append_printf(gstr_union,  "{ 'type': '%s', 'data': [ %s ] }",
                           UserDefNativeListUnionKind_lookup[kind],
                           gstr_list->str);

Same story.

The patch doesn't touch the _lookup[] subscripts you're going to replace
by qapi_enum_parse() in PATCH 07-11.  Understand, but I'd reorder the
patches: first replace by qapi_enum_parse(), because DRY (no need to
explain more at that point).  Then get rid of all the remaining
subscripting into _lookup[], i.e. this patch (explain it helps the next
one), then PATCH 12.

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

* Re: [Qemu-devel] [PATCH v2 07/54] tpm: simplify driver registration & lookup
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 07/54] tpm: simplify driver registration & lookup Marc-André Lureau
@ 2017-08-23  9:04   ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-08-23  9:04 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, stefanb

Note: cc'ing the code's author.

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

> Make be_drivers[n] match order of TpmType enum.
>
> Use qapi_enum_parse() in tpm_get_backend_driver.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  include/sysemu/tpm_backend.h |  2 +-
>  tpm.c                        | 42 ++++++++++++------------------------------
>  2 files changed, 13 insertions(+), 31 deletions(-)

Before the patch, we have a strict separation between enum TpmModel /
tpm_models[] and enum TpmType / be_drivers[]:

* TpmModel may have any number of members.  It just happens to have one.

* Same for TpmType.

* tpm_models[] may have any number of elements.  It just happens to have
  the same number of elements as TpmModel has members.

  If it had more, they'd be wasted: tpm_register_model() can't use more
  than one per TpmModel member.  If it had fewer, tpm_register_model()
  could fail.  Its caller ignores failure.

* be_drivers[] is different: tpm_register_driver() happily adds drivers
  as long as be_drivers[] has space.  Its caller ignores failure.

  If you register more than one with a given TpmType,
  tpm_driver_find_by_type(), tpm_get_backend_driver() will find only the
  one one that registered first.  tpm_display_backend_drivers() happily
  shows all of them.

* The order of TpmModel members and tpm_models[] elements is
  independent.  The former is fixed in the QAPI schema, the latter is
  determined by registration order, which is unspecified.

  Corollary: using a TpmModel to subscript tpm_models[] is wrong.
  
* Same for TpmType and be_drivers[]: using a TpmType to subscript
  be_drivers[] is wrong.

Hard to tell whether this is / has become more a case of overengineering
or more a case of under-make-sense-ing.

> diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
> index b58f52d39f..1d21c6b19b 100644
> --- a/include/sysemu/tpm_backend.h
> +++ b/include/sysemu/tpm_backend.h
> @@ -227,6 +227,6 @@ TPMBackend *qemu_find_tpm(const char *id);
>  
>  const TPMDriverOps *tpm_get_backend_driver(const char *type);
>  int tpm_register_model(enum TpmModel model);
> -int tpm_register_driver(const TPMDriverOps *tdo);
> +void tpm_register_driver(const TPMDriverOps *tdo);
>  
>  #endif
> diff --git a/tpm.c b/tpm.c
> index c3b731b3f2..f175661bfe 100644
> --- a/tpm.c
> +++ b/tpm.c
> @@ -26,9 +26,8 @@ static QLIST_HEAD(, TPMBackend) tpm_backends =
>  
>  
>  #define TPM_MAX_MODELS      1
> -#define TPM_MAX_DRIVERS     1
>  
> -static TPMDriverOps const *be_drivers[TPM_MAX_DRIVERS] = {
> +static TPMDriverOps const *be_drivers[TPM_TYPE__MAX] = {
>      NULL,
>  };
>  
> @@ -64,31 +63,18 @@ static bool tpm_model_is_registered(enum TpmModel model)
>  
>  const TPMDriverOps *tpm_get_backend_driver(const char *type)
>  {
> -    int i;
> +    int i = qapi_enum_parse(TpmType_lookup, type, TPM_TYPE__MAX, -1, NULL);
>  
> -    for (i = 0; i < TPM_MAX_DRIVERS && be_drivers[i] != NULL; i++) {
> -        if (!strcmp(TpmType_lookup[be_drivers[i]->type], type)) {
> -            return be_drivers[i];
> -        }
> -    }
> -
> -    return NULL;
> +    return i >= 0 ? be_drivers[i] : NULL;
>  }
>  
>  #ifdef CONFIG_TPM
>  
> -int tpm_register_driver(const TPMDriverOps *tdo)
> +void tpm_register_driver(const TPMDriverOps *tdo)
>  {
> -    int i;
> +    assert(!be_drivers[tdo->type]);
>  
> -    for (i = 0; i < TPM_MAX_DRIVERS; i++) {
> -        if (!be_drivers[i]) {
> -            be_drivers[i] = tdo;
> -            return 0;
> -        }
> -    }
> -    error_report("Could not register TPM driver");
> -    return 1;
> +    be_drivers[tdo->type] = tdo;
>  }
>  
>  /*
> @@ -101,9 +87,12 @@ static void tpm_display_backend_drivers(void)
>  
>      fprintf(stderr, "Supported TPM types (choose only one):\n");
>  
> -    for (i = 0; i < TPM_MAX_DRIVERS && be_drivers[i] != NULL; i++) {
> +    for (i = 0; i < TPM_TYPE__MAX; i++) {
> +        if (be_drivers[i] == NULL) {
> +            continue;
> +        }
>          fprintf(stderr, "%12s   %s\n",
> -                qapi_enum_lookup(TpmType_lookup, be_drivers[i]->type),
> +                qapi_enum_lookup(TpmType_lookup, i),
>                  be_drivers[i]->desc());
>      }
>      fprintf(stderr, "\n");
> @@ -241,14 +230,7 @@ int tpm_config_parse(QemuOptsList *opts_list, const char *optarg)
>  
>  static const TPMDriverOps *tpm_driver_find_by_type(enum TpmType type)
>  {
> -    int i;
> -
> -    for (i = 0; i < TPM_MAX_DRIVERS && be_drivers[i] != NULL; i++) {
> -        if (be_drivers[i]->type == type) {
> -            return be_drivers[i];
> -        }
> -    }
> -    return NULL;
> +    return be_drivers[type];
>  }
>  
>  static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv)

You kill the separation of TpmType and be_drivers[]: TpmType values
become valid subscripts of be_drivers[].  Good!

You don't touch TpmModel and tpm_models[].  Half of the mess remains in
place to confuse the next reader (it certainly confused me, thus the
long "before the patch" treatise).  Not wrong, therefore

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

but could you complete the cleanup job?  Pretty-please?

Also: since I wrote the "before the patch" treatise already, could (some
of) it be worked into the commit message?

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

* Re: [Qemu-devel] [PATCH v2 08/54] hmp: use qapi_enum_parse() in hmp_migrate_set_capability
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 08/54] hmp: use qapi_enum_parse() in hmp_migrate_set_capability Marc-André Lureau
@ 2017-08-23  9:34   ` Markus Armbruster
  2017-08-24 11:29   ` Dr. David Alan Gilbert
  1 sibling, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-08-23  9:34 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Dr. David Alan Gilbert

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

> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  hmp.c | 24 +++++++++++-------------
>  1 file changed, 11 insertions(+), 13 deletions(-)
>
> diff --git a/hmp.c b/hmp.c
> index 29e42ab661..4ba50e8e26 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -1544,23 +1544,21 @@ void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict)
>      bool state = qdict_get_bool(qdict, "state");
>      Error *err = NULL;
>      MigrationCapabilityStatusList *caps = g_malloc0(sizeof(*caps));
> -    int i;
> +    int val;
>  
> -    for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
> -        if (strcmp(cap, MigrationCapability_lookup[i]) == 0) {
> -            caps->value = g_malloc0(sizeof(*caps->value));
> -            caps->value->capability = i;
> -            caps->value->state = state;
> -            caps->next = NULL;
> -            qmp_migrate_set_capabilities(caps, &err);
> -            break;
> -        }
> +    val = qapi_enum_parse(MigrationCapability_lookup, cap,
> +                          MIGRATION_CAPABILITY__MAX, -1, &err);
> +    if (val < 0) {
> +        goto end;
>      }
>  
> -    if (i == MIGRATION_CAPABILITY__MAX) {
> -        error_setg(&err, QERR_INVALID_PARAMETER, cap);
> -    }
> +    caps->value = g_malloc0(sizeof(*caps->value));
> +    caps->value->capability = val;
> +    caps->value->state = state;
> +    caps->next = NULL;
> +    qmp_migrate_set_capabilities(caps, &err);
>  
> +end:
>      qapi_free_MigrationCapabilityStatusList(caps);
>  
>      if (err) {

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

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

* Re: [Qemu-devel] [PATCH v2 09/54] hmp: use qapi_enum_parse() in hmp_migrate_set_parameter
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 09/54] hmp: use qapi_enum_parse() in hmp_migrate_set_parameter Marc-André Lureau
@ 2017-08-23  9:43   ` Markus Armbruster
  2017-08-24 13:16     ` Dr. David Alan Gilbert
  0 siblings, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-08-23  9:43 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Dr. David Alan Gilbert

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

> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  hmp.c | 139 ++++++++++++++++++++++++++++++++----------------------------------
>  1 file changed, 68 insertions(+), 71 deletions(-)
>
> diff --git a/hmp.c b/hmp.c
> index 4ba50e8e26..ccc58e6d88 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -1574,84 +1574,81 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
>      MigrateSetParameters *p = g_new0(MigrateSetParameters, 1);
>      uint64_t valuebw = 0;
>      Error *err = NULL;
> -    int i, ret;
> -
> -    for (i = 0; i < MIGRATION_PARAMETER__MAX; i++) {
> -        if (strcmp(param, MigrationParameter_lookup[i]) == 0) {
> -            switch (i) {
> -            case MIGRATION_PARAMETER_COMPRESS_LEVEL:
> -                p->has_compress_level = true;
> -                visit_type_int(v, param, &p->compress_level, &err);
> -                break;
> -            case MIGRATION_PARAMETER_COMPRESS_THREADS:
> -                p->has_compress_threads = true;
> -                visit_type_int(v, param, &p->compress_threads, &err);
> -                break;
> -            case MIGRATION_PARAMETER_DECOMPRESS_THREADS:
> -                p->has_decompress_threads = true;
> -                visit_type_int(v, param, &p->decompress_threads, &err);
> -                break;
> -            case MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL:
> -                p->has_cpu_throttle_initial = true;
> -                visit_type_int(v, param, &p->cpu_throttle_initial, &err);
> -                break;
> -            case MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT:
> -                p->has_cpu_throttle_increment = true;
> -                visit_type_int(v, param, &p->cpu_throttle_increment, &err);
> -                break;
> -            case MIGRATION_PARAMETER_TLS_CREDS:
> -                p->has_tls_creds = true;
> -                p->tls_creds = g_new0(StrOrNull, 1);
> -                p->tls_creds->type = QTYPE_QSTRING;
> -                visit_type_str(v, param, &p->tls_creds->u.s, &err);
> -                break;
> -            case MIGRATION_PARAMETER_TLS_HOSTNAME:
> -                p->has_tls_hostname = true;
> -                p->tls_hostname = g_new0(StrOrNull, 1);
> -                p->tls_hostname->type = QTYPE_QSTRING;
> -                visit_type_str(v, param, &p->tls_hostname->u.s, &err);
> -                break;
> -            case MIGRATION_PARAMETER_MAX_BANDWIDTH:
> -                p->has_max_bandwidth = true;
> -                /*
> -                 * Can't use visit_type_size() here, because it
> -                 * defaults to Bytes rather than Mebibytes.
> -                 */
> -                ret = qemu_strtosz_MiB(valuestr, NULL, &valuebw);
> -                if (ret < 0 || valuebw > INT64_MAX
> -                    || (size_t)valuebw != valuebw) {
> -                    error_setg(&err, "Invalid size %s", valuestr);
> -                    break;
> -                }
> -                p->max_bandwidth = valuebw;
> -                break;
> -            case MIGRATION_PARAMETER_DOWNTIME_LIMIT:
> -                p->has_downtime_limit = true;
> -                visit_type_int(v, param, &p->downtime_limit, &err);
> -                break;
> -            case MIGRATION_PARAMETER_X_CHECKPOINT_DELAY:
> -                p->has_x_checkpoint_delay = true;
> -                visit_type_int(v, param, &p->x_checkpoint_delay, &err);
> -                break;
> -            case MIGRATION_PARAMETER_BLOCK_INCREMENTAL:
> -                p->has_block_incremental = true;
> -                visit_type_bool(v, param, &p->block_incremental, &err);
> -                break;
> -            }
> +    int val, ret;
>  
> -            if (err) {
> -                goto cleanup;
> -            }
> -
> -            qmp_migrate_set_parameters(p, &err);
> +    val = qapi_enum_parse(MigrationParameter_lookup, param,
> +                          MIGRATION_PARAMETER__MAX,  -1, &err);
> +    if (val < 0) {
> +        goto cleanup;
> +    }
> +
> +    switch (val) {
> +    case MIGRATION_PARAMETER_COMPRESS_LEVEL:
> +        p->has_compress_level = true;
> +        visit_type_int(v, param, &p->compress_level, &err);
> +        break;
> +    case MIGRATION_PARAMETER_COMPRESS_THREADS:
> +        p->has_compress_threads = true;
> +        visit_type_int(v, param, &p->compress_threads, &err);
> +        break;
> +    case MIGRATION_PARAMETER_DECOMPRESS_THREADS:
> +        p->has_decompress_threads = true;
> +        visit_type_int(v, param, &p->decompress_threads, &err);
> +        break;
> +    case MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL:
> +        p->has_cpu_throttle_initial = true;
> +        visit_type_int(v, param, &p->cpu_throttle_initial, &err);
> +        break;
> +    case MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT:
> +        p->has_cpu_throttle_increment = true;
> +        visit_type_int(v, param, &p->cpu_throttle_increment, &err);
> +        break;
> +    case MIGRATION_PARAMETER_TLS_CREDS:
> +        p->has_tls_creds = true;
> +        p->tls_creds = g_new0(StrOrNull, 1);
> +        p->tls_creds->type = QTYPE_QSTRING;
> +        visit_type_str(v, param, &p->tls_creds->u.s, &err);
> +        break;
> +    case MIGRATION_PARAMETER_TLS_HOSTNAME:
> +        p->has_tls_hostname = true;
> +        p->tls_hostname = g_new0(StrOrNull, 1);
> +        p->tls_hostname->type = QTYPE_QSTRING;
> +        visit_type_str(v, param, &p->tls_hostname->u.s, &err);
> +        break;
> +    case MIGRATION_PARAMETER_MAX_BANDWIDTH:
> +        p->has_max_bandwidth = true;
> +        /*
> +         * Can't use visit_type_size() here, because it
> +         * defaults to Bytes rather than Mebibytes.
> +         */
> +        ret = qemu_strtosz_MiB(valuestr, NULL, &valuebw);
> +        if (ret < 0 || valuebw > INT64_MAX
> +            || (size_t)valuebw != valuebw) {
> +            error_setg(&err, "Invalid size %s", valuestr);
>              break;
>          }
> +        p->max_bandwidth = valuebw;
> +        break;
> +    case MIGRATION_PARAMETER_DOWNTIME_LIMIT:
> +        p->has_downtime_limit = true;
> +        visit_type_int(v, param, &p->downtime_limit, &err);
> +        break;
> +    case MIGRATION_PARAMETER_X_CHECKPOINT_DELAY:
> +        p->has_x_checkpoint_delay = true;
> +        visit_type_int(v, param, &p->x_checkpoint_delay, &err);
> +        break;
> +    case MIGRATION_PARAMETER_BLOCK_INCREMENTAL:
> +        p->has_block_incremental = true;
> +        visit_type_bool(v, param, &p->block_incremental, &err);
> +        break;
>      }
>  
> -    if (i == MIGRATION_PARAMETER__MAX) {
> -        error_setg(&err, QERR_INVALID_PARAMETER, param);
> +    if (err) {
> +        goto cleanup;
>      }
>  
> +    qmp_migrate_set_parameters(p, &err);
> +
>   cleanup:
>      qapi_free_MigrateSetParameters(p);
>      visit_free(v);

Easier to review with space change ignored:

  diff --git a/hmp.c b/hmp.c
  index 4ba50e8..ccc58e6 100644
  --- a/hmp.c
  +++ b/hmp.c
  @@ -1574,11 +1574,15 @@
       MigrateSetParameters *p = g_new0(MigrateSetParameters, 1);
       uint64_t valuebw = 0;
       Error *err = NULL;
  -    int i, ret;
  +    int val, ret;

  -    for (i = 0; i < MIGRATION_PARAMETER__MAX; i++) {
  -        if (strcmp(param, MigrationParameter_lookup[i]) == 0) {
  -            switch (i) {
  +    val = qapi_enum_parse(MigrationParameter_lookup, param,
  +                          MIGRATION_PARAMETER__MAX,  -1, &err);
  +    if (val < 0) {
  +        goto cleanup;
  +    }
  +
  +    switch (val) {
               case MIGRATION_PARAMETER_COMPRESS_LEVEL:
                   p->has_compress_level = true;
                   visit_type_int(v, param, &p->compress_level, &err);
  @@ -1644,13 +1648,6 @@
               }

               qmp_migrate_set_parameters(p, &err);
  -            break;
  -        }
  -    }
  -
  -    if (i == MIGRATION_PARAMETER__MAX) {
  -        error_setg(&err, QERR_INVALID_PARAMETER, param);
  -    }

    cleanup:
       qapi_free_MigrateSetParameters(p);
  -- 
  2.7.5

Looks good, although a default: abort() wouldn't hurt.

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

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

* Re: [Qemu-devel] [PATCH v2 10/54] block: use qemu_enum_parse() in blkdebug_debug_breakpoint
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 10/54] block: use qemu_enum_parse() in blkdebug_debug_breakpoint Marc-André Lureau
@ 2017-08-23 10:05   ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-08-23 10:05 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: qemu-devel, Kevin Wolf, open list:blkdebug, Max Reitz

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

> This slightly change the error report message from "Invalid event
> name" to "Invalid parameter".

Actually from

    qemu-system-x86_64: LOCATION: Invalid event name "VALUE"

to

    qemu-system-x86_64: LOCATION: invalid parameter value: VALUE

Let's get that exactly right in the commit message.

Slight degradation, but the message is sub-par even before the patch.
When complaining about a parameter value, both parameter name and value
should be mentioned, as the value may well not be unique.  Not this
patch's problem.

Aside: LOCATION points to where the blkdebug driver is configured.  It
should point to the error's actual location instead: the configuration
file named with config=...  Also not this patch's problem.

>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  block/blkdebug.c | 28 ++++++++--------------------
>  1 file changed, 8 insertions(+), 20 deletions(-)
>
> diff --git a/block/blkdebug.c b/block/blkdebug.c
> index c19ab28f07..50edda2a31 100644
> --- a/block/blkdebug.c
> +++ b/block/blkdebug.c
> @@ -32,6 +32,7 @@
>  #include "qapi/qmp/qbool.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qmp/qstring.h"
> +#include "qapi/util.h"
>  #include "sysemu/qtest.h"
>  
>  typedef struct BDRVBlkdebugState {
> @@ -149,20 +150,6 @@ static QemuOptsList *config_groups[] = {
>      NULL
>  };
>  
> -static int get_event_by_name(const char *name, BlkdebugEvent *event)
> -{
> -    int i;
> -
> -    for (i = 0; i < BLKDBG__MAX; i++) {
> -        if (!strcmp(BlkdebugEvent_lookup[i], name)) {
> -            *event = i;
> -            return 0;
> -        }
> -    }
> -
> -    return -1;
> -}
> -
>  struct add_rule_data {
>      BDRVBlkdebugState *s;
>      int action;
> @@ -173,7 +160,7 @@ static int add_rule(void *opaque, QemuOpts *opts, Error **errp)
>      struct add_rule_data *d = opaque;
>      BDRVBlkdebugState *s = d->s;
>      const char* event_name;
> -    BlkdebugEvent event;
> +    int event;
>      struct BlkdebugRule *rule;
>      int64_t sector;
>  
> @@ -182,8 +169,9 @@ static int add_rule(void *opaque, QemuOpts *opts, Error **errp)
>      if (!event_name) {
>          error_setg(errp, "Missing event name for rule");
>          return -1;
> -    } else if (get_event_by_name(event_name, &event) < 0) {
> -        error_setg(errp, "Invalid event name \"%s\"", event_name);
> +    }
> +    event = qapi_enum_parse(BlkdebugEvent_lookup, event_name, BLKDBG__MAX, -1, errp);

Long line.

> +    if (event < 0) {
>          return -1;
>      }
>  
> @@ -743,13 +731,13 @@ static int blkdebug_debug_breakpoint(BlockDriverState *bs, const char *event,
>  {
>      BDRVBlkdebugState *s = bs->opaque;
>      struct BlkdebugRule *rule;
> -    BlkdebugEvent blkdebug_event;
> +    int blkdebug_event;
>  
> -    if (get_event_by_name(event, &blkdebug_event) < 0) {
> +    blkdebug_event = qapi_enum_parse(BlkdebugEvent_lookup, event, BLKDBG__MAX, -1, NULL);

Long line.

> +    if (blkdebug_event < 0) {
>          return -ENOENT;
>      }
>  
> -
>      rule = g_malloc(sizeof(*rule));
>      *rule = (struct BlkdebugRule) {
>          .event  = blkdebug_event,

With the nits touched up:
Reviewed-by: Markus Armbruster <armbru@redhat.com>

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

* Re: [Qemu-devel] [PATCH v2 06/54] qapi: introduce qapi_enum_lookup()
  2017-08-23  8:02   ` Markus Armbruster
@ 2017-08-23 10:10     ` Marc-André Lureau
  2017-08-24 11:14       ` Dr. David Alan Gilbert
  0 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-23 10:10 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, open list:Sheepdog, Stefan Hajnoczi,
	Michael S. Tsirkin, Jeff Cody, Michael Roth, Gerd Hoffmann,
	Josh Durgin, zhanghailiang, open list:Block Jobs, Juan Quintela,
	Liu Yuan, Jason Wang, Eduardo Habkost, Stefan Weil, Peter Lieven,
	Dr. David Alan Gilbert, Ronnie Sahlberg, Igor Mammedov,
	John Snow, Kevin Wolf, Hitoshi Mitake, Max Reitz, Paolo Bonzini

Hi

----- Original Message -----
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> 
> > This will help with the introduction of a new structure to handle
> > enum lookup.
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> [...]
> >  45 files changed, 206 insertions(+), 122 deletions(-)
> 
> Hmm.
> 
> > diff --git a/include/qapi/util.h b/include/qapi/util.h
> > index 7436ed815c..60733b6a80 100644
> > --- a/include/qapi/util.h
> > +++ b/include/qapi/util.h
> > @@ -11,6 +11,8 @@
> >  #ifndef QAPI_UTIL_H
> >  #define QAPI_UTIL_H
> >  
> > +const char *qapi_enum_lookup(const char * const lookup[], int val);
> > +
> >  int qapi_enum_parse(const char * const lookup[], const char *buf,
> >                      int max, int def, Error **errp);
> >  
> > diff --git a/backends/hostmem.c b/backends/hostmem.c
> > index 4606b73849..c4f795475c 100644
> > --- a/backends/hostmem.c
> > +++ b/backends/hostmem.c
> > @@ -13,6 +13,7 @@
> >  #include "sysemu/hostmem.h"
> >  #include "hw/boards.h"
> >  #include "qapi/error.h"
> > +#include "qapi/util.h"
> >  #include "qapi/visitor.h"
> >  #include "qapi-types.h"
> >  #include "qapi-visit.h"
> > @@ -304,7 +305,7 @@ host_memory_backend_memory_complete(UserCreatable *uc,
> > Error **errp)
> >              return;
> >          } else if (maxnode == 0 && backend->policy != MPOL_DEFAULT) {
> >              error_setg(errp, "host-nodes must be set for policy %s",
> > -                       HostMemPolicy_lookup[backend->policy]);
> > +                qapi_enum_lookup(HostMemPolicy_lookup, backend->policy));
> >              return;
> >          }
> >  
> 
> Lookup becomes even more verbose.
> 
> Could we claw back some readability with macros?  Say in addition to
> 
>     typedef enum FOO {
>         ...
>     } FOO;
> 
>     extern const char *const FOO_lookup[];
> 
> generate
> 
>     #define FOO_str(val) qapi_enum_lookup(FOO_lookup, (val))
> 
> Needs a matching qapi-code-gen.txt update.
> 
> With that, this patch hunk would become
> 
>                error_setg(errp, "host-nodes must be set for policy %s",
>   -                       HostMemPolicy_lookup[backend->policy]);
>   +                       HostMemPolicy_str(backend->policy);
> 
> Perhaps we could even throw in some type checking:
> 
>     #define FOO_str(val) (type_check(typeof((val)), FOO) \
>                           + qapi_enum_lookup(FOO_lookup, (val)))
> 
> What do you think?  Want me to explore a fixup patch you could squash
> in?
> 

Yes, I had similar thoughts, but didn't spent too much time finding the best proposal, that wasn't my main goal in the series. 

Indeed, I would prefer that further improvements be done as follow-up. Or if you have a ready solution, I can squash it there. I can picture the conflicts with the next patch though... 

> [Skipping lots of mechanical changes...]
> 
> I think you missed test-qobject-input-visitor.c and
> string-input-visitor.c.
> 
> In test-qobject-input-visitor.c's test_visitor_in_enum():
> 
>         v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
> 
> You update it in PATCH 12, but the code only works as long as EnumOne
> has no holes.  Mapping the enum to string like we do everywhere else in
> this patch would be cleaner.
> 

ok

> The loop control also subscripts EnumOne_lookup[i].  You take care of
> that one in PATCH 12.  That's okay.
> 
> Same for test-string-input-visitor.c's test_visitor_in_enum().
> 
> There's one more in test_native_list_integer_helper():
> 
>     g_string_append_printf(gstr_union,  "{ 'type': '%s', 'data': [ %s ] }",
>                            UserDefNativeListUnionKind_lookup[kind],
>                            gstr_list->str);
> 
> Same story.
> 
> The patch doesn't touch the _lookup[] subscripts you're going to replace
> by qapi_enum_parse() in PATCH 07-11.  Understand, but I'd reorder the
> patches: first replace by qapi_enum_parse(), because DRY (no need to
> explain more at that point).  Then get rid of all the remaining
> subscripting into _lookup[], i.e. this patch (explain it helps the next
> one), then PATCH 12.
> 

ok

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

* Re: [Qemu-devel] [PATCH v2 53/54] qapi: make query-cpu-model-expansion depend on s390 or x86
  2017-08-22 18:42   ` Eduardo Habkost
@ 2017-08-23 10:21     ` Marc-André Lureau
  2017-08-23 12:57       ` Eduardo Habkost
  0 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-23 10:21 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: qemu-devel, Dr. David Alan Gilbert, Markus Armbruster,
	Eric Blake, Paolo Bonzini, Richard Henderson, Alexander Graf

Hi

----- Original Message -----
> On Tue, Aug 22, 2017 at 03:22:54PM +0200, Marc-André Lureau wrote:
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >  qapi-schema.json                       |  4 +++-
> >  include/sysemu/arch_init.h             |  3 ---
> >  monitor.c                              |  3 ---
> >  qmp.c                                  |  7 -------
> >  stubs/arch-query-cpu-model-expansion.c | 12 ------------
> >  target/i386/cpu.c                      |  2 +-
> >  target/s390x/cpu_models.c              |  3 ++-
> >  stubs/Makefile.objs                    |  1 -
> >  8 files changed, 6 insertions(+), 29 deletions(-)
> >  delete mode 100644 stubs/arch-query-cpu-model-expansion.c
> > 
> > diff --git a/qapi-schema.json b/qapi-schema.json
> > index 6c1adb35b5..127a2c71c6 100644
> > --- a/qapi-schema.json
> > +++ b/qapi-schema.json
> > @@ -4535,7 +4535,9 @@
> >  { 'command': 'query-cpu-model-expansion',
> >    'data': { 'type': 'CpuModelExpansionType',
> >              'model': 'CpuModelInfo' },
> > -  'returns': 'CpuModelExpansionInfo' }
> > +  'returns': 'CpuModelExpansionInfo',
> > +  'if': ['defined(NEED_CPU_H)',
> > +         'defined(TARGET_S390X) || defined(TARGET_I386)']}
> 
> Maybe this is already documented somewhere in the series (I'm
> still going through the other patches), but: why exactly is
> 'defined(NEED_CPU_H)' in the list, too?

The point of this series is to make qapi schema configurable.

Some types/commands/events are target-specifc. In order to #ifdef on poisoined symbols, we make most of QAPI generated code built per-target in patch 49/54. But the common code still need to compile some units, that's why #ifdef NEED_CPU_U. The clean solution is probably to split the generated schema to common & per-target, that's not covered in the series.

> 
> I always assumed that all the QAPI and QMP dispatching code would
> be compiled only once, and never be compiled with -DNEED_CPU_H
> defined.

No longer after 49/54.

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

* Re: [Qemu-devel] [PATCH v2 11/54] quorum: use qapi_enum_parse() in quorum_open
  2017-08-22 13:40   ` Alberto Garcia
@ 2017-08-23 11:15     ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-08-23 11:15 UTC (permalink / raw)
  To: Alberto Garcia
  Cc: Marc-André Lureau, qemu-devel, Kevin Wolf, open list:Quorum,
	Max Reitz

Alberto Garcia <berto@igalia.com> writes:

> On Tue 22 Aug 2017 03:22:12 PM CEST, Marc-André Lureau wrote:
>
>> @@ -925,7 +908,13 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
>>          goto exit;
>>      }
>>  
>> -    ret = parse_read_pattern(qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN));
>> +    if (!qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN)) {
>> +        ret = QUORUM_READ_PATTERN_QUORUM;
>> +    } else {
>> +        ret = qapi_enum_parse(QuorumReadPattern_lookup,
>> +                              qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN),
>> +                              QUORUM_READ_PATTERN__MAX, -EINVAL, NULL);
>> +    }
>
> I don't like so much that you call qemu_opt_get() twice with the same
> parameters,

Easy enough to avoid.

>             but else the change makes sense.

Is that an R-by?  R-by if qemu_opt_get() is called just once?

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

* Re: [Qemu-devel] [PATCH v2 11/54] quorum: use qapi_enum_parse() in quorum_open
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 11/54] quorum: use qapi_enum_parse() in quorum_open Marc-André Lureau
  2017-08-22 13:40   ` Alberto Garcia
@ 2017-08-23 11:24   ` Markus Armbruster
  2017-08-23 11:53     ` Alberto Garcia
  1 sibling, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-08-23 11:24 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: qemu-devel, Kevin Wolf, Alberto Garcia, open list:Quorum, Max Reitz

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

> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  block/quorum.c | 27 ++++++++-------------------
>  1 file changed, 8 insertions(+), 19 deletions(-)
>
> diff --git a/block/quorum.c b/block/quorum.c
> index d04da4f430..e4271caa7a 100644
> --- a/block/quorum.c
> +++ b/block/quorum.c
> @@ -22,6 +22,7 @@
>  #include "qapi/qmp/qjson.h"
>  #include "qapi/qmp/qlist.h"
>  #include "qapi/qmp/qstring.h"
> +#include "qapi/util.h"
>  #include "qapi-event.h"
>  #include "crypto/hash.h"
>  
> @@ -867,24 +868,6 @@ static QemuOptsList quorum_runtime_opts = {
>      },
>  };
>  
> -static int parse_read_pattern(const char *opt)
> -{
> -    int i;
> -
> -    if (!opt) {
> -        /* Set quorum as default */
> -        return QUORUM_READ_PATTERN_QUORUM;
> -    }
> -
> -    for (i = 0; i < QUORUM_READ_PATTERN__MAX; i++) {
> -        if (!strcmp(opt, QuorumReadPattern_lookup[i])) {
> -            return i;
> -        }
> -    }
> -
> -    return -EINVAL;
> -}
> -
>  static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
>                         Error **errp)
>  {
> @@ -925,7 +908,13 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
>          goto exit;
>      }
>  
> -    ret = parse_read_pattern(qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN));
> +    if (!qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN)) {
> +        ret = QUORUM_READ_PATTERN_QUORUM;
> +    } else {
> +        ret = qapi_enum_parse(QuorumReadPattern_lookup,
> +                              qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN),
> +                              QUORUM_READ_PATTERN__MAX, -EINVAL, NULL);
> +    }
>      if (ret < 0) {
>          error_setg(&local_err, "Please set read-pattern as fifo or quorum");
>          goto exit;

qapi_enum_parse() copes with null input: it returns its fourth argument
then.  I don't like that also returns it on error, but that shouldn't be
a problem here.

If we can live with qapi_enum_parse()'s sub-par error message, then this
should do:

       ret = qapi_enum_parse(QuorumReadPattern_lookup,
                             qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN),
                             QUORUM_READ_PATTERN__MAX,
                             QUORUM_READ_PATTERN_QUORUM, &local_err);
       if (local_err) {
           goto exit;
       }

If not, we'd have to replace @local_err:

       if (local_err) {
           error_free(local_err);
           error_setg(&local_err, "Please set read-pattern as fifo or quorum");
           goto exit;
       }

or amend it with error_append_hint() or error_prepend().

Berto, what do you think?

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

* Re: [Qemu-devel] [PATCH v2 11/54] quorum: use qapi_enum_parse() in quorum_open
  2017-08-23 11:24   ` Markus Armbruster
@ 2017-08-23 11:53     ` Alberto Garcia
  0 siblings, 0 replies; 140+ messages in thread
From: Alberto Garcia @ 2017-08-23 11:53 UTC (permalink / raw)
  To: Markus Armbruster, Marc-André Lureau
  Cc: qemu-devel, Kevin Wolf, open list:Quorum, Max Reitz

On Wed 23 Aug 2017 01:24:09 PM CEST, Markus Armbruster wrote:
>>  static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
>>                         Error **errp)
>>  {
>> @@ -925,7 +908,13 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
>>          goto exit;
>>      }
>>  
>> -    ret = parse_read_pattern(qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN));
>> +    if (!qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN)) {
>> +        ret = QUORUM_READ_PATTERN_QUORUM;
>> +    } else {
>> +        ret = qapi_enum_parse(QuorumReadPattern_lookup,
>> +                              qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN),
>> +                              QUORUM_READ_PATTERN__MAX, -EINVAL, NULL);
>> +    }
>>      if (ret < 0) {
>>          error_setg(&local_err, "Please set read-pattern as fifo or quorum");
>>          goto exit;
>
> qapi_enum_parse() copes with null input: it returns its fourth argument
> then.  I don't like that also returns it on error, but that shouldn't be
> a problem here.
>
> If we can live with qapi_enum_parse()'s sub-par error message, then this
> should do:
>
>        ret = qapi_enum_parse(QuorumReadPattern_lookup,
>                              qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN),
>                              QUORUM_READ_PATTERN__MAX,
>                              QUORUM_READ_PATTERN_QUORUM, &local_err);
>        if (local_err) {
>            goto exit;
>        }

That actually doesn't sound so bad.

> If not, we'd have to replace @local_err:
>
>        if (local_err) {
>            error_free(local_err);
>            error_setg(&local_err, "Please set read-pattern as fifo or quorum");
>            goto exit;
>        }

Instead of replacing @local_err I'd rather have an intermediate variable
like this:

    pattern_str = qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN); 
    if (!pattern_str) {
        ret = QUORUM_READ_PATTERN_QUORUM;
    } else {
        ret = qapi_enum_parse(QuorumReadPattern_lookup, pattern_str,
                              QUORUM_READ_PATTERN__MAX, -EINVAL, NULL);
    }

I think I prefer this last one the best, but using the default error
message is also ok. With either solution,

Reviewed-by: Alberto Garcia <berto@igalia.com>

Berto

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

* Re: [Qemu-devel] [PATCH v2 12/54] qapi: change enum lookup structure
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 12/54] qapi: change enum lookup structure Marc-André Lureau
@ 2017-08-23 12:09   ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-08-23 12:09 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: qemu-devel, open list:Sheepdog, Stefan Hajnoczi,
	Michael S. Tsirkin, Jeff Cody, Michael Roth, Gerd Hoffmann,
	Denis V. Lunev, Josh Durgin, Alberto Garcia, zhanghailiang,
	open list:Block layer core, Juan Quintela, Liu Yuan, Jason Wang,
	Eduardo Habkost, Stefan Weil, Peter Lieven,
	Dr. David Alan Gilbert, Ronnie Sahlberg, Igor Mammedov,
	John Snow, Kevin Wolf, Hitoshi Mitake, Max Reitz, Paolo Bonzini,
	Andreas Färber

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

> Store the length in the lookup table, i.e. change it from
> const char *const[] to struct { int n, const char *const s[] }.
>
> The following conditional enum entry change will create "hole"
> elements in the generated lookup array, that should be skipped.

The commit message could use some love.  I know what the "conditional
enum entry change" will be about, but most other's won't, and even I may
not remember it in a few months.

>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  66 files changed, 241 insertions(+), 248 deletions(-)

Lot's of churn because we need to take the address of FOO_lookup now.
Macros in PATCH 06 could perhaps limit the churn to that patch.  I'll
play with it.

> diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
> index 0f3b8cb459..62a51a54cb 100644
> --- a/include/qapi/visitor.h
> +++ b/include/qapi/visitor.h
> @@ -469,7 +469,7 @@ bool visit_optional(Visitor *v, const char *name, bool *present);
>   * that visit_type_str() must have no unwelcome side effects.
>   */
>  void visit_type_enum(Visitor *v, const char *name, int *obj,
> -                     const char *const strings[], Error **errp);
> +                     const QEnumLookup *lookup, Error **errp);
>  
>  /*
>   * Check if visitor is an input visitor.
> diff --git a/scripts/qapi.py b/scripts/qapi.py
> index a3ac799535..314d7e0365 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi.py
> @@ -1851,7 +1851,7 @@ def guardend(name):
>  def gen_enum_lookup(name, values, prefix=None):
>      ret = mcgen('''
>  
> -const char *const %(c_name)s_lookup[] = {
> +static const char *const %(c_name)s_array[] = {
>  ''',
>                  c_name=c_name(name))
>      for value in values:
> @@ -1865,8 +1865,13 @@ const char *const %(c_name)s_lookup[] = {
>      ret += mcgen('''
>      [%(max_index)s] = NULL,
>  };
> +
> +const QEnumLookup %(c_name)s_lookup = {
> +    .array = %(c_name)s_array,
> +    .size = %(max_index)s
> +};
>  ''',
> -                 max_index=max_index)
> +                 max_index=max_index, c_name=c_name(name))
>      return ret
>  
>  

This generates

    static const char *const ACPISlotType_array[] = {
        [ACPI_SLOT_TYPE_DIMM] = "DIMM",
        [ACPI_SLOT_TYPE_CPU] = "CPU",
        [ACPI_SLOT_TYPE__MAX] = NULL,
    };

    const QEnumLookup ACPISlotType_lookup = {
        .array = ACPISlotType_array,
        .size = ACPI_SLOT_TYPE__MAX
    };

Old-fashioned.  We can avoid the extra variable easily:

    const QEnumLookup ACPISlotType_lookup = {
        .array = (const char *const[]) {
            [ACPI_SLOT_TYPE_DIMM] = "DIMM",
            [ACPI_SLOT_TYPE_CPU] = "CPU",
            [ACPI_SLOT_TYPE__MAX] = NULL,
        },
        .size = ACPI_SLOT_TYPE__MAX
    };

Could be done in a followup.  Extra churn.  Up to you.

> @@ -1896,7 +1901,7 @@ typedef enum %(c_name)s {
>  
>      ret += mcgen('''
>  
> -extern const char *const %(c_name)s_lookup[];
> +extern const QEnumLookup %(c_name)s_lookup;
>  ''',
>                   c_name=c_name(name))
>      return ret
> diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
> index b45e7b5634..dc05268917 100644
> --- a/scripts/qapi-types.py
> +++ b/scripts/qapi-types.py
> @@ -179,6 +179,12 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
>          self.defn = ''
>          self._fwdecl = ''
>          self._btin = guardstart('QAPI_TYPES_BUILTIN')
> +        self._btin += '''
> +typedef struct QEnumLookup {
> +    const char *const *array;
> +    int size;
> +} QEnumLookup;
> +'''
>  
>      def visit_end(self):
>          self.decl = self._fwdecl + self.decl
> diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
> index bd0b742236..7e1cfc13f0 100644
> --- a/scripts/qapi-visit.py
> +++ b/scripts/qapi-visit.py
> @@ -153,7 +153,7 @@ def gen_visit_enum(name):
>  void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s *obj, Error **errp)
>  {
>      int value = *obj;
> -    visit_type_enum(v, name, &value, %(c_name)s_lookup, errp);
> +    visit_type_enum(v, name, &value, &%(c_name)s_lookup, errp);
>      *obj = value;
>  }
>  ''',
> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
> index ae317286a4..089146197f 100644
> --- a/include/hw/qdev-core.h
> +++ b/include/hw/qdev-core.h
> @@ -249,7 +249,7 @@ struct Property {
>  struct PropertyInfo {
>      const char *name;
>      const char *description;
> -    const char * const *enum_table;
> +    const QEnumLookup *enum_table;
>      int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
>      void (*set_default_value)(Object *obj, const Property *prop);
>      void (*create)(Object *obj, Property *prop, Error **errp);
> diff --git a/include/qapi/util.h b/include/qapi/util.h
> index 60733b6a80..613f82bdcd 100644
> --- a/include/qapi/util.h
> +++ b/include/qapi/util.h
> @@ -11,10 +11,10 @@
>  #ifndef QAPI_UTIL_H
>  #define QAPI_UTIL_H
>  
> -const char *qapi_enum_lookup(const char * const lookup[], int val);
> +const char *qapi_enum_lookup(const QEnumLookup *lookup, int val);
>  
> -int qapi_enum_parse(const char * const lookup[], const char *buf,
> -                    int max, int def, Error **errp);
> +int qapi_enum_parse(const QEnumLookup *lookup, const char *buf,
> +                    int def, Error **errp);
>  
>  int parse_qapi_name(const char *name, bool complete);
>  
> diff --git a/include/qom/object.h b/include/qom/object.h
> index 1b828994fa..f3e5cff37a 100644
> --- a/include/qom/object.h
> +++ b/include/qom/object.h
> @@ -1415,14 +1415,14 @@ void object_class_property_add_bool(ObjectClass *klass, const char *name,
>   */
>  void object_property_add_enum(Object *obj, const char *name,
>                                const char *typename,
> -                              const char * const *strings,
> +                              const QEnumLookup *lookup,
>                                int (*get)(Object *, Error **),
>                                void (*set)(Object *, int, Error **),
>                                Error **errp);
>  
>  void object_class_property_add_enum(ObjectClass *klass, const char *name,
>                                      const char *typename,
> -                                    const char * const *strings,
> +                                    const QEnumLookup *lookup,
>                                      int (*get)(Object *, Error **),
>                                      void (*set)(Object *, int, Error **),
>                                      Error **errp);
> diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
> index ed6d2af462..8876ecf0cd 100644
> --- a/qapi/qapi-visit-core.c
> +++ b/qapi/qapi-visit-core.c
> @@ -333,24 +333,22 @@ void visit_type_null(Visitor *v, const char *name, QNull **obj,
>  }
>  
>  static void output_type_enum(Visitor *v, const char *name, int *obj,
> -                             const char *const strings[], Error **errp)
> +                             const QEnumLookup *lookup, Error **errp)
>  {
> -    int i = 0;
>      int value = *obj;
>      char *enum_str;
>  
> -    while (strings[i++] != NULL);
> -    if (value < 0 || value >= i - 1) {
> +    if (value < 0 || value > lookup->size || !lookup->array[value]) {

!lookup->array[value] feels premature.  Hole support should be done in a
later patch, possibly a separate one.

>          error_setg(errp, QERR_INVALID_PARAMETER, name ? name : "null");
>          return;
>      }
>  
> -    enum_str = (char *)strings[value];
> +    enum_str = (char *)lookup->array[value];

Why not qapi_enum_lookup()?  In PATCH 06?

>      visit_type_str(v, name, &enum_str, errp);
>  }
>  
>  static void input_type_enum(Visitor *v, const char *name, int *obj,
> -                            const char *const strings[], Error **errp)
> +                            const QEnumLookup *lookup, Error **errp)
>  {
>      Error *local_err = NULL;
>      int64_t value = 0;
> @@ -362,14 +360,14 @@ static void input_type_enum(Visitor *v, const char *name, int *obj,
>          return;
>      }
>  
> -    while (strings[value] != NULL) {
> -        if (strcmp(strings[value], enum_str) == 0) {
> +    while (value < lookup->size) {
> +        if (!g_strcmp0(lookup->array[value], enum_str)) {
>              break;
>          }
>          value++;
>      }
>  
> -    if (strings[value] == NULL) {
> +    if (value == lookup->size) {
>          error_setg(errp, QERR_INVALID_PARAMETER, enum_str);
>          g_free(enum_str);
>          return;

Can we use qapi_enum_parse() here?  In a preparatory patch like PATCH
07-11?

> @@ -380,16 +378,16 @@ static void input_type_enum(Visitor *v, const char *name, int *obj,
>  }
>  
>  void visit_type_enum(Visitor *v, const char *name, int *obj,
> -                     const char *const strings[], Error **errp)
> +                     const QEnumLookup *lookup, Error **errp)
>  {
> -    assert(obj && strings);
> +    assert(obj && lookup);
>      trace_visit_type_enum(v, name, obj);
>      switch (v->type) {
>      case VISITOR_INPUT:
> -        input_type_enum(v, name, obj, strings, errp);
> +        input_type_enum(v, name, obj, lookup, errp);
>          break;
>      case VISITOR_OUTPUT:
> -        output_type_enum(v, name, obj, strings, errp);
> +        output_type_enum(v, name, obj, lookup, errp);
>          break;
>      case VISITOR_CLONE:
>          /* nothing further to do, scalar value was already copied by
[Skipping churn I hope to reduce...]
> diff --git a/block/parallels.c b/block/parallels.c
> index e1e06d23cc..f870bbac3e 100644
> --- a/block/parallels.c
> +++ b/block/parallels.c
> @@ -69,12 +69,16 @@ typedef enum ParallelsPreallocMode {
>      PRL_PREALLOC_MODE__MAX = 2,
>  } ParallelsPreallocMode;
>  
> -static const char *prealloc_mode_lookup[] = {
> +static const char *prealloc_mode_array[] = {
>      "falloc",
>      "truncate",
>      NULL,
>  };
>  
> +static QEnumLookup prealloc_mode_lookup = {
> +    .array = prealloc_mode_array,
> +    .size = G_N_ELEMENTS(prealloc_mode_array),
> +};
>  
>  typedef struct BDRVParallelsState {
>      /** Locking is conservative, the lock protects

My comment on scripts/qapi.py applies.

> @@ -696,8 +700,8 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
>          qemu_opt_get_size_del(opts, PARALLELS_OPT_PREALLOC_SIZE, 0);
>      s->prealloc_size = MAX(s->tracks, s->prealloc_size >> BDRV_SECTOR_BITS);
>      buf = qemu_opt_get_del(opts, PARALLELS_OPT_PREALLOC_MODE);
> -    s->prealloc_mode = qapi_enum_parse(prealloc_mode_lookup, buf,
> -            PRL_PREALLOC_MODE__MAX, PRL_PREALLOC_MODE_FALLOCATE, &local_err);
> +    s->prealloc_mode = qapi_enum_parse(&prealloc_mode_lookup, buf,
> +                                       PRL_PREALLOC_MODE_FALLOCATE, &local_err);
>      g_free(buf);
>      if (local_err != NULL) {
>          goto fail_options;
[Skipping more churn...]
> diff --git a/crypto/block-luks.c b/crypto/block-luks.c
> index b78a6345f3..a3c96d768b 100644
> --- a/crypto/block-luks.c
> +++ b/crypto/block-luks.c
> @@ -258,47 +258,39 @@ qcrypto_block_luks_cipher_alg_lookup(QCryptoCipherAlgorithm alg,
>      }
>  
>      error_setg(errp, "Algorithm '%s' not supported",
> -               qapi_enum_lookup(QCryptoCipherAlgorithm_lookup, alg));
> +               qapi_enum_lookup(&QCryptoCipherAlgorithm_lookup, alg));
>      return NULL;
>  }
>  
> -/* XXX replace with qapi_enum_parse() in future, when we can
> +/* XXX replace with qapi_enum_parse(&) in future, when we can

Whoops!

>   * make that function emit a more friendly error message */
>  static int qcrypto_block_luks_name_lookup(const char *name,
> -                                          const char *const *map,
> -                                          size_t maplen,
> +                                          const QEnumLookup *lookup,
>                                            const char *type,
>                                            Error **errp)
>  {
> -    size_t i;
> -    for (i = 0; i < maplen; i++) {
> -        if (g_str_equal(map[i], name)) {
> -            return i;
> -        }
> +    int i = qapi_enum_parse(lookup, name, -1, NULL);
> +    if (i < 0) {
> +        error_setg(errp, "%s %s not supported", type, name);
>      }
> -
> -    error_setg(errp, "%s %s not supported", type, name);
> -    return 0;
> +    return i;
>  }

Here, you do use qapi_enum_parse().  Good, but let's do it in a
separate, preparatory patch like PATCH 07-11.

[Skipping more churn...]
> diff --git a/qapi/qapi-util.c b/qapi/qapi-util.c
> index 7677caa51e..363214efb1 100644
> --- a/qapi/qapi-util.c
> +++ b/qapi/qapi-util.c
> @@ -15,8 +15,8 @@
>  #include "qemu-common.h"
>  #include "qapi/util.h"
>  
> -int qapi_enum_parse(const char * const lookup[], const char *buf,
> -                    int max, int def, Error **errp)
> +int qapi_enum_parse(const QEnumLookup *lookup, const char *buf,
> +                    int def, Error **errp)
>  {
>      int i;
>  
> @@ -24,8 +24,8 @@ int qapi_enum_parse(const char * const lookup[], const char *buf,
>          return def;
>      }
>  
> -    for (i = 0; i < max; i++) {
> -        if (!strcmp(buf, lookup[i])) {
> +    for (i = 0; i < lookup->size; i++) {
> +        if (!g_strcmp0(buf, lookup->array[i])) {
>              return i;
>          }
>      }

Why switch from strcmp() to g_strcmp0()?

If it's to support holes: hole support should be done in a later patch,
possibly a separate one.

> @@ -34,11 +34,12 @@ int qapi_enum_parse(const char * const lookup[], const char *buf,
>      return def;
>  }
>  
> -const char *qapi_enum_lookup(const char * const lookup[], int val)
> +const char *qapi_enum_lookup(const QEnumLookup *lookup, int val)
>  {
>      assert(val >= 0);
> +    assert(val < lookup->size);

The additional bounds check is a nice extra.  But let's fuse the
assertions.

The patch that introduces hole support should additionally assert
lookup->array[val].

>  
> -    return lookup[val];
> +    return lookup->array[val];
>  }
>  
>  /*
[Skipping more churn...]
> diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c
> index c51e6e734d..0ba8b55ce1 100644
> --- a/tests/check-qom-proplist.c
> +++ b/tests/check-qom-proplist.c
> @@ -53,6 +53,11 @@ static const char *const dummy_animal_map[DUMMY_LAST + 1] = {
>      [DUMMY_LAST] = NULL,
>  };
>  
> +const QEnumLookup dummy_animal_lookup = {
> +    .array = dummy_animal_map,
> +    .size = DUMMY_LAST
> +};
> +
>  struct DummyObject {
>      Object parent_obj;
>  

My comment on scripts/qapi.py applies.

> @@ -142,7 +147,7 @@ static void dummy_class_init(ObjectClass *cls, void *data)
>                                    NULL);
>      object_class_property_add_enum(cls, "av",
>                                     "DummyAnimal",
> -                                   dummy_animal_map,
> +                                   &dummy_animal_lookup,
>                                     dummy_get_av,
>                                     dummy_set_av,
>                                     NULL);
[Skipping more churn...]
> index bdd00f6bd8..be7d7ea654 100644
> --- a/tests/test-qobject-input-visitor.c
> +++ b/tests/test-qobject-input-visitor.c
> @@ -382,10 +382,10 @@ static void test_visitor_in_enum(TestInputVisitorData *data,
>      Visitor *v;
>      EnumOne i;
>  
> -    for (i = 0; EnumOne_lookup[i]; i++) {
> +    for (i = 0; i < EnumOne_lookup.size; i++) {
>          EnumOne res = -1;
>  
> -        v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
> +        v = visitor_input_test_init(data, "%s", EnumOne_lookup.array[i]);
>  
>          visit_type_EnumOne(v, NULL, &res, &error_abort);
>          g_assert_cmpint(i, ==, res);
> @@ -699,7 +699,7 @@ static void test_native_list_integer_helper(TestInputVisitorData *data,
>          }
>      }
>      g_string_append_printf(gstr_union,  "{ 'type': '%s', 'data': [ %s ] }",
> -                           UserDefNativeListUnionKind_lookup[kind],
> +                           UserDefNativeListUnionKind_lookup.array[kind],

PATCH 06 should have changed this to qapi_enum_lookup(), as noted in my
review there.

>                             gstr_list->str);
>      v = visitor_input_test_init_raw(data,  gstr_union->str);
>  
> @@ -1110,7 +1110,7 @@ static void test_visitor_in_fail_struct_missing(TestInputVisitorData *data,
>      error_free_or_abort(&err);
>      visit_optional(v, "optional", &present);
>      g_assert(!present);
> -    visit_type_enum(v, "enum", &en, EnumOne_lookup, &err);
> +    visit_type_enum(v, "enum", &en, &EnumOne_lookup, &err);
>      error_free_or_abort(&err);
>      visit_type_int(v, "i64", &i64, &err);
>      error_free_or_abort(&err);
> diff --git a/tests/test-qobject-output-visitor.c b/tests/test-qobject-output-visitor.c
> index bb2d66b666..55a8c932e0 100644
> --- a/tests/test-qobject-output-visitor.c
> +++ b/tests/test-qobject-output-visitor.c
> @@ -135,7 +135,7 @@ static void test_visitor_out_enum(TestOutputVisitorData *data,
>          qstr = qobject_to_qstring(visitor_get(data));
>          g_assert(qstr);
>          g_assert_cmpstr(qstring_get_str(qstr), ==,
> -                        qapi_enum_lookup(EnumOne_lookup, i));
> +                        qapi_enum_lookup(&EnumOne_lookup, i));
>          visitor_reset(data);
>      }
>  }
> diff --git a/tests/test-string-input-visitor.c b/tests/test-string-input-visitor.c
> index 79313a7f7a..5828359830 100644
> --- a/tests/test-string-input-visitor.c
> +++ b/tests/test-string-input-visitor.c
> @@ -279,10 +279,10 @@ static void test_visitor_in_enum(TestInputVisitorData *data,
>      Visitor *v;
>      EnumOne i;
>  
> -    for (i = 0; EnumOne_lookup[i]; i++) {
> +    for (i = 0; i < EnumOne_lookup.size; i++) {
>          EnumOne res = -1;
>  
> -        v = visitor_input_test_init(data, EnumOne_lookup[i]);
> +        v = visitor_input_test_init(data, EnumOne_lookup.array[i]);
>  
>          visit_type_EnumOne(v, NULL, &res, &err);

Likewise.

>          g_assert(!err);
> diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c
> index 0b2087d312..a5d26ac0ca 100644
> --- a/tests/test-string-output-visitor.c
> +++ b/tests/test-string-output-visitor.c
> @@ -196,12 +196,12 @@ static void test_visitor_out_enum(TestOutputVisitorData *data,
>          str = visitor_get(data);
>          if (data->human) {
>              char *str_human =
> -                g_strdup_printf("\"%s\"", qapi_enum_lookup(EnumOne_lookup, i));
> +                g_strdup_printf("\"%s\"", qapi_enum_lookup(&EnumOne_lookup, i));
>  
>              g_assert_cmpstr(str, ==, str_human);
>              g_free(str_human);
>          } else {
> -            g_assert_cmpstr(str, ==, qapi_enum_lookup(EnumOne_lookup, i));
> +            g_assert_cmpstr(str, ==, qapi_enum_lookup(&EnumOne_lookup, i));
>          }
>          visitor_reset(data);
>      }
> diff --git a/tpm.c b/tpm.c
> index f175661bfe..3ddd889906 100644
> --- a/tpm.c
> +++ b/tpm.c
> @@ -63,7 +63,7 @@ static bool tpm_model_is_registered(enum TpmModel model)
>  
>  const TPMDriverOps *tpm_get_backend_driver(const char *type)
>  {
> -    int i = qapi_enum_parse(TpmType_lookup, type, TPM_TYPE__MAX, -1, NULL);
> +    int i = qapi_enum_parse(&TpmType_lookup, type, -1, NULL);
>  
>      return i >= 0 ? be_drivers[i] : NULL;
>  }
> @@ -92,7 +92,7 @@ static void tpm_display_backend_drivers(void)
>              continue;
>          }
>          fprintf(stderr, "%12s   %s\n",
> -                qapi_enum_lookup(TpmType_lookup, i),
> +                qapi_enum_lookup(&TpmType_lookup, i),
>                  be_drivers[i]->desc());
>      }
>      fprintf(stderr, "\n");
> diff --git a/ui/input-legacy.c b/ui/input-legacy.c
> index 7159747404..c597bdc711 100644
> --- a/ui/input-legacy.c
> +++ b/ui/input-legacy.c
> @@ -61,9 +61,9 @@ int index_from_key(const char *key, size_t key_length)
>  {
>      int i;
>  
> -    for (i = 0; QKeyCode_lookup[i] != NULL; i++) {
> -        if (!strncmp(key, QKeyCode_lookup[i], key_length) &&
> -            !QKeyCode_lookup[i][key_length]) {
> +    for (i = 0; QKeyCode_lookup.array[i] != NULL; i++) {
> +        if (!strncmp(key, QKeyCode_lookup.array[i], key_length) &&
> +            !QKeyCode_lookup.array[i][key_length]) {
>              break;
>          }
>      }

This is almost qapi_enum_parse(), but not quite: the key isn't
zero-terminated.  Pity, because it looks like the last user that dots
into QEnumLookup.  If we get rid of it, we can make it opaque.  I'd do
it right away, but if you prefer to leave it for later, I can accept
that.

[Skipping more churn...]

I may well have missed issues in the stuff I skipped here.  Hopefully, I
can reduce the churn and make this patch reviewable in full.

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

* Re: [Qemu-devel] [PATCH v2 13/54] qapi: drop the sentinel in enum array
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 13/54] qapi: drop the sentinel in enum array Marc-André Lureau
@ 2017-08-23 12:37   ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-08-23 12:37 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: qemu-devel, Kevin Wolf, Michael Roth, open list:parallels,
	Max Reitz, Gerd Hoffmann, Stefan Hajnoczi, Denis V. Lunev

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

> Now that all usages have been converted to user lookup helpers.

I don't think you got them all:

    $ git-grep -F _lookup.
    tests/test-qobject-input-visitor.c:    for (i = 0; i < EnumOne_lookup.size; i++) {
    tests/test-qobject-input-visitor.c:        v = visitor_input_test_init(data, "%s", EnumOne_lookup.array[i]);
    tests/test-qobject-input-visitor.c:                           UserDefNativeListUnionKind_lookup.array[kind],
    tests/test-string-input-visitor.c:    for (i = 0; i < EnumOne_lookup.size; i++) {
    tests/test-string-input-visitor.c:        v = visitor_input_test_init(data, EnumOne_lookup.array[i]);
    ui/input-legacy.c:    for (i = 0; i < QKeyCode_lookup.size; i++) {
    ui/input-legacy.c:        if (!strncmp(key, QKeyCode_lookup.array[i], key_length) &&
    ui/input-legacy.c:            !QKeyCode_lookup.array[i][key_length]) {

I think I commented on all of these guys in my review of PATCH 06-12.

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

* Re: [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code
  2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
                   ` (54 preceding siblings ...)
  2017-08-22 14:47 ` [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code no-reply
@ 2017-08-23 12:46 ` Markus Armbruster
  55 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-08-23 12:46 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

PATCH 01 is a bug fix I'll apply it to qapi-next right away.

PATCH 02-05 changes qmp-introspect.c's data structure from plain string
to recursive structure, in preparation of the real QAPI work that starts
in PATCH 15.  PATCH 03 needs splitting.  Apart from that, I only asked
for minor tweaks, I think.

I believe PATCH 06-13 can stand on their own.  Let's spin them off into
their own series.  Since I want to play with them to explore ideas to
reduce churn, I'll do that myself.

I'll return to the remainder of this series once I'm done with that.

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

* Re: [Qemu-devel] [PATCH v2 53/54] qapi: make query-cpu-model-expansion depend on s390 or x86
  2017-08-23 10:21     ` Marc-André Lureau
@ 2017-08-23 12:57       ` Eduardo Habkost
  2017-08-23 13:58         ` Marc-André Lureau
  0 siblings, 1 reply; 140+ messages in thread
From: Eduardo Habkost @ 2017-08-23 12:57 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: qemu-devel, Dr. David Alan Gilbert, Markus Armbruster,
	Eric Blake, Paolo Bonzini, Richard Henderson, Alexander Graf

On Wed, Aug 23, 2017 at 06:21:16AM -0400, Marc-André Lureau wrote:
> Hi
> 
> ----- Original Message -----
> > On Tue, Aug 22, 2017 at 03:22:54PM +0200, Marc-André Lureau wrote:
> > > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > > ---
> > >  qapi-schema.json                       |  4 +++-
> > >  include/sysemu/arch_init.h             |  3 ---
> > >  monitor.c                              |  3 ---
> > >  qmp.c                                  |  7 -------
> > >  stubs/arch-query-cpu-model-expansion.c | 12 ------------
> > >  target/i386/cpu.c                      |  2 +-
> > >  target/s390x/cpu_models.c              |  3 ++-
> > >  stubs/Makefile.objs                    |  1 -
> > >  8 files changed, 6 insertions(+), 29 deletions(-)
> > >  delete mode 100644 stubs/arch-query-cpu-model-expansion.c
> > > 
> > > diff --git a/qapi-schema.json b/qapi-schema.json
> > > index 6c1adb35b5..127a2c71c6 100644
> > > --- a/qapi-schema.json
> > > +++ b/qapi-schema.json
> > > @@ -4535,7 +4535,9 @@
> > >  { 'command': 'query-cpu-model-expansion',
> > >    'data': { 'type': 'CpuModelExpansionType',
> > >              'model': 'CpuModelInfo' },
> > > -  'returns': 'CpuModelExpansionInfo' }
> > > +  'returns': 'CpuModelExpansionInfo',
> > > +  'if': ['defined(NEED_CPU_H)',
> > > +         'defined(TARGET_S390X) || defined(TARGET_I386)']}
> > 
> > Maybe this is already documented somewhere in the series (I'm
> > still going through the other patches), but: why exactly is
> > 'defined(NEED_CPU_H)' in the list, too?
> 
> The point of this series is to make qapi schema configurable.
> 
> Some types/commands/events are target-specifc. In order to
> #ifdef on poisoined symbols, we make most of QAPI generated
> code built per-target in patch 49/54. But the common code still
> need to compile some units, that's why #ifdef NEED_CPU_U. The
> clean solution is probably to split the generated schema to
> common & per-target, that's not covered in the series.

I see.  I'm worried about one thing: what if the QMP dispatch
code is incorrectly moved back to common code later?  It will
silently skip all the arch-dependent commands without any
warnings.

e.g.: I just applied the following change on top of your series,
and all arch-dependent commands are silently skipped:

  diff --git a/Makefile.objs b/Makefile.objs
  index 2664720..24a4ea0 100644
  --- a/Makefile.objs
  +++ b/Makefile.objs
  @@ -2,7 +2,7 @@
   # Common libraries for tools and emulators
   stub-obj-y = stubs/ crypto/
   util-obj-y = util/ qobject/ qapi/
  -util-obj-y += qapi-types.o qapi-visit.o
  +util-obj-y += qmp-introspect.o qapi-types.o qapi-visit.o qapi-event.o
   
   chardev-obj-y = chardev/
   
  @@ -72,6 +72,13 @@ common-obj-y += chardev/
   common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o
   
   common-obj-$(CONFIG_FDT) += device_tree.o
  +
  +######################################################################
  +# qapi
  +
  +common-obj-y += qmp-marshal.o
  +common-obj-y += qmp-introspect.o
  +common-obj-y += qmp.o hmp.o
   endif
   
   #######################################################################
  diff --git a/Makefile.target b/Makefile.target
  index c5f8ded..7f42c45 100644
  --- a/Makefile.target
  +++ b/Makefile.target
  @@ -157,10 +157,6 @@ endif
   
   GENERATED_FILES += hmp-commands.h hmp-commands-info.h
   
  -obj-y += qmp-introspect.o qapi-types.o qapi-visit.o qapi-event.o
  -obj-y += qmp-marshal.o qmp-introspect.o
  -obj-y += qmp.o hmp.o
  -
   endif # CONFIG_SOFTMMU
   
   # Workaround for http://gcc.gnu.org/PR55489, see configure.


We wouldn't need to check NEED_CPU_H at all if the condition on
QMP commands affect only the actual QMP dispatch code, and not
the generated types or declarations.  e.g.:


diff --git a/qapi-schema.json b/qapi-schema.json
index 194859f..67b46ad 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3578,7 +3578,7 @@
 ##
 { 'command': 'dump-skeys',
   'data': { 'filename': 'str' },
-  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
+  'if': ['defined(TARGET_S390X)']}
 
 ##
 # @netdev_add:
@@ -4434,8 +4434,7 @@
 # Since: 1.2.0
 ##
 { 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'],
-  'if': ['defined(NEED_CPU_H)',
-         'defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_I386) || defined(TARGET_S390X)'] }
+  'if': ['defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_I386) || defined(TARGET_S390X)'] }
 
 ##
 # @CpuModelInfo:
@@ -4538,8 +4537,7 @@
   'data': { 'type': 'CpuModelExpansionType',
             'model': 'CpuModelInfo' },
   'returns': 'CpuModelExpansionInfo',
-  'if': ['defined(NEED_CPU_H)',
-         'defined(TARGET_S390X) || defined(TARGET_I386)']}
+  'if': ['defined(TARGET_S390X) || defined(TARGET_I386)']}
 
 ##
 # @CpuModelCompareResult:
@@ -4627,7 +4625,7 @@
 { 'command': 'query-cpu-model-comparison',
   'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
   'returns': 'CpuModelCompareInfo',
-  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
+  'if': ['defined(TARGET_S390X)']}
 
 
 ##
@@ -4681,7 +4679,7 @@
   'data': { 'modela': 'CpuModelInfo',
             'modelb': 'CpuModelInfo' },
   'returns': 'CpuModelBaselineInfo',
-  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
+  'if': ['defined(TARGET_S390X)']}
 
 ##
 # @AddfdInfo:
@@ -6303,7 +6301,7 @@
 #
 ##
 { 'command': 'rtc-reset-reinjection',
-  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_I386)'] }
+  'if': ['defined(TARGET_I386)'] }
 
 # Rocker ethernet network switch
 { 'include': 'qapi/rocker.json' }
@@ -6466,7 +6464,7 @@
 #
 ##
 { 'command': 'query-gic-capabilities', 'returns': ['GICCapability'],
-  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_ARM)']}
+  'if': ['defined(TARGET_ARM)']}
 
 ##
 # @CpuInstanceProperties:
diff --git a/scripts/qapi.py b/scripts/qapi.py
index bcd8d37..769a730 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -1720,8 +1720,7 @@ class QAPISchema(object):
         ifcond = expr.get('if')
         if isinstance(data, OrderedDict):
             data = self._make_implicit_object_type(
-                name, info, doc, 'arg', self._make_members(data, info),
-                ifcond)
+                name, info, doc, 'arg', self._make_members(data, info))
         if isinstance(rets, list):
             assert len(rets) == 1
             rets = self._make_array_type(rets[0], info)
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index db45415..2baa73f 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -228,7 +228,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
         self.defn = None
         self._regy = None
         self._visited_ret_types = None
-        self.if_members = ['decl', 'defn', '_regy']
+        self.if_members = ['defn', '_regy']
 
     def visit_begin(self, schema):
         self.decl = ''


-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v2 53/54] qapi: make query-cpu-model-expansion depend on s390 or x86
  2017-08-23 12:57       ` Eduardo Habkost
@ 2017-08-23 13:58         ` Marc-André Lureau
  2017-08-23 14:13           ` Eduardo Habkost
  0 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-23 13:58 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: qemu-devel, Dr. David Alan Gilbert, Markus Armbruster,
	Eric Blake, Paolo Bonzini, Richard Henderson, Alexander Graf

Hi

----- Original Message -----
> On Wed, Aug 23, 2017 at 06:21:16AM -0400, Marc-André Lureau wrote:
> > Hi
> > 
> > ----- Original Message -----
> > > On Tue, Aug 22, 2017 at 03:22:54PM +0200, Marc-André Lureau wrote:
> > > > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > > > ---
> > > >  qapi-schema.json                       |  4 +++-
> > > >  include/sysemu/arch_init.h             |  3 ---
> > > >  monitor.c                              |  3 ---
> > > >  qmp.c                                  |  7 -------
> > > >  stubs/arch-query-cpu-model-expansion.c | 12 ------------
> > > >  target/i386/cpu.c                      |  2 +-
> > > >  target/s390x/cpu_models.c              |  3 ++-
> > > >  stubs/Makefile.objs                    |  1 -
> > > >  8 files changed, 6 insertions(+), 29 deletions(-)
> > > >  delete mode 100644 stubs/arch-query-cpu-model-expansion.c
> > > > 
> > > > diff --git a/qapi-schema.json b/qapi-schema.json
> > > > index 6c1adb35b5..127a2c71c6 100644
> > > > --- a/qapi-schema.json
> > > > +++ b/qapi-schema.json
> > > > @@ -4535,7 +4535,9 @@
> > > >  { 'command': 'query-cpu-model-expansion',
> > > >    'data': { 'type': 'CpuModelExpansionType',
> > > >              'model': 'CpuModelInfo' },
> > > > -  'returns': 'CpuModelExpansionInfo' }
> > > > +  'returns': 'CpuModelExpansionInfo',
> > > > +  'if': ['defined(NEED_CPU_H)',
> > > > +         'defined(TARGET_S390X) || defined(TARGET_I386)']}
> > > 
> > > Maybe this is already documented somewhere in the series (I'm
> > > still going through the other patches), but: why exactly is
> > > 'defined(NEED_CPU_H)' in the list, too?
> > 
> > The point of this series is to make qapi schema configurable.
> > 
> > Some types/commands/events are target-specifc. In order to
> > #ifdef on poisoined symbols, we make most of QAPI generated
> > code built per-target in patch 49/54. But the common code still
> > need to compile some units, that's why #ifdef NEED_CPU_U. The
> > clean solution is probably to split the generated schema to
> > common & per-target, that's not covered in the series.
> 
> I see.  I'm worried about one thing: what if the QMP dispatch
> code is incorrectly moved back to common code later?  It will
> silently skip all the arch-dependent commands without any
> warnings.
> 
> e.g.: I just applied the following change on top of your series,
> and all arch-dependent commands are silently skipped:
> 

And it doesn't fail a full/all-arch make check? It probably should.

>   diff --git a/Makefile.objs b/Makefile.objs
>   index 2664720..24a4ea0 100644
>   --- a/Makefile.objs
>   +++ b/Makefile.objs
>   @@ -2,7 +2,7 @@
>    # Common libraries for tools and emulators
>    stub-obj-y = stubs/ crypto/
>    util-obj-y = util/ qobject/ qapi/
>   -util-obj-y += qapi-types.o qapi-visit.o
>   +util-obj-y += qmp-introspect.o qapi-types.o qapi-visit.o qapi-event.o
>    
>    chardev-obj-y = chardev/
>    
>   @@ -72,6 +72,13 @@ common-obj-y += chardev/
>    common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o
>    
>    common-obj-$(CONFIG_FDT) += device_tree.o
>   +
>   +######################################################################
>   +# qapi
>   +
>   +common-obj-y += qmp-marshal.o
>   +common-obj-y += qmp-introspect.o
>   +common-obj-y += qmp.o hmp.o
>    endif
>    
>    #######################################################################
>   diff --git a/Makefile.target b/Makefile.target
>   index c5f8ded..7f42c45 100644
>   --- a/Makefile.target
>   +++ b/Makefile.target
>   @@ -157,10 +157,6 @@ endif
>    
>    GENERATED_FILES += hmp-commands.h hmp-commands-info.h
>    
>   -obj-y += qmp-introspect.o qapi-types.o qapi-visit.o qapi-event.o
>   -obj-y += qmp-marshal.o qmp-introspect.o
>   -obj-y += qmp.o hmp.o
>   -
>    endif # CONFIG_SOFTMMU
>    
>    # Workaround for http://gcc.gnu.org/PR55489, see configure.
> 
> 
> We wouldn't need to check NEED_CPU_H at all if the condition on
> QMP commands affect only the actual QMP dispatch code, and not
> the generated types or declarations.  e.g.:
> 

Possible, but is it desirable? I would prefer if all the generated code would be configured, so we can more easily compile out dead code when disabling a feature. 

> 
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 194859f..67b46ad 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -3578,7 +3578,7 @@
>  ##
>  { 'command': 'dump-skeys',
>    'data': { 'filename': 'str' },
> -  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
> +  'if': ['defined(TARGET_S390X)']}
>  
>  ##
>  # @netdev_add:
> @@ -4434,8 +4434,7 @@
>  # Since: 1.2.0
>  ##
>  { 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'],
> -  'if': ['defined(NEED_CPU_H)',
> -         'defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_I386)
> || defined(TARGET_S390X)'] }
> +  'if': ['defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_I386)
> || defined(TARGET_S390X)'] }
>  
>  ##
>  # @CpuModelInfo:
> @@ -4538,8 +4537,7 @@
>    'data': { 'type': 'CpuModelExpansionType',
>              'model': 'CpuModelInfo' },
>    'returns': 'CpuModelExpansionInfo',
> -  'if': ['defined(NEED_CPU_H)',
> -         'defined(TARGET_S390X) || defined(TARGET_I386)']}
> +  'if': ['defined(TARGET_S390X) || defined(TARGET_I386)']}
>  
>  ##
>  # @CpuModelCompareResult:
> @@ -4627,7 +4625,7 @@
>  { 'command': 'query-cpu-model-comparison',
>    'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
>    'returns': 'CpuModelCompareInfo',
> -  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
> +  'if': ['defined(TARGET_S390X)']}
>  
>  
>  ##
> @@ -4681,7 +4679,7 @@
>    'data': { 'modela': 'CpuModelInfo',
>              'modelb': 'CpuModelInfo' },
>    'returns': 'CpuModelBaselineInfo',
> -  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
> +  'if': ['defined(TARGET_S390X)']}
>  
>  ##
>  # @AddfdInfo:
> @@ -6303,7 +6301,7 @@
>  #
>  ##
>  { 'command': 'rtc-reset-reinjection',
> -  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_I386)'] }
> +  'if': ['defined(TARGET_I386)'] }
>  
>  # Rocker ethernet network switch
>  { 'include': 'qapi/rocker.json' }
> @@ -6466,7 +6464,7 @@
>  #
>  ##
>  { 'command': 'query-gic-capabilities', 'returns': ['GICCapability'],
> -  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_ARM)']}
> +  'if': ['defined(TARGET_ARM)']}
>  
>  ##
>  # @CpuInstanceProperties:
> diff --git a/scripts/qapi.py b/scripts/qapi.py
> index bcd8d37..769a730 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi.py
> @@ -1720,8 +1720,7 @@ class QAPISchema(object):
>          ifcond = expr.get('if')
>          if isinstance(data, OrderedDict):
>              data = self._make_implicit_object_type(
> -                name, info, doc, 'arg', self._make_members(data, info),
> -                ifcond)
> +                name, info, doc, 'arg', self._make_members(data, info))
>          if isinstance(rets, list):
>              assert len(rets) == 1
>              rets = self._make_array_type(rets[0], info)
> diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
> index db45415..2baa73f 100644
> --- a/scripts/qapi-commands.py
> +++ b/scripts/qapi-commands.py
> @@ -228,7 +228,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
>          self.defn = None
>          self._regy = None
>          self._visited_ret_types = None
> -        self.if_members = ['decl', 'defn', '_regy']
> +        self.if_members = ['defn', '_regy']
>  
>      def visit_begin(self, schema):
>          self.decl = ''
> 
> 
> --
> Eduardo
> 

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

* Re: [Qemu-devel] [PATCH v2 53/54] qapi: make query-cpu-model-expansion depend on s390 or x86
  2017-08-23 13:58         ` Marc-André Lureau
@ 2017-08-23 14:13           ` Eduardo Habkost
  0 siblings, 0 replies; 140+ messages in thread
From: Eduardo Habkost @ 2017-08-23 14:13 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: qemu-devel, Dr. David Alan Gilbert, Markus Armbruster,
	Eric Blake, Paolo Bonzini, Richard Henderson, Alexander Graf

On Wed, Aug 23, 2017 at 09:58:59AM -0400, Marc-André Lureau wrote:
> Hi
> 
> ----- Original Message -----
> > On Wed, Aug 23, 2017 at 06:21:16AM -0400, Marc-André Lureau wrote:
> > > Hi
> > > 
> > > ----- Original Message -----
> > > > On Tue, Aug 22, 2017 at 03:22:54PM +0200, Marc-André Lureau wrote:
> > > > > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > > > > ---
> > > > >  qapi-schema.json                       |  4 +++-
> > > > >  include/sysemu/arch_init.h             |  3 ---
> > > > >  monitor.c                              |  3 ---
> > > > >  qmp.c                                  |  7 -------
> > > > >  stubs/arch-query-cpu-model-expansion.c | 12 ------------
> > > > >  target/i386/cpu.c                      |  2 +-
> > > > >  target/s390x/cpu_models.c              |  3 ++-
> > > > >  stubs/Makefile.objs                    |  1 -
> > > > >  8 files changed, 6 insertions(+), 29 deletions(-)
> > > > >  delete mode 100644 stubs/arch-query-cpu-model-expansion.c
> > > > > 
> > > > > diff --git a/qapi-schema.json b/qapi-schema.json
> > > > > index 6c1adb35b5..127a2c71c6 100644
> > > > > --- a/qapi-schema.json
> > > > > +++ b/qapi-schema.json
> > > > > @@ -4535,7 +4535,9 @@
> > > > >  { 'command': 'query-cpu-model-expansion',
> > > > >    'data': { 'type': 'CpuModelExpansionType',
> > > > >              'model': 'CpuModelInfo' },
> > > > > -  'returns': 'CpuModelExpansionInfo' }
> > > > > +  'returns': 'CpuModelExpansionInfo',
> > > > > +  'if': ['defined(NEED_CPU_H)',
> > > > > +         'defined(TARGET_S390X) || defined(TARGET_I386)']}
> > > > 
> > > > Maybe this is already documented somewhere in the series (I'm
> > > > still going through the other patches), but: why exactly is
> > > > 'defined(NEED_CPU_H)' in the list, too?
> > > 
> > > The point of this series is to make qapi schema configurable.
> > > 
> > > Some types/commands/events are target-specifc. In order to
> > > #ifdef on poisoined symbols, we make most of QAPI generated
> > > code built per-target in patch 49/54. But the common code still
> > > need to compile some units, that's why #ifdef NEED_CPU_U. The
> > > clean solution is probably to split the generated schema to
> > > common & per-target, that's not covered in the series.
> > 
> > I see.  I'm worried about one thing: what if the QMP dispatch
> > code is incorrectly moved back to common code later?  It will
> > silently skip all the arch-dependent commands without any
> > warnings.
> > 
> > e.g.: I just applied the following change on top of your series,
> > and all arch-dependent commands are silently skipped:
> > 
> 
> And it doesn't fail a full/all-arch make check? It probably should.

I don't know, I will test it.

> 
> >   diff --git a/Makefile.objs b/Makefile.objs
> >   index 2664720..24a4ea0 100644
> >   --- a/Makefile.objs
> >   +++ b/Makefile.objs
> >   @@ -2,7 +2,7 @@
> >    # Common libraries for tools and emulators
> >    stub-obj-y = stubs/ crypto/
> >    util-obj-y = util/ qobject/ qapi/
> >   -util-obj-y += qapi-types.o qapi-visit.o
> >   +util-obj-y += qmp-introspect.o qapi-types.o qapi-visit.o qapi-event.o
> >    
> >    chardev-obj-y = chardev/
> >    
> >   @@ -72,6 +72,13 @@ common-obj-y += chardev/
> >    common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o
> >    
> >    common-obj-$(CONFIG_FDT) += device_tree.o
> >   +
> >   +######################################################################
> >   +# qapi
> >   +
> >   +common-obj-y += qmp-marshal.o
> >   +common-obj-y += qmp-introspect.o
> >   +common-obj-y += qmp.o hmp.o
> >    endif
> >    
> >    #######################################################################
> >   diff --git a/Makefile.target b/Makefile.target
> >   index c5f8ded..7f42c45 100644
> >   --- a/Makefile.target
> >   +++ b/Makefile.target
> >   @@ -157,10 +157,6 @@ endif
> >    
> >    GENERATED_FILES += hmp-commands.h hmp-commands-info.h
> >    
> >   -obj-y += qmp-introspect.o qapi-types.o qapi-visit.o qapi-event.o
> >   -obj-y += qmp-marshal.o qmp-introspect.o
> >   -obj-y += qmp.o hmp.o
> >   -
> >    endif # CONFIG_SOFTMMU
> >    
> >    # Workaround for http://gcc.gnu.org/PR55489, see configure.
> > 
> > 
> > We wouldn't need to check NEED_CPU_H at all if the condition on
> > QMP commands affect only the actual QMP dispatch code, and not
> > the generated types or declarations.  e.g.:
> > 
> 
> Possible, but is it desirable? I would prefer if all the
> generated code would be configured, so we can more easily
> compile out dead code when disabling a feature. 

That's a valid question.

A check for defined(NEED_CPU_H) inside a .c file still feels
wrong to me.  But if "make check" will detect a mistake like the
one above and QAPI maintainers don't mind, I won't mind either.


> > 
> > diff --git a/qapi-schema.json b/qapi-schema.json
> > index 194859f..67b46ad 100644
> > --- a/qapi-schema.json
> > +++ b/qapi-schema.json
> > @@ -3578,7 +3578,7 @@
> >  ##
> >  { 'command': 'dump-skeys',
> >    'data': { 'filename': 'str' },
> > -  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
> > +  'if': ['defined(TARGET_S390X)']}
> >  
> >  ##
> >  # @netdev_add:
> > @@ -4434,8 +4434,7 @@
> >  # Since: 1.2.0
> >  ##
> >  { 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'],
> > -  'if': ['defined(NEED_CPU_H)',
> > -         'defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_I386)
> > || defined(TARGET_S390X)'] }
> > +  'if': ['defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_I386)
> > || defined(TARGET_S390X)'] }
> >  
> >  ##
> >  # @CpuModelInfo:
> > @@ -4538,8 +4537,7 @@
> >    'data': { 'type': 'CpuModelExpansionType',
> >              'model': 'CpuModelInfo' },
> >    'returns': 'CpuModelExpansionInfo',
> > -  'if': ['defined(NEED_CPU_H)',
> > -         'defined(TARGET_S390X) || defined(TARGET_I386)']}
> > +  'if': ['defined(TARGET_S390X) || defined(TARGET_I386)']}
> >  
> >  ##
> >  # @CpuModelCompareResult:
> > @@ -4627,7 +4625,7 @@
> >  { 'command': 'query-cpu-model-comparison',
> >    'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
> >    'returns': 'CpuModelCompareInfo',
> > -  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
> > +  'if': ['defined(TARGET_S390X)']}
> >  
> >  
> >  ##
> > @@ -4681,7 +4679,7 @@
> >    'data': { 'modela': 'CpuModelInfo',
> >              'modelb': 'CpuModelInfo' },
> >    'returns': 'CpuModelBaselineInfo',
> > -  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_S390X)']}
> > +  'if': ['defined(TARGET_S390X)']}
> >  
> >  ##
> >  # @AddfdInfo:
> > @@ -6303,7 +6301,7 @@
> >  #
> >  ##
> >  { 'command': 'rtc-reset-reinjection',
> > -  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_I386)'] }
> > +  'if': ['defined(TARGET_I386)'] }
> >  
> >  # Rocker ethernet network switch
> >  { 'include': 'qapi/rocker.json' }
> > @@ -6466,7 +6464,7 @@
> >  #
> >  ##
> >  { 'command': 'query-gic-capabilities', 'returns': ['GICCapability'],
> > -  'if': ['defined(NEED_CPU_H)', 'defined(TARGET_ARM)']}
> > +  'if': ['defined(TARGET_ARM)']}
> >  
> >  ##
> >  # @CpuInstanceProperties:
> > diff --git a/scripts/qapi.py b/scripts/qapi.py
> > index bcd8d37..769a730 100644
> > --- a/scripts/qapi.py
> > +++ b/scripts/qapi.py
> > @@ -1720,8 +1720,7 @@ class QAPISchema(object):
> >          ifcond = expr.get('if')
> >          if isinstance(data, OrderedDict):
> >              data = self._make_implicit_object_type(
> > -                name, info, doc, 'arg', self._make_members(data, info),
> > -                ifcond)
> > +                name, info, doc, 'arg', self._make_members(data, info))
> >          if isinstance(rets, list):
> >              assert len(rets) == 1
> >              rets = self._make_array_type(rets[0], info)
> > diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
> > index db45415..2baa73f 100644
> > --- a/scripts/qapi-commands.py
> > +++ b/scripts/qapi-commands.py
> > @@ -228,7 +228,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
> >          self.defn = None
> >          self._regy = None
> >          self._visited_ret_types = None
> > -        self.if_members = ['decl', 'defn', '_regy']
> > +        self.if_members = ['defn', '_regy']
> >  
> >      def visit_begin(self, schema):
> >          self.decl = ''
> > 
> > 
> > --
> > Eduardo
> > 

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v2 06/54] qapi: introduce qapi_enum_lookup()
  2017-08-23 10:10     ` Marc-André Lureau
@ 2017-08-24 11:14       ` Dr. David Alan Gilbert
  0 siblings, 0 replies; 140+ messages in thread
From: Dr. David Alan Gilbert @ 2017-08-24 11:14 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: Markus Armbruster, qemu-devel, open list:Sheepdog,
	Stefan Hajnoczi, Michael S. Tsirkin, Jeff Cody, Michael Roth,
	Gerd Hoffmann, Josh Durgin, zhanghailiang, open list:Block Jobs,
	Juan Quintela, Liu Yuan, Jason Wang, Eduardo Habkost,
	Stefan Weil, Peter Lieven, Ronnie Sahlberg, Igor Mammedov,
	John Snow, Kevin Wolf, Hitoshi Mitake, Max Reitz, Paolo Bonzini

* Marc-André Lureau (marcandre.lureau@redhat.com) wrote:
> Hi
> 
> ----- Original Message -----
> > Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> > 
> > > This will help with the introduction of a new structure to handle
> > > enum lookup.

It would be good to make that comment explain why it's necessary.

> > > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > > ---
> > [...]
> > >  45 files changed, 206 insertions(+), 122 deletions(-)
> > 
> > Hmm.
> > 
> > > diff --git a/include/qapi/util.h b/include/qapi/util.h
> > > index 7436ed815c..60733b6a80 100644
> > > --- a/include/qapi/util.h
> > > +++ b/include/qapi/util.h
> > > @@ -11,6 +11,8 @@
> > >  #ifndef QAPI_UTIL_H
> > >  #define QAPI_UTIL_H
> > >  
> > > +const char *qapi_enum_lookup(const char * const lookup[], int val);
> > > +
> > >  int qapi_enum_parse(const char * const lookup[], const char *buf,
> > >                      int max, int def, Error **errp);
> > >  
> > > diff --git a/backends/hostmem.c b/backends/hostmem.c
> > > index 4606b73849..c4f795475c 100644
> > > --- a/backends/hostmem.c
> > > +++ b/backends/hostmem.c
> > > @@ -13,6 +13,7 @@
> > >  #include "sysemu/hostmem.h"
> > >  #include "hw/boards.h"
> > >  #include "qapi/error.h"
> > > +#include "qapi/util.h"
> > >  #include "qapi/visitor.h"
> > >  #include "qapi-types.h"
> > >  #include "qapi-visit.h"
> > > @@ -304,7 +305,7 @@ host_memory_backend_memory_complete(UserCreatable *uc,
> > > Error **errp)
> > >              return;
> > >          } else if (maxnode == 0 && backend->policy != MPOL_DEFAULT) {
> > >              error_setg(errp, "host-nodes must be set for policy %s",
> > > -                       HostMemPolicy_lookup[backend->policy]);
> > > +                qapi_enum_lookup(HostMemPolicy_lookup, backend->policy));
> > >              return;
> > >          }
> > >  
> > 
> > Lookup becomes even more verbose.
> > 
> > Could we claw back some readability with macros?  Say in addition to
> > 
> >     typedef enum FOO {
> >         ...
> >     } FOO;
> > 
> >     extern const char *const FOO_lookup[];
> > 
> > generate
> > 
> >     #define FOO_str(val) qapi_enum_lookup(FOO_lookup, (val))
> > 
> > Needs a matching qapi-code-gen.txt update.
> > 
> > With that, this patch hunk would become
> > 
> >                error_setg(errp, "host-nodes must be set for policy %s",
> >   -                       HostMemPolicy_lookup[backend->policy]);
> >   +                       HostMemPolicy_str(backend->policy);
> > 
> > Perhaps we could even throw in some type checking:
> > 
> >     #define FOO_str(val) (type_check(typeof((val)), FOO) \
> >                           + qapi_enum_lookup(FOO_lookup, (val)))
> > 
> > What do you think?  Want me to explore a fixup patch you could squash
> > in?
> > 
> 
> Yes, I had similar thoughts, but didn't spent too much time finding the best proposal, that wasn't my main goal in the series. 
> 
> Indeed, I would prefer that further improvements be done as follow-up. Or if you have a ready solution, I can squash it there. I can picture the conflicts with the next patch though... 

If you did it as a separate patch it would have to be another
huge patch changing lots of areas.
I think the use of the macro to keep it simple should be in this one;
you can add the type check change later.

Dave

> > [Skipping lots of mechanical changes...]
> > 
> > I think you missed test-qobject-input-visitor.c and
> > string-input-visitor.c.
> > 
> > In test-qobject-input-visitor.c's test_visitor_in_enum():
> > 
> >         v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
> > 
> > You update it in PATCH 12, but the code only works as long as EnumOne
> > has no holes.  Mapping the enum to string like we do everywhere else in
> > this patch would be cleaner.
> > 
> 
> ok
> 
> > The loop control also subscripts EnumOne_lookup[i].  You take care of
> > that one in PATCH 12.  That's okay.
> > 
> > Same for test-string-input-visitor.c's test_visitor_in_enum().
> > 
> > There's one more in test_native_list_integer_helper():
> > 
> >     g_string_append_printf(gstr_union,  "{ 'type': '%s', 'data': [ %s ] }",
> >                            UserDefNativeListUnionKind_lookup[kind],
> >                            gstr_list->str);
> > 
> > Same story.
> > 
> > The patch doesn't touch the _lookup[] subscripts you're going to replace
> > by qapi_enum_parse() in PATCH 07-11.  Understand, but I'd reorder the
> > patches: first replace by qapi_enum_parse(), because DRY (no need to
> > explain more at that point).  Then get rid of all the remaining
> > subscripting into _lookup[], i.e. this patch (explain it helps the next
> > one), then PATCH 12.
> > 
> 
> ok
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

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

* Re: [Qemu-devel] [PATCH v2 08/54] hmp: use qapi_enum_parse() in hmp_migrate_set_capability
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 08/54] hmp: use qapi_enum_parse() in hmp_migrate_set_capability Marc-André Lureau
  2017-08-23  9:34   ` Markus Armbruster
@ 2017-08-24 11:29   ` Dr. David Alan Gilbert
  1 sibling, 0 replies; 140+ messages in thread
From: Dr. David Alan Gilbert @ 2017-08-24 11:29 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

* Marc-André Lureau (marcandre.lureau@redhat.com) wrote:
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  hmp.c | 24 +++++++++++-------------
>  1 file changed, 11 insertions(+), 13 deletions(-)
> 
> diff --git a/hmp.c b/hmp.c
> index 29e42ab661..4ba50e8e26 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -1544,23 +1544,21 @@ void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict)
>      bool state = qdict_get_bool(qdict, "state");
>      Error *err = NULL;
>      MigrationCapabilityStatusList *caps = g_malloc0(sizeof(*caps));
> -    int i;
> +    int val;
>  
> -    for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
> -        if (strcmp(cap, MigrationCapability_lookup[i]) == 0) {
> -            caps->value = g_malloc0(sizeof(*caps->value));
> -            caps->value->capability = i;
> -            caps->value->state = state;
> -            caps->next = NULL;
> -            qmp_migrate_set_capabilities(caps, &err);
> -            break;
> -        }
> +    val = qapi_enum_parse(MigrationCapability_lookup, cap,
> +                          MIGRATION_CAPABILITY__MAX, -1, &err);

It would be nice to macro that to something like:
   MigrationCapability_parse(cap, -1, &err);

which would stop the inevitable case of someone using the wrong _lookup
with the wrong _MAX.

I also wonder if having the qapi_enum_parse return a bool and take a
&int would be nicer - it would get rid of the need for the -1 default
and mean actually it could be an unsigned.

Still, those are only suggestions, so:

Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

> +    if (val < 0) {
> +        goto end;
>      }
>  
> -    if (i == MIGRATION_CAPABILITY__MAX) {
> -        error_setg(&err, QERR_INVALID_PARAMETER, cap);
> -    }
> +    caps->value = g_malloc0(sizeof(*caps->value));
> +    caps->value->capability = val;
> +    caps->value->state = state;
> +    caps->next = NULL;
> +    qmp_migrate_set_capabilities(caps, &err);
>  
> +end:
>      qapi_free_MigrationCapabilityStatusList(caps);
>  
>      if (err) {
> -- 
> 2.14.1.146.gd35faa819
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

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

* Re: [Qemu-devel] [PATCH v2 09/54] hmp: use qapi_enum_parse() in hmp_migrate_set_parameter
  2017-08-23  9:43   ` Markus Armbruster
@ 2017-08-24 13:16     ` Dr. David Alan Gilbert
  0 siblings, 0 replies; 140+ messages in thread
From: Dr. David Alan Gilbert @ 2017-08-24 13:16 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: Marc-André Lureau, qemu-devel

* Markus Armbruster (armbru@redhat.com) wrote:
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> 
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >  hmp.c | 139 ++++++++++++++++++++++++++++++++----------------------------------
> >  1 file changed, 68 insertions(+), 71 deletions(-)
> >
> > diff --git a/hmp.c b/hmp.c
> > index 4ba50e8e26..ccc58e6d88 100644
> > --- a/hmp.c
> > +++ b/hmp.c
> > @@ -1574,84 +1574,81 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
> >      MigrateSetParameters *p = g_new0(MigrateSetParameters, 1);
> >      uint64_t valuebw = 0;
> >      Error *err = NULL;
> > -    int i, ret;
> > -
> > -    for (i = 0; i < MIGRATION_PARAMETER__MAX; i++) {
> > -        if (strcmp(param, MigrationParameter_lookup[i]) == 0) {
> > -            switch (i) {
> > -            case MIGRATION_PARAMETER_COMPRESS_LEVEL:
> > -                p->has_compress_level = true;
> > -                visit_type_int(v, param, &p->compress_level, &err);
> > -                break;
> > -            case MIGRATION_PARAMETER_COMPRESS_THREADS:
> > -                p->has_compress_threads = true;
> > -                visit_type_int(v, param, &p->compress_threads, &err);
> > -                break;
> > -            case MIGRATION_PARAMETER_DECOMPRESS_THREADS:
> > -                p->has_decompress_threads = true;
> > -                visit_type_int(v, param, &p->decompress_threads, &err);
> > -                break;
> > -            case MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL:
> > -                p->has_cpu_throttle_initial = true;
> > -                visit_type_int(v, param, &p->cpu_throttle_initial, &err);
> > -                break;
> > -            case MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT:
> > -                p->has_cpu_throttle_increment = true;
> > -                visit_type_int(v, param, &p->cpu_throttle_increment, &err);
> > -                break;
> > -            case MIGRATION_PARAMETER_TLS_CREDS:
> > -                p->has_tls_creds = true;
> > -                p->tls_creds = g_new0(StrOrNull, 1);
> > -                p->tls_creds->type = QTYPE_QSTRING;
> > -                visit_type_str(v, param, &p->tls_creds->u.s, &err);
> > -                break;
> > -            case MIGRATION_PARAMETER_TLS_HOSTNAME:
> > -                p->has_tls_hostname = true;
> > -                p->tls_hostname = g_new0(StrOrNull, 1);
> > -                p->tls_hostname->type = QTYPE_QSTRING;
> > -                visit_type_str(v, param, &p->tls_hostname->u.s, &err);
> > -                break;
> > -            case MIGRATION_PARAMETER_MAX_BANDWIDTH:
> > -                p->has_max_bandwidth = true;
> > -                /*
> > -                 * Can't use visit_type_size() here, because it
> > -                 * defaults to Bytes rather than Mebibytes.
> > -                 */
> > -                ret = qemu_strtosz_MiB(valuestr, NULL, &valuebw);
> > -                if (ret < 0 || valuebw > INT64_MAX
> > -                    || (size_t)valuebw != valuebw) {
> > -                    error_setg(&err, "Invalid size %s", valuestr);
> > -                    break;
> > -                }
> > -                p->max_bandwidth = valuebw;
> > -                break;
> > -            case MIGRATION_PARAMETER_DOWNTIME_LIMIT:
> > -                p->has_downtime_limit = true;
> > -                visit_type_int(v, param, &p->downtime_limit, &err);
> > -                break;
> > -            case MIGRATION_PARAMETER_X_CHECKPOINT_DELAY:
> > -                p->has_x_checkpoint_delay = true;
> > -                visit_type_int(v, param, &p->x_checkpoint_delay, &err);
> > -                break;
> > -            case MIGRATION_PARAMETER_BLOCK_INCREMENTAL:
> > -                p->has_block_incremental = true;
> > -                visit_type_bool(v, param, &p->block_incremental, &err);
> > -                break;
> > -            }
> > +    int val, ret;
> >  
> > -            if (err) {
> > -                goto cleanup;
> > -            }
> > -
> > -            qmp_migrate_set_parameters(p, &err);
> > +    val = qapi_enum_parse(MigrationParameter_lookup, param,
> > +                          MIGRATION_PARAMETER__MAX,  -1, &err);
> > +    if (val < 0) {
> > +        goto cleanup;
> > +    }
> > +
> > +    switch (val) {
> > +    case MIGRATION_PARAMETER_COMPRESS_LEVEL:
> > +        p->has_compress_level = true;
> > +        visit_type_int(v, param, &p->compress_level, &err);
> > +        break;
> > +    case MIGRATION_PARAMETER_COMPRESS_THREADS:
> > +        p->has_compress_threads = true;
> > +        visit_type_int(v, param, &p->compress_threads, &err);
> > +        break;
> > +    case MIGRATION_PARAMETER_DECOMPRESS_THREADS:
> > +        p->has_decompress_threads = true;
> > +        visit_type_int(v, param, &p->decompress_threads, &err);
> > +        break;
> > +    case MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL:
> > +        p->has_cpu_throttle_initial = true;
> > +        visit_type_int(v, param, &p->cpu_throttle_initial, &err);
> > +        break;
> > +    case MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT:
> > +        p->has_cpu_throttle_increment = true;
> > +        visit_type_int(v, param, &p->cpu_throttle_increment, &err);
> > +        break;
> > +    case MIGRATION_PARAMETER_TLS_CREDS:
> > +        p->has_tls_creds = true;
> > +        p->tls_creds = g_new0(StrOrNull, 1);
> > +        p->tls_creds->type = QTYPE_QSTRING;
> > +        visit_type_str(v, param, &p->tls_creds->u.s, &err);
> > +        break;
> > +    case MIGRATION_PARAMETER_TLS_HOSTNAME:
> > +        p->has_tls_hostname = true;
> > +        p->tls_hostname = g_new0(StrOrNull, 1);
> > +        p->tls_hostname->type = QTYPE_QSTRING;
> > +        visit_type_str(v, param, &p->tls_hostname->u.s, &err);
> > +        break;
> > +    case MIGRATION_PARAMETER_MAX_BANDWIDTH:
> > +        p->has_max_bandwidth = true;
> > +        /*
> > +         * Can't use visit_type_size() here, because it
> > +         * defaults to Bytes rather than Mebibytes.
> > +         */
> > +        ret = qemu_strtosz_MiB(valuestr, NULL, &valuebw);
> > +        if (ret < 0 || valuebw > INT64_MAX
> > +            || (size_t)valuebw != valuebw) {
> > +            error_setg(&err, "Invalid size %s", valuestr);
> >              break;
> >          }
> > +        p->max_bandwidth = valuebw;
> > +        break;
> > +    case MIGRATION_PARAMETER_DOWNTIME_LIMIT:
> > +        p->has_downtime_limit = true;
> > +        visit_type_int(v, param, &p->downtime_limit, &err);
> > +        break;
> > +    case MIGRATION_PARAMETER_X_CHECKPOINT_DELAY:
> > +        p->has_x_checkpoint_delay = true;
> > +        visit_type_int(v, param, &p->x_checkpoint_delay, &err);
> > +        break;
> > +    case MIGRATION_PARAMETER_BLOCK_INCREMENTAL:
> > +        p->has_block_incremental = true;
> > +        visit_type_bool(v, param, &p->block_incremental, &err);
> > +        break;
> >      }
> >  
> > -    if (i == MIGRATION_PARAMETER__MAX) {
> > -        error_setg(&err, QERR_INVALID_PARAMETER, param);
> > +    if (err) {
> > +        goto cleanup;
> >      }
> >  
> > +    qmp_migrate_set_parameters(p, &err);
> > +
> >   cleanup:
> >      qapi_free_MigrateSetParameters(p);
> >      visit_free(v);
> 
> Easier to review with space change ignored:
> 
>   diff --git a/hmp.c b/hmp.c
>   index 4ba50e8..ccc58e6 100644
>   --- a/hmp.c
>   +++ b/hmp.c
>   @@ -1574,11 +1574,15 @@
>        MigrateSetParameters *p = g_new0(MigrateSetParameters, 1);
>        uint64_t valuebw = 0;
>        Error *err = NULL;
>   -    int i, ret;
>   +    int val, ret;
> 
>   -    for (i = 0; i < MIGRATION_PARAMETER__MAX; i++) {
>   -        if (strcmp(param, MigrationParameter_lookup[i]) == 0) {
>   -            switch (i) {
>   +    val = qapi_enum_parse(MigrationParameter_lookup, param,
>   +                          MIGRATION_PARAMETER__MAX,  -1, &err);
>   +    if (val < 0) {
>   +        goto cleanup;
>   +    }
>   +
>   +    switch (val) {
>                case MIGRATION_PARAMETER_COMPRESS_LEVEL:
>                    p->has_compress_level = true;
>                    visit_type_int(v, param, &p->compress_level, &err);
>   @@ -1644,13 +1648,6 @@
>                }
> 
>                qmp_migrate_set_parameters(p, &err);
>   -            break;
>   -        }
>   -    }
>   -
>   -    if (i == MIGRATION_PARAMETER__MAX) {
>   -        error_setg(&err, QERR_INVALID_PARAMETER, param);
>   -    }
> 
>     cleanup:
>        qapi_free_MigrateSetParameters(p);
>   -- 
>   2.7.5
> 
> Looks good, although a default: abort() wouldn't hurt.
> 
> Reviewed-by: Markus Armbruster <armbru@redhat.com>

Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

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

* Re: [Qemu-devel] [PATCH v2 01/54] qapi: fix type_seen key error
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 01/54] qapi: fix type_seen key error Marc-André Lureau
  2017-08-22 15:00   ` Markus Armbruster
@ 2017-08-25  6:02   ` Markus Armbruster
  2017-08-25 12:57     ` Eduardo Habkost
  1 sibling, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-08-25  6:02 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth, Eduardo Habkost

Conflicts with Eduardo's "[PATCH v2] qapi: Fix error handling code on
alternate conflict".
Message-Id: <20170717180926.14924-1-ehabkost@redhat.com>

Marc-André, could you have a look?  You can rebase your fix on top of
Eduardo's, or merge the two into one commit.

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

> The type_seen member can be of a different type than the 'qtype' being
> checked, since a string create several conflicts. Lookup the real
> conflicting type in the conflict set, that one must be present in
> type_seen.
>
> This fixes the following error, reproducible with the modified test:
>
> Traceback (most recent call last):
>   File "/home/elmarco/src/qq/tests/qapi-schema/test-qapi.py", line 56, in <module>
>     schema = QAPISchema(sys.argv[1])
>   File "/home/elmarco/src/qq/scripts/qapi.py", line 1470, in __init__
>     self.exprs = check_exprs(parser.exprs)
>   File "/home/elmarco/src/qq/scripts/qapi.py", line 959, in check_exprs
>     check_alternate(expr, info)
>   File "/home/elmarco/src/qq/scripts/qapi.py", line 831, in check_alternate
>     % (name, key, types_seen[qtype]))
> KeyError: 'QTYPE_QSTRING'
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi.py                                  | 6 ++++--
>  tests/qapi-schema/alternate-conflict-string.json | 4 ++--
>  2 files changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/scripts/qapi.py b/scripts/qapi.py
> index 8aa2775f12..a3ac799535 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi.py
> @@ -825,10 +825,12 @@ def check_alternate(expr, info):
>              else:
>                  conflicting.add('QTYPE_QNUM')
>                  conflicting.add('QTYPE_QBOOL')
> -        if conflicting & set(types_seen):
> +        conflict = conflicting & set(types_seen)
> +        if conflict:
> +            conflict_qtype = list(conflict)[0]
>              raise QAPISemError(info, "Alternate '%s' member '%s' can't "
>                                 "be distinguished from member '%s'"
> -                               % (name, key, types_seen[qtype]))
> +                               % (name, key, types_seen[conflict_qtype]))
>          for qt in conflicting:
>              types_seen[qt] = key
>  
> diff --git a/tests/qapi-schema/alternate-conflict-string.json b/tests/qapi-schema/alternate-conflict-string.json
> index 85adbd4adc..bb2702978e 100644
> --- a/tests/qapi-schema/alternate-conflict-string.json
> +++ b/tests/qapi-schema/alternate-conflict-string.json
> @@ -1,4 +1,4 @@
>  # alternate branches of 'str' type conflict with all scalar types
>  { 'alternate': 'Alt',
> -  'data': { 'one': 'str',
> -            'two': 'int' } }
> +  'data': { 'one': 'int',
> +            'two': 'str' } }

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

* Re: [Qemu-devel] [PATCH v2 01/54] qapi: fix type_seen key error
  2017-08-25  6:02   ` Markus Armbruster
@ 2017-08-25 12:57     ` Eduardo Habkost
  2017-08-25 14:12       ` Marc-André Lureau
  0 siblings, 1 reply; 140+ messages in thread
From: Eduardo Habkost @ 2017-08-25 12:57 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: Marc-André Lureau, qemu-devel, Michael Roth

On Fri, Aug 25, 2017 at 08:02:26AM +0200, Markus Armbruster wrote:
> Conflicts with Eduardo's "[PATCH v2] qapi: Fix error handling code on
> alternate conflict".
> Message-Id: <20170717180926.14924-1-ehabkost@redhat.com>
> 
> Marc-André, could you have a look?  You can rebase your fix on top of
> Eduardo's, or merge the two into one commit.

Both patches seem to be fixing the same bug.

> 
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> 
> > The type_seen member can be of a different type than the 'qtype' being
> > checked, since a string create several conflicts. Lookup the real
> > conflicting type in the conflict set, that one must be present in
> > type_seen.
> >
> > This fixes the following error, reproducible with the modified test:
> >
> > Traceback (most recent call last):
> >   File "/home/elmarco/src/qq/tests/qapi-schema/test-qapi.py", line 56, in <module>
> >     schema = QAPISchema(sys.argv[1])
> >   File "/home/elmarco/src/qq/scripts/qapi.py", line 1470, in __init__
> >     self.exprs = check_exprs(parser.exprs)
> >   File "/home/elmarco/src/qq/scripts/qapi.py", line 959, in check_exprs
> >     check_alternate(expr, info)
> >   File "/home/elmarco/src/qq/scripts/qapi.py", line 831, in check_alternate
> >     % (name, key, types_seen[qtype]))
> > KeyError: 'QTYPE_QSTRING'
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >  scripts/qapi.py                                  | 6 ++++--
> >  tests/qapi-schema/alternate-conflict-string.json | 4 ++--
> >  2 files changed, 6 insertions(+), 4 deletions(-)
> >
> > diff --git a/scripts/qapi.py b/scripts/qapi.py
> > index 8aa2775f12..a3ac799535 100644
> > --- a/scripts/qapi.py
> > +++ b/scripts/qapi.py
> > @@ -825,10 +825,12 @@ def check_alternate(expr, info):
> >              else:
> >                  conflicting.add('QTYPE_QNUM')
> >                  conflicting.add('QTYPE_QBOOL')
> > -        if conflicting & set(types_seen):
> > +        conflict = conflicting & set(types_seen)
> > +        if conflict:
> > +            conflict_qtype = list(conflict)[0]
> >              raise QAPISemError(info, "Alternate '%s' member '%s' can't "
> >                                 "be distinguished from member '%s'"
> > -                               % (name, key, types_seen[qtype]))
> > +                               % (name, key, types_seen[conflict_qtype]))
> >          for qt in conflicting:
> >              types_seen[qt] = key
> >  
> > diff --git a/tests/qapi-schema/alternate-conflict-string.json b/tests/qapi-schema/alternate-conflict-string.json
> > index 85adbd4adc..bb2702978e 100644
> > --- a/tests/qapi-schema/alternate-conflict-string.json
> > +++ b/tests/qapi-schema/alternate-conflict-string.json
> > @@ -1,4 +1,4 @@
> >  # alternate branches of 'str' type conflict with all scalar types
> >  { 'alternate': 'Alt',
> > -  'data': { 'one': 'str',
> > -            'two': 'int' } }
> > +  'data': { 'one': 'int',
> > +            'two': 'str' } }

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v2 01/54] qapi: fix type_seen key error
  2017-08-25 12:57     ` Eduardo Habkost
@ 2017-08-25 14:12       ` Marc-André Lureau
  2017-08-28 10:52         ` Markus Armbruster
  0 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-08-25 14:12 UTC (permalink / raw)
  To: Eduardo Habkost, Markus Armbruster; +Cc: qemu-devel, Michael Roth

On Fri, Aug 25, 2017 at 2:57 PM Eduardo Habkost <ehabkost@redhat.com> wrote:

> On Fri, Aug 25, 2017 at 08:02:26AM +0200, Markus Armbruster wrote:
> > Conflicts with Eduardo's "[PATCH v2] qapi: Fix error handling code on
> > alternate conflict".
> > Message-Id: <20170717180926.14924-1-ehabkost@redhat.com>
> >
> > Marc-André, could you have a look?  You can rebase your fix on top of
> > Eduardo's, or merge the two into one commit.
>
> Both patches seem to be fixing the same bug.
>

Yes, it is solved differently. But take Eduardo's patch, it has more
extensive tests .

>
> >
> > Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> >
> > > The type_seen member can be of a different type than the 'qtype' being
> > > checked, since a string create several conflicts. Lookup the real
> > > conflicting type in the conflict set, that one must be present in
> > > type_seen.
> > >
> > > This fixes the following error, reproducible with the modified test:
> > >
> > > Traceback (most recent call last):
> > >   File "/home/elmarco/src/qq/tests/qapi-schema/test-qapi.py", line 56,
> in <module>
> > >     schema = QAPISchema(sys.argv[1])
> > >   File "/home/elmarco/src/qq/scripts/qapi.py", line 1470, in __init__
> > >     self.exprs = check_exprs(parser.exprs)
> > >   File "/home/elmarco/src/qq/scripts/qapi.py", line 959, in check_exprs
> > >     check_alternate(expr, info)
> > >   File "/home/elmarco/src/qq/scripts/qapi.py", line 831, in
> check_alternate
> > >     % (name, key, types_seen[qtype]))
> > > KeyError: 'QTYPE_QSTRING'
> > >
> > > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > > ---
> > >  scripts/qapi.py                                  | 6 ++++--
> > >  tests/qapi-schema/alternate-conflict-string.json | 4 ++--
> > >  2 files changed, 6 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/scripts/qapi.py b/scripts/qapi.py
> > > index 8aa2775f12..a3ac799535 100644
> > > --- a/scripts/qapi.py
> > > +++ b/scripts/qapi.py
> > > @@ -825,10 +825,12 @@ def check_alternate(expr, info):
> > >              else:
> > >                  conflicting.add('QTYPE_QNUM')
> > >                  conflicting.add('QTYPE_QBOOL')
> > > -        if conflicting & set(types_seen):
> > > +        conflict = conflicting & set(types_seen)
> > > +        if conflict:
> > > +            conflict_qtype = list(conflict)[0]
> > >              raise QAPISemError(info, "Alternate '%s' member '%s'
> can't "
> > >                                 "be distinguished from member '%s'"
> > > -                               % (name, key, types_seen[qtype]))
> > > +                               % (name, key,
> types_seen[conflict_qtype]))
> > >          for qt in conflicting:
> > >              types_seen[qt] = key
> > >
> > > diff --git a/tests/qapi-schema/alternate-conflict-string.json
> b/tests/qapi-schema/alternate-conflict-string.json
> > > index 85adbd4adc..bb2702978e 100644
> > > --- a/tests/qapi-schema/alternate-conflict-string.json
> > > +++ b/tests/qapi-schema/alternate-conflict-string.json
> > > @@ -1,4 +1,4 @@
> > >  # alternate branches of 'str' type conflict with all scalar types
> > >  { 'alternate': 'Alt',
> > > -  'data': { 'one': 'str',
> > > -            'two': 'int' } }
> > > +  'data': { 'one': 'int',
> > > +            'two': 'str' } }
>
> --
> Eduardo
>
> --
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH v2 02/54] qdict: add qdict_put_null() helper
  2017-08-22 15:09   ` Markus Armbruster
@ 2017-08-25 15:46     ` Eric Blake
  0 siblings, 0 replies; 140+ messages in thread
From: Eric Blake @ 2017-08-25 15:46 UTC (permalink / raw)
  To: Markus Armbruster, Marc-André Lureau; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1036 bytes --]

On 08/22/2017 10:09 AM, Markus Armbruster wrote:

>    #define qdict_put_bool(qdict, key, value) \
>>          qdict_put(qdict, key, qbool_from_bool(value))
>>  #define qdict_put_str(qdict, key, value) \
>>          qdict_put(qdict, key, qstring_from_str(value))
>> +#define qdict_put_null(qdict, key) \
>> +        qdict_put(qdict, key, qnull())
>>  
>>  /* High level helpers */
>>  double qdict_get_double(const QDict *qdict, const char *key);
> 
> Marginal.  I can accept it for completeness's sake, or rather a step
> towards completeness.  But please update the "Helpers for ..." comment,
> and convert existing qdict_put(QD, K, qnull()) to use qdict_put_null().
> A quick grep finds some in target/i386/cpu.c.  There might be more.

And we already used Coccinelle to find candidates for qdict_put_bool and
friends, so that should be the reasonable approach to use here as well.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 619 bytes --]

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

* Re: [Qemu-devel] [PATCH v2 01/54] qapi: fix type_seen key error
  2017-08-25 14:12       ` Marc-André Lureau
@ 2017-08-28 10:52         ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-08-28 10:52 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: Eduardo Habkost, qemu-devel, Michael Roth

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

> On Fri, Aug 25, 2017 at 2:57 PM Eduardo Habkost <ehabkost@redhat.com> wrote:
>
>> On Fri, Aug 25, 2017 at 08:02:26AM +0200, Markus Armbruster wrote:
>> > Conflicts with Eduardo's "[PATCH v2] qapi: Fix error handling code on
>> > alternate conflict".
>> > Message-Id: <20170717180926.14924-1-ehabkost@redhat.com>
>> >
>> > Marc-André, could you have a look?  You can rebase your fix on top of
>> > Eduardo's, or merge the two into one commit.
>>
>> Both patches seem to be fixing the same bug.
>>
>
> Yes, it is solved differently. But take Eduardo's patch, it has more
> extensive tests .

Okay.

Too bad I didn't remember Eduardo's patch when I got yours.

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

* Re: [Qemu-devel] [PATCH v2 14/54] qapi2texi: minor python code simplification
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 14/54] qapi2texi: minor python code simplification Marc-André Lureau
  2017-08-22 13:56   ` Philippe Mathieu-Daudé
@ 2017-09-01 15:49   ` Markus Armbruster
  2017-09-04  8:18     ` Marc-André Lureau
  1 sibling, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-09-01 15:49 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi2texi.py | 7 +++----
>  1 file changed, 3 insertions(+), 4 deletions(-)
>
> diff --git a/scripts/qapi2texi.py b/scripts/qapi2texi.py
> index a317526e51..8b542f9fff 100755
> --- a/scripts/qapi2texi.py
> +++ b/scripts/qapi2texi.py
> @@ -136,10 +136,9 @@ def texi_enum_value(value):
>  def texi_member(member, suffix=''):
>      """Format a table of members item for an object type member"""
>      typ = member.type.doc_type()
> -    return '@item @code{%s%s%s}%s%s\n' % (
> -        member.name,
> -        ': ' if typ else '',
> -        typ if typ else '',
> +    membertype = ': %s' % typ if typ else ''

I'd use string concatenation (': ' + typ) instead of interpolation.
Matter of taste.  Could make the change when I apply.

> +    return '@item @code{%s%s}%s%s\n' % (
> +        member.name, membertype,
>          ' (optional)' if member.optional else '',
>          suffix)

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

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

* Re: [Qemu-devel] [PATCH v2 14/54] qapi2texi: minor python code simplification
  2017-09-01 15:49   ` Markus Armbruster
@ 2017-09-04  8:18     ` Marc-André Lureau
  0 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-09-04  8:18 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth

Hi

----- Original Message -----
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> 
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >  scripts/qapi2texi.py | 7 +++----
> >  1 file changed, 3 insertions(+), 4 deletions(-)
> >
> > diff --git a/scripts/qapi2texi.py b/scripts/qapi2texi.py
> > index a317526e51..8b542f9fff 100755
> > --- a/scripts/qapi2texi.py
> > +++ b/scripts/qapi2texi.py
> > @@ -136,10 +136,9 @@ def texi_enum_value(value):
> >  def texi_member(member, suffix=''):
> >      """Format a table of members item for an object type member"""
> >      typ = member.type.doc_type()
> > -    return '@item @code{%s%s%s}%s%s\n' % (
> > -        member.name,
> > -        ': ' if typ else '',
> > -        typ if typ else '',
> > +    membertype = ': %s' % typ if typ else ''
> 
> I'd use string concatenation (': ' + typ) instead of interpolation.
> Matter of taste.  Could make the change when I apply.

Good idea

> 
> > +    return '@item @code{%s%s}%s%s\n' % (
> > +        member.name, membertype,
> >          ' (optional)' if member.optional else '',
> >          suffix)
> 
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
> 

thanks

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

* Re: [Qemu-devel] [PATCH v2 15/54] qapi: add 'if' to top-level expressions
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 15/54] qapi: add 'if' to top-level expressions Marc-André Lureau
@ 2017-09-04 13:27   ` Markus Armbruster
  2017-09-05 13:58     ` Marc-André Lureau
  0 siblings, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-09-04 13:27 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

Lost line break?

> 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>
> ---
>  scripts/qapi.py                         | 13 +++++++++++++
>  tests/test-qmp-commands.c               |  6 ++++++
>  tests/qapi-schema/qapi-schema-test.json | 20 ++++++++++++++++++++
>  tests/qapi-schema/qapi-schema-test.out  | 22 ++++++++++++++++++++++
>  4 files changed, 61 insertions(+)
>
> diff --git a/scripts/qapi.py b/scripts/qapi.py
> index 73adb90379..a94d93ada4 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi.py
> @@ -639,6 +639,16 @@ def add_name(name, info, meta, implicit=False):
>      all_names[name] = meta
>  
>  
> +def check_if(expr, info):
> +    ifcond = expr.get('if')
> +    if not ifcond or isinstance(ifcond, str):
> +        return
> +    if (not isinstance(ifcond, list) or
> +            any([not isinstance(elt, str) for elt in ifcond])):
> +        raise QAPISemError(info, "'if' condition requires a string or "
> +                           "a list of string")

The error also triggers on inputs 'if': '' and 'if': [].

The first one doesn't make sense (the C compiler will surely barf).  We
could leave rejecting it to the C compiler.  If we choose to reject it
here, we need a better error message, because the one above is
misleading.

The second one is a roundabout way to say "unconditional".  If we choose
to reject that, we also need a non-misleading error message.

The error can't trigger on absent 'if', because we don't get called
then.  To make that locally obvious, please say

       ifcond = expr['if']

Moreover, I'd prefer to avoid mixing conditionals with opposite sense,
i.e. if good: return; if bad: raise.

Taken together:

   def check_if(expr, info):
       ifcond = expr['if']
       if isinstance(ifcond, str):
           if ifcond == '':
               raise QAPISemError(info, "'if' condition '' makes no sense")
           return
       if isinstance(ifcond, list):
           if ifcond == []:
               raise QAPISemError(info, "'if' condition [] is useless")
           for elt in ifcond:
               if not isinstance(elt, str):
                   raise QAPISemError(
                           info, "'if' condition %s makes no sense" % elt)
           return
       raise QAPISemError(
               info, "'if' condition must be a string or a list of strings")

Written this way (one case after the other), each error has to report
just one narrow problem.  Makes crafting precise error messages easier.

> +
> +
>  def check_type(info, source, value, allow_array=False,
>                 allow_dict=False, allow_optional=False,
>                 allow_metas=[]):
> @@ -865,6 +875,7 @@ def check_keys(expr_elem, meta, required, optional=[]):
>      expr = expr_elem['expr']
>      info = expr_elem['info']
>      name = expr[meta]
> +    optional = optional + ['if']  # all top-level elem accept if
>      if not isinstance(name, str):
>          raise QAPISemError(info, "'%s' key must have a string value" % meta)
>      required = required + [meta]

All top-level expressions require 'data'.  Done the obvious way: all
callers pass 'data' in @required.  Let's do 'if' the same way for
consistency.

> @@ -880,6 +891,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'"
> diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
> index 904c89d4d4..9b9a7ffee7 100644
> --- a/tests/test-qmp-commands.c
> +++ b/tests/test-qmp-commands.c
> @@ -10,6 +10,12 @@
>  
>  static QmpCommandList qmp_commands;
>  
> +/* #if defined(TEST_IF_CMD) */
> +void qmp_TestIfCmd(TestIfStruct *foo, Error **errp)
> +{
> +}
> +/* #endif */
> +
>  void qmp_user_def_cmd(Error **errp)
>  {
>  }
> diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
> index c72dbd8050..dc2c444fc1 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 3b1e9082d3..7fbaea19bc 100644
> --- a/tests/qapi-schema/qapi-schema-test.out
> +++ b/tests/qapi-schema/qapi-schema-test.out
> @@ -52,6 +52,22 @@ enum QEnumTwo ['value1', 'value2']
>      prefix QENUM_TWO
>  enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
> +alternate TestIfAlternate
> +    tag type
> +    case foo: int
> +    case bar: TestStruct
> +command TestIfCmd q_obj_TestIfCmd-arg -> None
> +   gen=True success_response=True boxed=False
> +enum TestIfEnum ['foo', 'bar']
> +event TestIfEvent q_obj_TestIfEvent-arg
> +   boxed=False
> +object TestIfStruct
> +    member foo: int optional=False
> +object TestIfUnion
> +    member type: TestIfUnionKind optional=False
> +    tag type
> +    case foo: q_obj_TestStruct-wrapper
> +enum TestIfUnionKind ['foo']
>  object TestStruct
>      member integer: int optional=False
>      member boolean: bool optional=False
> @@ -172,6 +188,12 @@ object q_obj_EVENT_D-arg
>      member b: str optional=False
>      member c: str optional=True
>      member enum3: EnumOne optional=True
> +object q_obj_TestIfCmd-arg
> +    member foo: TestIfStruct optional=False
> +object q_obj_TestIfEvent-arg
> +    member foo: TestIfStruct optional=False
> +object q_obj_TestStruct-wrapper
> +    member data: TestStruct optional=False
>  object q_obj_UserDefFlatUnion2-base
>      member integer: int optional=True
>      member string: str optional=False

The conditionals aren't visible in qapi-schema-test.out.  They should
be.

*Much* easier to review than its predecessor PATCH 07/26.  Appreciated!

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

* Re: [Qemu-devel] [PATCH v2 16/54] qapi: add a test for invalid 'if'
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 16/54] qapi: add a test for invalid 'if' Marc-André Lureau
@ 2017-09-04 13:31   ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-09-04 13:31 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  tests/Makefile.include        | 1 +
>  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
>  5 files changed, 6 insertions(+)
>  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/tests/Makefile.include b/tests/Makefile.include
> index 3653c7b40a..1f1d8f075b 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -396,6 +396,7 @@ 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-type-bool.json
>  qapi-schema += bad-type-dict.json
>  qapi-schema += bad-type-int.json
> diff --git a/tests/qapi-schema/bad-if.err b/tests/qapi-schema/bad-if.err
> new file mode 100644
> index 0000000000..8054fbb143
> --- /dev/null
> +++ b/tests/qapi-schema/bad-if.err
> @@ -0,0 +1 @@
> +tests/qapi-schema/bad-if.json:2: 'if' condition requires a string or a list of string
> 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

Adding a test for each error is good practice.  You did, but your error
is a bit of a catch-all.  The code I proposed in my review of the
previous patch splits it up.  To keep up good practice, we need a test
case for each shard.

I'd squash this into the previous patch to stop "you're lacking tests"
review comments :)

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

* Re: [Qemu-devel] [PATCH v2 17/54] qapi: add 'if' condition on entity objects
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 17/54] qapi: add 'if' condition on entity objects Marc-André Lureau
@ 2017-09-04 16:13   ` Markus Armbruster
  2017-09-05 15:38     ` Marc-André Lureau
  0 siblings, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-09-04 16:13 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> Take 'if' from expression, and use it to construct entity objects.
> Shared implicit objects must share the same 'if' condition.

Shared by what?

>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi.py | 81 +++++++++++++++++++++++++++++++++++++--------------------
>  1 file changed, 53 insertions(+), 28 deletions(-)
>
> diff --git a/scripts/qapi.py b/scripts/qapi.py
> index a94d93ada4..dc40d74abb 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi.py
> @@ -992,7 +992,7 @@ def check_exprs(exprs):
>  #
>  
>  class QAPISchemaEntity(object):
> -    def __init__(self, name, info, doc):
> +    def __init__(self, name, info, doc, ifcond=None):
>          assert isinstance(name, str)
>          self.name = name
>          # For explicitly defined entities, info points to the (explicit)

Not visible here: QAPISchemaType inherits this.

> @@ -1002,6 +1002,7 @@ class QAPISchemaEntity(object):
>          # such place).
>          self.info = info
>          self.doc = doc
> +        self.ifcond = ifcond
>  
>      def c_name(self):
>          return c_name(self.name)
> @@ -1118,8 +1119,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, values, prefix, ifcond=None):
> +        QAPISchemaType.__init__(self, name, info, doc, ifcond)
>          for v in values:
>              assert isinstance(v, QAPISchemaMember)
>              v.set_owner(name)
> @@ -1162,6 +1163,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

This is subtler than it looks on first glance.

All the other entities set self.ifcond in their constructor to the true
value passed in as argument.

QAPISchemaArrayType doesn't take such an argument.  Instead, it inherits
its .ifcond from its .element_type.  However, .element_type isn't known
at construction time if it's a forward reference.  We therefore delay
setting it until .check() time.  You do the same for .ifcond (no
choice).

Before .check(), .ifcond is None, because the constructor sets it that
way: it calls QAPISchemaType.__init__() without passing a ifcond
argument, which then sets self.ifcond to its default argument None.

Pitfall: accessing ent.ifcond before ent.check() works *except* when ent
is an array type.  Hmm.

>  
>      def is_implicit(self):
>          return True
> @@ -1183,11 +1185,12 @@ class QAPISchemaArrayType(QAPISchemaType):
>  
>  
>  class QAPISchemaObjectType(QAPISchemaType):
> -    def __init__(self, name, info, doc, base, local_members, variants):
> +    def __init__(self, name, info, doc, base, local_members, variants,
> +                 ifcond=None):
>          # 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)
> @@ -1375,8 +1378,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, variants, ifcond):
> +        QAPISchemaType.__init__(self, name, info, doc, ifcond)
>          assert isinstance(variants, QAPISchemaObjectTypeVariants)
>          assert variants.tag_member
>          variants.set_owner(name)
> @@ -1413,8 +1416,8 @@ class QAPISchemaAlternateType(QAPISchemaType):
>  
>  class QAPISchemaCommand(QAPISchemaEntity):
>      def __init__(self, name, info, doc, arg_type, ret_type,
> -                 gen, success_response, boxed):
> -        QAPISchemaEntity.__init__(self, name, info, doc)
> +                 gen, success_response, boxed, ifcond):
> +        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
> @@ -1451,8 +1454,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, arg_type, boxed, ifcond):
> +        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

Hmm.  You're adding parameter ifcond to all entity constructors.  The
entity constructors' signatures all look like this:

    def __init__(<common parameters>, <specific parameters>)

where <common parameters> is self, name, info, doc.

Since ifcond is common, let's add it to <common parameters>.  Pick a
position you like.

> @@ -1547,11 +1550,11 @@ class QAPISchema(object):
>      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, values, ifcond):
>          # 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, self._make_enum_members(values), None, ifcond))
>          return name

Called by _def_union_type() to create the implicit tag enum, with the
same ifcond it passes to QAPISchemaObjectType().  Thus, the implicit
type's ifcond matches the ifcond of its only user.  Good.

>  
>      def _make_array_type(self, element_type, info):
> @@ -1560,22 +1563,29 @@ 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, role, members,
> +                                   ifcond=None):
>          if not members:
>              return None
>          # See also QAPISchemaObjectTypeMember._pretty_owner()
>          name = 'q_obj_%s-%s' % (name, role)
> -        if not self.lookup_entity(name, QAPISchemaObjectType):
> +        typ = self.lookup_entity(name, QAPISchemaObjectType)
> +        if typ:
> +            # FIXME: generating the disjunction of all conditions

What are "all conditions"?  I hope I can shed some light on that below.

> +            assert ifcond == typ.ifcond
> +        else:
>              self._def_entity(QAPISchemaObjectType(name, info, doc, None,
> -                                                  members, None))
> +                                                  members, None, ifcond))
>          return name

Several callers:

* _make_simple_variant() to create a wrapper type, with the wrapped
  type's ifcond.  The wrapped type's ifcond is necessary for the wrapper
  type to compile.  It's not sufficient for it to be needed.  The
  "needed" condition is the disjunction of all users' ifcond.

  In other words, your code generates condition that is correct, but not
  tight.  Your FIXME is about tightening it.  I'd make it a TODO,
  because nothing is actually broken now.

  Need a comment explaining this.  Perhaps:

        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

  I hate simple unions.

* _def_union_type() to create an implicit base type, with same ifcond it
  passes to QAPISchemaObjectType().  Thus, the implicit base type's
  ifcond matches the ifcond of its only user.  Good.

* _def_command() to create an implicit argument type, with the same
  ifcond it passes to QAPISchemaCommand().  Thus, the implicit argument
  type's ifcond matches the ifcond of its only user.  Good.

* _def_event() likewise.

I still can't make sense of the commit message's "Shared implicit
objects must share the same 'if' condition."

>  
>      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, self._make_enum_members(data), prefix,
> +            ifcond))
>  
>      def _make_member(self, name, typ, info):
>          optional = False
> @@ -1595,9 +1605,10 @@ class QAPISchema(object):
>          name = expr['struct']
>          base = expr.get('base')
>          data = expr['data']
> +        ifcond = expr.get('if')
>          self._def_entity(QAPISchemaObjectType(name, info, doc, base,
>                                                self._make_members(data, info),
> -                                              None))
> +                                              None, ifcond))
>  
>      def _make_variant(self, case, typ):
>          return QAPISchemaObjectTypeVariant(case, typ)
> @@ -1606,19 +1617,23 @@ class QAPISchema(object):
>          if isinstance(typ, list):
>              assert len(typ) == 1
>              typ = self._make_array_type(typ[0], info)
> +        type_entity = self.lookup_type(typ)
>          typ = self._make_implicit_object_type(
> -            typ, info, None, 'wrapper', [self._make_member('data', typ, info)])
> +            typ, info, None, 'wrapper',
> +            [self._make_member('data', typ, info)], type_entity.ifcond)
>          return QAPISchemaObjectTypeVariant(case, typ)

This is where you create the wrapper type with the wrapped type's
ifcond.

I don't like the name type_entity.  I'd simply eliminate the variable.

>  
>      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, 'base', self._make_members(base, info),
> +                ifcond)
>          if tag_name:
>              variants = [self._make_variant(key, value)
>                          for (key, value) in data.iteritems()]

This is where you create a union's implicit base type with the union's
ifcond.

> @@ -1627,18 +1642,21 @@ class QAPISchema(object):
>              variants = [self._make_simple_variant(key, value, info)
>                          for (key, value) in data.iteritems()]
>              typ = self._make_implicit_enum_type(name, info,
> -                                                [v.name for v in variants])
> +                                                [v.name for v in variants],
> +                                                ifcond)
>              tag_member = QAPISchemaObjectTypeMember('type', typ, False)
>              members = [tag_member]

This is where you create a union's implicit tag enum with the union's ifcond.

>          self._def_entity(
>              QAPISchemaObjectType(name, info, doc, base, members,
>                                   QAPISchemaObjectTypeVariants(tag_name,
>                                                                tag_member,
> -                                                              variants)))
> +                                                              variants),
> +                                 ifcond))
>  
>      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.iteritems()]
>          tag_member = QAPISchemaObjectTypeMember('type', 'QType', False)
> @@ -1646,7 +1664,8 @@ class QAPISchema(object):
>              QAPISchemaAlternateType(name, info, doc,
>                                      QAPISchemaObjectTypeVariants(None,
>                                                                   tag_member,
> -                                                                 variants)))
> +                                                                 variants),
> +                                    ifcond))
>  
>      def _def_command(self, expr, info, doc):
>          name = expr['command']
> @@ -1655,23 +1674,29 @@ class QAPISchema(object):
>          gen = expr.get('gen', True)
>          success_response = expr.get('success-response', True)
>          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))
> +                name, info, doc, 'arg', self._make_members(data, info),
> +                ifcond)

This is where you create a command's implicit argument type with the
command's ifcond.

>          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,
> -                                           gen, success_response, boxed))
> +                                           gen, success_response, boxed,
> +                                           ifcond))
>  
>      def _def_event(self, expr, info, doc):
>          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, 'arg', self._make_members(data, info),
> +                ifcond)

This is where you create an event's implicit argument type with the
event's ifcond.

> +        self._def_entity(QAPISchemaEvent(name, info, doc, data, boxed,
> +                                         ifcond))
>  
>      def _def_exprs(self):
>          for expr_elem in self.exprs:

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

* Re: [Qemu-devel] [PATCH v2 18/54] qapi: add 'ifcond' to visitor methods
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 18/54] qapi: add 'ifcond' to visitor methods Marc-André Lureau
@ 2017-09-04 16:47   ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-09-04 16:47 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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>
> ---
>  scripts/qapi.py                        | 34 ++++++++++++++++++++--------------
>  scripts/qapi-commands.py               |  2 +-
>  scripts/qapi-event.py                  |  2 +-
>  scripts/qapi-introspect.py             | 12 ++++++------
>  scripts/qapi-types.py                  |  8 ++++----
>  scripts/qapi-visit.py                  |  8 ++++----
>  scripts/qapi2texi.py                   | 10 +++++-----
>  tests/qapi-schema/qapi-schema-test.out |  9 +++++++++
>  tests/qapi-schema/test-qapi.py         | 21 ++++++++++++++++-----
>  9 files changed, 66 insertions(+), 40 deletions(-)
>
> diff --git a/scripts/qapi.py b/scripts/qapi.py
> index dc40d74abb..86845a28f9 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi.py
> @@ -1031,26 +1031,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, values, prefix, ifcond):
>          pass
>  
> -    def visit_array_type(self, name, info, element_type):
> +    def visit_array_type(self, name, info, element_type, ifcond):
>          pass
>  
> -    def visit_object_type(self, name, info, base, members, variants):
> +    def visit_object_type(self, name, info, base, members, variants, ifcond):
>          pass
>  
> -    def visit_object_type_flat(self, name, info, members, variants):
> +    def visit_object_type_flat(self, name, info, members, variants, ifcond):
>          pass
>  
> -    def visit_alternate_type(self, name, info, variants):
> +    def visit_alternate_type(self, name, info, variants, ifcond):
>          pass
>  
>      def visit_command(self, name, info, arg_type, ret_type,
> -                      gen, success_response, boxed):
> +                      gen, success_response, boxed, ifcond):
>          pass
>  
> -    def visit_event(self, name, info, arg_type, boxed):
> +    def visit_event(self, name, info, arg_type, boxed, ifcond):
>          pass
>  
>  

Let's add the new common parameter ifcond among the existing common
parameters self, name, info.  Preferably in the same position as in
entity constructors.

> @@ -1150,7 +1150,7 @@ class QAPISchemaEnumType(QAPISchemaType):
>  
>      def visit(self, visitor):
>          visitor.visit_enum_type(self.name, self.info,
> -                                self.member_names(), self.prefix)
> +                                self.member_names(), self.prefix, self.ifcond)
>  
>  
>  class QAPISchemaArrayType(QAPISchemaType):
> @@ -1181,7 +1181,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.element_type,
> +                                 self.ifcond)
>  
>  
>  class QAPISchemaObjectType(QAPISchemaType):
> @@ -1263,9 +1264,11 @@ class QAPISchemaObjectType(QAPISchemaType):
>  
>      def visit(self, visitor):
>          visitor.visit_object_type(self.name, self.info,
> -                                  self.base, self.local_members, self.variants)
> +                                  self.base, self.local_members, self.variants,
> +                                  self.ifcond)
>          visitor.visit_object_type_flat(self.name, self.info,
> -                                       self.members, self.variants)
> +                                       self.members, self.variants,
> +                                       self.ifcond)
>  
>  
>  class QAPISchemaMember(object):
> @@ -1408,7 +1411,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.variants, self.ifcond)
>  
>      def is_empty(self):
>          return False
> @@ -1450,7 +1454,8 @@ class QAPISchemaCommand(QAPISchemaEntity):
>      def visit(self, visitor):
>          visitor.visit_command(self.name, self.info,
>                                self.arg_type, self.ret_type,
> -                              self.gen, self.success_response, self.boxed)
> +                              self.gen, self.success_response, self.boxed,
> +                              self.ifcond)
>  
>  
>  class QAPISchemaEvent(QAPISchemaEntity):
> @@ -1478,7 +1483,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.arg_type, self.boxed,
> +                            self.ifcond)
>  
>  
>  class QAPISchema(object):
> diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
> index 974d0a4a80..5eb96b2d95 100644
> --- a/scripts/qapi-commands.py
> +++ b/scripts/qapi-commands.py
> @@ -241,7 +241,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
>          self._visited_ret_types = None
>  
>      def visit_command(self, name, info, arg_type, ret_type,
> -                      gen, success_response, boxed):
> +                      gen, success_response, boxed, ifcond):
>          if not gen:
>              return
>          self.decl += gen_command_decl(name, arg_type, boxed, ret_type)
> diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
> index bcbef1035f..fec27fe2e1 100644
> --- a/scripts/qapi-event.py
> +++ b/scripts/qapi-event.py
> @@ -163,7 +163,7 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
>          self.defn += gen_enum_lookup(event_enum_name, self._event_names)
>          self._event_names = None
>  
> -    def visit_event(self, name, info, arg_type, boxed):
> +    def visit_event(self, name, info, arg_type, boxed, ifcond):
>          self.decl += gen_event_send_decl(name, arg_type, boxed)
>          self.defn += gen_event_send(name, arg_type, boxed)
>          self._event_names.append(name)
> diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
> index 1b96926fa7..4c437d60ec 100644
> --- a/scripts/qapi-introspect.py
> +++ b/scripts/qapi-introspect.py
> @@ -142,34 +142,34 @@ 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, values, prefix, ifcond):
>          self._gen_qlit(name, 'enum', {'values': values})
>  
> -    def visit_array_type(self, name, info, element_type):
> +    def visit_array_type(self, name, info, element_type, ifcond):
>          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, members, variants, ifcond):
>          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, variants, ifcond):
>          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,
> -                      gen, success_response, boxed):
> +                      gen, success_response, boxed, ifcond):
>          arg_type = arg_type or self._schema.the_empty_object_type
>          ret_type = ret_type or self._schema.the_empty_object_type
>          self._gen_qlit(name, 'command',
>                         {'arg-type': self._use_type(arg_type),
>                          'ret-type': self._use_type(ret_type)})
>  
> -    def visit_event(self, name, info, arg_type, boxed):
> +    def visit_event(self, name, info, arg_type, boxed, ifcond):
>          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 dc05268917..6f06720adc 100644
> --- a/scripts/qapi-types.py
> +++ b/scripts/qapi-types.py
> @@ -201,7 +201,7 @@ typedef struct QEnumLookup {
>          self.decl += gen_type_cleanup_decl(name)
>          self.defn += gen_type_cleanup(name)
>  
> -    def visit_enum_type(self, name, info, values, prefix):
> +    def visit_enum_type(self, name, info, values, prefix, ifcond):
>          # Special case for our lone builtin enum type
>          # TODO use something cleaner than existence of info
>          if not info:
> @@ -212,7 +212,7 @@ typedef struct QEnumLookup {
>              self._fwdecl += gen_enum(name, values, prefix)
>              self.defn += gen_enum_lookup(name, values, prefix)
>  
> -    def visit_array_type(self, name, info, element_type):
> +    def visit_array_type(self, name, info, element_type, ifcond):
>          if isinstance(element_type, QAPISchemaBuiltinType):
>              self._btin += gen_fwd_object_or_array(name)
>              self._btin += gen_array(name, element_type)
> @@ -224,7 +224,7 @@ typedef struct QEnumLookup {
>              self.decl += 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, base, members, variants, ifcond):
>          # Nothing to do for the special empty builtin
>          if name == 'q_empty':
>              return
> @@ -238,7 +238,7 @@ typedef struct QEnumLookup {
>              # 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, variants, ifcond):
>          self._fwdecl += gen_fwd_object_or_array(name)
>          self.decl += gen_object(name, None, [variants.tag_member], variants)
>          self._gen_type_cleanup(name)
> diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
> index 7e1cfc13f0..c29c2d869e 100644
> --- a/scripts/qapi-visit.py
> +++ b/scripts/qapi-visit.py
> @@ -282,7 +282,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
>          self.decl = self._btin + self.decl
>          self._btin = None
>  
> -    def visit_enum_type(self, name, info, values, prefix):
> +    def visit_enum_type(self, name, info, values, prefix, ifcond):
>          # Special case for our lone builtin enum type
>          # TODO use something cleaner than existence of info
>          if not info:
> @@ -293,7 +293,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
>              self.decl += gen_visit_decl(name, scalar=True)
>              self.defn += gen_visit_enum(name)
>  
> -    def visit_array_type(self, name, info, element_type):
> +    def visit_array_type(self, name, info, element_type, ifcond):
>          decl = gen_visit_decl(name)
>          defn = gen_visit_list(name, element_type)
>          if isinstance(element_type, QAPISchemaBuiltinType):
> @@ -304,7 +304,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
>              self.decl += decl
>              self.defn += defn
>  
> -    def visit_object_type(self, name, info, base, members, variants):
> +    def visit_object_type(self, name, info, base, members, variants, ifcond):
>          # Nothing to do for the special empty builtin
>          if name == 'q_empty':
>              return
> @@ -317,7 +317,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
>              self.decl += gen_visit_decl(name)
>              self.defn += gen_visit_object(name, base, members, variants)
>  
> -    def visit_alternate_type(self, name, info, variants):
> +    def visit_alternate_type(self, name, info, variants, ifcond):
>          self.decl += gen_visit_decl(name)
>          self.defn += gen_visit_alternate(name, variants)
>  
> diff --git a/scripts/qapi2texi.py b/scripts/qapi2texi.py
> index 8b542f9fff..ae7920aa87 100755
> --- a/scripts/qapi2texi.py
> +++ b/scripts/qapi2texi.py
> @@ -207,7 +207,7 @@ class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor):
>      def visit_begin(self, schema):
>          self.out = ''
>  
> -    def visit_enum_type(self, name, info, values, prefix):
> +    def visit_enum_type(self, name, info, values, prefix, ifcond):
>          doc = self.cur_doc
>          if self.out:
>              self.out += '\n'
> @@ -216,7 +216,7 @@ class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor):
>                               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, base, members, variants, ifcond):
>          doc = self.cur_doc
>          if base and base.is_implicit():
>              base = None
> @@ -226,7 +226,7 @@ class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor):
>                               name=doc.symbol,
>                               body=texi_entity(doc, 'Members', base, variants))
>  
> -    def visit_alternate_type(self, name, info, variants):
> +    def visit_alternate_type(self, name, info, variants, ifcond):
>          doc = self.cur_doc
>          if self.out:
>              self.out += '\n'
> @@ -235,7 +235,7 @@ class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor):
>                               body=texi_entity(doc, 'Members'))
>  
>      def visit_command(self, name, info, arg_type, ret_type,
> -                      gen, success_response, boxed):
> +                      gen, success_response, boxed, ifcond):
>          doc = self.cur_doc
>          if self.out:
>              self.out += '\n'
> @@ -249,7 +249,7 @@ class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor):
>                              name=doc.symbol,
>                              body=body)
>  
> -    def visit_event(self, name, info, arg_type, boxed):
> +    def visit_event(self, name, info, arg_type, boxed, ifcond):
>          doc = self.cur_doc
>          if self.out:
>              self.out += '\n'
> diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
> index 7fbaea19bc..fc5fd25f1b 100644
> --- a/tests/qapi-schema/qapi-schema-test.out
> +++ b/tests/qapi-schema/qapi-schema-test.out
> @@ -56,18 +56,25 @@ alternate TestIfAlternate
>      tag type
>      case foo: int
>      case bar: TestStruct
> +    if defined(TEST_IF_ALT) && 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)
>  enum TestIfEnum ['foo', 'bar']
> +    if defined(TEST_IF_ENUM)
>  event TestIfEvent q_obj_TestIfEvent-arg
>     boxed=False
> +    if defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)
>  object TestIfStruct
>      member foo: int optional=False
> +    if 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)
>  enum TestIfUnionKind ['foo']
> +    if defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)
>  object TestStruct
>      member integer: int optional=False
>      member boolean: bool optional=False
> @@ -190,8 +197,10 @@ object q_obj_EVENT_D-arg
>      member enum3: EnumOne optional=True
>  object q_obj_TestIfCmd-arg
>      member foo: TestIfStruct optional=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)
>  object q_obj_TestStruct-wrapper
>      member data: TestStruct optional=False
>  object q_obj_UserDefFlatUnion2-base

Ah, now the ifcond become visible!  Announcing that in PATCH 15 would've
avoided me asking for it :)

> diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
> index c7724d3437..17fd975812 100644
> --- a/tests/qapi-schema/test-qapi.py
> +++ b/tests/qapi-schema/test-qapi.py
> @@ -17,12 +17,13 @@ import sys
>  
>  
>  class QAPISchemaTestVisitor(QAPISchemaVisitor):
> -    def visit_enum_type(self, name, info, values, prefix):
> +    def visit_enum_type(self, name, info, values, prefix, ifcond):
>          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, base, members, variants, ifcond):
>          print 'object %s' % name
>          if base:
>              print '    base %s' % base.name
> @@ -30,21 +31,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, variants, ifcond):
>          print 'alternate %s' % name
>          self._print_variants(variants)
> +        self._print_if(ifcond)
>  
>      def visit_command(self, name, info, arg_type, ret_type,
> -                      gen, success_response, boxed):
> +                      gen, success_response, boxed, ifcond):
>          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, arg_type, boxed, ifcond):
>          print 'event %s %s' % (name, arg_type and arg_type.name)
>          print '   boxed=%s' % boxed
> +        self._print_if(ifcond)
>  
>      @staticmethod
>      def _print_variants(variants):
> @@ -53,6 +58,12 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
>              for v in variants.variants:
>                  print '    case %s: %s' % (v.name, v.type.name)
>  
> +    @staticmethod
> +    def _print_if(ifcond):
> +        if ifcond:
> +            print '    if %s' % ifcond
> +
> +
>  schema = QAPISchema(sys.argv[1])
>  schema.visit(QAPISchemaTestVisitor())

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

* Re: [Qemu-devel] [PATCH v2 19/54] qapi: add #if/#endif helpers
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 19/54] qapi: add #if/#endif helpers Marc-André Lureau
@ 2017-09-05  9:32   ` Markus Armbruster
  2017-09-06 15:19     ` Marc-André Lureau
  0 siblings, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-09-05  9:32 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> Add helpers to generate #if/#endif and wrap visitor methods generating
> code. Used in the following patches.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi.py | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 51 insertions(+)
>
> diff --git a/scripts/qapi.py b/scripts/qapi.py
> index 86845a28f9..52099332f1 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi.py
> @@ -1892,6 +1892,57 @@ def guardend(name):
>                   name=guardname(name))
>  
>  
> +def gen_if(ifcond):
> +    if not ifcond:
> +        return ''
> +    if isinstance(ifcond, str):
> +        ifcond = [ifcond]
> +    # Not using mcgen() because we don't want indent or \n stipped

s/stipped/stripped/ I guess.

Which newline exactly don't you want to strip?

Here's what mcgen() currently does:

* Strip one leading newline, so that this works:

      mcgen('''
  line 1
  line 2
  ''')

* Interpolate keywords

* Indent by @indent_level spaces

* Strip @eatspace.

> +    ret = '\n'
> +    for ifc in ifcond:
> +        ret += '#if %s\n' % ifc
> +    ret += '\n'
> +    return ret
> +
> +
> +def gen_endif(ifcond):
> +    if not ifcond:
> +        return ''
> +    if isinstance(ifcond, str):
> +        ifcond = [ifcond]
> +    # Not using mcgen() because we don't want indent or \n stipped

Likewise.

> +    ret = '\n'
> +    for ifc in reversed(ifcond):
> +        ret += '#endif /* %s */\n' % ifc
> +    ret += '\n'
> +    return ret

I guess factoring out the common parts of gen_if() and gen_endif() would
make the code longer and more complex.

> +
> +
> +# Wrap a method to add #if / #endif to generated code, only if some
> +# code was generated.
> +# self must have 'if_members' listing the attributes to wrap.
> +# The last argument of the wrapped function must be the 'ifcond'.
> +def ifcond_decorator(func):
> +
> +    def func_wrapper(self, *args, **kwargs):
> +        ifcond = args[-1]
> +        save = {}
> +        for mem in self.if_members:
> +            save[mem] = getattr(self, mem)
> +        func(self, *args, **kwargs)
> +        for mem, val in save.items():
> +            newval = getattr(self, mem)
> +            if newval != val:
> +                assert newval.startswith(val)
> +                newval = newval[len(val):]
> +                val += gen_if(ifcond)
> +                val += newval
> +                val += gen_endif(ifcond)
> +            setattr(self, mem, val)
> +
> +    return func_wrapper
> +
> +
>  def gen_enum_lookup(name, values, prefix=None):
>      ret = mcgen('''

My gut feeling is "too clever by half", but i'm reserving judgement
until after review of its use.

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

* Re: [Qemu-devel] [PATCH v2 20/54] qapi-introspect: modify to_qlit() to take an optional suffix
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 20/54] qapi-introspect: modify to_qlit() to take an optional suffix Marc-André Lureau
@ 2017-09-05  9:42   ` Markus Armbruster
  2017-09-06 14:02     ` Marc-André Lureau
  0 siblings, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-09-05  9:42 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> 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>
> ---
>  scripts/qapi-introspect.py | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
> index 4c437d60ec..dfb6d2ded4 100644
> --- a/scripts/qapi-introspect.py
> +++ b/scripts/qapi-introspect.py
> @@ -16,7 +16,7 @@ def to_c_string(s):
>      return '"' + s.replace('\\', r'\\').replace('"', r'\"') + '"'
>  
>  
> -def to_qlit(obj, level=0, first_indent=True):
> +def to_qlit(obj, level=0, first_indent=True, suffix=''):
>  
>      def indent(level):
>          return level * 4 * ' '
> @@ -29,11 +29,11 @@ def to_qlit(obj, level=0, first_indent=True):
>      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, suffix=',')
>                  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 = []
> @@ -46,7 +46,7 @@ def to_qlit(obj, level=0, first_indent=True):
>          ret += indent(level) + '}))'
>      else:
>          assert False                # not implemented
> -    return ret
> +    return ret + suffix
>  
>  
>  class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor):

Hmm.  I wonder the appended simpler patch would do.

diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index 4c437d60ec..73edb55cd5 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -33,7 +33,7 @@ def to_qlit(obj, level=0, first_indent=True):
                 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 = []
@@ -46,6 +46,8 @@ def to_qlit(obj, level=0, first_indent=True):
         ret += indent(level) + '}))'
     else:
         assert False                # not implemented
+    if level > 0:
+        ret += ','
     return ret
 
 

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

* Re: [Qemu-devel] [PATCH v2 15/54] qapi: add 'if' to top-level expressions
  2017-09-04 13:27   ` Markus Armbruster
@ 2017-09-05 13:58     ` Marc-André Lureau
  2017-09-06 11:36       ` Markus Armbruster
  0 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-09-05 13:58 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: QEMU, Michael Roth

Hi

On Mon, Sep 4, 2017 at 3:27 PM, 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)' }
>
> Lost line break?

yes

>
>> 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>
>> ---
>>  scripts/qapi.py                         | 13 +++++++++++++
>>  tests/test-qmp-commands.c               |  6 ++++++
>>  tests/qapi-schema/qapi-schema-test.json | 20 ++++++++++++++++++++
>>  tests/qapi-schema/qapi-schema-test.out  | 22 ++++++++++++++++++++++
>>  4 files changed, 61 insertions(+)
>>
>> diff --git a/scripts/qapi.py b/scripts/qapi.py
>> index 73adb90379..a94d93ada4 100644
>> --- a/scripts/qapi.py
>> +++ b/scripts/qapi.py
>> @@ -639,6 +639,16 @@ def add_name(name, info, meta, implicit=False):
>>      all_names[name] = meta
>>
>>
>> +def check_if(expr, info):
>> +    ifcond = expr.get('if')
>> +    if not ifcond or isinstance(ifcond, str):
>> +        return
>> +    if (not isinstance(ifcond, list) or
>> +            any([not isinstance(elt, str) for elt in ifcond])):
>> +        raise QAPISemError(info, "'if' condition requires a string or "
>> +                           "a list of string")
>
> The error also triggers on inputs 'if': '' and 'if': [].
>
> The first one doesn't make sense (the C compiler will surely barf).  We
> could leave rejecting it to the C compiler.  If we choose to reject it
> here, we need a better error message, because the one above is
> misleading.
>
> The second one is a roundabout way to say "unconditional".  If we choose
> to reject that, we also need a non-misleading error message.
>
> The error can't trigger on absent 'if', because we don't get called
> then.  To make that locally obvious, please say
>
>        ifcond = expr['if']
>
> Moreover, I'd prefer to avoid mixing conditionals with opposite sense,
> i.e. if good: return; if bad: raise.
>
> Taken together:
>
>    def check_if(expr, info):
>        ifcond = expr['if']
>        if isinstance(ifcond, str):
>            if ifcond == '':
>                raise QAPISemError(info, "'if' condition '' makes no sense")
>            return
>        if isinstance(ifcond, list):
>            if ifcond == []:
>                raise QAPISemError(info, "'if' condition [] is useless")
>            for elt in ifcond:
>                if not isinstance(elt, str):
>                    raise QAPISemError(
>                            info, "'if' condition %s makes no sense" % elt)
>            return
>        raise QAPISemError(
>                info, "'if' condition must be a string or a list of strings")
>
> Written this way (one case after the other), each error has to report
> just one narrow problem.  Makes crafting precise error messages easier.
>

ok, thanks

>> +
>> +
>>  def check_type(info, source, value, allow_array=False,
>>                 allow_dict=False, allow_optional=False,
>>                 allow_metas=[]):
>> @@ -865,6 +875,7 @@ def check_keys(expr_elem, meta, required, optional=[]):
>>      expr = expr_elem['expr']
>>      info = expr_elem['info']
>>      name = expr[meta]
>> +    optional = optional + ['if']  # all top-level elem accept if
>>      if not isinstance(name, str):
>>          raise QAPISemError(info, "'%s' key must have a string value" % meta)
>>      required = required + [meta]
>
> All top-level expressions require 'data'.  Done the obvious way: all
> callers pass 'data' in @required.  Let's do 'if' the same way for
> consistency.

Not all, 'data' is not required for commands & events.

And 'if' is always optional.

But anyway, I modified it now to pass it as argument...

>
>> @@ -880,6 +891,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'"
>> diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
>> index 904c89d4d4..9b9a7ffee7 100644
>> --- a/tests/test-qmp-commands.c
>> +++ b/tests/test-qmp-commands.c
>> @@ -10,6 +10,12 @@
>>
>>  static QmpCommandList qmp_commands;
>>
>> +/* #if defined(TEST_IF_CMD) */
>> +void qmp_TestIfCmd(TestIfStruct *foo, Error **errp)
>> +{
>> +}
>> +/* #endif */
>> +
>>  void qmp_user_def_cmd(Error **errp)
>>  {
>>  }
>> diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
>> index c72dbd8050..dc2c444fc1 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 3b1e9082d3..7fbaea19bc 100644
>> --- a/tests/qapi-schema/qapi-schema-test.out
>> +++ b/tests/qapi-schema/qapi-schema-test.out
>> @@ -52,6 +52,22 @@ enum QEnumTwo ['value1', 'value2']
>>      prefix QENUM_TWO
>>  enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>>      prefix QTYPE
>> +alternate TestIfAlternate
>> +    tag type
>> +    case foo: int
>> +    case bar: TestStruct
>> +command TestIfCmd q_obj_TestIfCmd-arg -> None
>> +   gen=True success_response=True boxed=False
>> +enum TestIfEnum ['foo', 'bar']
>> +event TestIfEvent q_obj_TestIfEvent-arg
>> +   boxed=False
>> +object TestIfStruct
>> +    member foo: int optional=False
>> +object TestIfUnion
>> +    member type: TestIfUnionKind optional=False
>> +    tag type
>> +    case foo: q_obj_TestStruct-wrapper
>> +enum TestIfUnionKind ['foo']
>>  object TestStruct
>>      member integer: int optional=False
>>      member boolean: bool optional=False
>> @@ -172,6 +188,12 @@ object q_obj_EVENT_D-arg
>>      member b: str optional=False
>>      member c: str optional=True
>>      member enum3: EnumOne optional=True
>> +object q_obj_TestIfCmd-arg
>> +    member foo: TestIfStruct optional=False
>> +object q_obj_TestIfEvent-arg
>> +    member foo: TestIfStruct optional=False
>> +object q_obj_TestStruct-wrapper
>> +    member data: TestStruct optional=False
>>  object q_obj_UserDefFlatUnion2-base
>>      member integer: int optional=True
>>      member string: str optional=False
>
> The conditionals aren't visible in qapi-schema-test.out.  They should
> be.
>

That's a follow-up patch "qapi: add 'ifcond' to visitor methods"

> *Much* easier to review than its predecessor PATCH 07/26.  Appreciated!



-- 
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH v2 22/54] qapi-introspect: add preprocessor conditions to generated QLit
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 22/54] qapi-introspect: add preprocessor conditions to generated QLit Marc-André Lureau
@ 2017-09-05 14:24   ` Markus Armbruster
  2017-09-05 16:24     ` Marc-André Lureau
  2017-09-06 11:38   ` Markus Armbruster
  1 sibling, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-09-05 14:24 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> Add 'ifcond' condition to QLit objects.
>
> to_qlit() handles the (obj, ifcond) tuples.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi-introspect.py | 20 +++++++++++---------
>  1 file changed, 11 insertions(+), 9 deletions(-)
>
> diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
> index 9ef6f271d4..5e736a06df 100644
> --- a/scripts/qapi-introspect.py
> +++ b/scripts/qapi-introspect.py
> @@ -125,12 +125,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))

If I read this correctly, all elements of self._qlits become pairs, even
the unconditional ones.  They all go through to_qlit()'s tuple case.
Works, because gen_if(None) and gen_endif(None) do nothing.

Would

           if ifcond:
               obj = (obj, ifcond)
           self.qlits.append(obj)

be clearer?  It could be a bit more efficient, but I doubt that matters.

>  
>      def _gen_member(self, member):
>          ret = {'name': member.name, 'type': self._use_type(member.type)}
> @@ -146,26 +146,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}, None)
>  
>      def visit_enum_type(self, name, info, values, prefix, ifcond):
> -        self._gen_qlit(name, 'enum', {'values': values})
> +        self._gen_qlit(name, 'enum', {'values': values}, ifcond)
>  
>      def visit_array_type(self, name, info, element_type, ifcond):
>          element = self._use_type(element_type)
> -        self._gen_qlit('[' + element + ']', 'array', {'element-type': element})
> +        self._gen_qlit('[' + element + ']', 'array', {'element-type': element},
> +                       ifcond)
>  
>      def visit_object_type_flat(self, name, info, members, variants, ifcond):
>          obj = {'members': [self._gen_member(m) for m in members]}
>          if variants:
>              obj.update(self._gen_variants(variants.tag_member.name,
>                                            variants.variants))
> -        self._gen_qlit(name, 'object', obj)
> +        self._gen_qlit(name, 'object', obj, ifcond)
>  
>      def visit_alternate_type(self, name, info, variants, ifcond):
>          self._gen_qlit(name, 'alternate',
>                         {'members': [{'type': self._use_type(m.type)}
> -                                    for m in variants.variants]})
> +                                    for m in variants.variants]}, ifcond)
>  
>      def visit_command(self, name, info, arg_type, ret_type,
>                        gen, success_response, boxed, ifcond):
> @@ -173,11 +174,12 @@ const QLitObject %(c_name)s = %(c_string)s;
>          ret_type = ret_type or self._schema.the_empty_object_type
>          self._gen_qlit(name, 'command',
>                         {'arg-type': self._use_type(arg_type),
> -                        'ret-type': self._use_type(ret_type)})
> +                        'ret-type': self._use_type(ret_type)}, ifcond)
>  
>      def visit_event(self, name, info, arg_type, boxed, ifcond):
>          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)
>  
>  # Debugging aid: unmask QAPI schema's type names
>  # We normally mask them, because they're not QMP wire ABI

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

* Re: [Qemu-devel] [PATCH v2 23/54] qapi-commands: add #if conditions to commands
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 23/54] qapi-commands: add #if conditions to commands Marc-André Lureau
@ 2017-09-05 14:53   ` Markus Armbruster
  2017-09-05 15:05     ` Marc-André Lureau
  0 siblings, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-09-05 14:53 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> Wrap generated code with #if/#endif using the ifcond_decorator.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi-commands.py  | 2 ++
>  tests/test-qmp-commands.c | 4 ++--
>  2 files changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
> index 5eb96b2d95..db45415c41 100644
> --- a/scripts/qapi-commands.py
> +++ b/scripts/qapi-commands.py
> @@ -228,6 +228,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
>          self.defn = None
>          self._regy = None
>          self._visited_ret_types = None
> +        self.if_members = ['decl', 'defn', '_regy']
>  
>      def visit_begin(self, schema):
>          self.decl = ''
> @@ -240,6 +241,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
>          self._regy = None
>          self._visited_ret_types = None
>  
> +    @ifcond_decorator
>      def visit_command(self, name, info, arg_type, ret_type,
>                        gen, success_response, boxed, ifcond):
>          if not gen:
> diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
> index 9b9a7ffee7..ad7b6e4e1d 100644
> --- a/tests/test-qmp-commands.c
> +++ b/tests/test-qmp-commands.c
> @@ -10,11 +10,11 @@
>  
>  static QmpCommandList qmp_commands;
>  
> -/* #if defined(TEST_IF_CMD) */
> +#if defined(TEST_IF_CMD)
>  void qmp_TestIfCmd(TestIfStruct *foo, Error **errp)
>  {
>  }
> -/* #endif */
> +#endif
>  
>  void qmp_user_def_cmd(Error **errp)
>  {

To find out whether the clever decorator is worth its keep, I replaced
it with the dumbest, most obvious code I could think of (appended).
Does this make visit_command() easier or harder to understand?



diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index db45415c41..13d37d2ac2 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -228,7 +228,6 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
         self.defn = None
         self._regy = None
         self._visited_ret_types = None
-        self.if_members = ['decl', 'defn', '_regy']
 
     def visit_begin(self, schema):
         self.decl = ''
@@ -241,18 +240,21 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
         self._regy = None
         self._visited_ret_types = None
 
-    @ifcond_decorator
     def visit_command(self, name, info, arg_type, ret_type,
                       gen, success_response, boxed, ifcond):
         if not gen:
             return
-        self.decl += gen_command_decl(name, arg_type, boxed, ret_type)
+        decl = gen_command_decl(name, arg_type, boxed, ret_type)
+        defn = ''
         if ret_type and ret_type not in self._visited_ret_types:
             self._visited_ret_types.add(ret_type)
-            self.defn += gen_marshal_output(ret_type)
-        self.decl += gen_marshal_decl(name)
-        self.defn += gen_marshal(name, arg_type, boxed, ret_type)
-        self._regy += gen_register_command(name, success_response)
+            defn += gen_marshal_output(ret_type)
+        decl += gen_marshal_decl(name)
+        defn += gen_marshal(name, arg_type, boxed, ret_type)
+        self.decl += gen_ifcond(ifcond, decl)
+        self.defn += gen_ifcond(ifcond, defn)
+        self._regy += gen_ifcond(ifcond,
+                                 gen_register_command(name, success_response))
 
 
 (input_file, output_dir, do_c, do_h, prefix, opts) = parse_command_line()
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 52099332f1..3de5b8b8f0 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -1918,29 +1918,10 @@ def gen_endif(ifcond):
     return ret
 
 
-# Wrap a method to add #if / #endif to generated code, only if some
-# code was generated.
-# self must have 'if_members' listing the attributes to wrap.
-# The last argument of the wrapped function must be the 'ifcond'.
-def ifcond_decorator(func):
-
-    def func_wrapper(self, *args, **kwargs):
-        ifcond = args[-1]
-        save = {}
-        for mem in self.if_members:
-            save[mem] = getattr(self, mem)
-        func(self, *args, **kwargs)
-        for mem, val in save.items():
-            newval = getattr(self, mem)
-            if newval != val:
-                assert newval.startswith(val)
-                newval = newval[len(val):]
-                val += gen_if(ifcond)
-                val += newval
-                val += gen_endif(ifcond)
-            setattr(self, mem, val)
-
-    return func_wrapper
+def gen_ifcond(ifcond, ctext):
+    if ifcond:
+        return gen_if(ifcond) + ctext + gen_endif(ifcond)
+    return ctext
 
 
 def gen_enum_lookup(name, values, prefix=None):

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

* Re: [Qemu-devel] [PATCH v2 23/54] qapi-commands: add #if conditions to commands
  2017-09-05 14:53   ` Markus Armbruster
@ 2017-09-05 15:05     ` Marc-André Lureau
  2017-09-05 15:08       ` Marc-André Lureau
  0 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-09-05 15:05 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth

Hi

----- Original Message -----
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> 
> > Wrap generated code with #if/#endif using the ifcond_decorator.
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >  scripts/qapi-commands.py  | 2 ++
> >  tests/test-qmp-commands.c | 4 ++--
> >  2 files changed, 4 insertions(+), 2 deletions(-)
> >
> > diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
> > index 5eb96b2d95..db45415c41 100644
> > --- a/scripts/qapi-commands.py
> > +++ b/scripts/qapi-commands.py
> > @@ -228,6 +228,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
> >          self.defn = None
> >          self._regy = None
> >          self._visited_ret_types = None
> > +        self.if_members = ['decl', 'defn', '_regy']
> >  
> >      def visit_begin(self, schema):
> >          self.decl = ''
> > @@ -240,6 +241,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
> >          self._regy = None
> >          self._visited_ret_types = None
> >  
> > +    @ifcond_decorator
> >      def visit_command(self, name, info, arg_type, ret_type,
> >                        gen, success_response, boxed, ifcond):
> >          if not gen:
> > diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
> > index 9b9a7ffee7..ad7b6e4e1d 100644
> > --- a/tests/test-qmp-commands.c
> > +++ b/tests/test-qmp-commands.c
> > @@ -10,11 +10,11 @@
> >  
> >  static QmpCommandList qmp_commands;
> >  
> > -/* #if defined(TEST_IF_CMD) */
> > +#if defined(TEST_IF_CMD)
> >  void qmp_TestIfCmd(TestIfStruct *foo, Error **errp)
> >  {
> >  }
> > -/* #endif */
> > +#endif
> >  
> >  void qmp_user_def_cmd(Error **errp)
> >  {
> 
> To find out whether the clever decorator is worth its keep, I replaced
> it with the dumbest, most obvious code I could think of (appended).
> Does this make visit_command() easier or harder to understand?
> 
> 
> 
> diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
> index db45415c41..13d37d2ac2 100644
> --- a/scripts/qapi-commands.py
> +++ b/scripts/qapi-commands.py
> @@ -228,7 +228,6 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
>          self.defn = None
>          self._regy = None
>          self._visited_ret_types = None
> -        self.if_members = ['decl', 'defn', '_regy']
>  
>      def visit_begin(self, schema):
>          self.decl = ''
> @@ -241,18 +240,21 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
>          self._regy = None
>          self._visited_ret_types = None
>  
> -    @ifcond_decorator
>      def visit_command(self, name, info, arg_type, ret_type,
>                        gen, success_response, boxed, ifcond):
>          if not gen:
>              return
> -        self.decl += gen_command_decl(name, arg_type, boxed, ret_type)
> +        decl = gen_command_decl(name, arg_type, boxed, ret_type)
> +        defn = ''
>          if ret_type and ret_type not in self._visited_ret_types:
>              self._visited_ret_types.add(ret_type)
> -            self.defn += gen_marshal_output(ret_type)
> -        self.decl += gen_marshal_decl(name)
> -        self.defn += gen_marshal(name, arg_type, boxed, ret_type)
> -        self._regy += gen_register_command(name, success_response)
> +            defn += gen_marshal_output(ret_type)
> +        decl += gen_marshal_decl(name)
> +        defn += gen_marshal(name, arg_type, boxed, ret_type)
> +        self.decl += gen_ifcond(ifcond, decl)
> +        self.defn += gen_ifcond(ifcond, defn)
> +        self._regy += gen_ifcond(ifcond,
> +                                 gen_register_command(name,
> success_response))

This is one of the most simple case, and it is already very intrusive. If you have more branches / early return it becomes awful.

Do it for all the places where we have @ifcond_decorator and you will probably prefer the concise decorated version. For me this case is one of the reason why decorators exist: to wrap enter/exit of a function.

>  
>  
>  (input_file, output_dir, do_c, do_h, prefix, opts) = parse_command_line()
> diff --git a/scripts/qapi.py b/scripts/qapi.py
> index 52099332f1..3de5b8b8f0 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi.py
> @@ -1918,29 +1918,10 @@ def gen_endif(ifcond):
>      return ret
>  
>  
> -# Wrap a method to add #if / #endif to generated code, only if some
> -# code was generated.
> -# self must have 'if_members' listing the attributes to wrap.
> -# The last argument of the wrapped function must be the 'ifcond'.
> -def ifcond_decorator(func):
> -
> -    def func_wrapper(self, *args, **kwargs):
> -        ifcond = args[-1]
> -        save = {}
> -        for mem in self.if_members:
> -            save[mem] = getattr(self, mem)
> -        func(self, *args, **kwargs)
> -        for mem, val in save.items():
> -            newval = getattr(self, mem)
> -            if newval != val:
> -                assert newval.startswith(val)
> -                newval = newval[len(val):]
> -                val += gen_if(ifcond)
> -                val += newval
> -                val += gen_endif(ifcond)
> -            setattr(self, mem, val)
> -
> -    return func_wrapper
> +def gen_ifcond(ifcond, ctext):
> +    if ifcond:
> +        return gen_if(ifcond) + ctext + gen_endif(ifcond)
> +    return ctext
>  
>  
>  def gen_enum_lookup(name, values, prefix=None):
> 

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

* Re: [Qemu-devel] [PATCH v2 23/54] qapi-commands: add #if conditions to commands
  2017-09-05 15:05     ` Marc-André Lureau
@ 2017-09-05 15:08       ` Marc-André Lureau
  2017-09-05 16:34         ` Markus Armbruster
  0 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-09-05 15:08 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth



----- Original Message -----
> Hi
> 
> ----- Original Message -----
> > Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> > 
> > > Wrap generated code with #if/#endif using the ifcond_decorator.
> > >
> > > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > > ---
> > >  scripts/qapi-commands.py  | 2 ++
> > >  tests/test-qmp-commands.c | 4 ++--
> > >  2 files changed, 4 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
> > > index 5eb96b2d95..db45415c41 100644
> > > --- a/scripts/qapi-commands.py
> > > +++ b/scripts/qapi-commands.py
> > > @@ -228,6 +228,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
> > >          self.defn = None
> > >          self._regy = None
> > >          self._visited_ret_types = None
> > > +        self.if_members = ['decl', 'defn', '_regy']
> > >  
> > >      def visit_begin(self, schema):
> > >          self.decl = ''
> > > @@ -240,6 +241,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
> > >          self._regy = None
> > >          self._visited_ret_types = None
> > >  
> > > +    @ifcond_decorator
> > >      def visit_command(self, name, info, arg_type, ret_type,
> > >                        gen, success_response, boxed, ifcond):
> > >          if not gen:
> > > diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
> > > index 9b9a7ffee7..ad7b6e4e1d 100644
> > > --- a/tests/test-qmp-commands.c
> > > +++ b/tests/test-qmp-commands.c
> > > @@ -10,11 +10,11 @@
> > >  
> > >  static QmpCommandList qmp_commands;
> > >  
> > > -/* #if defined(TEST_IF_CMD) */
> > > +#if defined(TEST_IF_CMD)
> > >  void qmp_TestIfCmd(TestIfStruct *foo, Error **errp)
> > >  {
> > >  }
> > > -/* #endif */
> > > +#endif
> > >  
> > >  void qmp_user_def_cmd(Error **errp)
> > >  {
> > 
> > To find out whether the clever decorator is worth its keep, I replaced
> > it with the dumbest, most obvious code I could think of (appended).
> > Does this make visit_command() easier or harder to understand?
> > 
> > 
> > 
> > diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
> > index db45415c41..13d37d2ac2 100644
> > --- a/scripts/qapi-commands.py
> > +++ b/scripts/qapi-commands.py
> > @@ -228,7 +228,6 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
> >          self.defn = None
> >          self._regy = None
> >          self._visited_ret_types = None
> > -        self.if_members = ['decl', 'defn', '_regy']
> >  
> >      def visit_begin(self, schema):
> >          self.decl = ''
> > @@ -241,18 +240,21 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
> >          self._regy = None
> >          self._visited_ret_types = None
> >  
> > -    @ifcond_decorator
> >      def visit_command(self, name, info, arg_type, ret_type,
> >                        gen, success_response, boxed, ifcond):
> >          if not gen:
> >              return
> > -        self.decl += gen_command_decl(name, arg_type, boxed, ret_type)
> > +        decl = gen_command_decl(name, arg_type, boxed, ret_type)
> > +        defn = ''
> >          if ret_type and ret_type not in self._visited_ret_types:
> >              self._visited_ret_types.add(ret_type)
> > -            self.defn += gen_marshal_output(ret_type)
> > -        self.decl += gen_marshal_decl(name)
> > -        self.defn += gen_marshal(name, arg_type, boxed, ret_type)
> > -        self._regy += gen_register_command(name, success_response)
> > +            defn += gen_marshal_output(ret_type)
> > +        decl += gen_marshal_decl(name)
> > +        defn += gen_marshal(name, arg_type, boxed, ret_type)
> > +        self.decl += gen_ifcond(ifcond, decl)
> > +        self.defn += gen_ifcond(ifcond, defn)
> > +        self._regy += gen_ifcond(ifcond,
> > +                                 gen_register_command(name,
> > success_response))
> 
> This is one of the most simple case, and it is already very intrusive. If you
> have more branches / early return it becomes awful.
> 
> Do it for all the places where we have @ifcond_decorator and you will
> probably prefer the concise decorated version. For me this case is one of
> the reason why decorators exist: to wrap enter/exit of a function.
> 

Oh and your version looks inferior, since it will generate empty #if/#endif blocks. You seemed to be quite strict about having the generated output be nicely formatted & human friendly, so I thought clearing those empty block was a must for you.

> >  
> >  
> >  (input_file, output_dir, do_c, do_h, prefix, opts) = parse_command_line()
> > diff --git a/scripts/qapi.py b/scripts/qapi.py
> > index 52099332f1..3de5b8b8f0 100644
> > --- a/scripts/qapi.py
> > +++ b/scripts/qapi.py
> > @@ -1918,29 +1918,10 @@ def gen_endif(ifcond):
> >      return ret
> >  
> >  
> > -# Wrap a method to add #if / #endif to generated code, only if some
> > -# code was generated.
> > -# self must have 'if_members' listing the attributes to wrap.
> > -# The last argument of the wrapped function must be the 'ifcond'.
> > -def ifcond_decorator(func):
> > -
> > -    def func_wrapper(self, *args, **kwargs):
> > -        ifcond = args[-1]
> > -        save = {}
> > -        for mem in self.if_members:
> > -            save[mem] = getattr(self, mem)
> > -        func(self, *args, **kwargs)
> > -        for mem, val in save.items():
> > -            newval = getattr(self, mem)
> > -            if newval != val:
> > -                assert newval.startswith(val)
> > -                newval = newval[len(val):]
> > -                val += gen_if(ifcond)
> > -                val += newval
> > -                val += gen_endif(ifcond)
> > -            setattr(self, mem, val)
> > -
> > -    return func_wrapper
> > +def gen_ifcond(ifcond, ctext):
> > +    if ifcond:
> > +        return gen_if(ifcond) + ctext + gen_endif(ifcond)
> > +    return ctext
> >  
> >  
> >  def gen_enum_lookup(name, values, prefix=None):
> > 
> 

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

* Re: [Qemu-devel] [PATCH v2 17/54] qapi: add 'if' condition on entity objects
  2017-09-04 16:13   ` Markus Armbruster
@ 2017-09-05 15:38     ` Marc-André Lureau
  2017-09-05 16:31       ` Markus Armbruster
  0 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-09-05 15:38 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth

Hi

----- Original Message -----
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> 
> > Take 'if' from expression, and use it to construct entity objects.
> > Shared implicit objects must share the same 'if' condition.
> 
> Shared by what?

Shared by various make_implicit_object_type() users.

> 
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >  scripts/qapi.py | 81
> >  +++++++++++++++++++++++++++++++++++++--------------------
> >  1 file changed, 53 insertions(+), 28 deletions(-)
> >
> > diff --git a/scripts/qapi.py b/scripts/qapi.py
> > index a94d93ada4..dc40d74abb 100644
> > --- a/scripts/qapi.py
> > +++ b/scripts/qapi.py
> > @@ -992,7 +992,7 @@ def check_exprs(exprs):
> >  #
> >  
> >  class QAPISchemaEntity(object):
> > -    def __init__(self, name, info, doc):
> > +    def __init__(self, name, info, doc, ifcond=None):
> >          assert isinstance(name, str)
> >          self.name = name
> >          # For explicitly defined entities, info points to the (explicit)
> 
> Not visible here: QAPISchemaType inherits this.
> 
> > @@ -1002,6 +1002,7 @@ class QAPISchemaEntity(object):
> >          # such place).
> >          self.info = info
> >          self.doc = doc
> > +        self.ifcond = ifcond
> >  
> >      def c_name(self):
> >          return c_name(self.name)
> > @@ -1118,8 +1119,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, values, prefix, ifcond=None):
> > +        QAPISchemaType.__init__(self, name, info, doc, ifcond)
> >          for v in values:
> >              assert isinstance(v, QAPISchemaMember)
> >              v.set_owner(name)
> > @@ -1162,6 +1163,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
> 
> This is subtler than it looks on first glance.
> 
> All the other entities set self.ifcond in their constructor to the true
> value passed in as argument.
> 
> QAPISchemaArrayType doesn't take such an argument.  Instead, it inherits
> its .ifcond from its .element_type.  However, .element_type isn't known
> at construction time if it's a forward reference.  We therefore delay
> setting it until .check() time.  You do the same for .ifcond (no
> choice).
> 
> Before .check(), .ifcond is None, because the constructor sets it that
> way: it calls QAPISchemaType.__init__() without passing a ifcond
> argument, which then sets self.ifcond to its default argument None.
> 
> Pitfall: accessing ent.ifcond before ent.check() works *except* when ent
> is an array type.  Hmm.
> 
> >  
> >      def is_implicit(self):
> >          return True
> > @@ -1183,11 +1185,12 @@ class QAPISchemaArrayType(QAPISchemaType):
> >  
> >  
> >  class QAPISchemaObjectType(QAPISchemaType):
> > -    def __init__(self, name, info, doc, base, local_members, variants):
> > +    def __init__(self, name, info, doc, base, local_members, variants,
> > +                 ifcond=None):
> >          # 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)
> > @@ -1375,8 +1378,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, variants, ifcond):
> > +        QAPISchemaType.__init__(self, name, info, doc, ifcond)
> >          assert isinstance(variants, QAPISchemaObjectTypeVariants)
> >          assert variants.tag_member
> >          variants.set_owner(name)
> > @@ -1413,8 +1416,8 @@ class QAPISchemaAlternateType(QAPISchemaType):
> >  
> >  class QAPISchemaCommand(QAPISchemaEntity):
> >      def __init__(self, name, info, doc, arg_type, ret_type,
> > -                 gen, success_response, boxed):
> > -        QAPISchemaEntity.__init__(self, name, info, doc)
> > +                 gen, success_response, boxed, ifcond):
> > +        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
> > @@ -1451,8 +1454,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, arg_type, boxed, ifcond):
> > +        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
> 
> Hmm.  You're adding parameter ifcond to all entity constructors.  The
> entity constructors' signatures all look like this:
> 
>     def __init__(<common parameters>, <specific parameters>)
> 
> where <common parameters> is self, name, info, doc.
> 
> Since ifcond is common, let's add it to <common parameters>.  Pick a
> position you like.
> 

ok

> > @@ -1547,11 +1550,11 @@ class QAPISchema(object):
> >      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, values, ifcond):
> >          # 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, self._make_enum_members(values), None,
> > ifcond))
> >          return name
> 
> Called by _def_union_type() to create the implicit tag enum, with the
> same ifcond it passes to QAPISchemaObjectType().  Thus, the implicit
> type's ifcond matches the ifcond of its only user.  Good.
> 
> >  
> >      def _make_array_type(self, element_type, info):
> > @@ -1560,22 +1563,29 @@ 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, role, members,
> > +                                   ifcond=None):
> >          if not members:
> >              return None
> >          # See also QAPISchemaObjectTypeMember._pretty_owner()
> >          name = 'q_obj_%s-%s' % (name, role)
> > -        if not self.lookup_entity(name, QAPISchemaObjectType):
> > +        typ = self.lookup_entity(name, QAPISchemaObjectType)
> > +        if typ:
> > +            # FIXME: generating the disjunction of all conditions
> 
> What are "all conditions"?  I hope I can shed some light on that below.
> 
> > +            assert ifcond == typ.ifcond
> > +        else:
> >              self._def_entity(QAPISchemaObjectType(name, info, doc, None,
> > -                                                  members, None))
> > +                                                  members, None, ifcond))
> >          return name
> 
> Several callers:
> 
> * _make_simple_variant() to create a wrapper type, with the wrapped
>   type's ifcond.  The wrapped type's ifcond is necessary for the wrapper
>   type to compile.  It's not sufficient for it to be needed.  The
>   "needed" condition is the disjunction of all users' ifcond.
> 
>   In other words, your code generates condition that is correct, but not
>   tight.  Your FIXME is about tightening it.  I'd make it a TODO,
>   because nothing is actually broken now.
> 
>   Need a comment explaining this.  Perhaps:
> 
>         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
> 
>   I hate simple unions.

ok

> 
> * _def_union_type() to create an implicit base type, with same ifcond it
>   passes to QAPISchemaObjectType().  Thus, the implicit base type's
>   ifcond matches the ifcond of its only user.  Good.
> 
> * _def_command() to create an implicit argument type, with the same
>   ifcond it passes to QAPISchemaCommand().  Thus, the implicit argument
>   type's ifcond matches the ifcond of its only user.  Good.
> 
> * _def_event() likewise.
> 
> I still can't make sense of the commit message's "Shared implicit
> objects must share the same 'if' condition."
> 
> >  
> >      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, self._make_enum_members(data), prefix,
> > +            ifcond))
> >  
> >      def _make_member(self, name, typ, info):
> >          optional = False
> > @@ -1595,9 +1605,10 @@ class QAPISchema(object):
> >          name = expr['struct']
> >          base = expr.get('base')
> >          data = expr['data']
> > +        ifcond = expr.get('if')
> >          self._def_entity(QAPISchemaObjectType(name, info, doc, base,
> >                                                self._make_members(data,
> >                                                info),
> > -                                              None))
> > +                                              None, ifcond))
> >  
> >      def _make_variant(self, case, typ):
> >          return QAPISchemaObjectTypeVariant(case, typ)
> > @@ -1606,19 +1617,23 @@ class QAPISchema(object):
> >          if isinstance(typ, list):
> >              assert len(typ) == 1
> >              typ = self._make_array_type(typ[0], info)
> > +        type_entity = self.lookup_type(typ)
> >          typ = self._make_implicit_object_type(
> > -            typ, info, None, 'wrapper', [self._make_member('data', typ,
> > info)])
> > +            typ, info, None, 'wrapper',
> > +            [self._make_member('data', typ, info)], type_entity.ifcond)
> >          return QAPISchemaObjectTypeVariant(case, typ)
> 
> This is where you create the wrapper type with the wrapped type's
> ifcond.
> 
> I don't like the name type_entity.  I'd simply eliminate the variable.
> 

ok

> >  
> >      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, 'base', self._make_members(base, info),
> > +                ifcond)
> >          if tag_name:
> >              variants = [self._make_variant(key, value)
> >                          for (key, value) in data.iteritems()]
> 
> This is where you create a union's implicit base type with the union's
> ifcond.
> 
> > @@ -1627,18 +1642,21 @@ class QAPISchema(object):
> >              variants = [self._make_simple_variant(key, value, info)
> >                          for (key, value) in data.iteritems()]
> >              typ = self._make_implicit_enum_type(name, info,
> > -                                                [v.name for v in
> > variants])
> > +                                                [v.name for v in
> > variants],
> > +                                                ifcond)
> >              tag_member = QAPISchemaObjectTypeMember('type', typ, False)
> >              members = [tag_member]
> 
> This is where you create a union's implicit tag enum with the union's ifcond.
> 
> >          self._def_entity(
> >              QAPISchemaObjectType(name, info, doc, base, members,
> >                                   QAPISchemaObjectTypeVariants(tag_name,
> >                                                                tag_member,
> > -                                                              variants)))
> > +                                                              variants),
> > +                                 ifcond))
> >  
> >      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.iteritems()]
> >          tag_member = QAPISchemaObjectTypeMember('type', 'QType', False)
> > @@ -1646,7 +1664,8 @@ class QAPISchema(object):
> >              QAPISchemaAlternateType(name, info, doc,
> >                                      QAPISchemaObjectTypeVariants(None,
> >                                                                   tag_member,
> > -
> > variants)))
> > +
> > variants),
> > +                                    ifcond))
> >  
> >      def _def_command(self, expr, info, doc):
> >          name = expr['command']
> > @@ -1655,23 +1674,29 @@ class QAPISchema(object):
> >          gen = expr.get('gen', True)
> >          success_response = expr.get('success-response', True)
> >          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))
> > +                name, info, doc, 'arg', self._make_members(data, info),
> > +                ifcond)
> 
> This is where you create a command's implicit argument type with the
> command's ifcond.
> 
> >          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,
> > -                                           gen, success_response, boxed))
> > +                                           gen, success_response, boxed,
> > +                                           ifcond))
> >  
> >      def _def_event(self, expr, info, doc):
> >          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, 'arg', self._make_members(data, info),
> > +                ifcond)
> 
> This is where you create an event's implicit argument type with the
> event's ifcond.
> 
> > +        self._def_entity(QAPISchemaEvent(name, info, doc, data, boxed,
> > +                                         ifcond))
> >  
> >      def _def_exprs(self):
> >          for expr_elem in self.exprs:
> 

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

* Re: [Qemu-devel] [PATCH v2 22/54] qapi-introspect: add preprocessor conditions to generated QLit
  2017-09-05 14:24   ` Markus Armbruster
@ 2017-09-05 16:24     ` Marc-André Lureau
  0 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-09-05 16:24 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: QEMU, Michael Roth

On Tue, Sep 5, 2017 at 4:24 PM, Markus Armbruster <armbru@redhat.com> wrote:
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
>> Add 'ifcond' condition to QLit objects.
>>
>> to_qlit() handles the (obj, ifcond) tuples.
>>
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> ---
>>  scripts/qapi-introspect.py | 20 +++++++++++---------
>>  1 file changed, 11 insertions(+), 9 deletions(-)
>>
>> diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
>> index 9ef6f271d4..5e736a06df 100644
>> --- a/scripts/qapi-introspect.py
>> +++ b/scripts/qapi-introspect.py
>> @@ -125,12 +125,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))
>
> If I read this correctly, all elements of self._qlits become pairs, even
> the unconditional ones.  They all go through to_qlit()'s tuple case.
> Works, because gen_if(None) and gen_endif(None) do nothing.
>
> Would
>
>            if ifcond:
>                obj = (obj, ifcond)
>            self.qlits.append(obj)
>
> be clearer?  It could be a bit more efficient, but I doubt that matters.

I prefer the tuple case only version, but up to you if you want me to change it.

>
>>
>>      def _gen_member(self, member):
>>          ret = {'name': member.name, 'type': self._use_type(member.type)}
>> @@ -146,26 +146,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}, None)
>>
>>      def visit_enum_type(self, name, info, values, prefix, ifcond):
>> -        self._gen_qlit(name, 'enum', {'values': values})
>> +        self._gen_qlit(name, 'enum', {'values': values}, ifcond)
>>
>>      def visit_array_type(self, name, info, element_type, ifcond):
>>          element = self._use_type(element_type)
>> -        self._gen_qlit('[' + element + ']', 'array', {'element-type': element})
>> +        self._gen_qlit('[' + element + ']', 'array', {'element-type': element},
>> +                       ifcond)
>>
>>      def visit_object_type_flat(self, name, info, members, variants, ifcond):
>>          obj = {'members': [self._gen_member(m) for m in members]}
>>          if variants:
>>              obj.update(self._gen_variants(variants.tag_member.name,
>>                                            variants.variants))
>> -        self._gen_qlit(name, 'object', obj)
>> +        self._gen_qlit(name, 'object', obj, ifcond)
>>
>>      def visit_alternate_type(self, name, info, variants, ifcond):
>>          self._gen_qlit(name, 'alternate',
>>                         {'members': [{'type': self._use_type(m.type)}
>> -                                    for m in variants.variants]})
>> +                                    for m in variants.variants]}, ifcond)
>>
>>      def visit_command(self, name, info, arg_type, ret_type,
>>                        gen, success_response, boxed, ifcond):
>> @@ -173,11 +174,12 @@ const QLitObject %(c_name)s = %(c_string)s;
>>          ret_type = ret_type or self._schema.the_empty_object_type
>>          self._gen_qlit(name, 'command',
>>                         {'arg-type': self._use_type(arg_type),
>> -                        'ret-type': self._use_type(ret_type)})
>> +                        'ret-type': self._use_type(ret_type)}, ifcond)
>>
>>      def visit_event(self, name, info, arg_type, boxed, ifcond):
>>          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)
>>
>>  # Debugging aid: unmask QAPI schema's type names
>>  # We normally mask them, because they're not QMP wire ABI
>



-- 
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH v2 17/54] qapi: add 'if' condition on entity objects
  2017-09-05 15:38     ` Marc-André Lureau
@ 2017-09-05 16:31       ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-09-05 16:31 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> Hi
>
> ----- Original Message -----
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>> 
>> > Take 'if' from expression, and use it to construct entity objects.
>> > Shared implicit objects must share the same 'if' condition.
>> 
>> Shared by what?
>
> Shared by various make_implicit_object_type() users.

The only ones that are shared right now are simple union wrappers.  For
those, you pick a condition that isn't tight, but works.  Now we need to
work that into the commit message.  Perhaps:

    qapi: Pass 'if' condition into QAPISchemaEntity objects

    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 wrapper types 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.

[...]

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

* Re: [Qemu-devel] [PATCH v2 23/54] qapi-commands: add #if conditions to commands
  2017-09-05 15:08       ` Marc-André Lureau
@ 2017-09-05 16:34         ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-09-05 16:34 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> ----- Original Message -----
>> Hi
>> 
>> ----- Original Message -----
>> > Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>> > 
>> > > Wrap generated code with #if/#endif using the ifcond_decorator.
>> > >
>> > > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> > > ---
>> > >  scripts/qapi-commands.py  | 2 ++
>> > >  tests/test-qmp-commands.c | 4 ++--
>> > >  2 files changed, 4 insertions(+), 2 deletions(-)
>> > >
>> > > diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
>> > > index 5eb96b2d95..db45415c41 100644
>> > > --- a/scripts/qapi-commands.py
>> > > +++ b/scripts/qapi-commands.py
>> > > @@ -228,6 +228,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
>> > >          self.defn = None
>> > >          self._regy = None
>> > >          self._visited_ret_types = None
>> > > +        self.if_members = ['decl', 'defn', '_regy']
>> > >  
>> > >      def visit_begin(self, schema):
>> > >          self.decl = ''
>> > > @@ -240,6 +241,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
>> > >          self._regy = None
>> > >          self._visited_ret_types = None
>> > >  
>> > > +    @ifcond_decorator
>> > >      def visit_command(self, name, info, arg_type, ret_type,
>> > >                        gen, success_response, boxed, ifcond):
>> > >          if not gen:
>> > > diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
>> > > index 9b9a7ffee7..ad7b6e4e1d 100644
>> > > --- a/tests/test-qmp-commands.c
>> > > +++ b/tests/test-qmp-commands.c
>> > > @@ -10,11 +10,11 @@
>> > >  
>> > >  static QmpCommandList qmp_commands;
>> > >  
>> > > -/* #if defined(TEST_IF_CMD) */
>> > > +#if defined(TEST_IF_CMD)
>> > >  void qmp_TestIfCmd(TestIfStruct *foo, Error **errp)
>> > >  {
>> > >  }
>> > > -/* #endif */
>> > > +#endif
>> > >  
>> > >  void qmp_user_def_cmd(Error **errp)
>> > >  {
>> > 
>> > To find out whether the clever decorator is worth its keep, I replaced
>> > it with the dumbest, most obvious code I could think of (appended).
>> > Does this make visit_command() easier or harder to understand?
>> > 
>> > 
>> > 
>> > diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
>> > index db45415c41..13d37d2ac2 100644
>> > --- a/scripts/qapi-commands.py
>> > +++ b/scripts/qapi-commands.py
>> > @@ -228,7 +228,6 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
>> >          self.defn = None
>> >          self._regy = None
>> >          self._visited_ret_types = None
>> > -        self.if_members = ['decl', 'defn', '_regy']
>> >  
>> >      def visit_begin(self, schema):
>> >          self.decl = ''
>> > @@ -241,18 +240,21 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
>> >          self._regy = None
>> >          self._visited_ret_types = None
>> >  
>> > -    @ifcond_decorator
>> >      def visit_command(self, name, info, arg_type, ret_type,
>> >                        gen, success_response, boxed, ifcond):
>> >          if not gen:
>> >              return
>> > -        self.decl += gen_command_decl(name, arg_type, boxed, ret_type)
>> > +        decl = gen_command_decl(name, arg_type, boxed, ret_type)
>> > +        defn = ''
>> >          if ret_type and ret_type not in self._visited_ret_types:
>> >              self._visited_ret_types.add(ret_type)
>> > -            self.defn += gen_marshal_output(ret_type)
>> > -        self.decl += gen_marshal_decl(name)
>> > -        self.defn += gen_marshal(name, arg_type, boxed, ret_type)
>> > -        self._regy += gen_register_command(name, success_response)
>> > +            defn += gen_marshal_output(ret_type)
>> > +        decl += gen_marshal_decl(name)
>> > +        defn += gen_marshal(name, arg_type, boxed, ret_type)
>> > +        self.decl += gen_ifcond(ifcond, decl)
>> > +        self.defn += gen_ifcond(ifcond, defn)
>> > +        self._regy += gen_ifcond(ifcond,
>> > +                                 gen_register_command(name,
>> > success_response))
>> 
>> This is one of the most simple case, and it is already very intrusive. If you
>> have more branches / early return it becomes awful.
>> 
>> Do it for all the places where we have @ifcond_decorator and you will
>> probably prefer the concise decorated version. For me this case is one of
>> the reason why decorators exist: to wrap enter/exit of a function.

This is just a quick experiment.  We certainly have to compare complete
solutions to decide whether the decorator is worthwhile.

> Oh and your version looks inferior, since it will generate empty #if/#endif blocks. You seemed to be quite strict about having the generated output be nicely formatted & human friendly, so I thought clearing those empty block was a must for you.

Yes, it is a must for me.  Should be easy enough to fix: in
gen_ifcond(), replace "if ifcond" by "if ifcond and text is not blank".

>> >  
>> >  
>> >  (input_file, output_dir, do_c, do_h, prefix, opts) = parse_command_line()
>> > diff --git a/scripts/qapi.py b/scripts/qapi.py
>> > index 52099332f1..3de5b8b8f0 100644
>> > --- a/scripts/qapi.py
>> > +++ b/scripts/qapi.py
>> > @@ -1918,29 +1918,10 @@ def gen_endif(ifcond):
>> >      return ret
>> >  
>> >  
>> > -# Wrap a method to add #if / #endif to generated code, only if some
>> > -# code was generated.
>> > -# self must have 'if_members' listing the attributes to wrap.
>> > -# The last argument of the wrapped function must be the 'ifcond'.
>> > -def ifcond_decorator(func):
>> > -
>> > -    def func_wrapper(self, *args, **kwargs):
>> > -        ifcond = args[-1]
>> > -        save = {}
>> > -        for mem in self.if_members:
>> > -            save[mem] = getattr(self, mem)
>> > -        func(self, *args, **kwargs)
>> > -        for mem, val in save.items():
>> > -            newval = getattr(self, mem)
>> > -            if newval != val:
>> > -                assert newval.startswith(val)
>> > -                newval = newval[len(val):]
>> > -                val += gen_if(ifcond)
>> > -                val += newval
>> > -                val += gen_endif(ifcond)
>> > -            setattr(self, mem, val)
>> > -
>> > -    return func_wrapper
>> > +def gen_ifcond(ifcond, ctext):
>> > +    if ifcond:
>> > +        return gen_if(ifcond) + ctext + gen_endif(ifcond)
>> > +    return ctext
>> >  
>> >  
>> >  def gen_enum_lookup(name, values, prefix=None):
>> > 
>> 

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

* Re: [Qemu-devel] [PATCH v2 28/54] qapi: do not define enumeration value explicitely
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 28/54] qapi: do not define enumeration value explicitely Marc-André Lureau
  2017-08-22 14:00   ` Philippe Mathieu-Daudé
@ 2017-09-05 17:45   ` Markus Armbruster
  2017-09-06 12:09     ` Marc-André Lureau
  1 sibling, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-09-05 17:45 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> The C standard has the initial value at 0 and the subsequent values
> incremented by 1. No need to set this explicitely.
>
> This will prevent from artificial "gaps" when compiling out some enum
> values and having unnecessarily large MAX values & enums arrays.

Yes, but it also risks entertaining mishaps like compiling this one

    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.

> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi.py | 7 ++-----
>  1 file changed, 2 insertions(+), 5 deletions(-)
>
> diff --git a/scripts/qapi.py b/scripts/qapi.py
> index 52099332f1..9d075440d3 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi.py
> @@ -1979,14 +1979,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;

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

* Re: [Qemu-devel] [PATCH v2 25/54] qapi-visit: add #if conditions to visitors
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 25/54] qapi-visit: add #if conditions to visitors Marc-André Lureau
@ 2017-09-06 10:54   ` Markus Armbruster
  2017-09-06 14:22     ` Marc-André Lureau
  0 siblings, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-09-06 10:54 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> Wrap generated code with #if/#endif using the ifcond_decorator.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi-visit.py | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
> index c29c2d869e..bb18c9edee 100644
> --- a/scripts/qapi-visit.py
> +++ b/scripts/qapi-visit.py
> @@ -267,6 +267,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
>          self.decl = None
>          self.defn = None
>          self._btin = None
> +        self.if_members = ['decl', 'defn', '_btin']
>  
>      def visit_begin(self, schema):
>          self.decl = ''
> @@ -282,6 +283,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
>          self.decl = self._btin + self.decl
>          self._btin = None
>  
> +    @ifcond_decorator
>      def visit_enum_type(self, name, info, values, prefix, ifcond):
>          # Special case for our lone builtin enum type
>          # TODO use something cleaner than existence of info
> @@ -293,6 +295,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
>              self.decl += gen_visit_decl(name, scalar=True)
>              self.defn += gen_visit_enum(name)
>  
> +    @ifcond_decorator
>      def visit_array_type(self, name, info, element_type, ifcond):
>          decl = gen_visit_decl(name)
>          defn = gen_visit_list(name, element_type)
> @@ -304,6 +307,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
>              self.decl += decl
>              self.defn += defn
>  
> +    @ifcond_decorator
>      def visit_object_type(self, name, info, base, members, variants, ifcond):
>          # Nothing to do for the special empty builtin
>          if name == 'q_empty':
> @@ -317,6 +321,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
>              self.decl += gen_visit_decl(name)
>              self.defn += gen_visit_object(name, base, members, variants)
>  
> +    @ifcond_decorator
>      def visit_alternate_type(self, name, info, variants, ifcond):
>          self.decl += gen_visit_decl(name)
>          self.defn += gen_visit_alternate(name, variants)

make check fails to compile, first error:

make -C ~/work/qemu/bld-x86/ check
make: Entering directory '/work/armbru/qemu/bld-x86'
[...]
  GEN     tests/test-qapi-types.c
  CC      tests/test-qapi-types.o
tests/test-qapi-types.c: In function ‘qapi_free_TestIfAlternate’:
tests/test-qapi-types.c:190:5: warning: implicit declaration of function ‘visit_type_TestIfAlternate’; did you mean ‘visit_type_UserDefAlternate’? [-Wimplicit-function-declaration]
     visit_type_TestIfAlternate(v, NULL, &obj, NULL);
     ^~~~~~~~~~~~~~~~~~~~~~~~~~
     visit_type_UserDefAlternate
tests/test-qapi-types.c:190:5: warning: nested extern declaration of ‘visit_type_TestIfAlternate’ [-Wnested-externs]
tests/test-qapi-types.c: In function ‘qapi_free_TestIfStruct’:
tests/test-qapi-types.c:213:5: warning: implicit declaration of function ‘visit_type_TestIfStruct’; did you mean ‘visit_type_TestStruct’? [-Wimplicit-function-declaration]
     visit_type_TestIfStruct(v, NULL, &obj, NULL);
     ^~~~~~~~~~~~~~~~~~~~~~~
     visit_type_TestStruct
tests/test-qapi-types.c:213:5: warning: nested extern declaration of ‘visit_type_TestIfStruct’ [-Wnested-externs]
tests/test-qapi-types.c: In function ‘qapi_free_TestIfUnion’:
tests/test-qapi-types.c:226:5: warning: implicit declaration of function ‘visit_type_TestIfUnion’; did you mean ‘visit_type_TestStruct’? [-Wimplicit-function-declaration]
     visit_type_TestIfUnion(v, NULL, &obj, NULL);
     ^~~~~~~~~~~~~~~~~~~~~~
     visit_type_TestStruct
tests/test-qapi-types.c:226:5: warning: nested extern declaration of ‘visit_type_TestIfUnion’ [-Wnested-externs]
  GEN     tests/test-qapi-event.c
  CC      tests/test-qapi-event.o
  GEN     tests/test-qmp-introspect.c
  CC      tests/test-qmp-introspect.o
  LINK    tests/test-qobject-output-visitor
tests/test-qapi-types.o: In function `qapi_free_TestIfAlternate':
/work/armbru/qemu/bld-x86/tests/test-qapi-types.c:190: undefined reference to `visit_type_TestIfAlternate'
tests/test-qapi-types.o: In function `qapi_free_TestIfStruct':
test-qapi-types.c:(.text+0x361): undefined reference to `visit_type_TestIfStruct'
tests/test-qapi-types.o: In function `qapi_free_TestIfUnion':
test-qapi-types.c:(.text+0x3af): undefined reference to `visit_type_TestIfUnion'
collect2: error: ld returned 1 exit status
make: *** [/work/armbru/qemu/rules.mak:121: tests/test-qobject-output-visitor] Error 1
make: Leaving directory '/work/armbru/qemu/bld-x86'

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

* Re: [Qemu-devel] [PATCH v2 15/54] qapi: add 'if' to top-level expressions
  2017-09-05 13:58     ` Marc-André Lureau
@ 2017-09-06 11:36       ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-09-06 11:36 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: QEMU, Michael Roth

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

> Hi
>
> On Mon, Sep 4, 2017 at 3:27 PM, 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)' }
>>
>> Lost line break?
>
> yes
>
>>
>>> 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>
[...]
>>> diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
>>> index 3b1e9082d3..7fbaea19bc 100644
>>> --- a/tests/qapi-schema/qapi-schema-test.out
>>> +++ b/tests/qapi-schema/qapi-schema-test.out
>>> @@ -52,6 +52,22 @@ enum QEnumTwo ['value1', 'value2']
>>>      prefix QENUM_TWO
>>>  enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>>>      prefix QTYPE
>>> +alternate TestIfAlternate
>>> +    tag type
>>> +    case foo: int
>>> +    case bar: TestStruct
>>> +command TestIfCmd q_obj_TestIfCmd-arg -> None
>>> +   gen=True success_response=True boxed=False
>>> +enum TestIfEnum ['foo', 'bar']
>>> +event TestIfEvent q_obj_TestIfEvent-arg
>>> +   boxed=False
>>> +object TestIfStruct
>>> +    member foo: int optional=False
>>> +object TestIfUnion
>>> +    member type: TestIfUnionKind optional=False
>>> +    tag type
>>> +    case foo: q_obj_TestStruct-wrapper
>>> +enum TestIfUnionKind ['foo']
>>>  object TestStruct
>>>      member integer: int optional=False
>>>      member boolean: bool optional=False
>>> @@ -172,6 +188,12 @@ object q_obj_EVENT_D-arg
>>>      member b: str optional=False
>>>      member c: str optional=True
>>>      member enum3: EnumOne optional=True
>>> +object q_obj_TestIfCmd-arg
>>> +    member foo: TestIfStruct optional=False
>>> +object q_obj_TestIfEvent-arg
>>> +    member foo: TestIfStruct optional=False
>>> +object q_obj_TestStruct-wrapper
>>> +    member data: TestStruct optional=False
>>>  object q_obj_UserDefFlatUnion2-base
>>>      member integer: int optional=True
>>>      member string: str optional=False
>>
>> The conditionals aren't visible in qapi-schema-test.out.  They should
>> be.
>>
>
> That's a follow-up patch "qapi: add 'ifcond' to visitor methods"

Which I've since found %-}

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

Let's point this out in the commit message.

Remember, your poor, ignorant reviewer squints at your patches through a
toiler paper tube, and may need your help to see the bigger picture.

>> *Much* easier to review than its predecessor PATCH 07/26.  Appreciated!

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

* Re: [Qemu-devel] [PATCH v2 22/54] qapi-introspect: add preprocessor conditions to generated QLit
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 22/54] qapi-introspect: add preprocessor conditions to generated QLit Marc-André Lureau
  2017-09-05 14:24   ` Markus Armbruster
@ 2017-09-06 11:38   ` Markus Armbruster
  2017-09-06 14:26     ` Marc-André Lureau
  1 sibling, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-09-06 11:38 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> Add 'ifcond' condition to QLit objects.
>
> to_qlit() handles the (obj, ifcond) tuples.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

I my testing, the generated code changes like this:

    diff -rup qapi-gen-21-64300535f0/test-qmp-introspect.c qapi-gen-22-050f2a5d9d/test-qmp-introspect.c
    --- qapi-gen-21-64300535f0/test-qmp-introspect.c	2017-09-06 12:02:11.808681800 +0200
    +++ qapi-gen-22-050f2a5d9d/test-qmp-introspect.c	2017-09-06 12:02:19.085578791 +0200
    @@ -51,19 +51,31 @@ const QLitObject test_qmp_schema_qlit =
             { "name", QLIT_QSTR("EVENT_F") },
             {}
         })),
    -    QLIT_QDICT(((QLitDictEntry[]) {
    +    
    +#if defined(TEST_IF_CMD) && defined(TEST_IF_STRUCT)
    +
--> +QLIT_QDICT(((QLitDictEntry[]) {
             { "arg-type", QLIT_QSTR("5") },
             { "meta-type", QLIT_QSTR("command") },
             { "name", QLIT_QSTR("TestIfCmd") },

Indentation's off at the line I marked.

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

* Re: [Qemu-devel] [PATCH v2 27/54] qapi-types: add #if conditions to types
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 27/54] qapi-types: add #if conditions to types Marc-André Lureau
@ 2017-09-06 11:43   ` Markus Armbruster
  2017-09-06 14:56     ` Marc-André Lureau
  0 siblings, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-09-06 11:43 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> Wrap generated code with #if/#endif using the ifcond_decorator.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

In my testing, this generates repeated conditionals, e.g.

    diff -rup qapi-gen-24-dc1833e3fb/test-qapi-types.c qapi-gen-27-9600b4638d/test-qapi-types.c
    --- qapi-gen-24-dc1833e3fb/test-qapi-types.c	2017-09-06 12:02:33.440375590 +0200
    +++ qapi-gen-27-9600b4638d/test-qapi-types.c	2017-09-06 12:55:08.709973386 +0200
    @@ -178,6 +178,12 @@ const QEnumLookup QEnumTwo_lookup = {
         .size = QENUM_TWO__MAX
     };

    +#if defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)
    +
    +
    +#if defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)
    +
    +
     void qapi_free_TestIfAlternate(TestIfAlternate *obj)
     {
         Visitor *v;
    @@ -191,6 +197,15 @@ void qapi_free_TestIfAlternate(TestIfAlt
         visit_free(v);
     }

    +#endif /* defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT) */
    +
    +
    +#endif /* defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT) */
    +
    +

and

    diff -rup qapi-gen-24-dc1833e3fb/test-qapi-types.h qapi-gen-27-9600b4638d/test-qapi-types.h
    --- qapi-gen-24-dc1833e3fb/test-qapi-types.h	2017-09-06 12:02:27.386461287 +0200
    +++ qapi-gen-27-9600b4638d/test-qapi-types.h	2017-09-06 12:55:02.365062236 +0200
    [...]
    @@ -486,6 +498,9 @@ struct NestedEnumsOne {

     void qapi_free_NestedEnumsOne(NestedEnumsOne *obj);

    +#if defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)
    +
    +
     struct TestIfAlternate {
         QType type;
         union { /* union tag is @type */
    @@ -494,18 +509,42 @@ struct TestIfAlternate {
         } u;
     };

    +#if defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)
    +
    +
     void qapi_free_TestIfAlternate(TestIfAlternate *obj);

    +#endif /* defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT) */
    +
    +
    +#endif /* defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT) */
    +
    +

Let's ignore this until we've made up our mind *how* to best generate
conditionals.

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

* Re: [Qemu-devel] [PATCH v2 28/54] qapi: do not define enumeration value explicitely
  2017-09-05 17:45   ` Markus Armbruster
@ 2017-09-06 12:09     ` Marc-André Lureau
  2017-09-06 13:39       ` Markus Armbruster
  0 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-09-06 12:09 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth



----- Original Message -----
> 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.
> 
> Yes, but it also risks entertaining mishaps like compiling this one
> 
>     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 is also true with other kind of types, like struct.

One of the main reason why we should have schemas for target-only and the NEED_CPU_H is a temporary working hack.

> 
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >  scripts/qapi.py | 7 ++-----
> >  1 file changed, 2 insertions(+), 5 deletions(-)
> >
> > diff --git a/scripts/qapi.py b/scripts/qapi.py
> > index 52099332f1..9d075440d3 100644
> > --- a/scripts/qapi.py
> > +++ b/scripts/qapi.py
> > @@ -1979,14 +1979,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;
> 

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

* Re: [Qemu-devel] [PATCH v2 29/54] qapi: add 'if' to enum members
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 29/54] qapi: add 'if' to enum members Marc-André Lureau
@ 2017-09-06 13:01   ` Markus Armbruster
  2017-09-07 14:11     ` Markus Armbruster
  0 siblings, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-09-06 13:01 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi.py                         | 33 +++++++++++++++++++++++++++------
>  tests/qapi-schema/enum-dict-member.err  |  1 -
>  tests/qapi-schema/enum-dict-member.exit |  2 +-
>  tests/qapi-schema/enum-dict-member.json |  3 +--
>  tests/qapi-schema/enum-dict-member.out  |  4 ++++
>  tests/qapi-schema/qapi-schema-test.json |  5 +++--
>  tests/qapi-schema/qapi-schema-test.out  |  3 ++-
>  tests/qapi-schema/test-qapi.py          |  4 +++-
>  8 files changed, 41 insertions(+), 14 deletions(-)
>
> diff --git a/scripts/qapi.py b/scripts/qapi.py
> index 9d075440d3..9c7c01c11d 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi.py
> @@ -729,6 +729,10 @@ def check_event(expr, info):
>                 allow_metas=meta)
>  
>  
> +def enum_get_values(expr):
> +    return [e if isinstance(e, str) else e['name'] for e in expr['data']]
> +
> +

An iterator would be more efficient, but this will do.

>  def check_union(expr, info):
>      name = expr['union']
>      base = expr.get('base')
> @@ -788,7 +792,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_values(enum_define):
>                  raise QAPISemError(info,
>                                     "Discriminator value '%s' is not found in "
>                                     "enum '%s'"
> @@ -796,7 +800,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_values(enum_define):
>              if value not in members.keys():
>                  raise QAPISemError(info, "Union '%s' data missing '%s' branch"
>                                     % (name, value))
> @@ -827,7 +831,7 @@ def check_alternate(expr, info):
>          if qtype == 'QTYPE_QSTRING':
>              enum_expr = enum_types.get(value)
>              if enum_expr:
> -                for v in enum_expr['data']:
> +                for v in enum_get_values(enum_expr):
>                      if v in ['on', 'off']:
>                          conflicting.add('QTYPE_QBOOL')
>                      if re.match(r'[-+0-9.]', v): # lazy, could be tightened
> @@ -857,6 +861,12 @@ def check_enum(expr, info):
>          raise QAPISemError(info,
>                             "Enum '%s' requires a string for 'prefix'" % name)
>      for member in members:
> +        if isinstance(member, dict):
> +            if not 'name' in member:
> +                raise QAPISemError(info, "Dictionary member of enum '%s' must "
> +                                   "have a 'name' key" % name)
> +            check_if(member, info)
> +            member = member['name']
>          check_name(info, "Member of enum '%s'" % name, member,
>                     enum_member=True)
>  

Looks like you got all uses of enum's 'data' in the old semantic
checker.

Aside: work like this is why I dislike how the old semantic checker
works directly on the parse trees represented as OrderedDict.
Everything is a dictionary, and almost everything's key is 'data'.

> @@ -1145,12 +1155,15 @@ class QAPISchemaEnumType(QAPISchemaType):
>      def member_names(self):
>          return [v.name for v in self.values]
>  
> +    def members(self):
> +        return [(v.name, v.ifcond) for v in self.values]
> +
>      def json_type(self):
>          return 'string'
>  
>      def visit(self, visitor):
>          visitor.visit_enum_type(self.name, self.info,
> -                                self.member_names(), self.prefix, self.ifcond)
> +                                self.members(), self.prefix, self.ifcond)
>  
>  

This is the only use of .members().  Should it be ._members()?

You're changing the signature of QAPISchemaVisitor.visit_enum_type():
its @values parameter now takes a list of pairs of str instead of a list
of str.  Easy to miss in review; a heads-up in the commit message is
appreaciated in such cases.

The change affects the classes that implement visit_enum_type():

* QAPISchemaGenIntrospectVisitor

  Doesn't examine @values itself, passes it on to self._gen_qlit().
  PATCH 21 prepared it for this change of input.  Okay.

* QAPISchemaGenTypeVisitor

  Doesn't examine @values itself, passes it on to gen_enum() and
  gen_enum_lookup().  They get updated for this change below.  Okay.

* QAPISchemaGenVisitVisitor

  Doesn't use @values at all.  Okay.

* QAPISchemaGenDocVisitor

  Doesn't use @values at all.  Kind of surprising, until you realize
  that the code gets the members from the doc string instead.  Okay.

I can figure out stuff like that only because you got your patches split
up nicely in v2.  Appreciated!  On the other hand, I need to figure out
stuff like that the hard way because your commit messages don't mention
them.  Without a hint from you, a casual reviewer may miss that the
change of the visitor.visit_enum_type() call above is an interface
change, with non-local impact.  This reviewer will (on a good day) go
"WTF?!?", and reach for the extra-fine comb.

Explaining WTF-triggers proactively can speed up review significantly.
Eric's pretty good at it.

>  class QAPISchemaArrayType(QAPISchemaType):
> @@ -1274,9 +1287,11 @@ class QAPISchemaObjectType(QAPISchemaType):
>  class QAPISchemaMember(object):
>      role = 'member'
>  
> -    def __init__(self, name):
> +    def __init__(self, name, ifcond=None):
>          assert isinstance(name, str)
> +        assert ifcond is None or isinstance(ifcond, str)
>          self.name = name
> +        self.ifcond = ifcond
>          self.owner = None
>  
>      def set_owner(self, name):
> @@ -1554,7 +1569,9 @@ class QAPISchema(object):
>                                              qtype_values, 'QTYPE'))
>  
>      def _make_enum_members(self, values):
> -        return [QAPISchemaMember(v) for v in values]
> +        return [QAPISchemaMember(v['name'], v.get('if')) if isinstance(v, dict)
> +                else QAPISchemaMember(v)
> +                for v in values]

I'm afraid this list comprehension has become incomprehensible :)

Perhaps something like that would do:

    def _make_enum_member(self, value):
        if isinstance(value, 'str'):
            value = { 'name': value }
        return QAPISchemaMember(name, value['name'], value.get('if')

    def _make_enum_members(self, values):
        return [self._make_enum_members(v) for v in values]

Makes the desugaring blatantly obvious.

>  
>      def _make_implicit_enum_type(self, name, info, values, ifcond):
>          # See also QAPISchemaObjectTypeMember._pretty_owner()
> @@ -1950,6 +1967,8 @@ static const char *const %(c_name)s_array[] = {

This is gen_enum_lookup().

>  ''',
>                  c_name=c_name(name))
>      for value in values:
> +        if isinstance(value, tuple):
> +            value, ifcond = value

Any future use of ifcond outside isinstance(value, tuple) won't work.
Are you missing else: ifcond = None?

>          index = c_enum_const(name, value, prefix)
>          ret += mcgen('''
>      [%(index)s] = "%(value)s",
> @@ -1980,6 +1999,8 @@ typedef enum %(c_name)s {

This is gen_enum().

>                  c_name=c_name(name))
>  
>      for value in enum_values:
> +        if isinstance(value, tuple):
> +            value, ifcond = value

Same question.

>          ret += mcgen('''
>      %(c_enum)s,
>  ''',
> diff --git a/tests/qapi-schema/enum-dict-member.err b/tests/qapi-schema/enum-dict-member.err
> index 8ca146ea59..e69de29bb2 100644
> --- a/tests/qapi-schema/enum-dict-member.err
> +++ b/tests/qapi-schema/enum-dict-member.err
> @@ -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.exit b/tests/qapi-schema/enum-dict-member.exit
> index d00491fd7e..573541ac97 100644
> --- a/tests/qapi-schema/enum-dict-member.exit
> +++ b/tests/qapi-schema/enum-dict-member.exit
> @@ -1 +1 @@
> -1
> +0
> diff --git a/tests/qapi-schema/enum-dict-member.json b/tests/qapi-schema/enum-dict-member.json
> index 79672e0f09..b09a83061c 100644
> --- a/tests/qapi-schema/enum-dict-member.json
> +++ b/tests/qapi-schema/enum-dict-member.json
> @@ -1,2 +1 @@
> -# we reject any enum member that is not a string
> -{ 'enum': 'MyEnum', 'data': [ { 'value': 'str' } ] }
> +{ 'enum': 'TestEnum', 'data': [ { 'name': 'foo' }, { 'name': 'bar' } ]}

This negative test needs to be replaced.

Positive tests should generally go into qapi-schema-test.json, because
there their generated code gets fed to the compiler.  Peeking ahead a
bit, I can see you add a suitable positive test there.

Looks like you got replacements in PATCH 31.  I haven't looked at PATCH
31, so I can't yet say whether the replacements provide sufficient
coverage.

You can probably drop enum-dict-member.json, and squash PATCH 31 into
this one.

> diff --git a/tests/qapi-schema/enum-dict-member.out b/tests/qapi-schema/enum-dict-member.out
> index e69de29bb2..cf8e3cce2b 100644
> --- a/tests/qapi-schema/enum-dict-member.out
> +++ b/tests/qapi-schema/enum-dict-member.out
> @@ -0,0 +1,4 @@
> +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
> +    prefix QTYPE
> +enum TestEnum ['foo', 'bar']
> +object q_empty
> diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
> index dc2c444fc1..ad2b405d83 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 fc5fd25f1b..211c367632 100644
> --- a/tests/qapi-schema/qapi-schema-test.out
> +++ b/tests/qapi-schema/qapi-schema-test.out
> @@ -60,7 +60,7 @@ alternate TestIfAlternate
>  command TestIfCmd q_obj_TestIfCmd-arg -> None
>     gen=True success_response=True boxed=False
>      if defined(TEST_IF_CMD) && defined(TEST_IF_STRUCT)
> -enum TestIfEnum ['foo', 'bar']
> +enum TestIfEnum ['foo', ('bar', 'defined(TEST_IF_ENUM_BAR)')]

I've had a nagging bad feeling about this tuple business, and I just
realized why: *everything* else in QAPISchema is a proper object.  The
whole *purpose* of QAPISchema is to have objects rather than parse trees
represented as dictionaries and lists.

In the original design of QAPISchema, enum members had just one
property: their name.  Thus, I chose to represent them by their name.
That was a mistake.  You're adding a second property: ifcond (you're
going to add it to other kinds of members, too).  It's time to correct
my design mistake and make enum members objects.

You change QAPISchemaEnumType.values from list of str to list of (str or
pair of str).  It needs to change to list of QAPISchemaMember instead.

If we ever need to add more properties to enum members, we'll have nice
objects we can extend, just like for members of other types.

>      if defined(TEST_IF_ENUM)
>  event TestIfEvent q_obj_TestIfEvent-arg
>     boxed=False
> @@ -197,6 +197,7 @@ object q_obj_EVENT_D-arg
>      member enum3: EnumOne optional=True
>  object q_obj_TestIfCmd-arg
>      member foo: TestIfStruct optional=False
> +    member bar: TestIfEnum optional=False
>      if defined(TEST_IF_CMD) && defined(TEST_IF_STRUCT)
>  object q_obj_TestIfEvent-arg
>      member foo: TestIfStruct optional=False
> diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
> index 17fd975812..70054848f0 100644
> --- a/tests/qapi-schema/test-qapi.py
> +++ b/tests/qapi-schema/test-qapi.py
> @@ -18,7 +18,9 @@ import sys
>  
>  class QAPISchemaTestVisitor(QAPISchemaVisitor):
>      def visit_enum_type(self, name, info, values, prefix, ifcond):
> -        print 'enum %s %s' % (name, values)
> +        values = ', '.join(["'%s'" % v[0] if not v[1] else str(v)
> +                            for v in values])
> +        print 'enum %s [%s]' % (name, values)

Since members of enums are QAPISchemaMember, let's print them just like
we print QAPISchemaMember elsewhere.  Should look roughly like this:

enum TestIfEnum
    member foo:
    member bar: if=defined(TEST_IF_ENUM_BAR)
    if defined(TEST_IF_ENUM)

>          if prefix:
>              print '    prefix %s' % prefix
>          self._print_if(ifcond)

In my testing, the generated code's indentation is off in places,
similar to what I observed for PATCH 22:

   diff -rup qapi-gen-28-da2a3fdd1d/test-qmp-introspect.c qapi-gen-29-e4c1659ff2/test-qmp-introspect.c
   --- qapi-gen-28-da2a3fdd1d/test-qmp-introspect.c	2017-09-06 12:55:17.502850257 +0200
   +++ qapi-gen-29-e4c1659ff2/test-qmp-introspect.c	2017-09-06 12:55:25.979731553 +0200
   [...]
    @@ -678,19 +683,41 @@ QLIT_QDICT(((QLitDictEntry[]) {
     #endif /* defined(TEST_IF_STRUCT) */


    -    QLIT_QDICT(((QLitDictEntry[]) {
    +    
    +#if defined(TEST_IF_ENUM)
    +
    +QLIT_QDICT(((QLitDictEntry[]) {
             { "meta-type", QLIT_QSTR("enum") },
             { "name", QLIT_QSTR("22") },
             { "values", QLIT_QLIST(((QLitObject[]) {
    +            QLIT_QSTR("foo"),
    +            
    +#if defined(TEST_IF_ENUM_BAR)
    +
--> +QLIT_QSTR("bar"),
    +#endif /* defined(TEST_IF_ENUM_BAR) */
    +
    +
    +            {}
    +        })) },
    +        {}
    +    })),
    +#endif /* defined(TEST_IF_ENUM) */
    +
    +
    +    QLIT_QDICT(((QLitDictEntry[]) {
    +        { "meta-type", QLIT_QSTR("enum") },
    +        { "name", QLIT_QSTR("23") },
    +        { "values", QLIT_QLIST(((QLitObject[]) {
                 QLIT_QSTR("__org.qemu_x-value"),
                 {}
             })) },
             {}

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

* Re: [Qemu-devel] [PATCH v2 28/54] qapi: do not define enumeration value explicitely
  2017-09-06 12:09     ` Marc-André Lureau
@ 2017-09-06 13:39       ` Markus Armbruster
  2017-09-06 13:55         ` Marc-André Lureau
  0 siblings, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-09-06 13:39 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> ----- Original Message -----
>> 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.
>> 
>> Yes, but it also risks entertaining mishaps like compiling this one
>> 
>>     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 is also true with other kind of types, like struct.
>
> One of the main reason why we should have schemas for target-only and the NEED_CPU_H is a temporary working hack.

A temporary hack that's ugly or occasionally breaks in an obvious way is
okay, but this is an open deathtrap.  I'm afraid we need to rethink our
short term conditional code generation strategy.

Stupidest solution that could possibly work: apply conditionals *only*
to qmp-introspect.c, leave everything unconditional elsewhere.  What do
you think?

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

* Re: [Qemu-devel] [PATCH v2 28/54] qapi: do not define enumeration value explicitely
  2017-09-06 13:39       ` Markus Armbruster
@ 2017-09-06 13:55         ` Marc-André Lureau
  2017-09-06 15:20           ` Markus Armbruster
  0 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-09-06 13:55 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth

Hi

----- Original Message -----
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> 
> > ----- Original Message -----
> >> 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.
> >> 
> >> Yes, but it also risks entertaining mishaps like compiling this one
> >> 
> >>     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 is also true with other kind of types, like struct.
> >
> > One of the main reason why we should have schemas for target-only and the
> > NEED_CPU_H is a temporary working hack.
> 
> A temporary hack that's ugly or occasionally breaks in an obvious way is
> okay, but this is an open deathtrap.  I'm afraid we need to rethink our
> short term conditional code generation strategy.
> 
> Stupidest solution that could possibly work: apply conditionals *only*
> to qmp-introspect.c, leave everything unconditional elsewhere.  What do
> you think?

That's not what I had in mind when I started. My first 45 loc approach would have saved us a lot of troubles :)

I would rather fix this, and split the schema. I'll investigate.

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

* Re: [Qemu-devel] [PATCH v2 20/54] qapi-introspect: modify to_qlit() to take an optional suffix
  2017-09-05  9:42   ` Markus Armbruster
@ 2017-09-06 14:02     ` Marc-André Lureau
  0 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-09-06 14:02 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: QEMU, Michael Roth

On Tue, Sep 5, 2017 at 11:42 AM, Markus Armbruster <armbru@redhat.com> wrote:
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
>> 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>
>> ---
>>  scripts/qapi-introspect.py | 8 ++++----
>>  1 file changed, 4 insertions(+), 4 deletions(-)
>>
>> diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
>> index 4c437d60ec..dfb6d2ded4 100644
>> --- a/scripts/qapi-introspect.py
>> +++ b/scripts/qapi-introspect.py
>> @@ -16,7 +16,7 @@ def to_c_string(s):
>>      return '"' + s.replace('\\', r'\\').replace('"', r'\"') + '"'
>>
>>
>> -def to_qlit(obj, level=0, first_indent=True):
>> +def to_qlit(obj, level=0, first_indent=True, suffix=''):
>>
>>      def indent(level):
>>          return level * 4 * ' '
>> @@ -29,11 +29,11 @@ def to_qlit(obj, level=0, first_indent=True):
>>      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, suffix=',')
>>                  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 = []
>> @@ -46,7 +46,7 @@ def to_qlit(obj, level=0, first_indent=True):
>>          ret += indent(level) + '}))'
>>      else:
>>          assert False                # not implemented
>> -    return ret
>> +    return ret + suffix
>>
>>
>>  class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor):
>
> Hmm.  I wonder the appended simpler patch would do.

It works, thanks for the suggestion

>
> diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
> index 4c437d60ec..73edb55cd5 100644
> --- a/scripts/qapi-introspect.py
> +++ b/scripts/qapi-introspect.py
> @@ -33,7 +33,7 @@ def to_qlit(obj, level=0, first_indent=True):
>                  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 = []
> @@ -46,6 +46,8 @@ def to_qlit(obj, level=0, first_indent=True):
>          ret += indent(level) + '}))'
>      else:
>          assert False                # not implemented
> +    if level > 0:
> +        ret += ','
>      return ret
>
>
>



-- 
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH v2 25/54] qapi-visit: add #if conditions to visitors
  2017-09-06 10:54   ` Markus Armbruster
@ 2017-09-06 14:22     ` Marc-André Lureau
  0 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-09-06 14:22 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth



----- Original Message -----
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> 
> > Wrap generated code with #if/#endif using the ifcond_decorator.
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >  scripts/qapi-visit.py | 5 +++++
> >  1 file changed, 5 insertions(+)
> >
> > diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
> > index c29c2d869e..bb18c9edee 100644
> > --- a/scripts/qapi-visit.py
> > +++ b/scripts/qapi-visit.py
> > @@ -267,6 +267,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
> >          self.decl = None
> >          self.defn = None
> >          self._btin = None
> > +        self.if_members = ['decl', 'defn', '_btin']
> >  
> >      def visit_begin(self, schema):
> >          self.decl = ''
> > @@ -282,6 +283,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
> >          self.decl = self._btin + self.decl
> >          self._btin = None
> >  
> > +    @ifcond_decorator
> >      def visit_enum_type(self, name, info, values, prefix, ifcond):
> >          # Special case for our lone builtin enum type
> >          # TODO use something cleaner than existence of info
> > @@ -293,6 +295,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
> >              self.decl += gen_visit_decl(name, scalar=True)
> >              self.defn += gen_visit_enum(name)
> >  
> > +    @ifcond_decorator
> >      def visit_array_type(self, name, info, element_type, ifcond):
> >          decl = gen_visit_decl(name)
> >          defn = gen_visit_list(name, element_type)
> > @@ -304,6 +307,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
> >              self.decl += decl
> >              self.defn += defn
> >  
> > +    @ifcond_decorator
> >      def visit_object_type(self, name, info, base, members, variants,
> >      ifcond):
> >          # Nothing to do for the special empty builtin
> >          if name == 'q_empty':
> > @@ -317,6 +321,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
> >              self.decl += gen_visit_decl(name)
> >              self.defn += gen_visit_object(name, base, members, variants)
> >  
> > +    @ifcond_decorator
> >      def visit_alternate_type(self, name, info, variants, ifcond):
> >          self.decl += gen_visit_decl(name)
> >          self.defn += gen_visit_alternate(name, variants)
> 
> make check fails to compile, first error:
> 

I'll merge back qapi-types & qapi-visited #if addition (regression from the split). 

> make -C ~/work/qemu/bld-x86/ check
> make: Entering directory '/work/armbru/qemu/bld-x86'
> [...]
>   GEN     tests/test-qapi-types.c
>   CC      tests/test-qapi-types.o
> tests/test-qapi-types.c: In function ‘qapi_free_TestIfAlternate’:
> tests/test-qapi-types.c:190:5: warning: implicit declaration of function
> ‘visit_type_TestIfAlternate’; did you mean ‘visit_type_UserDefAlternate’?
> [-Wimplicit-function-declaration]
>      visit_type_TestIfAlternate(v, NULL, &obj, NULL);
>      ^~~~~~~~~~~~~~~~~~~~~~~~~~
>      visit_type_UserDefAlternate
> tests/test-qapi-types.c:190:5: warning: nested extern declaration of
> ‘visit_type_TestIfAlternate’ [-Wnested-externs]
> tests/test-qapi-types.c: In function ‘qapi_free_TestIfStruct’:
> tests/test-qapi-types.c:213:5: warning: implicit declaration of function
> ‘visit_type_TestIfStruct’; did you mean ‘visit_type_TestStruct’?
> [-Wimplicit-function-declaration]
>      visit_type_TestIfStruct(v, NULL, &obj, NULL);
>      ^~~~~~~~~~~~~~~~~~~~~~~
>      visit_type_TestStruct
> tests/test-qapi-types.c:213:5: warning: nested extern declaration of
> ‘visit_type_TestIfStruct’ [-Wnested-externs]
> tests/test-qapi-types.c: In function ‘qapi_free_TestIfUnion’:
> tests/test-qapi-types.c:226:5: warning: implicit declaration of function
> ‘visit_type_TestIfUnion’; did you mean ‘visit_type_TestStruct’?
> [-Wimplicit-function-declaration]
>      visit_type_TestIfUnion(v, NULL, &obj, NULL);
>      ^~~~~~~~~~~~~~~~~~~~~~
>      visit_type_TestStruct
> tests/test-qapi-types.c:226:5: warning: nested extern declaration of
> ‘visit_type_TestIfUnion’ [-Wnested-externs]
>   GEN     tests/test-qapi-event.c
>   CC      tests/test-qapi-event.o
>   GEN     tests/test-qmp-introspect.c
>   CC      tests/test-qmp-introspect.o
>   LINK    tests/test-qobject-output-visitor
> tests/test-qapi-types.o: In function `qapi_free_TestIfAlternate':
> /work/armbru/qemu/bld-x86/tests/test-qapi-types.c:190: undefined reference to
> `visit_type_TestIfAlternate'
> tests/test-qapi-types.o: In function `qapi_free_TestIfStruct':
> test-qapi-types.c:(.text+0x361): undefined reference to
> `visit_type_TestIfStruct'
> tests/test-qapi-types.o: In function `qapi_free_TestIfUnion':
> test-qapi-types.c:(.text+0x3af): undefined reference to
> `visit_type_TestIfUnion'
> collect2: error: ld returned 1 exit status
> make: *** [/work/armbru/qemu/rules.mak:121:
> tests/test-qobject-output-visitor] Error 1
> make: Leaving directory '/work/armbru/qemu/bld-x86'
> 

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

* Re: [Qemu-devel] [PATCH v2 22/54] qapi-introspect: add preprocessor conditions to generated QLit
  2017-09-06 11:38   ` Markus Armbruster
@ 2017-09-06 14:26     ` Marc-André Lureau
  0 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-09-06 14:26 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth



----- Original Message -----
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> 
> > Add 'ifcond' condition to QLit objects.
> >
> > to_qlit() handles the (obj, ifcond) tuples.
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> 
> I my testing, the generated code changes like this:
> 
>     diff -rup qapi-gen-21-64300535f0/test-qmp-introspect.c
>     qapi-gen-22-050f2a5d9d/test-qmp-introspect.c
>     --- qapi-gen-21-64300535f0/test-qmp-introspect.c	2017-09-06
>     12:02:11.808681800 +0200
>     +++ qapi-gen-22-050f2a5d9d/test-qmp-introspect.c	2017-09-06
>     12:02:19.085578791 +0200
>     @@ -51,19 +51,31 @@ const QLitObject test_qmp_schema_qlit =
>              { "name", QLIT_QSTR("EVENT_F") },
>              {}
>          })),
>     -    QLIT_QDICT(((QLitDictEntry[]) {
>     +
>     +#if defined(TEST_IF_CMD) && defined(TEST_IF_STRUCT)
>     +
> --> +QLIT_QDICT(((QLitDictEntry[]) {
>              { "arg-type", QLIT_QSTR("5") },
>              { "meta-type", QLIT_QSTR("command") },
>              { "name", QLIT_QSTR("TestIfCmd") },
> 
> Indentation's off at the line I marked.
> 

fixed, thanks

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

* Re: [Qemu-devel] [PATCH v2 27/54] qapi-types: add #if conditions to types
  2017-09-06 11:43   ` Markus Armbruster
@ 2017-09-06 14:56     ` Marc-André Lureau
  0 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-09-06 14:56 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: QEMU, Michael Roth

Hi

On Wed, Sep 6, 2017 at 1:43 PM, Markus Armbruster <armbru@redhat.com> wrote:
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
>> Wrap generated code with #if/#endif using the ifcond_decorator.
>>
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> In my testing, this generates repeated conditionals, e.g.
>
>     diff -rup qapi-gen-24-dc1833e3fb/test-qapi-types.c qapi-gen-27-9600b4638d/test-qapi-types.c
>     --- qapi-gen-24-dc1833e3fb/test-qapi-types.c        2017-09-06 12:02:33.440375590 +0200
>     +++ qapi-gen-27-9600b4638d/test-qapi-types.c        2017-09-06 12:55:08.709973386 +0200
>     @@ -178,6 +178,12 @@ const QEnumLookup QEnumTwo_lookup = {
>          .size = QENUM_TWO__MAX
>      };
>
>     +#if defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)
>     +
>     +
>     +#if defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)
>     +
>     +
>      void qapi_free_TestIfAlternate(TestIfAlternate *obj)
>      {
>          Visitor *v;
>     @@ -191,6 +197,15 @@ void qapi_free_TestIfAlternate(TestIfAlt
>          visit_free(v);
>      }
>
>     +#endif /* defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT) */
>     +
>     +
>     +#endif /* defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT) */
>     +
>     +
>
> and
>
>     diff -rup qapi-gen-24-dc1833e3fb/test-qapi-types.h qapi-gen-27-9600b4638d/test-qapi-types.h
>     --- qapi-gen-24-dc1833e3fb/test-qapi-types.h        2017-09-06 12:02:27.386461287 +0200
>     +++ qapi-gen-27-9600b4638d/test-qapi-types.h        2017-09-06 12:55:02.365062236 +0200
>     [...]
>     @@ -486,6 +498,9 @@ struct NestedEnumsOne {
>
>      void qapi_free_NestedEnumsOne(NestedEnumsOne *obj);
>
>     +#if defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)
>     +
>     +
>      struct TestIfAlternate {
>          QType type;
>          union { /* union tag is @type */
>     @@ -494,18 +509,42 @@ struct TestIfAlternate {
>          } u;
>      };
>
>     +#if defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)
>     +
>     +
>      void qapi_free_TestIfAlternate(TestIfAlternate *obj);
>
>     +#endif /* defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT) */
>     +
>     +
>     +#endif /* defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT) */
>     +
>     +
>
> Let's ignore this until we've made up our mind *how* to best generate
> conditionals.
>

Fixed, that was being extra cautious :)



-- 
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH v2 19/54] qapi: add #if/#endif helpers
  2017-09-05  9:32   ` Markus Armbruster
@ 2017-09-06 15:19     ` Marc-André Lureau
  0 siblings, 0 replies; 140+ messages in thread
From: Marc-André Lureau @ 2017-09-06 15:19 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: QEMU, Michael Roth

On Tue, Sep 5, 2017 at 11:32 AM, Markus Armbruster <armbru@redhat.com> wrote:
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
>> Add helpers to generate #if/#endif and wrap visitor methods generating
>> code. Used in the following patches.
>>
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> ---
>>  scripts/qapi.py | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 51 insertions(+)
>>
>> diff --git a/scripts/qapi.py b/scripts/qapi.py
>> index 86845a28f9..52099332f1 100644
>> --- a/scripts/qapi.py
>> +++ b/scripts/qapi.py
>> @@ -1892,6 +1892,57 @@ def guardend(name):
>>                   name=guardname(name))
>>
>>
>> +def gen_if(ifcond):
>> +    if not ifcond:
>> +        return ''
>> +    if isinstance(ifcond, str):
>> +        ifcond = [ifcond]
>> +    # Not using mcgen() because we don't want indent or \n stipped
>
> s/stipped/stripped/ I guess.
>
> Which newline exactly don't you want to strip?

My first attempt at using mcgen() was a fail.

>
> Here's what mcgen() currently does:
>
> * Strip one leading newline, so that this works:
>
>       mcgen('''
>   line 1
>   line 2
>   ''')
>
> * Interpolate keywords
>
> * Indent by @indent_level spaces
>
> * Strip @eatspace.
>

So we don't need much from mcgen(), especailly, we don't want indent
on preprocessor lines. I have added a patch to fix that. And now, I
switch to mcgen() for more consistency.

>> +    ret = '\n'
>> +    for ifc in ifcond:
>> +        ret += '#if %s\n' % ifc
>> +    ret += '\n'
>> +    return ret
>> +
>> +
>> +def gen_endif(ifcond):
>> +    if not ifcond:
>> +        return ''
>> +    if isinstance(ifcond, str):
>> +        ifcond = [ifcond]
>> +    # Not using mcgen() because we don't want indent or \n stipped
>
> Likewise.
>
>> +    ret = '\n'
>> +    for ifc in reversed(ifcond):
>> +        ret += '#endif /* %s */\n' % ifc
>> +    ret += '\n'
>> +    return ret
>
> I guess factoring out the common parts of gen_if() and gen_endif() would
> make the code longer and more complex.
>
>> +
>> +
>> +# Wrap a method to add #if / #endif to generated code, only if some
>> +# code was generated.
>> +# self must have 'if_members' listing the attributes to wrap.
>> +# The last argument of the wrapped function must be the 'ifcond'.
>> +def ifcond_decorator(func):
>> +
>> +    def func_wrapper(self, *args, **kwargs):
>> +        ifcond = args[-1]
>> +        save = {}
>> +        for mem in self.if_members:
>> +            save[mem] = getattr(self, mem)
>> +        func(self, *args, **kwargs)
>> +        for mem, val in save.items():
>> +            newval = getattr(self, mem)
>> +            if newval != val:
>> +                assert newval.startswith(val)
>> +                newval = newval[len(val):]
>> +                val += gen_if(ifcond)
>> +                val += newval
>> +                val += gen_endif(ifcond)
>> +            setattr(self, mem, val)
>> +
>> +    return func_wrapper
>> +
>> +
>>  def gen_enum_lookup(name, values, prefix=None):
>>      ret = mcgen('''
>
> My gut feeling is "too clever by half", but i'm reserving judgement
> until after review of its use.
>

Well easy to change later on too, I'd not focus on this for now.

-- 
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH v2 28/54] qapi: do not define enumeration value explicitely
  2017-09-06 13:55         ` Marc-André Lureau
@ 2017-09-06 15:20           ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-09-06 15:20 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> Hi
>
> ----- Original Message -----
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>> 
>> > ----- Original Message -----
>> >> 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.
>> >> 
>> >> Yes, but it also risks entertaining mishaps like compiling this one
>> >> 
>> >>     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 is also true with other kind of types, like struct.
>> >
>> > One of the main reason why we should have schemas for target-only and the
>> > NEED_CPU_H is a temporary working hack.
>> 
>> A temporary hack that's ugly or occasionally breaks in an obvious way is
>> okay, but this is an open deathtrap.  I'm afraid we need to rethink our
>> short term conditional code generation strategy.
>> 
>> Stupidest solution that could possibly work: apply conditionals *only*
>> to qmp-introspect.c, leave everything unconditional elsewhere.  What do
>> you think?
>
> That's not what I had in mind when I started. My first 45 loc approach would have saved us a lot of troubles :)
>
> I would rather fix this, and split the schema. I'll investigate.

Beware of prerequisites escalating into "boil the ocean".

Don't get me wrong, I *want* the qapi monolith broken up.  I also think
applying conditionals everywhere would be neat, and save us quite a few
silly stubs.  But we need to identify intermedeate steps that are in
reasonably easy reach.

Applying conditionals just to qmp-introspect.c could be such a step.  It
solves the "can't introspect whether compile-time conditional stuff is
available" problem.  It may not be the simplest solution for that
problem, but it should be a stepping stone towards solving other
problems.

On breaking up the monolith, just to avoid misunderstandings: I don't
think we should split the schema into several independent schemas.
Instead, we should have the QAPI generators generate split output.

An obvious and stupid split is one set of files per .json, where the
headers include each other exactly like the .json do.  By itself not
enough to solve the poisoned symbol problem.  Could become enough if we
manage to move target-dependent stuff to separate .json.

We might need a smarter split.

Running a full generator once per generated file has always been stupid
and slow, and the more files we generate, the stupider and slower it'll
become.  There's no reason a single generator run can't generate all the
files.  Requires a bit of Make wizardry, though.

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

* Re: [Qemu-devel] [PATCH v2 30/54] qapi: add #if conditions on generated enum values
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 30/54] qapi: add #if conditions on generated enum values Marc-André Lureau
@ 2017-09-06 15:38   ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-09-06 15:38 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi.py | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/scripts/qapi.py b/scripts/qapi.py
> index 9c7c01c11d..201e425842 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi.py
> @@ -1967,13 +1967,16 @@ static const char *const %(c_name)s_array[] = {
>  ''',
>                  c_name=c_name(name))
>      for value in values:
> +        ifcond = None

I hoped I would see this line in a later patch when I asked for it in my
review of the previous patch :)

>          if isinstance(value, tuple):
>              value, ifcond = value
> +        ret += gen_if(ifcond)
>          index = c_enum_const(name, value, prefix)
>          ret += mcgen('''
>      [%(index)s] = "%(value)s",
>  ''',
>                       index=index, value=value)
> +        ret += gen_endif(ifcond)
>  
>      max_index = c_enum_const(name, '_MAX', prefix)
>      ret += mcgen('''
> @@ -1999,12 +2002,15 @@ typedef enum %(c_name)s {
>                  c_name=c_name(name))
>  
>      for value in enum_values:
> +        ifcond = None
>          if isinstance(value, tuple):
>              value, ifcond = value
> +        ret += gen_if(ifcond)
>          ret += mcgen('''
>      %(c_enum)s,
>  ''',
>                       c_enum=c_enum_const(name, value, prefix))
> +        ret += gen_endif(ifcond)
>  
>      ret += mcgen('''
>  } %(c_name)s;

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

* Re: [Qemu-devel] [PATCH v2 31/54] tests: add some enum members tests
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 31/54] tests: add some enum members tests Marc-André Lureau
@ 2017-09-06 15:41   ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-09-06 15:41 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

I'll revisit negative tests once the error conditions have stabilized.

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

* Re: [Qemu-devel] [PATCH v2 29/54] qapi: add 'if' to enum members
  2017-09-06 13:01   ` Markus Armbruster
@ 2017-09-07 14:11     ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-09-07 14:11 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

One more thing...

Markus Armbruster <armbru@redhat.com> writes:

> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> ---
>>  scripts/qapi.py                         | 33 +++++++++++++++++++++++++++------
>>  tests/qapi-schema/enum-dict-member.err  |  1 -
>>  tests/qapi-schema/enum-dict-member.exit |  2 +-
>>  tests/qapi-schema/enum-dict-member.json |  3 +--
>>  tests/qapi-schema/enum-dict-member.out  |  4 ++++
>>  tests/qapi-schema/qapi-schema-test.json |  5 +++--
>>  tests/qapi-schema/qapi-schema-test.out  |  3 ++-
>>  tests/qapi-schema/test-qapi.py          |  4 +++-
>>  8 files changed, 41 insertions(+), 14 deletions(-)
>>
>> diff --git a/scripts/qapi.py b/scripts/qapi.py
>> index 9d075440d3..9c7c01c11d 100644
>> --- a/scripts/qapi.py
>> +++ b/scripts/qapi.py
>> @@ -729,6 +729,10 @@ def check_event(expr, info):
>>                 allow_metas=meta)
>>  
>>  
>> +def enum_get_values(expr):
>> +    return [e if isinstance(e, str) else e['name'] for e in expr['data']]
>> +
>> +
>
> An iterator would be more efficient, but this will do.
>
>>  def check_union(expr, info):
>>      name = expr['union']
>>      base = expr.get('base')
>> @@ -788,7 +792,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_values(enum_define):
>>                  raise QAPISemError(info,
>>                                     "Discriminator value '%s' is not found in "
>>                                     "enum '%s'"
>> @@ -796,7 +800,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_values(enum_define):
>>              if value not in members.keys():
>>                  raise QAPISemError(info, "Union '%s' data missing '%s' branch"
>>                                     % (name, value))
>> @@ -827,7 +831,7 @@ def check_alternate(expr, info):
>>          if qtype == 'QTYPE_QSTRING':
>>              enum_expr = enum_types.get(value)
>>              if enum_expr:
>> -                for v in enum_expr['data']:
>> +                for v in enum_get_values(enum_expr):
>>                      if v in ['on', 'off']:
>>                          conflicting.add('QTYPE_QBOOL')
>>                      if re.match(r'[-+0-9.]', v): # lazy, could be tightened
>> @@ -857,6 +861,12 @@ def check_enum(expr, info):
>>          raise QAPISemError(info,
>>                             "Enum '%s' requires a string for 'prefix'" % name)
>>      for member in members:
>> +        if isinstance(member, dict):
>> +            if not 'name' in member:
>> +                raise QAPISemError(info, "Dictionary member of enum '%s' must "
>> +                                   "have a 'name' key" % name)
>> +            check_if(member, info)

Where are dictionary keys other than 'name' and 'if' rejected?

>> +            member = member['name']
>>          check_name(info, "Member of enum '%s'" % name, member,
>>                     enum_member=True)
>>  
>
> Looks like you got all uses of enum's 'data' in the old semantic
> checker.
>
> Aside: work like this is why I dislike how the old semantic checker
> works directly on the parse trees represented as OrderedDict.
> Everything is a dictionary, and almost everything's key is 'data'.
>
[...]

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

* Re: [Qemu-devel] [PATCH v2 32/54] qapi: add 'if' to struct members
  2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 32/54] qapi: add 'if' to struct members Marc-André Lureau
@ 2017-09-07 14:26   ` Markus Armbruster
  2017-09-07 15:30     ` Marc-André Lureau
  0 siblings, 1 reply; 140+ messages in thread
From: Markus Armbruster @ 2017-09-07 14:26 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi.py                         | 18 ++++++++++++++----
>  tests/qapi-schema/qapi-schema-test.json |  9 ++++++---
>  tests/qapi-schema/qapi-schema-test.out  |  4 +++-
>  tests/qapi-schema/test-qapi.py          |  3 ++-
>  4 files changed, 25 insertions(+), 9 deletions(-)
>
> diff --git a/scripts/qapi.py b/scripts/qapi.py
> index 201e425842..946df83854 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi.py
> @@ -678,7 +678,13 @@ def check_type(info, source, value, allow_array=False,
>          return
>  
>      if not allow_dict:
> -        raise QAPISemError(info, "%s should be a type name" % source)
> +        if isinstance(value, dict) and 'type' in value:

"not allow_dict" has become a lie: 

Not your patch's fault: we sometimes check for dict, and sometimes for
OrderedDict.  If there's a reason, it's not obvious.  If there isn't, we
should be more consistent.

> +            check_type(info, source, value['type'], allow_array,
> +                       allow_dict, allow_optional, allow_metas)
> +            check_if(value, info)

Where are dictionary keys other than 'type' and 'if' rejected?

> +            return
> +        else:
> +            raise QAPISemError(info, "%s should be a type name" % source)
>  
>      if not isinstance(value, OrderedDict):
>          raise QAPISemError(info,

check_type() is used all over the place.  Your commit message claims
that your patch only affects struct members.  That's not obvious, so
down I go the next rabbit hole you present me :)

First: no change unless allow_dict.  Let's review the callers that pass
allow_dict=True.

* check_command() for arguments when not boxed

* check_event() for arguments when not boxed

* check_union() for a flat union's base

* check_struct() for the struct's members

As far as I can tell, these all accept {'type': TYPE-NAME, 'if': 'COND'}
in addition to TYPE-NAME as values in their dictionaries.  That's not
what the commit message claims.  Which one needs fixing, commit message
or code?

I guess it's the commit message, because we want to support 'if' in all
these places, don't we?

> @@ -1332,8 +1338,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
> @@ -1612,13 +1618,17 @@ class QAPISchema(object):
>  
>      def _make_member(self, name, typ, info):
>          optional = False
> +        ifcond = None
>          if name.startswith('*'):
>              name = name[1:]
>              optional = True
> +        if isinstance(typ, dict):
> +            ifcond = typ.get('if')
> +            typ = typ['type']
>          if isinstance(typ, list):
>              assert len(typ) == 1
>              typ = self._make_array_type(typ[0], info)
> -        return QAPISchemaObjectTypeMember(name, typ, optional)
> +        return QAPISchemaObjectTypeMember(name, typ, optional, ifcond)
>  
>      def _make_members(self, data, info):
>          return [self._make_member(key, value, info)

We call _make_members() for exactly the four things I enumerated above:
command arguments, event arguments, flat union's base, struct members.
Good.

> diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
> index ad2b405d83..b136e4855f 100644
> --- a/tests/qapi-schema/qapi-schema-test.json
> +++ b/tests/qapi-schema/qapi-schema-test.json
> @@ -191,7 +191,8 @@
>  
>  # test 'if' condition handling
>  
> -{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
> +{ 'struct': 'TestIfStruct', 'data':
> +  { 'foo': 'int', 'bar': { 'type': 'int', 'if': 'defined(TEST_IF_STRUCT_BAR)'} },

Long line, suggest to break it before 'bar'.

>    'if': 'defined(TEST_IF_STRUCT)' }
>  
>  { 'enum': 'TestIfEnum', 'data':
> @@ -204,8 +205,10 @@
>  { '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)' } },

Likewise.

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

Likewise.

>    '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 211c367632..5d2f18e4aa 100644
> --- a/tests/qapi-schema/qapi-schema-test.out
> +++ b/tests/qapi-schema/qapi-schema-test.out
> @@ -67,6 +67,7 @@ event TestIfEvent q_obj_TestIfEvent-arg
>      if defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)
>  object TestIfStruct
>      member foo: int optional=False
> +    member bar: int optional=False if=defined(TEST_IF_STRUCT_BAR)
>      if defined(TEST_IF_STRUCT)
>  object TestIfUnion
>      member type: TestIfUnionKind optional=False
> @@ -197,10 +198,11 @@ object q_obj_EVENT_D-arg
>      member enum3: EnumOne optional=True
>  object q_obj_TestIfCmd-arg
>      member foo: TestIfStruct optional=False
> -    member bar: TestIfEnum optional=False
> +    member bar: TestIfEnum optional=False if=defined(TEST_IF_CMD_BAR)
>      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)
>  object q_obj_TestStruct-wrapper
>      member data: TestStruct optional=False
> diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
> index 70054848f0..5d2f67a1d3 100644
> --- a/tests/qapi-schema/test-qapi.py
> +++ b/tests/qapi-schema/test-qapi.py
> @@ -31,7 +31,8 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
>              print '    base %s' % base.name
>          for m in members:
>              print '    member %s: %s optional=%s' % \
> -                (m.name, m.type.name, m.optional)
> +                (m.name, m.type.name, m.optional) + \
> +                (' if=%s' % m.ifcond if m.ifcond else '')

Let's keep it simple & stupid:

               print '    member %s: %s optional=%s if=%s' % \
                   (m.name, m.type.name, m.optional, m.ifcond)

>          self._print_variants(variants)
>          self._print_if(ifcond)

Need negative tests, but I guess they're next.

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

* Re: [Qemu-devel] [PATCH v2 32/54] qapi: add 'if' to struct members
  2017-09-07 14:26   ` Markus Armbruster
@ 2017-09-07 15:30     ` Marc-André Lureau
  2017-09-07 15:52       ` Markus Armbruster
  0 siblings, 1 reply; 140+ messages in thread
From: Marc-André Lureau @ 2017-09-07 15:30 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth

Hi

----- Original Message -----
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> 
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >  scripts/qapi.py                         | 18 ++++++++++++++----
> >  tests/qapi-schema/qapi-schema-test.json |  9 ++++++---
> >  tests/qapi-schema/qapi-schema-test.out  |  4 +++-
> >  tests/qapi-schema/test-qapi.py          |  3 ++-
> >  4 files changed, 25 insertions(+), 9 deletions(-)
> >
> > diff --git a/scripts/qapi.py b/scripts/qapi.py
> > index 201e425842..946df83854 100644
> > --- a/scripts/qapi.py
> > +++ b/scripts/qapi.py
> > @@ -678,7 +678,13 @@ def check_type(info, source, value, allow_array=False,
> >          return
> >  
> >      if not allow_dict:
> > -        raise QAPISemError(info, "%s should be a type name" % source)
> > +        if isinstance(value, dict) and 'type' in value:
> 
> "not allow_dict" has become a lie:
> 
> Not your patch's fault: we sometimes check for dict, and sometimes for
> OrderedDict.  If there's a reason, it's not obvious.  If there isn't, we
> should be more consistent.
> 
> > +            check_type(info, source, value['type'], allow_array,
> > +                       allow_dict, allow_optional, allow_metas)
> > +            check_if(value, info)
> 
> Where are dictionary keys other than 'type' and 'if' rejected?
> 
> > +            return
> > +        else:
> > +            raise QAPISemError(info, "%s should be a type name" % source)
> >  
> >      if not isinstance(value, OrderedDict):
> >          raise QAPISemError(info,
> 
> check_type() is used all over the place.  Your commit message claims
> that your patch only affects struct members.  That's not obvious, so
> down I go the next rabbit hole you present me :)
> 
> First: no change unless allow_dict.  Let's review the callers that pass
> allow_dict=True.
> 
> * check_command() for arguments when not boxed
> 
> * check_event() for arguments when not boxed
> 
> * check_union() for a flat union's base
> 
> * check_struct() for the struct's members
> 
> As far as I can tell, these all accept {'type': TYPE-NAME, 'if': 'COND'}
> in addition to TYPE-NAME as values in their dictionaries.  That's not
> what the commit message claims.  Which one needs fixing, commit message
> or code?
> 
> I guess it's the commit message, because we want to support 'if' in all
> these places, don't we?

Yes

> 
> > @@ -1332,8 +1338,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
> > @@ -1612,13 +1618,17 @@ class QAPISchema(object):
> >  
> >      def _make_member(self, name, typ, info):
> >          optional = False
> > +        ifcond = None
> >          if name.startswith('*'):
> >              name = name[1:]
> >              optional = True
> > +        if isinstance(typ, dict):
> > +            ifcond = typ.get('if')
> > +            typ = typ['type']
> >          if isinstance(typ, list):
> >              assert len(typ) == 1
> >              typ = self._make_array_type(typ[0], info)
> > -        return QAPISchemaObjectTypeMember(name, typ, optional)
> > +        return QAPISchemaObjectTypeMember(name, typ, optional, ifcond)
> >  
> >      def _make_members(self, data, info):
> >          return [self._make_member(key, value, info)
> 
> We call _make_members() for exactly the four things I enumerated above:
> command arguments, event arguments, flat union's base, struct members.
> Good.
> 
> > diff --git a/tests/qapi-schema/qapi-schema-test.json
> > b/tests/qapi-schema/qapi-schema-test.json
> > index ad2b405d83..b136e4855f 100644
> > --- a/tests/qapi-schema/qapi-schema-test.json
> > +++ b/tests/qapi-schema/qapi-schema-test.json
> > @@ -191,7 +191,8 @@
> >  
> >  # test 'if' condition handling
> >  
> > -{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
> > +{ 'struct': 'TestIfStruct', 'data':
> > +  { 'foo': 'int', 'bar': { 'type': 'int', 'if':
> > 'defined(TEST_IF_STRUCT_BAR)'} },
> 
> Long line, suggest to break it before 'bar'.
> 

ok

> >    'if': 'defined(TEST_IF_STRUCT)' }
> >  
> >  { 'enum': 'TestIfEnum', 'data':
> > @@ -204,8 +205,10 @@
> >  { '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)' } },
> 
> Likewise.
> 
> >    '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)' } },
> 
> Likewise.
> 
> >    '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 211c367632..5d2f18e4aa 100644
> > --- a/tests/qapi-schema/qapi-schema-test.out
> > +++ b/tests/qapi-schema/qapi-schema-test.out
> > @@ -67,6 +67,7 @@ event TestIfEvent q_obj_TestIfEvent-arg
> >      if defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)
> >  object TestIfStruct
> >      member foo: int optional=False
> > +    member bar: int optional=False if=defined(TEST_IF_STRUCT_BAR)
> >      if defined(TEST_IF_STRUCT)
> >  object TestIfUnion
> >      member type: TestIfUnionKind optional=False
> > @@ -197,10 +198,11 @@ object q_obj_EVENT_D-arg
> >      member enum3: EnumOne optional=True
> >  object q_obj_TestIfCmd-arg
> >      member foo: TestIfStruct optional=False
> > -    member bar: TestIfEnum optional=False
> > +    member bar: TestIfEnum optional=False if=defined(TEST_IF_CMD_BAR)
> >      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)
> >  object q_obj_TestStruct-wrapper
> >      member data: TestStruct optional=False
> > diff --git a/tests/qapi-schema/test-qapi.py
> > b/tests/qapi-schema/test-qapi.py
> > index 70054848f0..5d2f67a1d3 100644
> > --- a/tests/qapi-schema/test-qapi.py
> > +++ b/tests/qapi-schema/test-qapi.py
> > @@ -31,7 +31,8 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
> >              print '    base %s' % base.name
> >          for m in members:
> >              print '    member %s: %s optional=%s' % \
> > -                (m.name, m.type.name, m.optional)
> > +                (m.name, m.type.name, m.optional) + \
> > +                (' if=%s' % m.ifcond if m.ifcond else '')
> 
> Let's keep it simple & stupid:
> 
>                print '    member %s: %s optional=%s if=%s' % \
>                    (m.name, m.type.name, m.optional, m.ifcond)
> 

I would rather not modify every existing test please.

The last version of the series uses the trailing , trick instead:

     print '%s optional=%s' % (m.type.name, m.optional),
     if m.ifcond:
         print 'if=%s' % m.ifcond,
     print

I think this is easier to deal with, is that ok for you too?

> >          self._print_variants(variants)
> >          self._print_if(ifcond)
> 
> Need negative tests, but I guess they're next.
> 

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

* Re: [Qemu-devel] [PATCH v2 32/54] qapi: add 'if' to struct members
  2017-09-07 15:30     ` Marc-André Lureau
@ 2017-09-07 15:52       ` Markus Armbruster
  0 siblings, 0 replies; 140+ messages in thread
From: Markus Armbruster @ 2017-09-07 15:52 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Michael Roth

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

> Hi
>
> ----- Original Message -----
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
[...]
>> > diff --git a/tests/qapi-schema/test-qapi.py
>> > b/tests/qapi-schema/test-qapi.py
>> > index 70054848f0..5d2f67a1d3 100644
>> > --- a/tests/qapi-schema/test-qapi.py
>> > +++ b/tests/qapi-schema/test-qapi.py
>> > @@ -31,7 +31,8 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
>> >              print '    base %s' % base.name
>> >          for m in members:
>> >              print '    member %s: %s optional=%s' % \
>> > -                (m.name, m.type.name, m.optional)
>> > +                (m.name, m.type.name, m.optional) + \
>> > +                (' if=%s' % m.ifcond if m.ifcond else '')
>> 
>> Let's keep it simple & stupid:
>> 
>>                print '    member %s: %s optional=%s if=%s' % \
>>                    (m.name, m.type.name, m.optional, m.ifcond)
>> 
>
> I would rather not modify every existing test please.
>
> The last version of the series uses the trailing , trick instead:
>
>      print '%s optional=%s' % (m.type.name, m.optional),
>      if m.ifcond:
>          print 'if=%s' % m.ifcond,
>      print
>
> I think this is easier to deal with, is that ok for you too?

Yes.

>> >          self._print_variants(variants)
>> >          self._print_if(ifcond)
>> 
>> Need negative tests, but I guess they're next.
>> 

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

end of thread, other threads:[~2017-09-07 15:52 UTC | newest]

Thread overview: 140+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-22 13:22 [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 01/54] qapi: fix type_seen key error Marc-André Lureau
2017-08-22 15:00   ` Markus Armbruster
2017-08-22 15:50     ` Marc-André Lureau
2017-08-22 16:40       ` Markus Armbruster
2017-08-25  6:02   ` Markus Armbruster
2017-08-25 12:57     ` Eduardo Habkost
2017-08-25 14:12       ` Marc-André Lureau
2017-08-28 10:52         ` Markus Armbruster
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 02/54] qdict: add qdict_put_null() helper Marc-André Lureau
2017-08-22 15:09   ` Markus Armbruster
2017-08-25 15:46     ` Eric Blake
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 03/54] qobject: add literal qobject type Marc-André Lureau
2017-08-22 15:31   ` Markus Armbruster
2017-08-22 15:42     ` Marc-André Lureau
2017-08-22 16:24       ` Markus Armbruster
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 04/54] qlit: add qobject_form_qlit() Marc-André Lureau
2017-08-22 15:40   ` Markus Armbruster
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 05/54] qapi: generate a literal qobject for introspection Marc-André Lureau
2017-08-22 16:33   ` Markus Armbruster
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 06/54] qapi: introduce qapi_enum_lookup() Marc-André Lureau
2017-08-22 18:10   ` John Snow
2017-08-23  8:02   ` Markus Armbruster
2017-08-23 10:10     ` Marc-André Lureau
2017-08-24 11:14       ` Dr. David Alan Gilbert
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 07/54] tpm: simplify driver registration & lookup Marc-André Lureau
2017-08-23  9:04   ` Markus Armbruster
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 08/54] hmp: use qapi_enum_parse() in hmp_migrate_set_capability Marc-André Lureau
2017-08-23  9:34   ` Markus Armbruster
2017-08-24 11:29   ` Dr. David Alan Gilbert
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 09/54] hmp: use qapi_enum_parse() in hmp_migrate_set_parameter Marc-André Lureau
2017-08-23  9:43   ` Markus Armbruster
2017-08-24 13:16     ` Dr. David Alan Gilbert
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 10/54] block: use qemu_enum_parse() in blkdebug_debug_breakpoint Marc-André Lureau
2017-08-23 10:05   ` Markus Armbruster
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 11/54] quorum: use qapi_enum_parse() in quorum_open Marc-André Lureau
2017-08-22 13:40   ` Alberto Garcia
2017-08-23 11:15     ` Markus Armbruster
2017-08-23 11:24   ` Markus Armbruster
2017-08-23 11:53     ` Alberto Garcia
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 12/54] qapi: change enum lookup structure Marc-André Lureau
2017-08-23 12:09   ` Markus Armbruster
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 13/54] qapi: drop the sentinel in enum array Marc-André Lureau
2017-08-23 12:37   ` Markus Armbruster
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 14/54] qapi2texi: minor python code simplification Marc-André Lureau
2017-08-22 13:56   ` Philippe Mathieu-Daudé
2017-09-01 15:49   ` Markus Armbruster
2017-09-04  8:18     ` Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 15/54] qapi: add 'if' to top-level expressions Marc-André Lureau
2017-09-04 13:27   ` Markus Armbruster
2017-09-05 13:58     ` Marc-André Lureau
2017-09-06 11:36       ` Markus Armbruster
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 16/54] qapi: add a test for invalid 'if' Marc-André Lureau
2017-09-04 13:31   ` Markus Armbruster
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 17/54] qapi: add 'if' condition on entity objects Marc-André Lureau
2017-09-04 16:13   ` Markus Armbruster
2017-09-05 15:38     ` Marc-André Lureau
2017-09-05 16:31       ` Markus Armbruster
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 18/54] qapi: add 'ifcond' to visitor methods Marc-André Lureau
2017-09-04 16:47   ` Markus Armbruster
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 19/54] qapi: add #if/#endif helpers Marc-André Lureau
2017-09-05  9:32   ` Markus Armbruster
2017-09-06 15:19     ` Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 20/54] qapi-introspect: modify to_qlit() to take an optional suffix Marc-André Lureau
2017-09-05  9:42   ` Markus Armbruster
2017-09-06 14:02     ` Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 21/54] qapi-introspect: modify to_qlit() to generate #if code Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 22/54] qapi-introspect: add preprocessor conditions to generated QLit Marc-André Lureau
2017-09-05 14:24   ` Markus Armbruster
2017-09-05 16:24     ` Marc-André Lureau
2017-09-06 11:38   ` Markus Armbruster
2017-09-06 14:26     ` Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 23/54] qapi-commands: add #if conditions to commands Marc-André Lureau
2017-09-05 14:53   ` Markus Armbruster
2017-09-05 15:05     ` Marc-André Lureau
2017-09-05 15:08       ` Marc-André Lureau
2017-09-05 16:34         ` Markus Armbruster
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 24/54] qapi-event: add #if conditions to events Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 25/54] qapi-visit: add #if conditions to visitors Marc-André Lureau
2017-09-06 10:54   ` Markus Armbruster
2017-09-06 14:22     ` Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 26/54] qapi-types: refactor variants handling Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 27/54] qapi-types: add #if conditions to types Marc-André Lureau
2017-09-06 11:43   ` Markus Armbruster
2017-09-06 14:56     ` Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 28/54] qapi: do not define enumeration value explicitely Marc-André Lureau
2017-08-22 14:00   ` Philippe Mathieu-Daudé
2017-09-05 17:45   ` Markus Armbruster
2017-09-06 12:09     ` Marc-André Lureau
2017-09-06 13:39       ` Markus Armbruster
2017-09-06 13:55         ` Marc-André Lureau
2017-09-06 15:20           ` Markus Armbruster
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 29/54] qapi: add 'if' to enum members Marc-André Lureau
2017-09-06 13:01   ` Markus Armbruster
2017-09-07 14:11     ` Markus Armbruster
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 30/54] qapi: add #if conditions on generated enum values Marc-André Lureau
2017-09-06 15:38   ` Markus Armbruster
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 31/54] tests: add some enum members tests Marc-André Lureau
2017-09-06 15:41   ` Markus Armbruster
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 32/54] qapi: add 'if' to struct members Marc-André Lureau
2017-09-07 14:26   ` Markus Armbruster
2017-09-07 15:30     ` Marc-André Lureau
2017-09-07 15:52       ` Markus Armbruster
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 33/54] qapi: add some struct member tests Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 34/54] qapi: add #if conditions to generated struct members Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 35/54] qapi: add 'if' on union variants Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 36/54] qapi: add #if conditions to generated variants Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 37/54] qapi: 'if' to alternate variant Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 38/54] qapi: add tests for invalid alternate Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 39/54] qapi: add #if conditions to generated alternate variants Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 40/54] docs: document schema configuration Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 41/54] qapi2texi: add 'If:' section to generated documentation Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 42/54] qapi2texi: add 'If:' condition to enum values Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 43/54] qapi2texi: add 'If:' condition to struct members Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 44/54] qapi2texi: add condition to variants Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 45/54] qapi: add conditions to VNC type/commands/events on the schema Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 46/54] qapi: add conditions to SPICE " Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 47/54] qapi: add conditions to REPLICATION type/commands " Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 48/54] tests/qmp-test: add query-qmp-schema test Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 49/54] build-sys: make qemu qapi objects per-target Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 50/54] qapi: make rtc-reset-reinjection depend on TARGET_I386 Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 51/54] qapi: make s390 commands depend on TARGET_S390X Marc-André Lureau
2017-08-22 14:24   ` Cornelia Huck
2017-08-22 14:25     ` David Hildenbrand
2017-08-22 14:41       ` Marc-André Lureau
2017-08-22 15:14         ` Cornelia Huck
2017-08-22 15:46           ` Marc-André Lureau
2017-08-22 15:58       ` Markus Armbruster
2017-08-22 16:01         ` David Hildenbrand
2017-08-22 16:25           ` Markus Armbruster
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 52/54] qapi: make query-gic-capabilities depend on TARGET_ARM Marc-André Lureau
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 53/54] qapi: make query-cpu-model-expansion depend on s390 or x86 Marc-André Lureau
2017-08-22 18:42   ` Eduardo Habkost
2017-08-23 10:21     ` Marc-André Lureau
2017-08-23 12:57       ` Eduardo Habkost
2017-08-23 13:58         ` Marc-André Lureau
2017-08-23 14:13           ` Eduardo Habkost
2017-08-22 13:22 ` [Qemu-devel] [PATCH v2 54/54] qapi: make query-cpu-definitions depend on specific targets Marc-André Lureau
2017-08-22 14:47 ` [Qemu-devel] [PATCH v2 00/54] qapi: add #if pre-processor conditions to generated code no-reply
2017-08-23 12:46 ` 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.